Merge branch 'developer'
This commit is contained in:
@@ -22,8 +22,13 @@
|
|||||||
:disabled="isViewMode || flowFormDisabled"
|
:disabled="isViewMode || flowFormDisabled"
|
||||||
class="compact-form"
|
class="compact-form"
|
||||||
>
|
>
|
||||||
<!-- 基本信息(三列紧凑) -->
|
<!-- 基础信息 -->
|
||||||
<div class="form-section-compact">
|
<el-divider content-position="left">
|
||||||
|
<span class="section-title">基础信息</span>
|
||||||
|
</el-divider>
|
||||||
|
<el-text v-if="!isEditMode && !isViewMode" type="info" size="small" class="mb12" style="display: block">
|
||||||
|
暂存时,基础信息必填
|
||||||
|
</el-text>
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
<el-form-item label="采购项目名称" prop="projectName">
|
<el-form-item label="采购项目名称" prop="projectName">
|
||||||
@@ -131,15 +136,18 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 采购详情(新增时需先填是否特殊情况、是否集采、预算金额后才显示) -->
|
<!-- 采购详情(新增时需先填是否特殊情况、是否集采、预算金额后才显示) -->
|
||||||
<div>
|
<div>
|
||||||
<el-alert v-if="!showPurchaseDetailBlocks" type="info" :closable="false" class="mb16" show-icon>
|
<el-alert v-if="!showPurchaseDetailBlocks" type="info" :closable="false" class="mb16" show-icon>
|
||||||
请先填写上方「是否特殊情况」「是否集采」「预算金额」,系统将根据填写结果展示「部门自行采购」或「学校统一采购」表单。
|
请先填写上方「是否特殊情况」「是否集采」「预算金额」,系统将根据填写结果展示「部门自行采购」或「学校统一采购」表单。
|
||||||
</el-alert>
|
</el-alert>
|
||||||
<!-- 部门采购会议纪要(预算超过2000元必须上传,不区分部门自行采购/学校统一采购) -->
|
|
||||||
<el-row :gutter="16" v-if="showPurchaseDetailBlocks && dataForm.budget != null && dataForm.budget >= BUDGET_DEPT_SELF_MEETING_MINUTES">
|
<!-- 分支一:部门自行采购(三列紧凑,textarea 单独一行) -->
|
||||||
|
<div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && isDeptPurchase">
|
||||||
|
<div class="step-title mb12">部门自行采购</div>
|
||||||
|
<!-- 部门采购会议纪要(预算超过2000元必须上传) -->
|
||||||
|
<el-row :gutter="16" v-if="dataForm.budget != null && dataForm.budget >= BUDGET_DEPT_SELF_MEETING_MINUTES">
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
<el-form-item label="部门采购会议纪要" prop="deptSelfMeetingMinutes" required>
|
<el-form-item label="部门采购会议纪要" prop="deptSelfMeetingMinutes" required>
|
||||||
<upload-file
|
<upload-file
|
||||||
@@ -153,9 +161,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 分支一:部门自行采购(三列紧凑,textarea 单独一行) -->
|
|
||||||
<div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && isDeptPurchase">
|
|
||||||
<div class="step-title mb12">部门自行采购</div>
|
|
||||||
<el-col :span="24" class="mb12">
|
<el-col :span="24" class="mb12">
|
||||||
<el-form-item label="采购内容" prop="projectContent">
|
<el-form-item label="采购内容" prop="projectContent">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -194,7 +199,7 @@
|
|||||||
:disabled="isPurchaseTypeDisabled"
|
:disabled="isPurchaseTypeDisabled"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in purchaseTypeDeptOptions" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in purchaseTypeDeptOptions" :key="item.value" :label="item.label" :value="item.value" :disabled="item.disabled" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -373,6 +378,21 @@
|
|||||||
<!-- 分支二:学校统一采购(三列紧凑) -->
|
<!-- 分支二:学校统一采购(三列紧凑) -->
|
||||||
<div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && !isDeptPurchase">
|
<div class="mb20 form-section-compact" v-if="showPurchaseDetailBlocks && !isDeptPurchase">
|
||||||
<div class="step-title mb12">学校统一采购</div>
|
<div class="step-title mb12">学校统一采购</div>
|
||||||
|
<!-- 部门采购会议纪要(预算超过2000元必须上传) -->
|
||||||
|
<el-row :gutter="16" v-if="dataForm.budget != null && dataForm.budget >= BUDGET_DEPT_SELF_MEETING_MINUTES">
|
||||||
|
<el-col :span="8" class="mb12">
|
||||||
|
<el-form-item label="部门采购会议纪要" prop="deptSelfMeetingMinutes" required>
|
||||||
|
<upload-file
|
||||||
|
v-model="dataForm.deptSelfMeetingMinutes"
|
||||||
|
:limit="1"
|
||||||
|
:file-type="['pdf', 'jpg', 'jpeg', 'png']"
|
||||||
|
:data="{ fileType: FILE_TYPE_MAP.deptSelfMeetingMinutes }"
|
||||||
|
upload-file-url="/purchase/purchasingfiles/upload"
|
||||||
|
:disabled="flowFieldDisabled('deptSelfMeetingMinutes')"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="8" class="mb12">
|
<el-col :span="8" class="mb12">
|
||||||
<el-form-item label="组织采购形式" prop="purchaseSchool" :required="isPurchaseSchoolRequired">
|
<el-form-item label="组织采购形式" prop="purchaseSchool" :required="isPurchaseSchoolRequired">
|
||||||
@@ -842,12 +862,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<el-button v-if="!isFlowEmbed" @click="handleCancel">取消</el-button>
|
<el-button v-if="!isFlowEmbed" @click="handleCancel">取消</el-button>
|
||||||
<el-button v-if="!isFlowEmbed && !flowSubmitDisabled" type="warning" @click="handleTempStore" :disabled="loading"> 暂存 </el-button>
|
<el-button v-if="!isFlowEmbed && !flowSubmitDisabled" type="warning" @click="handleTempStore" :disabled="loading"> 暂存 </el-button>
|
||||||
<!-- <el-button -->
|
<el-button v-if="!isFlowEmbed" type="primary" @click="handleSubmitFlow" :disabled="loading"> 提交 </el-button>
|
||||||
<!-- type="primary" -->
|
|
||||||
<!-- @click="handleSubmit" -->
|
|
||||||
<!-- :disabled="loading">-->
|
|
||||||
<!-- {{ isEditMode ? '保存' : '提交' }}-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -859,10 +874,10 @@
|
|||||||
<script setup lang="ts" name="PurchasingRequisitionAdd">
|
<script setup lang="ts" name="PurchasingRequisitionAdd">
|
||||||
import { reactive, ref, onMounted, computed, watch, nextTick } from 'vue';
|
import { reactive, ref, onMounted, computed, watch, nextTick } from 'vue';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import { addObj, tempStore, getObj, editObj, getApplyFiles } from '/@/api/purchase/purchasingrequisition';
|
import { addObj, tempStore, getObj, editObj, getApplyFiles, submitObj } from '/@/api/purchase/purchasingrequisition';
|
||||||
import { getTree } from '/@/api/purchase/purchasingcategory';
|
import { getTree } from '/@/api/purchase/purchasingcategory';
|
||||||
import { getDicts } from '/@/api/admin/dict';
|
import { getDicts } from '/@/api/admin/dict';
|
||||||
import { useMessage } from '/@/hooks/message';
|
import { useMessage, useMessageBox } from '/@/hooks/message';
|
||||||
import { useUserInfo } from '/@/stores/userInfo';
|
import { useUserInfo } from '/@/stores/userInfo';
|
||||||
import { usePurchaseRulesSingleton } from '/@/hooks/usePurchaseRules';
|
import { usePurchaseRulesSingleton } from '/@/hooks/usePurchaseRules';
|
||||||
import UploadFile from '/@/components/Upload/index.vue';
|
import UploadFile from '/@/components/Upload/index.vue';
|
||||||
@@ -1101,7 +1116,7 @@ const DEPT_PURCHASE_TYPE = {
|
|||||||
BUSINESS_NEGOTIATION: '3',
|
BUSINESS_NEGOTIATION: '3',
|
||||||
ENTRUST_CENTER: '4',
|
ENTRUST_CENTER: '4',
|
||||||
INQUIRY: '5',
|
INQUIRY: '5',
|
||||||
/** 公开招标(部门自行采购下委托采购中心采购时可选择) */
|
DIRECT_PURCHASE: '6',
|
||||||
OPEN_TENDERING: '100',
|
OPEN_TENDERING: '100',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -1441,6 +1456,16 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => dataForm.budget,
|
||||||
|
(budget) => {
|
||||||
|
const budgetNum = Number(budget) || 0;
|
||||||
|
if (budgetNum >= 2000 && dataForm.purchaseType === DEPT_PURCHASE_TYPE.DIRECT_PURCHASE) {
|
||||||
|
dataForm.purchaseType = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// 判断是否自动选择网上商城采购方式(5万<=金额<30万,服务类目,特殊服务类目)
|
// 判断是否自动选择网上商城采购方式(5万<=金额<30万,服务类目,特殊服务类目)
|
||||||
const isAutoSelectPurchaseType = computed(() => {
|
const isAutoSelectPurchaseType = computed(() => {
|
||||||
if (!dataForm.budget) return false;
|
if (!dataForm.budget) return false;
|
||||||
@@ -2183,12 +2208,16 @@ const getPurchaseTypeDeptDelegationDict = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 部门采购方式下拉选项:根据采购途径动态切换字典 */
|
/** 部门采购方式下拉选项:根据采购途径动态切换字典,直接采购仅预算<2000时可选 */
|
||||||
const purchaseTypeDeptOptions = computed(() => {
|
const purchaseTypeDeptOptions = computed(() => {
|
||||||
if (isEntrustCenterChannel.value) {
|
if (isEntrustCenterChannel.value) {
|
||||||
return purchaseTypeDeptDelegationList.value;
|
return purchaseTypeDeptDelegationList.value;
|
||||||
}
|
}
|
||||||
return purchaseTypeDeptList.value;
|
const budget = Number(dataForm.budget) || 0;
|
||||||
|
return purchaseTypeDeptList.value.map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
disabled: item.value === DEPT_PURCHASE_TYPE.DIRECT_PURCHASE && budget >= 2000,
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取学校采购形式字典
|
// 获取学校采购形式字典
|
||||||
@@ -2519,9 +2548,7 @@ const handleSubmit = async () => {
|
|||||||
router.push('/purchase/purchasingrequisition');
|
router.push('/purchase/purchasingrequisition');
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// 全局拦截器已经显示了错误提示,这里不需要再次显示
|
if (!err?._messageShown && !err?.msg) {
|
||||||
// 只有当错误没有 msg 时才显示默认错误提示
|
|
||||||
if (!err?.msg) {
|
|
||||||
useMessage().error('提交失败');
|
useMessage().error('提交失败');
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -2529,17 +2556,14 @@ const handleSubmit = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 暂存
|
// 暂存(跳过表单校验,允许部分填写)
|
||||||
const handleTempStore = async () => {
|
const handleTempStore = async () => {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const valid = await formRef.value?.validate().catch(() => {});
|
// 暂存模式不进行表单校验,允许用户部分填写后保存
|
||||||
if (!valid) {
|
// 提交时才会执行完整的校验规则
|
||||||
loading.value = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitData: any = {
|
const submitData: any = {
|
||||||
...dataForm,
|
...dataForm,
|
||||||
@@ -2611,7 +2635,7 @@ const handleTempStore = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (!err?.msg) {
|
if (!err?._messageShown && !err?.msg) {
|
||||||
useMessage().error('暂存失败');
|
useMessage().error('暂存失败');
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -2619,6 +2643,101 @@ const handleTempStore = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 提交(暂存后启动流程)
|
||||||
|
const handleSubmitFlow = async () => {
|
||||||
|
if (loading.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要提交该采购申请并启动流程吗?');
|
||||||
|
} catch {
|
||||||
|
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 = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理所有文件字段
|
||||||
|
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]) {
|
||||||
|
const ids = getFileIdsArray(submitData[field]);
|
||||||
|
allFileIds.push(...ids);
|
||||||
|
delete submitData[field];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allFileIds.length > 0) {
|
||||||
|
submitData.fileIds = allFileIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先暂存
|
||||||
|
const tempResult = await tempStore(submitData);
|
||||||
|
const applyId = tempResult?.data?.id || submitData.id || dataForm.id;
|
||||||
|
|
||||||
|
// 再提交
|
||||||
|
await submitObj({ id: applyId });
|
||||||
|
useMessage().success('提交成功');
|
||||||
|
|
||||||
|
if (window.parent !== window) {
|
||||||
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
|
type: 'purchasingrequisition:submitSuccess',
|
||||||
|
},
|
||||||
|
'*'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
router.push('/purchase/purchasingrequisition');
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
if (!err?._messageShown && !err?.msg) {
|
||||||
|
useMessage().error('提交失败');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 设置品目编码回显路径
|
// 设置品目编码回显路径
|
||||||
const setCategoryCodePath = () => {
|
const setCategoryCodePath = () => {
|
||||||
if (dataForm.categoryCode && categoryTreeData.value.length > 0) {
|
if (dataForm.categoryCode && categoryTreeData.value.length > 0) {
|
||||||
|
|||||||
@@ -206,7 +206,7 @@
|
|||||||
>委
|
>委
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
v-if="scope.row.purchaseMode === '1' && scope.row.purchaseChannel === '1'"
|
v-if="scope.row.status === '1' && scope.row.purchaseMode === '1' && scope.row.purchaseChannel === '1' && scope.row.purchaseType !=='6'"
|
||||||
:content="getSupplementTooltip(scope.row)"
|
:content="getSupplementTooltip(scope.row)"
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user