From a79c4f3489d21478bdf43c83c834d8aae21355c2 Mon Sep 17 00:00:00 2001 From: mashimin <3130004661@qq.com> Date: Fri, 8 Aug 2025 14:26:22 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=B8=AD=E6=8E=A7?= =?UTF-8?q?=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/project/personnel-dispatch.ts | 98 ++ src/apis/project/type.ts | 248 ++- src/router/route.ts | 23 + .../construction-personnel.vue | 952 ++++++++++++ .../personnel-dispatch/index.vue | 1372 +++++++++++++++++ 5 files changed, 2692 insertions(+), 1 deletion(-) create mode 100644 src/apis/project/personnel-dispatch.ts create mode 100644 src/views/project-management/personnel-dispatch/construction-personnel.vue create mode 100644 src/views/project-management/personnel-dispatch/index.vue diff --git a/src/apis/project/personnel-dispatch.ts b/src/apis/project/personnel-dispatch.ts new file mode 100644 index 0000000..617c763 --- /dev/null +++ b/src/apis/project/personnel-dispatch.ts @@ -0,0 +1,98 @@ +import type * as T from './type' +import http from '@/utils/http' + +export type * from './type' + +const BASE_URL = '/project-member' + +// ==================== 项目看板相关接口 ==================== + +/** @desc 获取项目看板统计数据 */ +export function getProjectKanbanStats() { + return http.get(`${BASE_URL}/kanban/stats`) +} + +/** @desc 获取项目看板数据 */ +export function getProjectKanbanData() { + return http.get(`${BASE_URL}/kanban/data`) +} + +/** @desc 获取项目详情 */ +export function getProjectDetail(id: string | number) { + return http.get(`${BASE_URL}/project/${id}/detail`) +} + +// ==================== 团队成员管理 ==================== + +/** @desc 获取项目团队成员列表(支持筛选、分页、搜索) */ +export function getProjectTeamMembers(params: T.TeamMemberQuery) { + const { projectId, ...queryParams } = params + return http.get(`${BASE_URL}/project/${projectId}/team-members`, { params: queryParams }) +} + +/** @desc 创建团队成员 */ +export function createTeamMember(data: T.CreateTeamMemberForm) { + return http.post(`${BASE_URL}/team-member`, data) +} + +/** @desc 更新团队成员信息(支持更新状态) */ +export function updateTeamMember(id: string | number, data: T.UpdateTeamMemberForm) { + return http.put(`${BASE_URL}/team-member/${id}`, data) +} + +/** @desc 删除团队成员(支持单个或批量删除) */ +export function deleteTeamMembers(ids: string | number | (string | number)[]) { + const idArray = Array.isArray(ids) ? ids : [ids] + return http.del(`${BASE_URL}/team-member/batch`, { data: { ids: idArray } }) +} + +/** @desc 导入团队成员数据 */ +export function importTeamMembers(projectId: string | number, file: File) { + const formData = new FormData() + formData.append('file', file) + formData.append('projectId', projectId.toString()) + return http.post(`${BASE_URL}/team-member/import`, formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** @desc 导出团队成员数据 */ +export function exportTeamMembers(params: T.TeamMemberExportQuery) { + return http.get(`${BASE_URL}/team-member/export`, { + params, + responseType: 'blob' + }) +} + +/** @desc 下载导入模板 */ +export function downloadImportTemplate() { + return http.get(`${BASE_URL}/team-member/template`, { + responseType: 'blob' + }) +} + +// ==================== 项目需求管理 ==================== + +/** @desc 获取项目需求列表 */ +export function getProjectRequirements(projectId: string | number) { + return http.get(`${BASE_URL}/project/${projectId}/requirements`) +} + +/** @desc 发布项目需求 */ +export function createProjectRequirement(data: T.CreateProjectRequirementForm) { + return http.post(`${BASE_URL}/requirement`, data) +} + +/** @desc 更新项目需求状态 */ +export function updateRequirementStatus(data: T.UpdateRequirementStatusForm) { + return http.patch(`${BASE_URL}/requirement/status`, data) +} + +/** @desc 删除项目需求 */ +export function deleteProjectRequirement(requirementId: string | number) { + return http.del(`${BASE_URL}/requirement/${requirementId}`) +} + + \ No newline at end of file diff --git a/src/apis/project/type.ts b/src/apis/project/type.ts index 32bc3b7..c15d7e8 100644 --- a/src/apis/project/type.ts +++ b/src/apis/project/type.ts @@ -85,4 +85,250 @@ export interface TaskQuery { status?: string } -export interface TaskPageQuery extends TaskQuery, PageQuery {} \ No newline at end of file +export interface TaskPageQuery extends TaskQuery, PageQuery {} + +// ==================== 人员调度相关类型 ==================== + +/** 项目看板统计数据 */ +export interface ProjectKanbanStats { + totalProjectsCount: string + pendingProjectCount: string + inProgressProjectCount: string + completedProjectCount: string + auditedProjectCount: string + acceptedProjectCount: string + totalTurbineCount: string + pendingTurbineCount: string + inProgressTurbineCount: string + completedTurbineCount: string + auditedTurbineCount: string + acceptedTurbineCount: string + totalTaskCount: string + pendingTaskCount: string + inProgressTaskCount: string + completedTaskCount: string + totalMemberCount: string + projectManagerCount: string + safetyOfficerCount: string + qualityOfficerCount: string + constructorCount: string + teamLeaderCount: string +} + +/** 项目看板数据 */ +export interface ProjectKanbanData { + inProgressProjects: never[] + preparingProjects: ProjectCard[] + ongoingProjects: ProjectCard[] + pendingProjects: ProjectCard[] +} + +/** 项目卡片信息 */ +export interface ProjectCard { + id: string | number + name: string + status: 'preparing' | 'ongoing' | 'pending' + budget: number + manager: string + teamSize: number + preparationProgress?: number + progress?: number + startDate?: string + endDate?: string + plannedStartDate?: string + alerts?: ProjectAlert[] + teamMembers: TeamMemberResp[] + requirements: ProjectRequirementResp[] +} + +/** 项目异常信息 */ +export interface ProjectAlert { + type: 'cost' | 'personnel' | 'schedule' | 'quality' + message: string +} + +/** 项目详情响应 */ +export interface ProjectDetailResp extends ProjectCard { + // 继承ProjectCard的所有字段,可以添加更多详情字段 +} + +/** 团队成员响应 */ +export interface TeamMemberResp { + id: string | number + name: string + position: string + phone?: string + email?: string + avatar?: string + joinDate?: string + performance?: number + remark?: string + status?: 'available' | 'busy' | 'offline' +} + +/** 后端返回的团队成员数据结构 */ +export interface BackendTeamMemberResp { + memberId: string + projectId: string + projectName: string + turbineId: string | null + turbineName: string | null + taskGroupId: string | null + taskGroupName: string | null + taskId: string | null + taskName: string | null + userId: string + name: string + phone: string | null + email: string | null + position: string + status: 'ACTIVE' | 'BUSY' | 'OFFLINE' + skills: string + joinDate: string + remark: string + userAccount: string + userAvatar: string | null + roleType: string + roleTypeDesc: string + jobCode: string + jobCodeDesc: string + jobDesc: string + leaveDate: string | null + statusDesc: string +} + +/** 团队成员查询参数(支持筛选、分页、搜索) */ +export interface TeamMemberQuery extends PageQuery { + projectId: string | number + name?: string // 姓名搜索 + position?: string // 岗位筛选 + status?: string // 状态筛选 + joinDateStart?: string // 入职日期开始 + joinDateEnd?: string // 入职日期结束 + sortBy?: 'name' | 'position' | 'joinDate' | 'status' // 排序字段 + sortOrder?: 'asc' | 'desc' // 排序方向 +} + +/** 团队成员导出查询参数(不包含分页) */ +export interface TeamMemberExportQuery { + projectId: string | number + name?: string // 姓名搜索 + position?: string // 岗位筛选 + status?: string // 状态筛选 + joinDateStart?: string // 入职日期开始 + joinDateEnd?: string // 入职日期结束 + sortBy?: 'name' | 'position' | 'joinDate' | 'status' // 排序字段 + sortOrder?: 'asc' | 'desc' // 排序方向 +} + +/** 创建团队成员表单 */ +export interface CreateTeamMemberForm { + projectId: string | number + name: string + phone: string + email?: string + position: string + status?: 'available' | 'busy' | 'offline' + joinDate?: string + remark?: string +} + +/** 更新团队成员表单 */ +export interface UpdateTeamMemberForm { + name?: string + phone?: string + email?: string + position?: string + status?: 'available' | 'busy' | 'offline' + joinDate?: string + remark?: string +} + + + +/** 批量操作表单 */ +export interface BatchOperationForm { + ids: (string | number)[] + operation: 'delete' | 'updateStatus' + status?: 'available' | 'busy' | 'offline' +} + +/** 导入结果响应 */ +export interface ImportResultResp { + success: boolean + totalCount: number + successCount: number + failCount: number + errors?: Array<{ + row: number + message: string + }> +} + +/** 人员需求响应 */ +export interface PersonnelRequirementResp { + id: string | number + title: string + type: 'personnel' | 'equipment' + position?: string + equipmentType?: string + count: number + skills: string[] + description?: string + priority: 'low' | 'medium' | 'high' + status: 'pending' | 'recruiting' | 'completed' + createTime: string + updateTime: string +} + +/** 创建需求表单 */ +export interface CreateRequirementForm { + projectId: string | number + type: 'personnel' | 'equipment' + position?: string + equipmentType?: string + count: number + skills: string[] + description?: string + priority: 'low' | 'medium' | 'high' +} + +/** 简化项目需求响应类型 */ +export interface ProjectRequirementResp { + id: string | number + title: string + description: string + priority: 'low' | 'medium' | 'high' + status: 'pending' | 'recruiting' | 'completed' + createTime: string + updateTime: string +} + +/** 简化创建项目需求表单类型 */ +export interface CreateProjectRequirementForm { + projectId: string | number + description: string + priority: 'low' | 'medium' | 'high' +} + +/** 更新需求状态表单 */ +export interface UpdateRequirementStatusForm { + requirementId: string | number + status: 'pending' | 'recruiting' | 'completed' +} + + + +/** 分页查询基础参数 */ +export interface PageQuery { + page: number + pageSize: number +} + +/** 分页响应 */ +export interface PageRes { + list: T[] + total: number + page: number + pageSize: number +} \ No newline at end of file diff --git a/src/router/route.ts b/src/router/route.ts index ba06fd2..99cb49e 100644 --- a/src/router/route.ts +++ b/src/router/route.ts @@ -830,6 +830,29 @@ export const systemRoutes: RouteRecordRaw[] = [ }, ], }, + + //项目中控台 + { + path: '/project-management/projects/personnel-dispatch', + name: 'PersonnelDispatch', + component: () => import('@/views/project-management/personnel-dispatch/index.vue'), + meta: { + title: '项目中控台', + icon: 'user-group', + hidden: false, + }, + }, + + { + path: '/project-management/personnel-dispatch/construction-personnel', + name: 'ConstructionPersonnel', + component: () => import('@/views/project-management/personnel-dispatch/construction-personnel.vue'), + meta: { + title: '团队成员管理', + icon: 'user', + hidden: true, + }, + }, ], }, diff --git a/src/views/project-management/personnel-dispatch/construction-personnel.vue b/src/views/project-management/personnel-dispatch/construction-personnel.vue new file mode 100644 index 0000000..f891def --- /dev/null +++ b/src/views/project-management/personnel-dispatch/construction-personnel.vue @@ -0,0 +1,952 @@ + + + + + + \ No newline at end of file diff --git a/src/views/project-management/personnel-dispatch/index.vue b/src/views/project-management/personnel-dispatch/index.vue new file mode 100644 index 0000000..7903e24 --- /dev/null +++ b/src/views/project-management/personnel-dispatch/index.vue @@ -0,0 +1,1372 @@ + + + + + + \ No newline at end of file From ae29bb661f71598e2df04096665b5393304fa9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E8=AF=97=E6=95=8F?= <3130004661@qq.com> Date: Fri, 8 Aug 2025 15:23:57 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=A2=E9=98=9F?= =?UTF-8?q?=E6=88=90=E5=91=98=E7=AE=A1=E7=90=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/project-management/personnel-dispatch/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/project-management/personnel-dispatch/index.vue b/src/views/project-management/personnel-dispatch/index.vue index 7903e24..57706a6 100644 --- a/src/views/project-management/personnel-dispatch/index.vue +++ b/src/views/project-management/personnel-dispatch/index.vue @@ -669,7 +669,7 @@ const closeProjectDetail = () => { const openPersonnelManagement = () => { if (currentProject.value && currentProject.value.id) { router.push({ - path: '/project-management/projects/personnel-dispatch/construction-personnel', + path: '/project-management/personnel-dispatch/construction-personnel', query: { projectId: currentProject.value.id } }) } else { From 5a1391169414f04150de9d7aa67d18869349f81d Mon Sep 17 00:00:00 2001 From: "Mr.j" <2221464500@qq.com> Date: Fri, 8 Aug 2025 15:44:56 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E5=8F=B0=E6=8E=A5=E6=94=B6=E5=88=B0=E9=87=87=E8=B4=AD=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types/components.d.ts | 59 --- .../approval/components/ApprovalSearch.vue | 21 +- .../device-management/approval/index.vue | 6 +- .../ProcurementApplicationModal.vue | 340 ++++++++++++++++++ .../device-management/procurement/index.vue | 68 ++++ 5 files changed, 416 insertions(+), 78 deletions(-) create mode 100644 src/views/system-resource/device-management/procurement/components/ProcurementApplicationModal.vue diff --git a/src/types/components.d.ts b/src/types/components.d.ts index 19a4246..7fa6b1b 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -7,66 +7,7 @@ export {} declare module 'vue' { export interface GlobalComponents { - Avatar: typeof import('./../components/Avatar/index.vue')['default'] - Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default'] - CellCopy: typeof import('./../components/CellCopy/index.vue')['default'] - Chart: typeof import('./../components/Chart/index.vue')['default'] - ColumnSetting: typeof import('./../components/GiTable/src/components/ColumnSetting.vue')['default'] - CronForm: typeof import('./../components/GenCron/CronForm/index.vue')['default'] - CronModal: typeof import('./../components/GenCron/CronModal/index.vue')['default'] - DateRangePicker: typeof import('./../components/DateRangePicker/index.vue')['default'] - DayForm: typeof import('./../components/GenCron/CronForm/component/day-form.vue')['default'] - FilePreview: typeof import('./../components/FilePreview/index.vue')['default'] - GiCellAvatar: typeof import('./../components/GiCell/GiCellAvatar.vue')['default'] - GiCellGender: typeof import('./../components/GiCell/GiCellGender.vue')['default'] - GiCellStatus: typeof import('./../components/GiCell/GiCellStatus.vue')['default'] - GiCellTag: typeof import('./../components/GiCell/GiCellTag.vue')['default'] - GiCellTags: typeof import('./../components/GiCell/GiCellTags.vue')['default'] - GiCodeView: typeof import('./../components/GiCodeView/index.vue')['default'] - GiDot: typeof import('./../components/GiDot/index.tsx')['default'] - GiEditTable: typeof import('./../components/GiEditTable/GiEditTable.vue')['default'] - GiFooter: typeof import('./../components/GiFooter/index.vue')['default'] - GiForm: typeof import('./../components/GiForm/src/GiForm.vue')['default'] - GiIconBox: typeof import('./../components/GiIconBox/index.vue')['default'] - GiIconSelector: typeof import('./../components/GiIconSelector/index.vue')['default'] - GiIframe: typeof import('./../components/GiIframe/index.vue')['default'] - GiOption: typeof import('./../components/GiOption/index.vue')['default'] - GiOptionItem: typeof import('./../components/GiOptionItem/index.vue')['default'] - GiPageLayout: typeof import('./../components/GiPageLayout/index.vue')['default'] - GiSpace: typeof import('./../components/GiSpace/index.vue')['default'] - GiSplitButton: typeof import('./../components/GiSplitButton/index.vue')['default'] - GiSplitPane: typeof import('./../components/GiSplitPane/index.vue')['default'] - GiSplitPaneFlexibleBox: typeof import('./../components/GiSplitPane/components/GiSplitPaneFlexibleBox.vue')['default'] - GiSvgIcon: typeof import('./../components/GiSvgIcon/index.vue')['default'] - GiTable: typeof import('./../components/GiTable/src/GiTable.vue')['default'] - GiTag: typeof import('./../components/GiTag/index.tsx')['default'] - GiThemeBtn: typeof import('./../components/GiThemeBtn/index.vue')['default'] - HourForm: typeof import('./../components/GenCron/CronForm/component/hour-form.vue')['default'] - Icon403: typeof import('./../components/icons/Icon403.vue')['default'] - Icon404: typeof import('./../components/icons/Icon404.vue')['default'] - Icon500: typeof import('./../components/icons/Icon500.vue')['default'] - IconBorders: typeof import('./../components/icons/IconBorders.vue')['default'] - IconTableSize: typeof import('./../components/icons/IconTableSize.vue')['default'] - IconTreeAdd: typeof import('./../components/icons/IconTreeAdd.vue')['default'] - IconTreeReduce: typeof import('./../components/icons/IconTreeReduce.vue')['default'] - ImageImport: typeof import('./../components/ImageImport/index.vue')['default'] - ImageImportWizard: typeof import('./../components/ImageImportWizard/index.vue')['default'] - IndustrialImageList: typeof import('./../components/IndustrialImageList/index.vue')['default'] - JsonPretty: typeof import('./../components/JsonPretty/index.vue')['default'] - MinuteForm: typeof import('./../components/GenCron/CronForm/component/minute-form.vue')['default'] - MonthForm: typeof import('./../components/GenCron/CronForm/component/month-form.vue')['default'] - ParentView: typeof import('./../components/ParentView/index.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] - SecondForm: typeof import('./../components/GenCron/CronForm/component/second-form.vue')['default'] - SplitPanel: typeof import('./../components/SplitPanel/index.vue')['default'] - TextCopy: typeof import('./../components/TextCopy/index.vue')['default'] - TurbineGrid: typeof import('./../components/TurbineGrid/index.vue')['default'] - UserSelect: typeof import('./../components/UserSelect/index.vue')['default'] - Verify: typeof import('./../components/Verify/index.vue')['default'] - VerifyPoints: typeof import('./../components/Verify/Verify/VerifyPoints.vue')['default'] - VerifySlide: typeof import('./../components/Verify/Verify/VerifySlide.vue')['default'] - WeekForm: typeof import('./../components/GenCron/CronForm/component/week-form.vue')['default'] - YearForm: typeof import('./../components/GenCron/CronForm/component/year-form.vue')['default'] } } diff --git a/src/views/system-resource/device-management/approval/components/ApprovalSearch.vue b/src/views/system-resource/device-management/approval/components/ApprovalSearch.vue index e90f809..f22658a 100644 --- a/src/views/system-resource/device-management/approval/components/ApprovalSearch.vue +++ b/src/views/system-resource/device-management/approval/components/ApprovalSearch.vue @@ -129,29 +129,18 @@ const debouncedSearch = debounce(() => { const search = () => { console.log('🔍 ApprovalSearch - 搜索按钮被点击') console.log('🔍 ApprovalSearch - 搜索表单数据:', searchForm) - console.log('🔍 ApprovalSearch - 搜索表单数据类型:', typeof searchForm) - console.log('🔍 ApprovalSearch - 搜索表单的键值对:') - Object.entries(searchForm).forEach(([key, value]) => { - console.log(` ${key}: ${value} (${typeof value})`) - }) - // 构建搜索参数 + // 构建搜索参数 - 参考设备采购功能的实现 const searchParams: EquipmentApprovalListReq = { equipmentName: searchForm.equipmentName || undefined, applicantName: searchForm.applicantName || undefined, - businessType: searchForm.businessType, - approvalStatus: searchForm.approvalStatus, - applyTimeStart: searchForm.applyTimeStart, - applyTimeEnd: searchForm.applyTimeEnd + businessType: searchForm.businessType || undefined, + approvalStatus: searchForm.approvalStatus || undefined, + applyTimeStart: searchForm.applyTimeStart || undefined, + applyTimeEnd: searchForm.applyTimeEnd || undefined, } console.log('🔍 ApprovalSearch - 发送的搜索参数:', searchParams) - console.log('🔍 ApprovalSearch - 发送参数的类型:', typeof searchParams) - console.log('🔍 ApprovalSearch - 发送参数的键值对:') - Object.entries(searchParams).forEach(([key, value]) => { - console.log(` ${key}: ${value} (${typeof value})`) - }) - emit('search', searchParams) } diff --git a/src/views/system-resource/device-management/approval/index.vue b/src/views/system-resource/device-management/approval/index.vue index 858d248..c665c07 100644 --- a/src/views/system-resource/device-management/approval/index.vue +++ b/src/views/system-resource/device-management/approval/index.vue @@ -458,10 +458,10 @@ const loadData = async (searchParams?: EquipmentApprovalListReq) => { loading.value = true try { + // 构建完整的请求参数 - 参考设备采购功能的实现 const params: EquipmentApprovalListReq = { - pageSize: pagination.pageSize || 10, - page: pagination.current || 1, - pageNum: pagination.current || 1, // 添加 pageNum 参数,以防后端期望这个名称 + pageSize: pagination.pageSize, + page: pagination.current, ...(searchParams || {}), } diff --git a/src/views/system-resource/device-management/procurement/components/ProcurementApplicationModal.vue b/src/views/system-resource/device-management/procurement/components/ProcurementApplicationModal.vue new file mode 100644 index 0000000..bad19be --- /dev/null +++ b/src/views/system-resource/device-management/procurement/components/ProcurementApplicationModal.vue @@ -0,0 +1,340 @@ + + + + + diff --git a/src/views/system-resource/device-management/procurement/index.vue b/src/views/system-resource/device-management/procurement/index.vue index d07edab..6dc9934 100644 --- a/src/views/system-resource/device-management/procurement/index.vue +++ b/src/views/system-resource/device-management/procurement/index.vue @@ -175,6 +175,19 @@ 编辑 + + + 申请采购 + + + + {{ getApprovalStatusText(record.approvalStatus) }} + + + + @@ -213,7 +233,9 @@ import { import message from '@arco-design/web-vue/es/message' import ProcurementModal from './components/ProcurementModal.vue' import ProcurementSearch from './components/ProcurementSearch.vue' +import ProcurementApplicationModal from './components/ProcurementApplicationModal.vue' import { equipmentProcurementApi } from '@/apis/equipment/procurement' +import { equipmentApprovalApi } from '@/apis/equipment/approval' import type { EquipmentListReq, EquipmentResp } from '@/apis/equipment/type' defineOptions({ name: 'EquipmentProcurement' }) @@ -243,6 +265,10 @@ const modalVisible = ref(false) const currentProcurement = ref(null) const modalMode = ref<'add' | 'edit' | 'view'>('add') +// 采购申请弹窗控制 +const applicationModalVisible = ref(false) +const currentApplicationData = ref(null) + // 表格选择 const selectedRowKeys = ref([]) const rowSelection = reactive({ @@ -611,6 +637,12 @@ const handleEdit = (record: EquipmentResp) => { modalVisible.value = true } +// 申请采购 +const handleApplyProcurement = (record: EquipmentResp) => { + currentApplicationData.value = { ...record } + applicationModalVisible.value = true +} + // 删除 const handleDelete = async (record: EquipmentResp) => { try { @@ -629,6 +661,12 @@ const handleModalSuccess = () => { loadData(currentSearchParams.value) } +// 采购申请成功回调 +const handleApplicationSuccess = () => { + applicationModalVisible.value = false + loadData(currentSearchParams.value) +} + // 刷新数据 const refreshData = () => { loadData(currentSearchParams.value) @@ -674,6 +712,36 @@ const getTotalAmount = () => { return formatPrice(total) } +// 检查是否可以申请采购 +const canApplyProcurement = (record: EquipmentResp) => { + // 检查是否有审批状态,如果没有或者状态为待申请,则可以申请 + return !record.approvalStatus || record.approvalStatus === 'PENDING_APPLICATION' +} + +// 获取审批状态颜色 +const getApprovalStatusColor = (status: string) => { + const colorMap: Record = { + 'PENDING_APPLICATION': 'blue', + 'PENDING': 'orange', + 'APPROVED': 'green', + 'REJECTED': 'red', + 'WITHDRAWN': 'gray' + } + return colorMap[status] || 'blue' +} + +// 获取审批状态文本 +const getApprovalStatusText = (status: string) => { + const textMap: Record = { + 'PENDING_APPLICATION': '待申请', + 'PENDING': '待审批', + 'APPROVED': '已通过', + 'REJECTED': '已拒绝', + 'WITHDRAWN': '已撤回' + } + return textMap[status] || '未知' +} + onMounted(() => { loadData() }) From f870f50be03e4a48d1d16652c13ada6abb31e2bd Mon Sep 17 00:00:00 2001 From: Maple <869445424@qq.com> Date: Fri, 8 Aug 2025 15:51:17 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=E6=94=B6=E5=85=A5=E5=90=88=E5=90=8C?= =?UTF-8?q?=E7=9A=84=E7=BC=96=E8=BE=91=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/http.ts | 4 - .../revenue-contract/ContractEdit.vue | 122 +++++++++++++ .../contract/revenue-contract/index.vue | 172 +++++++++++++++--- 3 files changed, 265 insertions(+), 33 deletions(-) create mode 100644 src/views/project-management/contract/revenue-contract/ContractEdit.vue diff --git a/src/utils/http.ts b/src/utils/http.ts index 5894b18..70adfa3 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -225,7 +225,3 @@ export default { requestRaw, download, } - -export const updateContract = (contractId, contractData) => { - return http.put(`/contract/${contractId}`, contractData) -} diff --git a/src/views/project-management/contract/revenue-contract/ContractEdit.vue b/src/views/project-management/contract/revenue-contract/ContractEdit.vue new file mode 100644 index 0000000..4ced636 --- /dev/null +++ b/src/views/project-management/contract/revenue-contract/ContractEdit.vue @@ -0,0 +1,122 @@ + + + diff --git a/src/views/project-management/contract/revenue-contract/index.vue b/src/views/project-management/contract/revenue-contract/index.vue index 0e79d54..28d7b37 100644 --- a/src/views/project-management/contract/revenue-contract/index.vue +++ b/src/views/project-management/contract/revenue-contract/index.vue @@ -1,25 +1,25 @@ - + + + + +