采购更新

This commit is contained in:
吴红兵
2026-03-11 22:14:38 +08:00
parent 4fe8453fdf
commit ad78c6c70d
4 changed files with 208 additions and 122 deletions

View File

@@ -75,7 +75,7 @@
<el-divider content-position="left">审核流程</el-divider> <el-divider content-position="left">审核流程</el-divider>
<flow-comment-timeline v-if="flowInstId" :flow-inst-id="flowInstId" /> <FlowCommentTimeline v-if="flowInstId" :curr-job="{ flowInstId }" />
</template> </template>
<template #footer> <template #footer>
@@ -91,11 +91,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref, defineAsyncComponent } from 'vue';
import { useMessage } from '/@/hooks/message'; import { useMessage } from '/@/hooks/message';
import { getDetail } from '/@/api/purchase/purchasingcontract'; import { getDetail } from '/@/api/purchase/purchasingcontract';
import { previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition'; import { previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition';
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
interface FileItem { interface FileItem {
id: string; id: string;
name: string; name: string;

View File

@@ -16,7 +16,7 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12" class="mb12"> <el-col :span="12" class="mb12">
<el-form-item label="合同编号" prop="contractNo"> <el-form-item label="合同编号" prop="contractNo">
<el-input v-model="formData.contractNo" placeholder="请输入合同编号" /> <el-input v-model="formData.contractNo" placeholder="请输入合同编号" disabled />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" class="mb12"> <el-col :span="12" class="mb12">
@@ -178,12 +178,17 @@ const open = async (id: string, openMode: 'add' | 'edit' | 'view' = 'add') => {
const res = await getObj(id); const res = await getObj(id);
applyData.value = res?.data || {}; applyData.value = res?.data || {};
// 新增时,合同编号默认为采购编号
if (mode.value === 'add') {
formData.value.contractNo = applyData.value.purchaseNo || '';
}
const contractRes = await getByPurchaseId(id); const contractRes = await getByPurchaseId(id);
const contractData = contractRes?.data; const contractData = contractRes?.data;
if (contractData) { if (contractData) {
formData.value = { formData.value = {
purchaseId: id, purchaseId: id,
contractNo: contractData.contractNo || '', contractNo: contractData.contractNo || applyData.value.purchaseNo || '',
contractName: contractData.contractName || '', contractName: contractData.contractName || '',
money: contractData.money, money: contractData.money,
isBidding: contractData.isBidding || '0', isBidding: contractData.isBidding || '0',

View File

@@ -33,24 +33,24 @@
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="160px" :disabled="isViewMode"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="160px" :disabled="isViewMode">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="合同编号" prop="contractNo"> <el-form-item label="合同编号" prop="contractNo">
<el-input v-model="formData.contractNo" placeholder="请输入合同编号" /> <el-input v-model="formData.contractNo" placeholder="请输入合同编号" disabled />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="合同名称" prop="contractName"> <el-form-item label="合同名称" prop="contractName">
<el-input v-model="formData.contractName" placeholder="请输入合同名称" /> <el-input v-model="formData.contractName" placeholder="请输入合同名称" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="合同金额(元)" prop="money"> <el-form-item label="合同金额(元)" prop="money">
<el-input-number v-model="formData.money" :precision="2" :min="0" :controls="false" style="width: 100%" /> <el-input-number v-model="formData.money" :precision="2" :min="0" :controls="false" style="width: 100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="是否需要招标" prop="isBidding"> <el-form-item label="是否需要招标" prop="isBidding">
<el-radio-group v-model="formData.isBidding"> <el-radio-group v-model="formData.isBidding">
<el-radio label="0"></el-radio> <el-radio label="0"></el-radio>
@@ -60,7 +60,7 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="是否需要法律顾问" prop="isLegalAdviser"> <el-form-item label="是否需要法律顾问" prop="isLegalAdviser">
<el-radio-group v-model="formData.isLegalAdviser"> <el-radio-group v-model="formData.isLegalAdviser">
<el-radio label="0"></el-radio> <el-radio label="0"></el-radio>
@@ -68,7 +68,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="是否涉及多个部门" prop="isDepts"> <el-form-item label="是否涉及多个部门" prop="isDepts">
<el-radio-group v-model="formData.isDepts"> <el-radio-group v-model="formData.isDepts">
<el-radio label="0"></el-radio> <el-radio label="0"></el-radio>
@@ -78,7 +78,7 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12" class="mb12">
<el-form-item label="是否全校合同" prop="isSchool"> <el-form-item label="是否全校合同" prop="isSchool">
<el-radio-group v-model="formData.isSchool"> <el-radio-group v-model="formData.isSchool">
<el-radio label="0"></el-radio> <el-radio label="0"></el-radio>
@@ -150,7 +150,7 @@ import { useRoute } from 'vue-router';
import { Document, Tickets, FolderOpened } from '@element-plus/icons-vue'; import { Document, Tickets, FolderOpened } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { getObj } from '/@/api/purchase/purchasingrequisition'; import { getObj } from '/@/api/purchase/purchasingrequisition';
import { getByPurchaseId, updateContract } from '/@/api/purchase/purchasingcontract'; import { getByPurchaseId, getByFlowInstId, updateContract } from '/@/api/purchase/purchasingcontract';
import { previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition'; import { previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition';
import { currElTabIsSave } from '/@/api/order/order-key-vue'; import { currElTabIsSave } from '/@/api/order/order-key-vue';
@@ -208,6 +208,13 @@ const previewVisible = ref(false);
const previewTitle = ref(''); const previewTitle = ref('');
const previewUrl = ref(''); const previewUrl = ref('');
const effectiveFlowInstId = computed(() => {
if (props.currJob?.flowInstId) {
return props.currJob.flowInstId;
}
return route.query.flowInstId ? Number(route.query.flowInstId) : null;
});
const effectivePurchaseId = computed(() => { const effectivePurchaseId = computed(() => {
if (props.currJob?.orderId) { if (props.currJob?.orderId) {
return String(props.currJob.orderId); return String(props.currJob.orderId);
@@ -232,41 +239,76 @@ const loadApplyData = async () => {
}; };
const loadContractData = async () => { const loadContractData = async () => {
if (!effectivePurchaseId.value) return; let contractData: any = null;
let purchaseId = effectivePurchaseId.value;
// 优先使用 flowInstId 获取合同数据(审核流程嵌入时)
if (effectiveFlowInstId.value) {
try { try {
fileLoading.value = true; fileLoading.value = true;
const res = await getByPurchaseId(effectivePurchaseId.value); const res = await getByFlowInstId(effectiveFlowInstId.value);
if (res.code === 0 && res.data) { if (res.code === 0 && res.data) {
const data = res.data; contractData = res.data;
formData.value = { purchaseId = res.data.purchaseId || purchaseId;
purchaseId: effectivePurchaseId.value,
contractNo: data.contractNo || '',
contractName: data.contractName || '',
money: data.money,
isBidding: data.isBidding || '0',
isLegalAdviser: data.isLegalAdviser || '0',
legalAdviserOpinion: data.legalAdviserOpinion || '',
isDepts: data.isDepts || '0',
isSchool: data.isSchool || '0',
remarks: data.remarks || '',
contractFileIds: [],
supplementFileIds: [],
};
(formData.value as any).flowStatus = data.flowStatus;
if (data.contractFiles && data.contractFiles.length > 0) {
contractFiles.value = data.contractFiles;
}
if (data.supplementFiles && data.supplementFiles.length > 0) {
supplementFiles.value = data.supplementFiles;
}
} }
} catch (e: any) { } catch (e: any) {
ElMessage.error(e?.msg || '加载合同信息失败'); ElMessage.error(e?.msg || '加载合同信息失败');
} finally { } finally {
fileLoading.value = false; fileLoading.value = false;
} }
}
// 如果通过 flowInstId 没有获取到数据,则使用 purchaseId 获取
if (!contractData && purchaseId) {
try {
fileLoading.value = true;
const res = await getByPurchaseId(purchaseId);
if (res.code === 0 && res.data) {
contractData = res.data;
}
} catch (e: any) {
ElMessage.error(e?.msg || '加载合同信息失败');
} finally {
fileLoading.value = false;
}
}
if (contractData) {
formData.value = {
purchaseId: purchaseId,
contractNo: contractData.contractNo || '',
contractName: contractData.contractName || '',
money: contractData.money,
isBidding: contractData.isBidding || '0',
isLegalAdviser: contractData.isLegalAdviser || '0',
legalAdviserOpinion: contractData.legalAdviserOpinion || '',
isDepts: contractData.isDepts || '0',
isSchool: contractData.isSchool || '0',
remarks: contractData.remarks || '',
contractFileIds: [],
supplementFileIds: [],
};
(formData.value as any).flowStatus = contractData.flowStatus;
if (contractData.contractFiles && contractData.contractFiles.length > 0) {
contractFiles.value = contractData.contractFiles;
}
if (contractData.supplementFiles && contractData.supplementFiles.length > 0) {
supplementFiles.value = contractData.supplementFiles;
}
// 如果有 purchaseId加载采购申请信息
if (purchaseId && !applyData.value.id) {
try {
const applyRes = await getObj(purchaseId);
if (applyRes.code === 0 && applyRes.data) {
applyData.value = applyRes.data;
}
} catch (e) {
console.error('加载采购申请信息失败', e);
}
}
}
}; };
const handlePreview = async (row: any) => { const handlePreview = async (row: any) => {
@@ -313,7 +355,7 @@ const handleFlowSave = async () => {
await updateContract({ await updateContract({
...formData.value, ...formData.value,
purchaseId: effectivePurchaseId.value, purchaseId: formData.value.purchaseId || effectivePurchaseId.value,
contractFileIds, contractFileIds,
supplementFileIds, supplementFileIds,
}); });

View File

@@ -39,6 +39,14 @@
<el-option label="是" value="1" /> <el-option label="是" value="1" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="是否特殊" prop="isSpecial">
<el-select v-model="state.queryForm.isSpecial" placeholder="请选择是否特殊" clearable style="width: 200px">
<el-option label="否" value="0" />
<el-option label="紧急" value="1" />
<el-option label="单一" value="2" />
<el-option label="进口" value="3" />
</el-select>
</el-form-item>
<el-form-item label="采购形式" prop="purchaseMode"> <el-form-item label="采购形式" prop="purchaseMode">
<el-select <el-select
v-model="state.queryForm.purchaseMode" v-model="state.queryForm.purchaseMode"
@@ -51,13 +59,25 @@
<el-option label="学校统一采购" value="2" /> <el-option label="学校统一采购" value="2" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="采购方式" prop="purchaseType"> <el-form-item v-if="state.queryForm.purchaseMode === '1'" label="采购途径" prop="purchaseChannel">
<el-select
v-model="state.queryForm.purchaseChannel"
placeholder="请选择采购途径"
clearable
style="width: 200px"
@change="handlePurchaseChannelChange"
>
<el-option label="自行采购" value="1" />
<el-option label="委托采购中心采购" value="2" />
</el-select>
</el-form-item>
<el-form-item v-if="showPurchaseTypeSelect" label="采购方式" prop="purchaseType">
<el-select v-model="state.queryForm.purchaseType" placeholder="请选择采购方式" clearable style="width: 200px"> <el-select v-model="state.queryForm.purchaseType" placeholder="请选择采购方式" clearable style="width: 200px">
<el-option v-for="item in purchaseTypeSearchOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in purchaseTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="需求部门" prop="deptId"> <el-form-item label="需求部门" prop="deptId">
<el-select v-model="state.queryForm.deptId" placeholder="请选择需求部门" clearable filterable style="width: 200px"> <el-select v-model="state.queryForm.deptCode" placeholder="请选择需求部门" clearable filterable style="width: 200px">
<el-option v-for="item in secondDeptList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in secondDeptList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -345,7 +365,14 @@
<template v-if="scope.row.status === '1'"> <template v-if="scope.row.status === '1'">
<el-tooltip v-if="scope.row.contractFlowStatus" content="点击查看合同详情" placement="top"> <el-tooltip v-if="scope.row.contractFlowStatus" content="点击查看合同详情" placement="top">
<el-tag <el-tag
v-if="scope.row.contractFlowStatus === '0'" v-if="scope.row.contractFlowStatus === '-1'"
type="info"
class="status-tag-clickable"
@click="handleEditContract(scope.row)"
>已上传
</el-tag>
<el-tag
v-else-if="scope.row.contractFlowStatus === '0'"
type="warning" type="warning"
class="status-tag-clickable" class="status-tag-clickable"
@click="handleShowContractDetail(scope.row)" @click="handleShowContractDetail(scope.row)"
@@ -365,9 +392,6 @@
@click="handleShowContractDetail(scope.row)" @click="handleShowContractDetail(scope.row)"
>已作废 >已作废
</el-tag> </el-tag>
<el-tag v-else type="info" class="status-tag-clickable" @click="handleShowContractDetail(scope.row)">{{
scope.row.contractFlowStatus
}}</el-tag>
</el-tooltip> </el-tooltip>
<el-button v-else type="primary" link size="small" @click="handleAddContract(scope.row)">添加合同</el-button> <el-button v-else type="primary" link size="small" @click="handleAddContract(scope.row)">添加合同</el-button>
</template> </template>
@@ -593,45 +617,46 @@ const dictData = ref({
const purchaseTypeDeptDelegationList = ref<any[]>([]); // 委托采购中心采购方式字典 const purchaseTypeDeptDelegationList = ref<any[]>([]); // 委托采购中心采购方式字典
const secondDeptList = ref<any[]>([]); // 二级部门列表 const secondDeptList = ref<any[]>([]); // 二级部门列表
// 采购方式搜索选项(根据采购形式动态变化) // 是否显示采购方式选择框
const purchaseTypeSearchOptions = computed(() => { const showPurchaseTypeSelect = computed(() => {
const mode = state.queryForm.purchaseMode;
if (mode === '2') {
// 学校统一采购:显示采购方式
return true;
} else if (mode === '1') {
// 部门自行采购:需要先选择采购途径
return !!state.queryForm.purchaseChannel;
}
return false;
});
// 采购方式选项(根据采购形式和采购途径动态变化)
const purchaseTypeOptions = computed(() => {
const mode = state.queryForm.purchaseMode; const mode = state.queryForm.purchaseMode;
if (mode === '2') { if (mode === '2') {
// 学校统一采购:使用 UNION_PURCHASE_TYPE 字典 // 学校统一采购:使用 UNION_PURCHASE_TYPE 字典
return dictData.value.purchaseTypeUnionList; return dictData.value.purchaseTypeUnionList;
} else if (mode === '1') { } else if (mode === '1') {
// 部门自行采购合并DEPT_PURCHASE_TYPE和PURCHASE_TYPE_DEPT_DELEGATION const channel = state.queryForm.purchaseChannel;
return [...dictData.value.purchaseTypeDeptList, ...purchaseTypeDeptDelegationList.value]; if (channel === '1') {
// 自行采购:使用 DEPT_PURCHASE_TYPE 字典
return dictData.value.purchaseTypeDeptList;
} else if (channel === '2') {
// 委托采购中心采购:使用 PURCHASE_TYPE_DEPT_DELEGATION 字典
return purchaseTypeDeptDelegationList.value;
} }
// 未选择采购形式时,显示所有选项 }
return [...dictData.value.purchaseTypeDeptList, ...purchaseTypeDeptDelegationList.value, ...dictData.value.purchaseTypeUnionList]; return [];
}); });
// 采购形式变化时清空采购方式 // 采购形式变化时清空采购途径和采购方式
const handlePurchaseModeChange = () => { const handlePurchaseModeChange = () => {
state.queryForm.purchaseChannel = '';
state.queryForm.purchaseType = ''; state.queryForm.purchaseType = '';
}; };
// 搜索条件相关数据 // 采购途径变化时清空采购方式
const purchaseTypeDeptDelegationList = ref<any[]>([]); // 委托采购中心采购方式字典 const handlePurchaseChannelChange = () => {
const secondDeptList = ref<any[]>([]); // 二级部门列表
// 采购方式搜索选项(根据采购形式动态变化)
const purchaseTypeSearchOptions = computed(() => {
const mode = state.queryForm.purchaseMode;
if (mode === '2') {
// 学校统一采购使用UNION_PURCHASE_TYPE字典
return dictData.value.purchaseTypeUnionList;
} else if (mode === '1') {
// 部门自行采购合并DEPT_PURCHASE_TYPE和PURCHASE_TYPE_DEPT_DELEGATION
return [...dictData.value.purchaseTypeDeptList, ...purchaseTypeDeptDelegationList.value];
}
// 未选择采购形式时,显示所有选项
return [...dictData.value.purchaseTypeDeptList, ...purchaseTypeDeptDelegationList.value, ...dictData.value.purchaseTypeUnionList];
});
// 采购形式变化时清空采购方式
const handlePurchaseModeChange = () => {
state.queryForm.purchaseType = ''; state.queryForm.purchaseType = '';
}; };
@@ -726,9 +751,11 @@ const state: BasicTableProps = reactive<BasicTableProps>({
projectType: '', projectType: '',
status: '', status: '',
isCentralized: '', isCentralized: '',
isSpecial: '',
purchaseMode: '', purchaseMode: '',
purchaseChannel: '',
purchaseType: '', purchaseType: '',
deptId: '', deptCode: '',
}, },
createdIsNeed: true, createdIsNeed: true,
}); });
@@ -837,6 +864,16 @@ const handleAddContract = (row: any) => {
purchaseContractDialogRef.value?.open(String(id), 'add'); purchaseContractDialogRef.value?.open(String(id), 'add');
}; };
/** 点击已上传合同:打开采购合同编辑弹窗 */
const handleEditContract = (row: any) => {
const id = row?.id ?? row?.purchaseId;
if (!id) {
useMessage().warning('无法获取采购申请ID');
return;
}
purchaseContractDialogRef.value?.open(String(id), 'edit');
};
/** 点击采购合同状态:打开采购合同详情弹窗 */ /** 点击采购合同状态:打开采购合同详情弹窗 */
const handleShowContractDetail = (row: any) => { const handleShowContractDetail = (row: any) => {
const id = row?.id ?? row?.purchaseId; const id = row?.id ?? row?.purchaseId;