From 38c215671ae1be06f2de17f02fce134c2c92eb85 Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Fri, 12 Dec 2025 08:41:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor(crmQuoteInfo):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=92=8C=E4=BC=98=E5=8C=96=E6=8A=A5=E4=BB=B7=E5=8D=95=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=8F=8A=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 统一路由参数管理,改用 routeParams 代替 route.query,增强一致性 - 将审批状态和页面类型获取逻辑调整为从路由参数和表单中读取 - submitVerify 组件新增 taskVariables 绑定,用于传递流程变量 - 删除不再使用的状态规范化方法及相关计算属性,精简代码 - 新增当前编辑物料行索引 currentMaterialIndex,优化物料编辑逻辑 - 物料编辑表单提交和删除逻辑针对索引进行操作,提升稳定性 - 暂存和提交审批流程中新增流程变量赋值及统一成功后行为 - 审批回调和弹窗打开逻辑调用改为统一接口,提升复用性 - 报价单列表操作列宽扩大,调整按钮展示和权限控制逻辑 - 编辑权限限制为仅草稿和退回状态,查看权限限制为非草稿状态 - 删除操作限制为草稿状态,新增模板导出按钮及审批记录组件引用 - 优化审批记录查看方式,统一通过新引入的 ApprovalRecord 组件展示 - 删除废弃的查看详情权限判断方法及相关注释,代码更简洁明了 --- src/views/oa/crm/crmQuoteInfo/edit.vue | 77 +++++++++++++------------ src/views/oa/crm/crmQuoteInfo/index.vue | 39 ++++++++----- 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/views/oa/crm/crmQuoteInfo/edit.vue b/src/views/oa/crm/crmQuoteInfo/edit.vue index 91c1eb7..ffa4c48 100644 --- a/src/views/oa/crm/crmQuoteInfo/edit.vue +++ b/src/views/oa/crm/crmQuoteInfo/edit.vue @@ -7,8 +7,8 @@ @handleApprovalRecord="handleApprovalRecord" :buttonLoading="buttonLoading" :id="form.quoteId as any" - :status="approvalStatus" - :pageType="pageTypeForButton" + :status="form.flowStatus as any" + :pageType="routeParams.type" :mode="false" /> @@ -397,7 +397,7 @@ - + @@ -440,8 +440,14 @@ const { business_direction, currency_type, quote_category, contract_type, materi const router = useRouter(); const route = useRoute(); +// 统一路由参数管理(与 projectInfo/projectPurchase 保持一致) +const routeParams = ref>({}); + // 查看/审批模式:根据路由type控制禁用 -const isView = computed(() => route.query.type === 'view' || route.query.type === 'approval'); +const isView = computed(() => routeParams.value.type === 'view' || routeParams.value.type === 'approval'); + +// 流程变量(传递给 submitVerify 组件) +const taskVariables = ref>({}); const buttonLoading = ref(false); const quoteFormRef = ref(); @@ -496,27 +502,6 @@ const getUnitInfoListSelect = async () => { const approvalRecordRef = ref>(); const submitVerifyRef = ref>(); -const normalizeFlowStatus = (status?: string) => { - if (!status) return 'draft'; - const dictList = wf_business_status.value || []; - const match = dictList.find((item: any) => item?.value === status || item?.label === status); - return match?.value || status; -}; - -const approvalStatus = computed(() => normalizeFlowStatus((form as any).flowStatus as any)); - -const pageTypeForButton = computed(() => { - const taskId = route.query.taskId as any; - const type = route.query.type as string | undefined; - if (taskId) { - return 'approval'; - } - if (type) { - return type; - } - return (form.quoteId ? 'update' : 'add') as string; -}); - // 物料编辑弹窗与表单 const materialDialog = reactive({ visible: false, title: '' }); const materialFormRef = ref(); @@ -542,6 +527,8 @@ const initMaterialFormData: CrmQuoteMaterialForm & { materialFlag?: string } = { activeFlag: '1' }; const materialForm = ref({ ...initMaterialFormData }); +// 当前编辑的物料行索引:null 表示新增 +const currentMaterialIndex = ref(null); const materialRules = { productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }], amount: [{ required: true, message: '数量不能为空', trigger: 'blur' }], @@ -567,6 +554,7 @@ const saleMaterialSelectCallBack = (data: any) => { const resetMaterialForm = () => { materialForm.value = { ...initMaterialFormData }; materialFormRef.value?.resetFields(); + currentMaterialIndex.value = null; }; const cancelMaterial = () => { resetMaterialForm(); @@ -593,6 +581,7 @@ const calculateSubtotal = () => { const handleAddMaterial = () => { resetMaterialForm(); materialForm.value.quoteId = form.quoteId as any; + currentMaterialIndex.value = null; materialDialog.visible = true; materialDialog.title = '新增报价物料'; }; @@ -600,28 +589,27 @@ const handleEditMaterial = (row: CrmQuoteMaterialForm & { materialFlag?: string resetMaterialForm(); // 优先使用已有 materialFlag,没有则根据是否选择物料ID推导标准/非标 const flag = (row as any).materialFlag ?? ((row as any).materialId ? '1' : '2'); + const idx = materialRows.value.indexOf(row as any); + currentMaterialIndex.value = idx !== -1 ? idx : null; materialForm.value = { ...(row as any), materialFlag: flag }; materialDialog.visible = true; materialDialog.title = '编辑报价物料'; }; const handleDeleteMaterial = async (row: CrmQuoteMaterialForm) => { await proxy?.$modal.confirm('是否确认删除该报价物料?'); - const idx = materialRows.value.findIndex((x: any) => x.quoteMaterialId === (row as any).quoteMaterialId); - if (idx !== -1) materialRows.value.splice(idx, 1); - else { - const i2 = materialRows.value.indexOf(row); - if (i2 !== -1) materialRows.value.splice(i2, 1); + const idx = materialRows.value.indexOf(row as any); + if (idx !== -1) { + materialRows.value.splice(idx, 1); } proxy?.$modal.msgSuccess('删除成功'); }; const submitMaterialForm = () => { materialFormRef.value?.validate((valid: boolean) => { if (!valid) return; - if ((materialForm.value as any).quoteMaterialId) { - const idx = materialRows.value.findIndex((x: any) => x.quoteMaterialId === (materialForm.value as any).quoteMaterialId); - if (idx !== -1) materialRows.value[idx] = { ...materialForm.value } as any; + if (currentMaterialIndex.value !== null && currentMaterialIndex.value >= 0) { + materialRows.value[currentMaterialIndex.value] = { ...materialForm.value } as any; } else { - const newItem = { ...materialForm.value, quoteMaterialId: Date.now() } as any; + const newItem = { ...materialForm.value } as any; materialRows.value.push(newItem); } proxy?.$modal.msgSuccess('操作成功'); @@ -801,6 +789,7 @@ const submitForm = (status: string, mode: boolean) => { })) }; if (status === 'draft') { + // === 暂存 === payload.quoteStatus = '1'; payload.flowStatus = 'draft'; if (!form.quoteId) { @@ -810,6 +799,7 @@ const submitForm = (status: string, mode: boolean) => { } proxy?.$modal.msgSuccess('暂存成功'); } else { + // === 提交审批 === payload.flowCode = FlowCodeEnum.QUOTE_CODE; //OACQ payload.variables = { quoteId: form.quoteId, @@ -827,8 +817,9 @@ const submitForm = (status: string, mode: boolean) => { if (res?.data) { Object.assign(form, res.data as any); } - proxy?.$modal.msgSuccess('已提交并发起流程'); + proxy?.$modal.msgSuccess('提交成功'); } + // 统一的成功后行为(与 projectInfo 保持一致) proxy?.$tab.closePage(route as any); router.go(-1); } finally { @@ -837,7 +828,17 @@ const submitForm = (status: string, mode: boolean) => { }); }; const approvalVerifyOpen = async () => { - await submitVerifyRef.value?.openDialog(route.query.taskId as any); + // 设置流程变量 + taskVariables.value = { + quoteId: form.quoteId, + quoteName: form.quoteName, + quoteCode: form.quoteCode, + totalPrice: totalIncludingTax.value + }; + const taskId = routeParams.value.taskId; + if (taskId) { + await submitVerifyRef.value?.openDialog(taskId); + } }; const handleApprovalRecord = () => { @@ -846,12 +847,16 @@ const handleApprovalRecord = () => { } }; +/** 提交审批回调(与 projectInfo 保持一致) */ const submitCallback = async () => { await proxy?.$tab.closePage(route as any); router.go(-1); }; onMounted(async () => { + // 初始化路由参数(与 projectInfo/projectPurchase 保持一致) + routeParams.value = { ...route.query }; + // 下拉数据初始化 const contactRes = await getCrmCustomerContactList({}); customerContactList.value = contactRes.data || []; diff --git a/src/views/oa/crm/crmQuoteInfo/index.vue b/src/views/oa/crm/crmQuoteInfo/index.vue index 092fa2a..b1d5da6 100644 --- a/src/views/oa/crm/crmQuoteInfo/index.vue +++ b/src/views/oa/crm/crmQuoteInfo/index.vue @@ -262,22 +262,29 @@ {{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }} - + --> + + @@ -478,6 +487,7 @@ import { CrmQuoteInfoForm, CrmQuoteInfoQuery, CrmQuoteInfoVO } from '@/api/oa/cr import { getCrmCustomerContactList } from '@/api/oa/crm/customerContact'; import FileSaver from 'file-saver'; import { blobValidate } from '@/utils/ruoyi'; +import ApprovalRecord from '@/components/Process/approvalRecord.vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const router = useRouter(); @@ -497,6 +507,7 @@ const total = ref(0); const queryFormRef = ref(); const crmQuoteInfoFormRef = ref(); +const approvalRecordRef = ref>(); const dialog = reactive({ visible: false, @@ -703,11 +714,6 @@ const handleView = (row?: CrmQuoteInfoVO) => { }); }; -/** 判断是否可以查看详情:仅非草稿状态可进入查看页 */ -const canViewDetail = (row: CrmQuoteInfoVO) => { - return row.quoteStatus !== '1'; -}; - /** 提交按钮 */ const submitForm = () => { crmQuoteInfoFormRef.value?.validate(async (valid: boolean) => { @@ -745,6 +751,11 @@ const handleExport = () => { ); }; +/** 审批记录按钮操作 */ +const handleApprovalRecord = (row: CrmQuoteInfoVO) => { + approvalRecordRef.value?.init(row.quoteId as any); +}; + /** 模板导出(支持选中或行内按钮,GET Blob 下载) */ const handleExportTemplate = async (row?: CrmQuoteInfoVO) => { const _quoteId = row?.quoteId || ids.value[0];