+
实施采购信息
@@ -591,10 +924,21 @@
-
-
@@ -609,61 +953,92 @@ import { addObj, tempStore, getObj, editObj, getApplyFiles } from '/@/api/purcha
import { getTree } from '/@/api/purchase/purchasingcategory';
import { getDicts } from '/@/api/admin/dict';
import { useMessage } from '/@/hooks/message';
-
+import { useUserInfo } from '/@/stores/userInfo';
import { usePurchaseRulesSingleton } from '/@/hooks/usePurchaseRules';
import UploadFile from '/@/components/Upload/index.vue';
import other from '/@/utils/other';
-import { Session } from '/@/utils/storage';
-import { Document } from '@element-plus/icons-vue';
+import { Document, Download, QuestionFilled } from '@element-plus/icons-vue';
import { fetchList as getBusinessDeptList } from '/@/api/purchase/purchasingBusinessDept';
import { getPage as getSchoolLeaderPage } from '/@/api/purchase/purchasingschoolleader';
import { fetchList as getPurchasingManagerList } from '/@/api/purchase/purchasingPurchaseManager';
import { fetchList as getBusinessLeaderList } from '/@/api/purchase/purchasingBusinessLeader';
+import { Session } from '/@/utils/storage';
import * as orderVue from '/@/api/order/order-key-vue';
-import { handleCustomFormPerm } from '/@/flow/utils/form-perm';
-// 流程嵌入时触发保存事件
-const emits = defineEmits(['handleJob']);
+/** 采购中心角色编码:审批时仅该角色可编辑采购方式/采购形式 */
+const PURCHASE_CENTER_ROLE_CODE = 'PURCHASE_CENTER';
+const PURCHASE_DEPT_APPLY_ROLE_CODE = 'ROLE_PURCHASE_DEPT_APPLY';
+// 兼容流程 dynamic-link 引用:接收 currJob / currElTab,并支持 handleJob 事件
+const props = defineProps({
+ currJob: { type: Object, default: null },
+ currElTab: { type: Object, default: null },
+});
+const emit = defineEmits(['handleJob']);
+
+// 路由
const router = useRouter();
const route = useRoute();
-// 流程嵌入时接收 currJob
-const props = defineProps({
- currJob: {
- type: Object,
- default: null,
- },
- currElTab: {
- type: Object,
- default: {},
- },
-});
-
-// 是否为流程嵌入模式
+/** 是否被流程 handle 页通过 dynamic-link 嵌入 */
const isFlowEmbed = computed(() => !!props.currJob);
-// 当前使用的申请单 ID(优先从流程 currJob.orderId 获取,否则从 URL query 获取)
+/** 当前使用的申请单 ID:优先来自流程 currJob.orderId,否则来自 route.query.id */
const effectiveQueryId = computed(() => {
- // 流程嵌入模式:优先使用 currJob.orderId
- if (props.currJob?.orderId) {
+ if (props.currJob?.orderId != null && props.currJob?.orderId !== '') {
return String(props.currJob.orderId);
}
- // URL 模式
const q = route.query.id;
return q ? String(q) : '';
});
-// 模式:add | edit | view
+// 模式:add | edit | view(URL 参数 或 流程嵌入时的 currJob/currElTab)
+const isEditMode = computed(() => {
+ if (isFlowEmbed.value && props.currElTab) {
+ return !!effectiveQueryId.value && props.currElTab.isFormEdit !== '0' && !props.currJob?.hiJob;
+ }
+ return String(route.query.mode) === 'edit';
+});
+const isViewMode = computed(() => {
+ if (isFlowEmbed.value && props.currJob) {
+ if (props.currJob.hiJob) return true;
+ if (props.currElTab?.isFormEdit === '0') return true;
+ return false;
+ }
+ return String(route.query.mode) === 'view';
+});
const pageTitle = computed(() => {
- const mode = String(route.query.mode);
- if (mode === 'view') return '查看采购申请';
- if (mode === 'edit') return '编辑采购申请';
+ if (isViewMode.value) return '查看采购申请';
+ if (isEditMode.value) return '编辑采购申请';
return '新增采购申请';
});
-// 是否为查看模式
-const isViewMode = computed(() => String(route.query.mode) === 'view');
+/** 流程嵌入时,由 currElTabIsView 控制的只读/禁用提交 */
+const flowFormDisabled = ref(false);
+const flowSubmitDisabled = ref(false);
+
+/** 流程嵌入时当前节点是否为采购中心(仅采购中心可编辑采购方式/采购形式) */
+const isPurchaseCenter = ref(false);
+
+/** 流程嵌入时:采购中心审核节点放开所有字段编辑;非采购中心节点只读 */
+function flowFieldDisabled(_key: string) {
+ if (isFlowEmbed.value && isPurchaseCenter.value) return false;
+ if (isFlowEmbed.value && isApplicant.value) return false;
+ return !!isFlowEmbed.value;
+}
+
+/** 当前用户是否为申请人(在流程中可编辑) */
+const isApplicant = computed(() => {
+
+ const stores = useUserInfo();
+ const currentUser = stores.userInfos?.user || {};
+ console.log(currentUser)
+ if (!dataForm.createBy) return false;
+
+ // const stores = useUserInfo();
+ // const currentUser = stores.userInfos?.user || {};
+ return dataForm.createBy === currentUser.username;
+});
// 定义变量内容
const formRef = ref();
@@ -691,17 +1066,31 @@ const dataForm = reactive({
marketPurchaseMinutes: '',
onlineMallMaterials: '',
inquiryTemplate: '', // 询价模板
+ entrustCenterType: '',
hasSupplier: '0',
suppliers: '', // 供应商名称(逗号或分号分隔)
+ serviceDirectSelect: '',
+ servicePublicSelect: '',
purchaseRequirementTemplate: '',
+
+ serviceInviteSelect: '',
+ servicePublicSelectAuto: '',
deptSelfMeetingMinutes: '', // 部门自行采购会议纪要
// 学校统一采购字段
purchaseRequirement: '',
meetingMinutes: '',
feasibilityReport: '',
+ meetingMinutesUrgent: '',
+ meetingMinutesSingle: '',
+ meetingMinutesImport: '',
singleSourceProof: '',
importApplication: '',
governmentPurchaseIntent: '',
+ servicePublicSelectSchool: '',
+ // 学校统一采购特殊规则字段(5万<=金额<40万)
+
+ serviceInviteSelectSchool: '',
+ servicePublicSelectSchoolAuto: '',
// 业务分管处室和分管校领导
deptClassifyUserId: '',
deptClassifyName: '',
@@ -747,22 +1136,32 @@ const loading = ref(false);
const helpDialogVisible = ref(false);
// 文件类型映射(对应数据库 file_type 字段)
-// 附件类型 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品申请及专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140:部门自行采购会议纪要 150:部门询价模
+// 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140: 部门自行采购会议纪要
const FILE_TYPE_MAP: Record
= {
businessNegotiationTable: '10', // 商务洽谈纪要
marketPurchaseMinutes: '20', // 市场采购纪要
+ inquiryTemplate: '20', // 询价模板(归类到市场采购纪要)
onlineMallMaterials: '30', // 网上商城采购相关材料
feasibilityReport: '40', // 可行性论证报告
meetingMinutes: '50', // 会议记录
+ meetingMinutesUrgent: '50', // 会议记录
+ meetingMinutesSingle: '50', // 会议记录
+ meetingMinutesImport: '50', // 会议记录
otherMaterials: '60', // 其他材料
singleSourceProof: '70', // 单一来源专家论证表
importApplication: '90', // 进口产品申请表
governmentPurchaseIntent: '100', // 政府采购意向表
// 需求文件相关 - 所有需求模板都应该是 120(采购需求表)
- // 需求文件(统一)- 采购需求表
+ serviceDirectSelect: '120', // 服务商城项目需求模板(直选)- 采购需求表
+ serviceInviteSelect: '120', // 服务商城项目需求模板(邀请比选)- 采购需求表
+ servicePublicSelect: '120', // 服务商城项目需求模板(公开比选)- 采购需求表
+ servicePublicSelectAuto: '120', // 服务商城项目需求模板(公开比选 - 自动)- 采购需求表
+ purchaseRequirementTemplate: '120', // 需求模板 - 采购需求表
purchaseRequirement: '120', // 需求模板 - 采购需求表
+ serviceInviteSelectSchool: '120', // 服务商城项目需求模板(邀请比选 - 学校)- 采购需求表
+ servicePublicSelectSchoolAuto: '120', // 服务商城项目需求模板(公开比选 - 学校 - 自动)- 采购需求表
+ servicePublicSelectSchool: '120', // 服务商城项目需求模板(公开比选 - 学校)- 采购需求表
deptSelfMeetingMinutes: '140', // 部门自行采购会议纪要
- inquiryTemplate: '150' // 询价模板
};
// fileType -> 表单字段名数组(顺序与回填分配一致,同类型多字段时按此顺序分配)
@@ -825,41 +1224,6 @@ const PURCHASE_CHANNEL = {
ENTRUST_CENTER: '2',
} as const;
-// 角色常量
-const PURCHASE_DEPT_APPLY_ROLE_CODE = 'PURCHASE_DEPT_APPLY';
-
-// 判断当前登录用户是否为部门申请角色
-const roleCode = computed(() => Session.getRoleCode() || '');
-const isDeptApplyRole = computed(() => roleCode.value === PURCHASE_DEPT_APPLY_ROLE_CODE);
-
-// 部门申请角色 + 委托采购中心采购:隐藏采购方式
-const isHidePurchaseType = computed(() => {
- return isDeptApplyRole.value && (isEntrustCenterChannel.value || !isDeptPurchase.value);
-});
-
-// 部门申请角色 + 学校统一采购:隐藏采购方式
-const isHidePurchaseSchool = computed(() => {
- return isDeptApplyRole.value || ( isDeptApplyRole.value && !isDeptPurchase.value);
-});
-
-
-// 学校统一采购 && 非特殊 && 预算小于30万 显示业务分管校领导
-const isShowPurchaseManagerUserId = computed(() => {
- return !isDeptPurchase.value && isSpecialType("0") && Number(dataForm.budget) < BUDGET_PUBLIC_SELECT_THRESHOLD.value;
-});
-// 学校统一采购 && 非特殊 显示业务分管校领导
-const isShowSchoolLeaderUserId = computed(() => {
- return !isDeptPurchase.value && (!isSpecialType("0") || Number(dataForm.budget) >= BUDGET_PUBLIC_SELECT_THRESHOLD.value);
-});
-
-// 部门申请角色 + 自行采购 + 服务类网上商城品目:采购方式默认网上商城且disabled
-const isPurchaseTypeLockedToOnlineMall = computed(() => {
- return isDeptApplyRole.value && isEntrustSelfChannel.value && isMallServiceCategory.value;
-});
-
-// 判断是否为自行采购
-const isEntrustSelfChannel = computed(() => dataForm.purchaseChannel === PURCHASE_CHANNEL.SELF);
-
// 判断是否为部门自行采购
// 条件:特殊情况=否 且 集采=否 且 预算金额<5万 → 部门自行采购
// 其他情况 → 学校统一采购
@@ -881,20 +1245,16 @@ const isDeptPurchase = computed(() => {
// 是否为“委托采购中心采购”途径
const isEntrustCenterChannel = computed(() => dataForm.purchaseChannel === PURCHASE_CHANNEL.ENTRUST_CENTER);
-// 第二步标题
-const stepTwoTitle = computed(() => {
- return isDeptPurchase.value ? '部门自行采购' : '学校统一采购';
-});
-
+// 是否已填入“是否特殊情况”“是否集采”“预算金额”,从而能明确是部门自行采购还是学校统一采购(新增时先隐藏采购详情,填完后再显示)
const isPurchaseTypeDetermined = computed(() => {
return dataForm.isSpecial !== '' && dataForm.isCentralized !== '' && dataForm.budget != null && Number(dataForm.budget) > 0;
});
-// 是否显示“部门自行采购/学校统一采购”区块:查看/编辑/已保存过 时直接显示;新增时仅当类型已明确后显示
+// 是否显示“部门自行采购/学校统一采购”区块:查看/编辑/流程嵌入/已保存过 时直接显示;新增时仅当类型已明确后显示
const showPurchaseDetailBlocks = computed(() => {
- return !!dataForm.id || isPurchaseTypeDetermined.value;
+ return !!isViewMode.value || !!isFlowEmbed.value || !!dataForm.id || isPurchaseTypeDetermined.value;
});
-// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1');
+// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1');5万~100万且集采=学校集中采购→学校自主('2')
const schoolUnifiedPurchaseFormDefault = computed(() => {
if (isDeptPurchase.value || dataForm.budget == null) return null;
const budget = Number(dataForm.budget);
@@ -902,19 +1262,39 @@ const schoolUnifiedPurchaseFormDefault = computed(() => {
if (budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value) {
if (dataForm.isCentralized === '0') return '2'; // 集采=否 → 学校自主采购
if (dataForm.isCentralized === '1') return '1'; // 政府集中采购 → 政府采购
-
+ if (dataForm.isCentralized === '2') return '2'; // 学校集中采购 → 学校自主采购
}
- return '2';
+ return null;
});
+// 学校统一采购时采购形式是否禁用
+// 申请阶段:始终可选(根据默认值自动选中后,允许用户自行修改)
+// 流程嵌入:采购中心节点可编辑,其他节点只读
+const schoolUnifiedPurchaseFormDisabled = computed(() => {
+ // if (!isFlowEmbed.value) {
+ // return false;
+ // }
+ // 流程嵌入且为采购中心:放开编辑
+ if (isPurchaseCenter.value) {
+ return false;
+ }
+ // 其他流程节点只读
+ return true;
+});
-
+// 特殊情况字典 value:0否 1紧急 2单一 3进口
+const isUrgentSpecial = computed(() => dataForm.isSpecial === '1');
// 是否为特殊情况(非0即为特殊情况:紧急、单一、进口)
const isSpecialCase = computed(() => {
return dataForm.isSpecial && dataForm.isSpecial !== '0';
});
+// 第二步标题
+const stepTwoTitle = computed(() => {
+ return isDeptPurchase.value ? '部门自行采购' : '学校统一采购';
+});
+
// 根据 code 查找完整路径(用于回显)
const findCategoryPath = (data: any[], targetCode: string, path: string[] = []): string[] | null => {
for (const item of data) {
@@ -979,31 +1359,66 @@ const isGoodsCategory = computed(() => {
return category.type === 'A';
});
-// 判断是否为服务类网上商城品目(isMallService=1、isProjectService=1)
-const isMallServiceCategory = computed(() => {
+// 判断是否为特殊服务类目(isMallService=1、isProjectService=1)
+const isSpecialServiceCategory = computed(() => {
const category = getCategoryInfo();
if (!category) return false;
return Number(category.isMallService) === 1 || Number(category.isProjectService) === 1;
});
-// 部门自行采购 & 采购途径=自行采购 & 服务类网上商城品目 → 采购方式固定网上商城
+// 部门自行采购 & 采购途径=自行采购 & 特殊服务类目 → 采购方式固定网上商城
const isDeptSelfMallLocked = computed(() => {
- return isDeptPurchase.value && !isEntrustCenterChannel.value && isMallServiceCategory.value;
+ return isDeptPurchase.value && !isEntrustCenterChannel.value && isSpecialServiceCategory.value;
});
-// 监听 isDeptPurchase 变化:当从部门自行采购切换到学校统一采购(或反向)时,清空采购方式
-watch(
- () => isDeptPurchase.value,
- (newVal, oldVal) => {
+// 委托采购中心方式自动判断:
+// - 服务类:若末级节点 isMallService=0 且 isMallProject=0,则选“其他方式”,否则选“服务类网上商城”
+// - 非服务类:默认选“其他方式”
+const calcEntrustCenterType = (): 'service_online' | 'other' | '' => {
+ if (!isEntrustCenterChannel.value) return '';
+ if (!dataForm.categoryCode) return '';
- // 仅当模式真正发生变化时(从 true 变为 false,或从 false 变为 true)才清空
- if (oldVal !== undefined && newVal !== oldVal) {
- dataForm.purchaseType = '';
- }
+ const category = getCategoryInfo();
+ if (!category) return '';
+
+ // 兼容字段:接口可能为 isMallProject,也可能历史字段为 isProjectService
+ const mallService = Number(category.isMallService ?? 0);
+ const mallProject = Number(category.isMallProject ?? category.isProjectService ?? 0);
+
+ if (isServiceCategory.value) {
+ return mallService === 0 && mallProject === 0 ? 'other' : 'service_online';
}
+ return 'other';
+};
+
+// 监听品目/采购途径变化,自动设置委托采购中心方式,并清理无关字段
+watch(
+ [() => dataForm.purchaseChannel, () => dataForm.categoryCode, () => categoryTreeData.value],
+ () => {
+ const nextType = calcEntrustCenterType();
+ if (!nextType) return;
+
+ const prevType = dataForm.entrustCenterType as any;
+ if (prevType === nextType) return;
+
+ dataForm.entrustCenterType = nextType;
+
+ // 切换时清理不相关字段,避免脏数据
+ if (nextType === 'other') {
+ dataForm.hasSupplier = '0';
+ dataForm.suppliers = '';
+ dataForm.serviceDirectSelect = '';
+ dataForm.serviceInviteSelect = '';
+ dataForm.servicePublicSelect = '';
+ dataForm.servicePublicSelectAuto = '';
+ } else if (nextType === 'service_online') {
+ dataForm.purchaseRequirementTemplate = '';
+ }
+ },
+ { immediate: true }
);
-// 判断是否自动选择网上商城采购方式(5万<=金额<30万,服务类目,服务类网上商城品目)
+// 判断是否自动选择网上商城采购方式(5万<=金额<40万,服务类目,特殊服务类目)
const isAutoSelectPurchaseType = computed(() => {
if (!dataForm.budget) return false;
const budget = dataForm.budget;
@@ -1011,78 +1426,59 @@ const isAutoSelectPurchaseType = computed(() => {
budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value &&
budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value &&
isServiceCategory.value &&
- isMallServiceCategory.value
+ isSpecialServiceCategory.value
);
});
-// 部门采购 && 委托采购 && 服务商城品目,判断是否需要显示供应商
+// 判断是否显示自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目)
const showAutoInviteSelect = computed(() => {
- return isDeptPurchase.value && isEntrustCenterChannel.value && isMallServiceCategory.value;
+ if (!isDeptPurchase.value) return false;
+ if (!dataForm.budget) return false;
+ const budget = dataForm.budget;
+ return (
+ budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value &&
+ budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value &&
+ isServiceCategory.value &&
+ isSpecialServiceCategory.value
+ );
});
-// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<30万,服务类目,服务类网上商城品目)
+// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目)
const showAutoInviteSelectSchool = computed(() => {
if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false;
const budget = dataForm.budget;
- return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value;
+ return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isSpecialServiceCategory.value;
});
-// 判断是否显示自动公开比选模版(30万<=金额<100万,服务类网上商城品目:isMallService=1、isProjectService=1)
+// 判断是否显示自动公开比选模版(40万<=金额<100万,特殊服务类目:isMallService=1、isProjectService=1)
const showAutoPublicSelect = computed(() => {
if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false;
const budget = dataForm.budget;
- return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value && isMallServiceCategory.value;
+ return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value && isSpecialServiceCategory.value;
});
-// 需求文件配置:统一使用 purchaseRequirement 字段,根据不同场景显示不同的模板
-const requirementFileConfig = computed(() => {
- const config = {
- field: 'purchaseRequirement',
- label: '需求文件',
- templateType: 'purchase_requirement',
- templateName: '需求模板',
- };
-
- // (部门自行采购 + 委托 ) + 有供应商
- if (showAutoInviteSelect.value && dataForm.hasSupplier === '1') {
- return { ...config, label: '需求文件', templateType: 'invite_select', templateName: '服务商城项目需求模板(邀请比选)' };
+// 获取需求文件的 prop 名称(用于表单验证)
+const getRequirementFileProp = () => {
+ if (showAutoInviteSelectSchool.value) {
+ if (dataForm.hasSupplier === '1') {
+ return 'serviceInviteSelectSchool';
+ } else if (dataForm.hasSupplier === '0') {
+ return 'servicePublicSelectSchoolAuto';
+ }
+ } else if (showAutoPublicSelect.value) {
+ return 'servicePublicSelectSchool';
}
+ return 'purchaseRequirement';
+};
- //(部门自行采购 + 委托 ) + 无供应商
- if ( showAutoInviteSelect.value && dataForm.hasSupplier === '0') {
- return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' };
- }
-
- // // 学校统一采购 + 5万~30万服务商城类目(有供应商)
- if (!isDeptPurchase.value && showAutoInviteSelectSchool.value && dataForm.hasSupplier === '1') {
- return { ...config, label: '需求文件', templateType: 'invite_select', templateName: '服务商城项目需求模板(邀请比选)' };
- }
-
- // 学校统一采购 + 5万~30万服务类商城类目(无供应商)
- if (!isDeptPurchase.value && showAutoInviteSelectSchool.value && dataForm.hasSupplier === '0') {
- return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' };
- }
- // 学校统一采购 + 30万~100万服务类特殊类目
- if (!isDeptPurchase.value && showAutoPublicSelect.value) {
- return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' };
- }
- // 学校统一采购 + 100万以上 待定
- // if (!isDeptPurchase.value && showAutoPublicSelect.value) {
- // return { ...config, label: '需求文件', templateType: 'public_select', templateName: '服务商城项目需求模板(公开比选)' };
- // }
- return config;
-});
-
-
-
-// 判断学校统一采购是否需要自动设置采购方式(5万<=金额<30万,服务类目,服务类网上商城品目)
+// 判断学校统一采购是否需要自动设置采购方式(5万<=金额<40万,服务类目,特殊服务类目)
const isAutoSelectPurchaseTypeUnion = computed(() => {
if (isDeptPurchase.value) return false;
if (!dataForm.budget) return false;
const budget = dataForm.budget;
- return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value;
+ return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isSpecialServiceCategory.value;
});
// 监听品目编码、预算金额、采购类型及采购途径变化,自动设置/清空采购方式
@@ -1091,34 +1487,19 @@ watch(
() => dataForm.categoryCode,
() => dataForm.budget,
() => isDeptPurchase.value,
-
+ () => isFlowEmbed.value,
() => dataForm.purchaseChannel,
-
+ () => isPurchaseCenter.value,
],
() => {
- // 部门申请角色 + 委托采购中心采购:清空采购方式(已隐藏)
- if (isDeptApplyRole.value && isEntrustCenterChannel.value) {
- dataForm.purchaseType = '';
- return;
- }
-
- // 部门申请角色 + 自行采购 + 服务类网上商城品目:固定网上商城
- if (isDeptApplyRole.value && isEntrustSelfChannel.value && isMallServiceCategory.value) {
- const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
- if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
- dataForm.purchaseType = onlineMallOption.value;
- }
- return;
- }
-
- // 部门自行采购 & 采购途径为"委托采购中心采购"且为新增申请阶段:采购方式隐藏且不设置
+ // 部门自行采购 & 采购途径为”委托采购中心采购”且为新增申请阶段:采购方式隐藏且不设置
// 注意:查看模式和编辑模式不清空已有的采购方式
- if (isDeptPurchase.value && isEntrustCenterChannel.value ) {
+ if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value && !isViewMode.value && !isEditMode.value) {
dataForm.purchaseType = '';
return;
}
- // 部门自行采购 & 采购途径为"自行采购" & 服务类网上商城品目:固定网上商城(无论金额区间)
+ // 部门自行采购 & 采购途径为“自行采购” & 特殊服务类目:固定网上商城(无论金额区间)
if (isDeptSelfMallLocked.value) {
const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
@@ -1128,7 +1509,7 @@ watch(
return;
}
- // 其他部门自行采购 & 采购途径为"自行采购":在金额区间内自动推荐网上商城
+ // 其他部门自行采购 & 采购途径为“自行采购”:在金额区间内自动推荐网上商城
if (isAutoSelectPurchaseType.value && isDeptPurchase.value && !isEntrustCenterChannel.value) {
const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
@@ -1136,8 +1517,8 @@ watch(
}
}
- // 部门自行采购 & 采购途径为"委托采购中心采购" & 采购中心审批节点:默认设置为网上商城
- if (isDeptPurchase.value && isEntrustCenterChannel.value) {
+ // 部门自行采购 & 采购途径为”委托采购中心采购” & 采购中心审批节点:默认设置为网上商城
+ if (isDeptPurchase.value && isEntrustCenterChannel.value && isFlowEmbed.value && isPurchaseCenter.value) {
const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value;
@@ -1146,7 +1527,7 @@ watch(
}
// 学校统一采购审批阶段:自动设置网上商城采购方式
- if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value) {
+ if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value && isFlowEmbed.value) {
const onlineMallOption = purchaseTypeUnionList.value.find((item) => item.value === UNION_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value;
@@ -1238,8 +1619,8 @@ const dataRules = reactive({
callback();
return;
}
- // 部门自行采购且采购途径为"委托采购中心采购"此处不校验采购方式
- if (isEntrustCenterChannel.value ) {
+ // 部门自行采购且采购途径为"委托采购中心采购"并且为申请阶段:此处不校验采购方式
+ if (isEntrustCenterChannel.value && !isFlowEmbed.value) {
callback();
return;
}
@@ -1252,21 +1633,6 @@ const dataRules = reactive({
trigger: 'change',
},
],
- // 部门采购会议纪要:预算超过2000元必填
- deptSelfMeetingMinutes: [
- {
- validator: (_rule: any, value: any, callback: (e?: Error) => void) => {
- if (dataForm.budget != null && dataForm.budget >= BUDGET_DEPT_SELF_MEETING_MINUTES.value) {
- if (!value || (Array.isArray(value) && value.length === 0) || (typeof value === 'string' && !value.trim())) {
- callback(new Error('请上传部门采购会议纪要'));
- return;
- }
- }
- callback();
- },
- trigger: 'change',
- },
- ],
// 学校统一采购时必填
deptClassifyUserId: [
{
@@ -1340,80 +1706,14 @@ const dataRules = reactive({
trigger: 'blur',
},
],
- // 需求模板:委托采购中心采购时,货物类/工程类/服务类必填
- purchaseRequirementTemplate: [
- {
- validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
- // 仅在委托采购中心采购且品目编码为A/B/C类时校验
- if (isEntrustCenterChannel.value && categoryCodePath.value && categoryCodePath.value.length > 0) {
- const firstCode = categoryCodePath.value[0];
- if ((firstCode === 'A' || firstCode === 'B' || firstCode === 'C') && (!value || String(value).trim() === '')) {
- callback(new Error('需求模板不能为空'));
- return;
- }
- }
- callback();
- },
- trigger: 'change',
- },
- ],
- // 商务洽谈表:采购方式为商务洽谈时必填
- businessNegotiationTable: [
- {
- validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
- if (isPurchaseType(DEPT_PURCHASE_TYPE.BUSINESS_NEGOTIATION) && (!value || String(value).trim() === '')) {
- callback(new Error('商务洽谈表不能为空'));
- return;
- }
- callback();
- },
- trigger: 'change',
- },
- ],
- // 市场采购纪要:采购方式为市场采购时必填
- marketPurchaseMinutes: [
- {
- validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
- if (isPurchaseType(DEPT_PURCHASE_TYPE.MARKET_PURCHASE) && (!value || String(value).trim() === '')) {
- callback(new Error('市场采购纪要不能为空'));
- return;
- }
- callback();
- },
- trigger: 'change',
- },
- ],
- // 网上商城采购相关材料:采购方式为网上商城时必填
- onlineMallMaterials: [
- {
- validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
- if (isPurchaseType(DEPT_PURCHASE_TYPE.ONLINE_MALL) && (!value || String(value).trim() === '')) {
- callback(new Error('网上商城采购相关材料不能为空'));
- return;
- }
- callback();
- },
- trigger: 'change',
- },
- ],
- // 询价模板:采购方式为询价时必填
- inquiryTemplate: [
- {
- validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
- if (isInquiryPurchaseType.value && (!value || String(value).trim() === '')) {
- callback(new Error('询价模板不能为空'));
- return;
- }
- callback();
- },
- trigger: 'change',
- },
- ],
});
// 取消
const handleCancel = () => {
-
+ // 流程嵌入时由流程页处理返回,不 postMessage
+ if (isFlowEmbed.value) {
+ return;
+ }
if (window.parent !== window) {
window.parent.postMessage(
{
@@ -1463,15 +1763,26 @@ async function loadDetail(applyId: string | number) {
marketPurchaseMinutes: detail.marketPurchaseMinutes ?? '',
onlineMallMaterials: detail.onlineMallMaterials ?? '',
inquiryTemplate: detail.inquiryTemplate ?? '',
+ entrustCenterType: detail.entrustCenterType ?? '',
hasSupplier: detail.hasSupplier != null && detail.hasSupplier !== '' ? detail.hasSupplier : '0',
suppliers: detail.suppliers ?? '',
+ serviceDirectSelect: detail.serviceDirectSelect ?? '',
+ servicePublicSelect: detail.servicePublicSelect ?? '',
purchaseRequirementTemplate: detail.purchaseRequirementTemplate ?? '',
+ serviceInviteSelect: detail.serviceInviteSelect ?? '',
+ servicePublicSelectAuto: detail.servicePublicSelectAuto ?? '',
purchaseRequirement: detail.purchaseRequirement ?? '',
meetingMinutes: detail.meetingMinutes ?? '',
feasibilityReport: detail.feasibilityReport ?? '',
+ meetingMinutesUrgent: detail.meetingMinutesUrgent ?? '',
+ meetingMinutesSingle: detail.meetingMinutesSingle ?? '',
+ meetingMinutesImport: detail.meetingMinutesImport ?? '',
singleSourceProof: detail.singleSourceProof ?? '',
importApplication: detail.importApplication ?? '',
governmentPurchaseIntent: detail.governmentPurchaseIntent ?? '',
+ servicePublicSelectSchool: detail.servicePublicSelectSchool ?? '',
+ serviceInviteSelectSchool: detail.serviceInviteSelectSchool ?? '',
+ servicePublicSelectSchoolAuto: detail.servicePublicSelectSchoolAuto ?? '',
deptClassifyUserId: detail.deptClassifyUserId ?? '',
deptClassifyName: detail.deptClassifyName ?? '',
schoolLeaderUserId: detail.schoolLeaderUserId ?? '',
@@ -1566,7 +1877,88 @@ function downloadImplementFile(file: { id?: string; remark?: string; fileTitle?:
other.downBlobFile(url, {}, file.fileTitle || '招标文件');
return;
}
-useMessage().warning('无法获取文件信息');
+ useMessage().warning('无法获取文件信息');
+}
+
+/** 流程嵌入时提供给 orderVue.currElTabIsView 的 methods(只读/禁用提交) */
+const flowMethods = {
+ disableForm(disabled?: boolean) {
+ flowFormDisabled.value = !!disabled;
+ },
+ disableSubmit() {
+ flowSubmitDisabled.value = true;
+ },
+ enableSubmit() {
+ flowSubmitDisabled.value = false;
+ },
+};
+
+/** 流程嵌入时采购申请权限:根据前端缓存的角色(cloud-ui:roleCode)判断,非采购中心整表只读,采购中心仅采购方式/采购形式可编辑;申请人在流程中可编辑 */
+function applyPurchaseApplyFormPerm() {
+ if (!isFlowEmbed.value) return;
+ const roleCode = Session.getRoleCode() || '';
+ isPurchaseCenter.value = roleCode === PURCHASE_CENTER_ROLE_CODE;
+ if (isApplicant.value) {
+ flowFormDisabled.value = false;
+ } else {
+ flowFormDisabled.value = !isPurchaseCenter.value;
+ }
+}
+
+/** 流程嵌入时的“保存”回调:校验后调用 editObj,并通知流程已保存 */
+async function flowSubmitForm() {
+ if (loading.value) return;
+ loading.value = true;
+ try {
+ const valid = await formRef.value?.validate().catch(() => false);
+ if (!valid) {
+ loading.value = false;
+ return;
+ }
+ const submitData: any = { ...dataForm };
+ const fileFields = [
+ 'businessNegotiationTable',
+ 'marketPurchaseMinutes',
+ 'onlineMallMaterials',
+ 'inquiryTemplate',
+ 'serviceDirectSelect',
+ 'servicePublicSelect',
+ 'purchaseRequirementTemplate',
+ 'serviceInviteSelect',
+ 'servicePublicSelectAuto',
+ 'deptSelfMeetingMinutes', // 部门自行采购会议纪要
+ 'purchaseRequirement',
+ 'meetingMinutes',
+ 'feasibilityReport',
+ 'meetingMinutesUrgent',
+ 'meetingMinutesSingle',
+ 'meetingMinutesImport',
+ 'singleSourceProof',
+ 'importApplication',
+ 'governmentPurchaseIntent',
+ 'servicePublicSelectSchool',
+ 'serviceInviteSelectSchool',
+ 'servicePublicSelectSchoolAuto',
+ 'otherMaterials',
+ ];
+ const allFileIds: string[] = [];
+ fileFields.forEach((field) => {
+ if (submitData[field]) {
+ allFileIds.push(...getFileIdsArray(submitData[field]));
+ delete submitData[field];
+ }
+ });
+ if (allFileIds.length > 0) submitData.fileIds = allFileIds;
+ await editObj(submitData);
+ useMessage().success('保存成功');
+ if (props.currJob && props.currElTab?.id) {
+ orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emit);
+ }
+ } catch (err: any) {
+ if (!err?.msg) useMessage().error('保存失败');
+ } finally {
+ loading.value = false;
+ }
}
// 获取品目树形数据
@@ -1939,6 +2331,106 @@ const getFileIdsArray = (fileIds: string | string[] | { id?: string; name?: stri
return ids;
};
+// 提交
+const handleSubmit = async () => {
+ if (loading.value) return;
+ loading.value = true;
+
+ try {
+ const valid = await formRef.value?.validate().catch(() => {});
+ if (!valid) {
+ loading.value = false;
+ return false;
+ }
+
+ const submitData: any = {
+ ...dataForm,
+ };
+
+ // 学校统一采购申请阶段:采购方式由审批环节补充,提交时不写入
+ if (!isFlowEmbed.value && !isDeptPurchase.value) {
+ submitData.purchaseType = '';
+ }
+
+ // 处理所有文件字段 - 收集所有文件ID到fileIds数组中
+ const fileFields = [
+ 'businessNegotiationTable',
+ 'marketPurchaseMinutes',
+ 'onlineMallMaterials',
+ 'inquiryTemplate',
+ 'serviceDirectSelect',
+ 'servicePublicSelect',
+ 'purchaseRequirementTemplate',
+ 'serviceInviteSelect',
+ 'servicePublicSelectAuto',
+ 'deptSelfMeetingMinutes', // 部门自行采购会议纪要
+ 'purchaseRequirement',
+ 'meetingMinutes',
+ 'feasibilityReport',
+ 'meetingMinutesUrgent',
+ 'meetingMinutesSingle',
+ 'meetingMinutesImport',
+ 'singleSourceProof',
+ 'importApplication',
+ 'governmentPurchaseIntent',
+ 'servicePublicSelectSchool',
+ 'serviceInviteSelectSchool',
+ 'servicePublicSelectSchoolAuto',
+ 'otherMaterials',
+ ];
+
+ // 收集所有文件ID到一个数组中
+ const allFileIds: string[] = [];
+
+ fileFields.forEach((field) => {
+ if (submitData[field]) {
+ const ids = getFileIdsArray(submitData[field]);
+ console.log(`字段 ${field} 的文件ID:`, ids);
+ // 收集到总数组中
+ allFileIds.push(...ids);
+ // 清空原字段,不再单独传递
+ delete submitData[field];
+ }
+ });
+
+ // 将所有文件ID统一放到fileIds字段中
+ if (allFileIds.length > 0) {
+ submitData.fileIds = allFileIds;
+ console.log('所有文件ID (fileIds):', allFileIds);
+ }
+
+ console.log('提交数据:', submitData);
+
+ if (dataForm.id) {
+ await editObj(submitData);
+ useMessage().success('保存成功');
+ } else {
+ await addObj(submitData);
+ useMessage().success('提交成功');
+ }
+
+ // 如果是在 iframe 中,向父窗口发送消息
+ if (window.parent !== window) {
+ window.parent.postMessage(
+ {
+ type: 'purchasingrequisition:submitSuccess',
+ },
+ '*'
+ );
+ } else {
+ router.push('/purchase/purchasingrequisition');
+ }
+ } catch (err: any) {
+ // 全局拦截器已经显示了错误提示,这里不需要再次显示
+ // 只有当错误没有 msg 时才显示默认错误提示
+ if (!err?.msg) {
+ useMessage().error('提交失败');
+ }
+ } finally {
+ loading.value = false;
+ }
+};
+
// 暂存
const handleTempStore = async () => {
if (loading.value) return;
@@ -1956,7 +2448,7 @@ const handleTempStore = async () => {
};
// 学校统一采购申请阶段:采购方式由审批环节补充,暂存时不写入
- if (!isDeptPurchase.value) {
+ if (!isFlowEmbed.value && !isDeptPurchase.value) {
submitData.purchaseType = '';
}
@@ -1966,14 +2458,24 @@ const handleTempStore = async () => {
'marketPurchaseMinutes',
'onlineMallMaterials',
'inquiryTemplate',
+ 'serviceDirectSelect',
+ 'servicePublicSelect',
'purchaseRequirementTemplate',
+ 'serviceInviteSelect',
+ 'servicePublicSelectAuto',
'deptSelfMeetingMinutes', // 部门自行采购会议纪要
'purchaseRequirement',
'meetingMinutes',
'feasibilityReport',
+ 'meetingMinutesUrgent',
+ 'meetingMinutesSingle',
+ 'meetingMinutesImport',
'singleSourceProof',
'importApplication',
'governmentPurchaseIntent',
+ 'servicePublicSelectSchool',
+ 'serviceInviteSelectSchool',
+ 'servicePublicSelectSchoolAuto',
'otherMaterials',
];
@@ -1997,16 +2499,18 @@ const handleTempStore = async () => {
await tempStore(submitData);
useMessage().success('暂存成功');
- // 暂存后跳转
- if (window.parent !== window) {
- window.parent.postMessage(
- {
- type: 'purchasingrequisition:submitSuccess',
- },
- '*'
- );
- } else {
- router.push('/purchase/purchasingrequisition');
+ // 流程嵌入时不关闭、不跳转
+ if (!isFlowEmbed.value) {
+ if (window.parent !== window) {
+ window.parent.postMessage(
+ {
+ type: 'purchasingrequisition:submitSuccess',
+ },
+ '*'
+ );
+ } else {
+ router.push('/purchase/purchasingrequisition');
+ }
}
} catch (err: any) {
if (!err?.msg) {
@@ -2017,78 +2521,6 @@ const handleTempStore = async () => {
}
};
-// 流程嵌入时保存表单并通知流程
-const handleFlowSave = async () => {
- if (loading.value) return;
- loading.value = true;
-
- try {
- const submitData: any = {
- ...dataForm,
- };
-
- // 学校统一采购申请阶段:采购方式由审批环节补充,暂存时不写入
- if (!isDeptPurchase.value) {
- submitData.purchaseType = '';
- }
-
- // 处理所有文件字段 - 收集所有文件ID到fileIds数组中
- const fileFields = [
- 'businessNegotiationTable',
- 'marketPurchaseMinutes',
- 'onlineMallMaterials',
- 'inquiryTemplate',
- 'purchaseRequirementTemplate',
- 'deptSelfMeetingMinutes',
- 'purchaseRequirement',
- 'meetingMinutes',
- 'feasibilityReport',
- 'singleSourceProof',
- 'importApplication',
- 'governmentPurchaseIntent',
- 'otherMaterials',
- ];
-
- const allFileIds: string[] = [];
-
- fileFields.forEach((field) => {
- if (submitData[field]) {
- const ids = getFileIdsArray(submitData[field]);
- allFileIds.push(...ids);
- delete submitData[field];
- }
- });
-
- if (allFileIds.length > 0) {
- submitData.fileIds = allFileIds;
- }
-
- await tempStore(submitData);
- // 通知流程保存成功
- orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emits);
- useMessage().success('保存成功');
- } catch (err: any) {
- if (!err?.msg) {
- useMessage().error('保存失败');
- }
- } finally {
- loading.value = false;
- }
-};
-
-// 监听 currJob 变化,流程嵌入时加载数据
-watch(
- () => props.currJob?.id,
- () => {
- if (isFlowEmbed.value) {
- const queryId = effectiveQueryId.value;
- if (queryId) {
- loadDetail(queryId);
- }
- }
- }
-);
-
// 设置品目编码回显路径
const setCategoryCodePath = () => {
if (dataForm.categoryCode && categoryTreeData.value.length > 0) {
@@ -2114,6 +2546,17 @@ watch(
{ deep: true }
);
+// 流程嵌入:切换工单时重新加载该 tab 对应的申请单
+watch(
+ () => props.currJob?.id,
+ async (newVal, oldVal) => {
+ if (!isFlowEmbed.value || !props.currJob?.orderId) return;
+ if (newVal !== oldVal) {
+ await loadDetail(props.currJob.orderId);
+ }
+ }
+);
+
// 初始化
onMounted(async () => {
// 检测是否在 iframe 中,如果是,则修改相关元素的 overflow 样式以支持滚动
@@ -2156,12 +2599,19 @@ onMounted(async () => {
getBusinessLeaderListData(),
]);
- // 编辑/查看:从 URL 加载详情
+ // 编辑/查看:从 URL 或流程 currJob.orderId 加载详情
const queryId = effectiveQueryId.value;
if (queryId) {
await loadDetail(queryId);
}
+ // 流程嵌入:注册 tab 显隐与保存回调,供审批页调用
+ if (isFlowEmbed.value && props.currJob && props.currElTab?.id) {
+ orderVue.currElTabIsExist(props.currJob, props.currElTab.id);
+ await orderVue.currElTabIsView(flowMethods, props.currJob, props.currElTab.id, flowSubmitForm);
+ applyPurchaseApplyFormPerm();
+ }
+
// 新增模式下设置默认值(只有在没有 id 的情况下才设置)
if (!dataForm.id) {
// 填报日期默认为当天
@@ -2182,16 +2632,6 @@ onMounted(async () => {
if (dataForm.categoryCode) {
setCategoryCodePath();
}
-
- // 流程嵌入模式:注册保存函数
- if (isFlowEmbed.value) {
- const elTab = props.currElTab;
- await handleCustomFormPerm(props, {}, {}, elTab);
- // 注册保存函数到流程
- if (props.currJob?.resolveSaves) {
- props.currJob.resolveSaves.push(handleFlowSave);
- }
- }
});