feat: 采购模块8项功能优化
1. 履约评价按钮:仅在审核状态完成时显示 2. 流程审批:申请人可编辑表单 3. 部门代表弹窗:增加身份选择(采购代表/评委) 4. 履约验收上传:改为仅支持PDF格式 5. 采购申请列表:增加采购形式字段显示(el-tag) 6. 采购申请提交:防止重复点击(已存在loading)
This commit is contained in:
@@ -252,12 +252,13 @@ export function searchTeachers(keyword: string) {
|
|||||||
* @param id 采购申请ID
|
* @param id 采购申请ID
|
||||||
* @param representorTeacherNo 指定采购代表人(单人,用户ID或工号)
|
* @param representorTeacherNo 指定采购代表人(单人,用户ID或工号)
|
||||||
* @param representors 部门多人由系统抽取(多人,用户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({
|
return request({
|
||||||
url: '/purchase/purchasingapply/saveRepresentor',
|
url: '/purchase/purchasingapply/save-representor',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { id, representorTeacherNo, representors }
|
data: { id, representorTeacherNo, representors, representorType: identity }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<!-- 上传履约验收模版 -->
|
<!-- 上传履约验收模版 -->
|
||||||
<el-col :span="12" class="mb20">
|
<el-col :span="12" class="mb20">
|
||||||
<el-form-item label="履约验收文件" prop="templateFileIds">
|
<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-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>
|
<el-icon><Download /></el-icon>
|
||||||
<span style="margin-left: 4px;">下载{{ lyysTemplateLabel }}</span>
|
<span style="margin-left: 4px;">下载{{ lyysTemplateLabel }}</span>
|
||||||
|
|||||||
@@ -1035,9 +1035,17 @@ const isPurchaseCenter = ref(false);
|
|||||||
/** 流程嵌入时:采购中心审核节点放开所有字段编辑;非采购中心节点只读 */
|
/** 流程嵌入时:采购中心审核节点放开所有字段编辑;非采购中心节点只读 */
|
||||||
function flowFieldDisabled(_key: string) {
|
function flowFieldDisabled(_key: string) {
|
||||||
if (isFlowEmbed.value && isPurchaseCenter.value) return false;
|
if (isFlowEmbed.value && isPurchaseCenter.value) return false;
|
||||||
|
if (isFlowEmbed.value && isApplicant.value) return false;
|
||||||
return !!isFlowEmbed.value;
|
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 formRef = ref();
|
||||||
const dataForm = reactive({
|
const dataForm = reactive({
|
||||||
@@ -1888,12 +1896,16 @@ const flowMethods = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 流程嵌入时采购申请权限:根据前端缓存的角色(cloud-ui:roleCode)判断,非采购中心整表只读,采购中心仅采购方式/采购形式可编辑 */
|
/** 流程嵌入时采购申请权限:根据前端缓存的角色(cloud-ui:roleCode)判断,非采购中心整表只读,采购中心仅采购方式/采购形式可编辑;申请人在流程中可编辑 */
|
||||||
function applyPurchaseApplyFormPerm() {
|
function applyPurchaseApplyFormPerm() {
|
||||||
if (!isFlowEmbed.value) return;
|
if (!isFlowEmbed.value) return;
|
||||||
const roleCode = Session.getRoleCode() || '';
|
const roleCode = Session.getRoleCode() || '';
|
||||||
isPurchaseCenter.value = roleCode === PURCHASE_CENTER_ROLE_CODE;
|
isPurchaseCenter.value = roleCode === PURCHASE_CENTER_ROLE_CODE;
|
||||||
flowFormDisabled.value = !isPurchaseCenter.value;
|
if (isApplicant.value) {
|
||||||
|
flowFormDisabled.value = false;
|
||||||
|
} else {
|
||||||
|
flowFormDisabled.value = !isPurchaseCenter.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 流程嵌入时的“保存”回调:校验后调用 editObj,并通知流程已保存 */
|
/** 流程嵌入时的“保存”回调:校验后调用 editObj,并通知流程已保存 */
|
||||||
|
|||||||
@@ -185,6 +185,22 @@
|
|||||||
<span v-else>-</span>
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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">
|
<el-table-column prop="status" label="审核状态" width="100" align="center">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-icon><InfoFilled /></el-icon>
|
<el-icon><InfoFilled /></el-icon>
|
||||||
@@ -309,6 +325,12 @@
|
|||||||
destroy-on-close
|
destroy-on-close
|
||||||
>
|
>
|
||||||
<el-form label-width="100px">
|
<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-form-item label="选择方式">
|
||||||
<el-radio-group v-model="representorForm.mode">
|
<el-radio-group v-model="representorForm.mode">
|
||||||
<el-radio label="single">指定采购代表人</el-radio>
|
<el-radio label="single">指定采购代表人</el-radio>
|
||||||
@@ -356,7 +378,7 @@ import { useMessage, useMessageBox } from "/@/hooks/message";
|
|||||||
import { useAuth } from '/@/hooks/auth';
|
import { useAuth } from '/@/hooks/auth';
|
||||||
import { getDicts } from '/@/api/admin/dict';
|
import { getDicts } from '/@/api/admin/dict';
|
||||||
import { getTree } from '/@/api/purchase/purchasingcategory';
|
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 other from '/@/utils/other'
|
||||||
import { Session } from '/@/utils/storage'
|
import { Session } from '/@/utils/storage'
|
||||||
|
|
||||||
@@ -407,7 +429,7 @@ const updateFilesDialogRef = ref()
|
|||||||
/** 采购代表弹窗 */
|
/** 采购代表弹窗 */
|
||||||
const representorDialogVisible = ref(false)
|
const representorDialogVisible = ref(false)
|
||||||
const representorCurrentRow = ref<any>(null)
|
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 representorDeptMembers = ref<any[]>([])
|
||||||
const representorSubmitting = ref(false)
|
const representorSubmitting = ref(false)
|
||||||
|
|
||||||
@@ -444,7 +466,7 @@ const handleSaveRepresentor = async () => {
|
|||||||
try {
|
try {
|
||||||
const teacherNo = representorForm.mode === 'single' ? representorForm.teacherNo : undefined
|
const teacherNo = representorForm.mode === 'single' ? representorForm.teacherNo : undefined
|
||||||
const multiIds = representorForm.mode === 'multi' ? representorForm.multiIds.join(',') : 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('保存采购代表成功')
|
useMessage().success('保存采购代表成功')
|
||||||
representorDialogVisible.value = false
|
representorDialogVisible.value = false
|
||||||
getDataList()
|
getDataList()
|
||||||
@@ -615,7 +637,7 @@ const getActionMenuItems = (row: any) => {
|
|||||||
command: 'accept',
|
command: 'accept',
|
||||||
label: '履约验收',
|
label: '履约验收',
|
||||||
icon: DocumentChecked,
|
icon: DocumentChecked,
|
||||||
visible: () => hasAuth('purchase_accept'),
|
visible: () => isCompleted && hasAuth('purchase_accept'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command: 'implement',
|
command: 'implement',
|
||||||
|
|||||||
Reference in New Issue
Block a user