From f7624a8fdeaac946f092c1776ed68f0624b9520c Mon Sep 17 00:00:00 2001 From: Yangk Date: Thu, 8 Jan 2026 16:09:25 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat(oa/crm):=20=E6=B7=BB=E5=8A=A0=E5=87=BA?= =?UTF-8?q?=E5=B7=AE=E5=8F=8D=E9=A6=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除编辑页面中的交流过程简述和结果反馈表单项 - 在列表页面操作列添加填写反馈按钮 - 添加出差反馈对话框组件,包含交流过程简述和结果反馈输入 - 实现出差反馈提交功能,更新出差申请信息 --- src/views/oa/crm/businessTripApply/edit.vue | 33 ------ src/views/oa/crm/businessTripApply/index.vue | 102 ++++++++++++++++++- 2 files changed, 100 insertions(+), 35 deletions(-) diff --git a/src/views/oa/crm/businessTripApply/edit.vue b/src/views/oa/crm/businessTripApply/edit.vue index f3bce39..9cce556 100644 --- a/src/views/oa/crm/businessTripApply/edit.vue +++ b/src/views/oa/crm/businessTripApply/edit.vue @@ -96,28 +96,6 @@ - - - - - - - - - - @@ -132,17 +110,6 @@ - - - - - diff --git a/src/views/oa/crm/businessTripApply/index.vue b/src/views/oa/crm/businessTripApply/index.vue index a5c9dd9..844eba9 100644 --- a/src/views/oa/crm/businessTripApply/index.vue +++ b/src/views/oa/crm/businessTripApply/index.vue @@ -120,7 +120,7 @@ - + From 4a6fe1b747cb24b1c2330694714d77c3b9cabe65 Mon Sep 17 00:00:00 2001 From: Yangk Date: Thu, 8 Jan 2026 16:18:02 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat(crm/businessTripApply):=20=E5=9C=A8?= =?UTF-8?q?=E5=87=BA=E5=B7=AE=E7=94=B3=E8=AF=B7=E9=A1=B5=E9=9D=A2=E4=B8=AD?= =?UTF-8?q?=E4=B8=BA=E4=B8=9A=E5=8A=A1=E6=96=B9=E5=90=91=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=97=E5=85=B8=E6=A0=87=E7=AD=BE=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/oa/crm/businessTripApply/index.vue | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/views/oa/crm/businessTripApply/index.vue b/src/views/oa/crm/businessTripApply/index.vue index 844eba9..36ff4b4 100644 --- a/src/views/oa/crm/businessTripApply/index.vue +++ b/src/views/oa/crm/businessTripApply/index.vue @@ -107,7 +107,11 @@ - + + + @@ -190,7 +194,7 @@ import { listBusinessTripApply, delBusinessTripApply, updateBusinessTripApply } import { BusinessTripApplyVO, BusinessTripApplyQuery } from '@/api/oa/crm/businessTripApply/types'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const { trip_status, trip_type } = toRefs(proxy?.useDict('trip_status', 'trip_type')); +const { trip_status, trip_type, business_direction } = toRefs(proxy?.useDict('trip_status', 'trip_type', 'business_direction')); const businessTripApplyList = ref([]); const loading = ref(true); From 3338d4fd90f07eb9763f6306888b521aea5e2428 Mon Sep 17 00:00:00 2001 From: Yangk Date: Fri, 9 Jan 2026 15:20:10 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat(oa):=20=E6=B7=BB=E5=8A=A0=E5=87=BA?= =?UTF-8?q?=E5=B7=AE=E7=94=B3=E8=AF=B7=E5=92=8C=E5=94=AE=E5=90=8E=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E7=9A=84=E6=8A=84=E9=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在出差申请编辑页面添加抄送人员选择下拉框 - 实现抄送人员的自动填充逻辑,包括默认人员和部门负责人 - 在售后申请中添加项目管理角色用户作为抄送对象 --- src/api/oa/crm/businessTripApply/types.ts | 5 ++ src/views/oa/crm/businessTripApply/edit.vue | 69 ++++++++++++++++----- src/views/oa/erp/afterSales/edit.vue | 8 ++- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/api/oa/crm/businessTripApply/types.ts b/src/api/oa/crm/businessTripApply/types.ts index 04e382f..cb5a53a 100644 --- a/src/api/oa/crm/businessTripApply/types.ts +++ b/src/api/oa/crm/businessTripApply/types.ts @@ -263,6 +263,11 @@ export interface BusinessTripApplyForm extends BaseEntity { * 流程编码 */ flowCode?: string; + + /** + * 抄送人员ID列表 + */ + copyUserIds?: string | string[]; } export interface BusinessTripApplyQuery extends PageQuery { diff --git a/src/views/oa/crm/businessTripApply/edit.vue b/src/views/oa/crm/businessTripApply/edit.vue index 9cce556..a48a465 100644 --- a/src/views/oa/crm/businessTripApply/edit.vue +++ b/src/views/oa/crm/businessTripApply/edit.vue @@ -181,7 +181,7 @@ - + + + + + + + + @@ -227,6 +233,7 @@ import ProjectSelect from '@/components/ProjectSelect/index.vue'; import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum'; import { getInfo } from '@/api/login'; import { listUser } from '@/api/system/user'; // 导入用户列表API +import { allListDept } from '@/api/system/dept'; // 导入部门列表API import { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types'; import dayjs from 'dayjs'; @@ -248,6 +255,10 @@ const projectSelectRef = ref>(); // const userSelectRef = ref>(); // 审批人选择 ref const userList = ref([]); // 用户列表 +const deptInfoList = ref([]); // 部门列表 + +// 默认抄送人员的昵称列表 +const defaultCopyUserNames = ['米兰', '于洋', '张兰艳', '张东辉', '冯俊杰']; // 流程相关数据 const submitFormData = ref({ @@ -283,7 +294,8 @@ const initFormData: BusinessTripApplyForm = { flowStatus: 'draft', remark: undefined, ossId: undefined, - variables: {} // 初始化 variables + variables: {}, // 初始化 variables + copyUserIds: [] as string[] // 抄送人员ID列表 }; const data = reactive({ @@ -327,15 +339,40 @@ onMounted(async () => { routeParams.value = route.query; const id = routeParams.value.id; + // 加载用户列表 (用于审批人选择和抄送人员选择) + const userRes = await listUser({ pageNum: 1, pageSize: 1000 }); + userList.value = userRes.rows; + + // 加载部门列表 (用于获取部门负责人和分管副总) + const deptRes = await allListDept({ deptCategory: '03' } as any); + deptInfoList.value = deptRes.data || []; + // 自动填充申请人信息 if (!id) { try { - const userRes = await getInfo(); - if (userRes.data?.user) { - form.value.applicantId = userRes.data.user.userId; - form.value.applicantName = userRes.data.user.nickName; - form.value.deptId = userRes.data.user.deptId; - form.value.deptName = userRes.data.user.deptName; + const infoRes = await getInfo(); + if (infoRes.data?.user) { + form.value.applicantId = infoRes.data.user.userId; + form.value.applicantName = infoRes.data.user.nickName; + form.value.deptId = infoRes.data.user.deptId; + form.value.deptName = infoRes.data.user.deptName; + + // 根据部门ID获取部门负责人和分管副总 + const deptInfo = deptInfoList.value.find((d: any) => d.deptId === infoRes.data.user.deptId); + if (deptInfo) { + const deptLeaderId = deptInfo.leader; + const vicePresidentId = deptInfo.vicePresident; + // 将部门负责人和分管副总加入默认抄送人员 + const deptCopyIds: string[] = []; + if (deptLeaderId) deptCopyIds.push(String(deptLeaderId)); + if (vicePresidentId) deptCopyIds.push(String(vicePresidentId)); + + // 根据昵称匹配默认抄送人员 + const defaultCopyIds = userList.value.filter((u: any) => defaultCopyUserNames.includes(u.nickName)).map((u: any) => String(u.userId)); + + // 合并默认抄送人员和部门负责人/分管副总(去重) + form.value.copyUserIds = [...new Set([...defaultCopyIds, ...deptCopyIds])]; + } } } catch (e) { console.error('获取用户信息失败', e); @@ -346,14 +383,13 @@ onMounted(async () => { } } - // 加载用户列表 (用于审批人选择) - listUser({ pageNum: 1, pageSize: 1000 }).then((res: any) => { - userList.value = res.rows; - }); - if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) { const res = await getBusinessTripApply(id); Object.assign(form.value, res.data); + // 将抄送人员字符串转换为数组 + if (form.value.copyUserIds && typeof form.value.copyUserIds === 'string') { + form.value.copyUserIds = (form.value.copyUserIds as string).split(',').filter((id) => id); + } } }); }); @@ -426,9 +462,12 @@ const executeSubmit = async (status: string, mode: boolean) => { // 提交审批 form.value.tripStatus = '2'; // 审批中 form.value.flowStatus = 'waiting'; + // 将抄送人员ID数组转换为逗号分隔字符串 + const copyUserIdsStr = Array.isArray(form.value.copyUserIds) ? form.value.copyUserIds.join(',') : form.value.copyUserIds || ''; form.value.variables = { ...form.value.variables, - tripType: form.value.tripType + tripType: form.value.tripType, + businessTripCopyUsers: copyUserIdsStr }; form.value.bizExt = { businessTitle: '出差申请', diff --git a/src/views/oa/erp/afterSales/edit.vue b/src/views/oa/erp/afterSales/edit.vue index 9505de4..0a9a5d1 100644 --- a/src/views/oa/erp/afterSales/edit.vue +++ b/src/views/oa/erp/afterSales/edit.vue @@ -461,6 +461,9 @@ const editingIndex = ref(-1); // 材料表编辑索引 (-1 为新增) const checkedLabor = ref([]); // 人员表选中项 const checkedMaterial = ref([]); // 材料表选中项 +// 项目管理角色用户昵称列表(抄送对象) +const projectMgrUserNames = ['于洋']; + // 流程相关变量 const submitFormData = ref({ businessId: '', flowCode: '', variables: {}, bizExt: {} }); const taskVariables = ref>({}); @@ -929,10 +932,13 @@ const executeSubmit = async (status: string, mode: boolean) => { if (status !== 'draft') { // --- 提交审批 --- submitData.flowCode = FlowCodeEnum.AFTER_SALES_KEY; + // 根据昵称匹配项目管理角色用户作为抄送对象 + const copyUserIds = userList.value.filter((u: any) => projectMgrUserNames.includes(u.nickName)).map((u: any) => String(u.userId)); submitData.variables = { afterSalesId: submitData.afterSalesId, totalCost: submitData.totalCost || 0, - startUserId: useUserStore().userId + startUserId: useUserStore().userId, + afterSalesCopyUsers: copyUserIds.join(',') }; submitData.bizExt = { businessTitle: `售后申请:${submitData.afterSalesSubject}`, From 4fcbf12442a5195512ddc64bf2877246079269d4 Mon Sep 17 00:00:00 2001 From: Yangk Date: Fri, 9 Jan 2026 16:23:47 +0800 Subject: [PATCH 4/8] =?UTF-8?q?refactor(crm/businessTripApply):=20?= =?UTF-8?q?=E5=87=BA=E5=B7=AE=E7=94=B3=E8=AF=B7=E8=B7=AF=E7=94=B1=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E4=BB=8E=E9=9D=99=E6=80=81=E8=B7=AF=E7=94=B1=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E8=8F=9C=E5=8D=95=E5=8A=A8=E6=80=81=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/oa/crm/businessTripApply/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/oa/crm/businessTripApply/index.vue b/src/views/oa/crm/businessTripApply/index.vue index 36ff4b4..6162c2e 100644 --- a/src/views/oa/crm/businessTripApply/index.vue +++ b/src/views/oa/crm/businessTripApply/index.vue @@ -294,7 +294,7 @@ const handleSelectionChange = (selection: BusinessTripApplyVO[]) => { /** 新增按钮操作 */ const handleAdd = (command: string) => { router.push({ - path: '/oa/crm/businessTripApply/edit', + path: '/tripapply/businessTripApply/edit', query: { type: 'add', tripType: command } }); }; @@ -303,7 +303,7 @@ const handleAdd = (command: string) => { const handleUpdate = (row?: BusinessTripApplyVO) => { const _tripId = row?.tripId || ids.value[0]; router.push({ - path: '/oa/crm/businessTripApply/edit', + path: '/tripapply/businessTripApply/edit', query: { id: _tripId, type: 'update' } }); }; @@ -312,7 +312,7 @@ const handleUpdate = (row?: BusinessTripApplyVO) => { const handleView = (row: BusinessTripApplyVO) => { const _tripId = row?.tripId; router.push({ - path: '/oa/crm/businessTripApply/edit', + path: '/tripapply/businessTripApply/edit', query: { id: _tripId, type: 'view' } }); }; From 9351bd701f252737834acacb5e388d2897a5d8d7 Mon Sep 17 00:00:00 2001 From: Yangk Date: Mon, 12 Jan 2026 15:52:39 +0800 Subject: [PATCH 5/8] =?UTF-8?q?fix(oa/afterSales):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E3=80=81=E6=9F=A5=E7=9C=8B=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=E9=99=84=E4=BB=B6=E6=97=A0=E6=B3=95=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/oa/erp/afterSales/edit.vue | 62 +++++++++++++++++++++++---- src/views/oa/erp/afterSales/index.vue | 2 +- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/views/oa/erp/afterSales/edit.vue b/src/views/oa/erp/afterSales/edit.vue index 0a9a5d1..8a48538 100644 --- a/src/views/oa/erp/afterSales/edit.vue +++ b/src/views/oa/erp/afterSales/edit.vue @@ -15,7 +15,7 @@ - + @@ -119,7 +119,10 @@ - + + +
+
- - - - - - - +
+
+
+ +
+ + + + + +
@@ -1007,4 +1021,34 @@ const submitCallback = async () => { .mt-2 { margin-top: 10px; } + +/* 问题描述和附件区域容器 - 使用 flexbox */ +.problem-attachment-row { + display: flex; + margin: 0; +} + +.problem-col { + flex: 0 0 50%; + max-width: 50%; + padding-right: 10px; +} + +.attachment-col { + flex: 0 0 50%; + max-width: 50%; + padding-left: 10px; +} + +/* 附件区域使用负 margin 拉到问题描述同行 */ +.file-upload-row { + margin-top: -95px; /* 向上拉到与问题描述同行 */ + margin-left: 50%; /* 偏移到右侧,与上方表单字段对齐 */ + padding-left: 10px; + padding-right: 10px; +} + +.file-upload-content { + /* 无需额外样式 */ +} diff --git a/src/views/oa/erp/afterSales/index.vue b/src/views/oa/erp/afterSales/index.vue index 4d6ef0a..48dd193 100644 --- a/src/views/oa/erp/afterSales/index.vue +++ b/src/views/oa/erp/afterSales/index.vue @@ -131,7 +131,7 @@ - + From 6592131311e343c7c093833aea41fcd248beb55c Mon Sep 17 00:00:00 2001 From: Yangk Date: Mon, 12 Jan 2026 17:34:44 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat(timesheetInfo):=20=E5=B7=A5=E6=97=B6?= =?UTF-8?q?=E5=A1=AB=E6=8A=A5=E9=A1=B5=E9=9D=A2=E6=96=B0=E5=A2=9E=E4=BA=BA?= =?UTF-8?q?=E5=91=98=E5=92=8C=E9=83=A8=E9=97=A8=E7=AD=9B=E9=80=89=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/oa/erp/timesheetInfo/index.vue | 30 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/views/oa/erp/timesheetInfo/index.vue b/src/views/oa/erp/timesheetInfo/index.vue index 9c389ed..42d9f87 100644 --- a/src/views/oa/erp/timesheetInfo/index.vue +++ b/src/views/oa/erp/timesheetInfo/index.vue @@ -4,8 +4,15 @@
- - + + + + + + + + + @@ -102,6 +109,10 @@ From dfc776a3c3a6af24e9ba2a4b6e530f44b83c7591 Mon Sep 17 00:00:00 2001 From: Yangk Date: Mon, 12 Jan 2026 17:56:26 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat(AfterSales,=20TimesheetInfo,=20Busines?= =?UTF-8?q?sTrip):=20=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=87=BA=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=94=AF=E6=8C=81=E6=8C=89ID=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/oa/crm/businessTripApply/index.vue | 4 +++- src/views/oa/erp/afterSales/index.vue | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/views/oa/crm/businessTripApply/index.vue b/src/views/oa/crm/businessTripApply/index.vue index 6162c2e..04931cb 100644 --- a/src/views/oa/crm/businessTripApply/index.vue +++ b/src/views/oa/crm/businessTripApply/index.vue @@ -331,7 +331,9 @@ const handleExport = () => { proxy?.download( 'oa/crm/businessTripApply/export', { - ...queryParams.value + ...queryParams.value, + // 如果选中了数据,则只导出选中的数据 + tripIds: ids.value.length > 0 ? ids.value.join(',') : undefined }, `businessTripApply_${new Date().getTime()}.xlsx` ); diff --git a/src/views/oa/erp/afterSales/index.vue b/src/views/oa/erp/afterSales/index.vue index 48dd193..ee8e67a 100644 --- a/src/views/oa/erp/afterSales/index.vue +++ b/src/views/oa/erp/afterSales/index.vue @@ -382,7 +382,9 @@ const handleExport = () => { proxy?.download( 'oa/erp/afterSales/export', { - ...queryParams.value + ...queryParams.value, + // 如果选中了数据,则只导出选中的数据 + afterSalesIds: ids.value.length > 0 ? ids.value.join(',') : undefined }, `afterSales_${new Date().getTime()}.xlsx` ); From 01914add571007a725e5c1c5a732b8eeecc4efee Mon Sep 17 00:00:00 2001 From: Yangk Date: Tue, 13 Jan 2026 17:45:54 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feat(oa):=20=E4=BC=98=E5=8C=96=E5=87=BA?= =?UTF-8?q?=E5=B7=AE=E7=94=B3=E8=AF=B7=E8=A1=A8=E5=8D=95=E5=92=8C=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在编辑模式下实现抄送人员的自动设置功能,默认添加部门负责人和分管副总 - 将申请人姓名和部门查询字段改为选择器组件,支持下拉选择 - 添加业务方向的选择器组件替换输入框 - 集成用户和部门列表数据用于查询条件筛选 - 实现页面初始化时异步加载用户和部门数据 --- src/views/oa/crm/businessTripApply/edit.vue | 27 ++++++++++++++++- src/views/oa/crm/businessTripApply/index.vue | 31 ++++++++++++++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/views/oa/crm/businessTripApply/edit.vue b/src/views/oa/crm/businessTripApply/edit.vue index a48a465..b116506 100644 --- a/src/views/oa/crm/businessTripApply/edit.vue +++ b/src/views/oa/crm/businessTripApply/edit.vue @@ -91,7 +91,7 @@ - + @@ -390,6 +390,31 @@ onMounted(async () => { if (form.value.copyUserIds && typeof form.value.copyUserIds === 'string') { form.value.copyUserIds = (form.value.copyUserIds as string).split(',').filter((id) => id); } + + // 编辑模式下,如果抄送人员为空,重新设置默认抄送人员 + if (routeParams.value.type === 'update' && (!form.value.copyUserIds || form.value.copyUserIds.length === 0)) { + // 根据部门ID获取部门负责人和分管副总 + const deptInfo = deptInfoList.value.find((d: any) => d.deptId === form.value.deptId); + if (deptInfo) { + const deptLeaderId = deptInfo.leader; + const vicePresidentId = deptInfo.vicePresident; + // 将部门负责人和分管副总加入默认抄送人员 + const deptCopyIds: string[] = []; + if (deptLeaderId) deptCopyIds.push(String(deptLeaderId)); + if (vicePresidentId) deptCopyIds.push(String(vicePresidentId)); + + // 根据昵称匹配默认抄送人员 + const defaultCopyIds = userList.value.filter((u: any) => defaultCopyUserNames.includes(u.nickName)).map((u: any) => String(u.userId)); + + // 合并默认抄送人员和部门负责人/分管副总(去重) + form.value.copyUserIds = [...new Set([...defaultCopyIds, ...deptCopyIds])]; + } + } + + // 确保 variables 对象存在 + if (!form.value.variables) { + form.value.variables = {}; + } } }); }); diff --git a/src/views/oa/crm/businessTripApply/index.vue b/src/views/oa/crm/businessTripApply/index.vue index 04931cb..414ddc7 100644 --- a/src/views/oa/crm/businessTripApply/index.vue +++ b/src/views/oa/crm/businessTripApply/index.vue @@ -12,11 +12,15 @@ - - + + + + - - + + + + @@ -28,7 +32,9 @@ - + + + @@ -192,6 +198,10 @@