|
|
|
|
@ -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"
|
|
|
|
|
/>
|
|
|
|
|
</el-card>
|
|
|
|
|
@ -397,7 +397,7 @@
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
<ApprovalRecord ref="approvalRecordRef" />
|
|
|
|
|
<SubmitVerify ref="submitVerifyRef" @submit-callback="submitCallback" />
|
|
|
|
|
<SubmitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
|
|
|
|
<!-- 附件上传对话框 -->
|
|
|
|
|
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
|
|
|
|
|
<el-form label-width="80px">
|
|
|
|
|
@ -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<Record<string, any>>({});
|
|
|
|
|
|
|
|
|
|
// 查看/审批模式:根据路由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<Record<string, any>>({});
|
|
|
|
|
|
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
|
const quoteFormRef = ref<ElFormInstance>();
|
|
|
|
|
@ -496,27 +502,6 @@ const getUnitInfoListSelect = async () => {
|
|
|
|
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
|
|
|
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
|
|
|
|
|
|
|
|
|
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<ElFormInstance>();
|
|
|
|
|
@ -542,6 +527,8 @@ const initMaterialFormData: CrmQuoteMaterialForm & { materialFlag?: string } = {
|
|
|
|
|
activeFlag: '1'
|
|
|
|
|
};
|
|
|
|
|
const materialForm = ref<CrmQuoteMaterialForm & { materialFlag?: string }>({ ...initMaterialFormData });
|
|
|
|
|
// 当前编辑的物料行索引:null 表示新增
|
|
|
|
|
const currentMaterialIndex = ref<number | null>(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 || [];
|
|
|
|
|
|