feat: 采购模块8项功能优化

1. 履约评价按钮:仅在审核状态完成时显示
2. 流程审批:申请人可编辑表单
3. 部门代表弹窗:增加身份选择(采购代表/评委)
4. 履约验收上传:改为仅支持PDF格式
5. 采购申请列表:增加采购形式字段显示(el-tag)
6. 采购申请提交:防止重复点击(已存在loading)
This commit is contained in:
吴红兵
2026-03-04 20:19:03 +08:00
parent e3437921e5
commit 69439fdfab
4 changed files with 45 additions and 10 deletions

View File

@@ -252,12 +252,13 @@ export function searchTeachers(keyword: string) {
* @param id 采购申请ID
* @param representorTeacherNo 指定采购代表人单人用户ID或工号
* @param representors 部门多人由系统抽取多人用户ID或工号逗号分隔
* @param identity 身份purchase_rep-采购代表judge-评委
*/
export function saveRepresentor(id: number, representorTeacherNo?: string, representors?: string) {
export function saveRepresentor(id: number, representorTeacherNo?: string, representors?: string, identity?: string) {
return request({
url: '/purchase/purchasingapply/saveRepresentor',
url: '/purchase/purchasingapply/save-representor',
method: 'post',
data: { id, representorTeacherNo, representors }
data: { id, representorTeacherNo, representors, representorType: identity }
});
}

View File

@@ -18,7 +18,7 @@
<!-- 上传履约验收模版 -->
<el-col :span="12" class="mb20">
<el-form-item label="履约验收文件" prop="templateFileIds">
<upload-file v-model="templateFiles" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ purchaseId: purchaseId || '', fileType: '110' }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="readonly" />
<upload-file v-model="templateFiles" :limit="1" :file-type="['pdf']" :data="{ purchaseId: purchaseId || '', fileType: '110' }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="readonly" />
<el-link v-if="!readonly" type="primary" :href="lyysTemplateUrl" :download="lyysTemplateDownloadName" target="_blank" style="margin-top: 8px; display: inline-flex; align-items: center;">
<el-icon><Download /></el-icon>
<span style="margin-left: 4px;">下载{{ lyysTemplateLabel }}</span>

View File

@@ -1035,9 +1035,17 @@ 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(() => {
if (!dataForm.createUser) return false;
const currentUser = Session.getUser() || {};
return dataForm.createUser === currentUser.userId || dataForm.createUser === currentUser.username;
});
// 定义变量内容
const formRef = ref();
const dataForm = reactive({
@@ -1888,12 +1896,16 @@ const flowMethods = {
},
};
/** 流程嵌入时采购申请权限根据前端缓存的角色cloud-ui:roleCode判断非采购中心整表只读采购中心仅采购方式/采购形式可编辑 */
/** 流程嵌入时采购申请权限根据前端缓存的角色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并通知流程已保存 */

View File

@@ -185,6 +185,22 @@
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="purchaseType" label="采购形式" width="120" align="center">
<template #header>
<el-icon><Shop /></el-icon>
<span style="margin-left: 4px">采购形式</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.purchaseType === '1'" type="success">网上商城</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '2'" type="warning">市场采购</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '3'" type="danger">商务洽谈</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '4'" type="primary">委托采购</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '5'" type="info">询价</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '100'" type="success">公开招标</el-tag>
<el-tag v-else-if="scope.row.purchaseType === '8'" type="success">网上商城</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="status" label="审核状态" width="100" align="center">
<template #header>
<el-icon><InfoFilled /></el-icon>
@@ -309,6 +325,12 @@
destroy-on-close
>
<el-form label-width="100px">
<el-form-item label="身份">
<el-radio-group v-model="representorForm.identity">
<el-radio label="purchase_rep">采购代表</el-radio>
<el-radio label="judge">评委</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="选择方式">
<el-radio-group v-model="representorForm.mode">
<el-radio label="single">指定采购代表人</el-radio>
@@ -356,7 +378,7 @@ import { useMessage, useMessageBox } from "/@/hooks/message";
import { useAuth } from '/@/hooks/auth';
import { getDicts } from '/@/api/admin/dict';
import { getTree } from '/@/api/purchase/purchasingcategory';
import { List, Document, DocumentCopy, Search, Money, CircleCheck, InfoFilled, Calendar, OfficeBuilding, Warning, DocumentChecked, Edit, Delete, Upload, FolderOpened, Download, User, RefreshRight } from '@element-plus/icons-vue'
import { List, Document, DocumentCopy, Search, Money, CircleCheck, InfoFilled, Calendar, OfficeBuilding, Warning, DocumentChecked, Edit, Delete, Upload, FolderOpened, Download, User, RefreshRight, Shop } from '@element-plus/icons-vue'
import other from '/@/utils/other'
import { Session } from '/@/utils/storage'
@@ -407,7 +429,7 @@ const updateFilesDialogRef = ref()
/** 采购代表弹窗 */
const representorDialogVisible = ref(false)
const representorCurrentRow = ref<any>(null)
const representorForm = reactive({ mode: 'single' as 'single' | 'multi', teacherNo: '', multiIds: [] as string[] })
const representorForm = reactive({ mode: 'single' as 'single' | 'multi', teacherNo: '', multiIds: [] as string[], identity: 'purchase_rep' as 'purchase_rep' | 'judge' })
const representorDeptMembers = ref<any[]>([])
const representorSubmitting = ref(false)
@@ -444,7 +466,7 @@ const handleSaveRepresentor = async () => {
try {
const teacherNo = representorForm.mode === 'single' ? representorForm.teacherNo : undefined
const multiIds = representorForm.mode === 'multi' ? representorForm.multiIds.join(',') : undefined
await saveRepresentor(Number(id), teacherNo, multiIds)
await saveRepresentor(Number(id), teacherNo, multiIds, representorForm.identity)
useMessage().success('保存采购代表成功')
representorDialogVisible.value = false
getDataList()
@@ -615,7 +637,7 @@ const getActionMenuItems = (row: any) => {
command: 'accept',
label: '履约验收',
icon: DocumentChecked,
visible: () => hasAuth('purchase_accept'),
visible: () => isCompleted && hasAuth('purchase_accept'),
},
{
command: 'implement',