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];