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