+
采购代表/评委
@@ -876,59 +540,10 @@
-
-
-
- 以下规则仅作为自动推荐与必填校验依据,实际录入时可在允许范围内调整。
-
-
-
- -
- 部门自行采购 / 学校统一采购划分: 当「是否特殊情况 = 否」「是否集采 = 否」且预算金额 < 5 万({{
- BUDGET_DEPT_PURCHASE_THRESHOLD
- }}
- 元)时,系统判定为「部门自行采购」,否则为「学校统一采购」。
-
- -
- 学校统一采购 - 采购形式默认值: 当预算金额 ≥ 100 万({{ BUDGET_GOV_PURCHASE_THRESHOLD }} 元)时默认「政府采购」;
- 当 5 万 ≤ 预算金额 < 100 万时,根据「是否集采」自动推荐「政府采购」或「学校自主采购」, 但申请人可以在界面上自行修改。
-
- -
- 部门自行采购 - 自动网上商城:
- 在「部门自行采购」且为服务类特殊品目时,系统会自动将采购方式推荐为「网上商城」(服务类),同时要求上传相应模板文件。
-
- -
- 学校统一采购 - 自动邀请/公开比选模板: 对服务类特殊品目: 当 5 万 ≤ 预算金额 < 40
- 万时,系统根据「是否有推荐供应商」在邀请比选 / 公开比选模板之间自动切换必填文件; 当 40 万 ≤ 预算金额 < 100
- 万时,系统默认要求使用公开比选模板。
-
- -
- 可行性论证与会议纪要(学校统一采购): 当预算金额 ≥ 30 万({{
- BUDGET_FEASIBILITY_THRESHOLD
- }}
- 元)且不是紧急/单一/进口等特殊情况时,
- 需要上传「项目可行性论证报告」和「会议纪要」;紧急、单一来源、进口等特殊情况对应有单独的证明材料与会议纪要要求。
-
- -
- 政府采购意向表: 当预算金额 ≥ 100 万({{
- BUDGET_GOV_PURCHASE_THRESHOLD
- }}
- 元),需要填写政府采购意向表并上传对应模板文件。
-
- -
- 委托采购中心采购:
- 在「部门自行采购」中选择「委托采购中心采购」作为采购途径时,申请阶段隐藏采购方式,由采购中心在审核环节选择;
- 对服务类特殊品目,采购中心会优先推荐「网上商城(服务网上商城)」方式。
-
-
-
-
- 我知道了
-
-
+
-
+
实施采购信息
@@ -976,21 +591,10 @@
-
+
@@ -1005,93 +609,34 @@ 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 { Document, Download, QuestionFilled } from '@element-plus/icons-vue';
+import { Session } from '/@/utils/storage';
+import { Document } 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';
-/** 采购中心角色编码:审批时仅该角色可编辑采购方式/采购形式 */
-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();
-/** 是否被流程 handle 页通过 dynamic-link 嵌入 */
-const isFlowEmbed = computed(() => !!props.currJob);
-
-/** 当前使用的申请单 ID:优先来自流程 currJob.orderId,否则来自 route.query.id */
+// 当前使用的申请单 ID
const effectiveQueryId = computed(() => {
- if (props.currJob?.orderId != null && props.currJob?.orderId !== '') {
- return String(props.currJob.orderId);
- }
const q = route.query.id;
return q ? String(q) : '';
});
-// 模式: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';
-});
+// 模式:add | edit | view
const pageTitle = computed(() => {
- if (isViewMode.value) return '查看采购申请';
- if (isEditMode.value) return '编辑采购申请';
+ const mode = String(route.query.mode);
+ if (mode === 'view') return '查看采购申请';
+ if (mode === 'edit') return '编辑采购申请';
return '新增采购申请';
});
-/** 流程嵌入时,由 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();
const dataForm = reactive({
@@ -1118,31 +663,17 @@ 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: '',
@@ -1188,32 +719,22 @@ const loading = ref(false);
const helpDialogVisible = ref(false);
// 文件类型映射(对应数据库 file_type 字段)
-// 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140: 部门自行采购会议纪要
+// 附件类型 10:商务洽谈纪要 20:市场采购纪要 30:网上商城采购相关材料 40:可行性论证报告 50:会议记录 60:其他材料 70:单一来源专家论证表 90:进口产品申请及专家论证表 100:政府采购意向表 110:履约验收单 120:采购需求表 130:招标文件 140:部门自行采购会议纪要 150:部门询价模
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 -> 表单字段名数组(顺序与回填分配一致,同类型多字段时按此顺序分配)
@@ -1276,6 +797,41 @@ 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 || ( 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万 → 部门自行采购
// 其他情况 → 学校统一采购
@@ -1297,16 +853,20 @@ 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 !!isViewMode.value || !!isFlowEmbed.value || !!dataForm.id || isPurchaseTypeDetermined.value;
+ return !!dataForm.id || isPurchaseTypeDetermined.value;
});
-// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1');5万~100万且集采=学校集中采购→学校自主('2')
+// 学校统一采购时采购形式默认值(不由用户选择):>=100万→政府采购('1');5万~100万且集采=否→学校自主('2');5万~100万且集采=政府集中采购→政府采购('1');
const schoolUnifiedPurchaseFormDefault = computed(() => {
if (isDeptPurchase.value || dataForm.budget == null) return null;
const budget = Number(dataForm.budget);
@@ -1314,39 +874,19 @@ 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 null;
+ return '2';
});
-// 学校统一采购时采购形式是否禁用
-// 申请阶段:始终可选(根据默认值自动选中后,允许用户自行修改)
-// 流程嵌入:采购中心节点可编辑,其他节点只读
-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) {
@@ -1411,66 +951,31 @@ const isGoodsCategory = computed(() => {
return category.type === 'A';
});
-// 判断是否为特殊服务类目(isMallService=1、isProjectService=1)
-const isSpecialServiceCategory = computed(() => {
+// 判断是否为服务类网上商城品目(isMallService=1、isProjectService=1)
+const isMallServiceCategory = 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 && isSpecialServiceCategory.value;
+ return isDeptPurchase.value && !isEntrustCenterChannel.value && isMallServiceCategory.value;
});
-// 委托采购中心方式自动判断:
-// - 服务类:若末级节点 isMallService=0 且 isMallProject=0,则选“其他方式”,否则选“服务类网上商城”
-// - 非服务类:默认选“其他方式”
-const calcEntrustCenterType = (): 'service_online' | 'other' | '' => {
- if (!isEntrustCenterChannel.value) return '';
- if (!dataForm.categoryCode) return '';
-
- 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';
-};
-
-// 监听品目/采购途径变化,自动设置委托采购中心方式,并清理无关字段
+// 监听 isDeptPurchase 变化:当从部门自行采购切换到学校统一采购(或反向)时,清空采购方式
watch(
- [() => dataForm.purchaseChannel, () => dataForm.categoryCode, () => categoryTreeData.value],
- () => {
- const nextType = calcEntrustCenterType();
- if (!nextType) return;
+ () => isDeptPurchase.value,
+ (newVal, oldVal) => {
- 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 = '';
+ // 仅当模式真正发生变化时(从 true 变为 false,或从 false 变为 true)才清空
+ if (oldVal !== undefined && newVal !== oldVal) {
+ dataForm.purchaseType = '';
}
- },
- { immediate: true }
+ }
);
-// 判断是否自动选择网上商城采购方式(5万<=金额<40万,服务类目,特殊服务类目)
+// 判断是否自动选择网上商城采购方式(5万<=金额<30万,服务类目,服务类网上商城品目)
const isAutoSelectPurchaseType = computed(() => {
if (!dataForm.budget) return false;
const budget = dataForm.budget;
@@ -1478,59 +983,78 @@ const isAutoSelectPurchaseType = computed(() => {
budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value &&
budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value &&
isServiceCategory.value &&
- isSpecialServiceCategory.value
+ isMallServiceCategory.value
);
});
-// 判断是否显示自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目)
+// 部门采购 && 委托采购 && 服务商城品目,判断是否需要显示供应商
const showAutoInviteSelect = 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 &&
- isServiceCategory.value &&
- isSpecialServiceCategory.value
- );
+ return isDeptPurchase.value && isEntrustCenterChannel.value && isMallServiceCategory.value;
});
-// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<40万,服务类目,特殊服务类目)
+// 判断是否显示学校统一采购的自动邀请比选模版(5万<=金额<30万,服务类目,服务类网上商城品目)
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 && isSpecialServiceCategory.value;
+ return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value;
});
-// 判断是否显示自动公开比选模版(40万<=金额<100万,特殊服务类目:isMallService=1、isProjectService=1)
+// 判断是否显示自动公开比选模版(30万<=金额<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 && isSpecialServiceCategory.value;
+ return budget >= BUDGET_PUBLIC_SELECT_THRESHOLD.value && budget < BUDGET_GOV_PURCHASE_THRESHOLD.value && isMallServiceCategory.value;
});
-// 获取需求文件的 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';
-};
+// 需求文件配置:统一使用 purchaseRequirement 字段,根据不同场景显示不同的模板
+const requirementFileConfig = computed(() => {
+ const config = {
+ field: 'purchaseRequirement',
+ label: '需求文件',
+ templateType: 'purchase_requirement',
+ templateName: '需求模板',
+ };
-// 判断学校统一采购是否需要自动设置采购方式(5万<=金额<40万,服务类目,特殊服务类目)
+ // (部门自行采购 + 委托 ) + 有供应商
+ if (showAutoInviteSelect.value && dataForm.hasSupplier === '1') {
+ return { ...config, label: '需求文件', templateType: 'invite_select', templateName: '服务商城项目需求模板(邀请比选)' };
+ }
+
+ //(部门自行采购 + 委托 ) + 无供应商
+ 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万,服务类目,服务类网上商城品目)
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 && isSpecialServiceCategory.value;
+ return budget >= BUDGET_DEPT_PURCHASE_THRESHOLD.value && budget < BUDGET_PUBLIC_SELECT_THRESHOLD.value && isMallServiceCategory.value;
});
// 监听品目编码、预算金额、采购类型及采购途径变化,自动设置/清空采购方式
@@ -1539,19 +1063,34 @@ watch(
() => dataForm.categoryCode,
() => dataForm.budget,
() => isDeptPurchase.value,
- () => isFlowEmbed.value,
+
() => dataForm.purchaseChannel,
- () => isPurchaseCenter.value,
+
],
() => {
- // 部门自行采购 & 采购途径为”委托采购中心采购”且为新增申请阶段:采购方式隐藏且不设置
- // 注意:查看模式和编辑模式不清空已有的采购方式
- if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value && !isViewMode.value && !isEditMode.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 ) {
+ 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) {
@@ -1561,7 +1100,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) {
@@ -1569,8 +1108,8 @@ watch(
}
}
- // 部门自行采购 & 采购途径为”委托采购中心采购” & 采购中心审批节点:默认设置为网上商城
- if (isDeptPurchase.value && isEntrustCenterChannel.value && isFlowEmbed.value && isPurchaseCenter.value) {
+ // 部门自行采购 & 采购途径为"委托采购中心采购" & 采购中心审批节点:默认设置为网上商城
+ if (isDeptPurchase.value && isEntrustCenterChannel.value) {
const onlineMallOption = purchaseTypeDeptList.value.find((item) => item.value === DEPT_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value;
@@ -1579,7 +1118,7 @@ watch(
}
// 学校统一采购审批阶段:自动设置网上商城采购方式
- if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value && isFlowEmbed.value) {
+ if (isAutoSelectPurchaseTypeUnion.value && !isDeptPurchase.value) {
const onlineMallOption = purchaseTypeUnionList.value.find((item) => item.value === UNION_PURCHASE_TYPE.ONLINE_MALL);
if (onlineMallOption && dataForm.purchaseType !== onlineMallOption.value) {
dataForm.purchaseType = onlineMallOption.value;
@@ -1671,8 +1210,8 @@ const dataRules = reactive({
callback();
return;
}
- // 部门自行采购且采购途径为"委托采购中心采购"并且为申请阶段:此处不校验采购方式
- if (isEntrustCenterChannel.value && !isFlowEmbed.value) {
+ // 部门自行采购且采购途径为"委托采购中心采购"此处不校验采购方式
+ if (isEntrustCenterChannel.value ) {
callback();
return;
}
@@ -1773,14 +1312,80 @@ 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(
{
@@ -1830,26 +1435,15 @@ 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 ?? '',
@@ -1944,88 +1538,7 @@ function downloadImplementFile(file: { id?: string; remark?: string; fileTitle?:
other.downBlobFile(url, {}, file.fileTitle || '招标文件');
return;
}
- 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;
- }
+useMessage().warning('无法获取文件信息');
}
// 获取品目树形数据
@@ -2398,106 +1911,6 @@ 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;
@@ -2515,7 +1928,7 @@ const handleTempStore = async () => {
};
// 学校统一采购申请阶段:采购方式由审批环节补充,暂存时不写入
- if (!isFlowEmbed.value && !isDeptPurchase.value) {
+ if (!isDeptPurchase.value) {
submitData.purchaseType = '';
}
@@ -2525,24 +1938,14 @@ 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',
];
@@ -2566,18 +1969,16 @@ const handleTempStore = async () => {
await tempStore(submitData);
useMessage().success('暂存成功');
- // 流程嵌入时不关闭、不跳转
- if (!isFlowEmbed.value) {
- if (window.parent !== window) {
- window.parent.postMessage(
- {
- type: 'purchasingrequisition:submitSuccess',
- },
- '*'
- );
- } else {
- router.push('/purchase/purchasingrequisition');
- }
+ // 暂存后跳转
+ if (window.parent !== window) {
+ window.parent.postMessage(
+ {
+ type: 'purchasingrequisition:submitSuccess',
+ },
+ '*'
+ );
+ } else {
+ router.push('/purchase/purchasingrequisition');
}
} catch (err: any) {
if (!err?.msg) {
@@ -2613,17 +2014,6 @@ 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 样式以支持滚动
@@ -2666,19 +2056,12 @@ onMounted(async () => {
getBusinessLeaderListData(),
]);
- // 编辑/查看:从 URL 或流程 currJob.orderId 加载详情
+ // 编辑/查看:从 URL 加载详情
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) {
// 填报日期默认为当天
diff --git a/src/views/purchase/purchasingrequisition/form.vue b/src/views/purchase/purchasingrequisition/form.vue
index c896d96..55d1f43 100644
--- a/src/views/purchase/purchasingrequisition/form.vue
+++ b/src/views/purchase/purchasingrequisition/form.vue
@@ -3,7 +3,6 @@
v-model="visible"
:title="dialogTitle"
width="90%"
- :style="{ maxWidth: '1600px' }"
:close-on-click-modal="false"
destroy-on-close
class="form-iframe-dialog"