diff --git a/src/api/finance/purchasingrequisition.ts b/src/api/finance/purchasingrequisition.ts index 64c1ea1..84b49f4 100644 --- a/src/api/finance/purchasingrequisition.ts +++ b/src/api/finance/purchasingrequisition.ts @@ -188,6 +188,20 @@ export function getDeptMembers() { }); } +/** + * 保存采购代表(指定单人或部门多人) + * @param id 采购申请ID + * @param representorTeacherNo 指定采购代表人(单人,用户ID或工号) + * @param representors 部门多人由系统抽取(多人,用户ID或工号逗号分隔) + */ +export function saveRepresentor(id: number, representorTeacherNo?: string, representors?: string) { + return request({ + url: '/purchase/purchasingapply/saveRepresentor', + method: 'post', + data: { id, representorTeacherNo, representors } + }); +} + /** * 文件归档:按文件类型打包下载该申请单下所有附件的下载地址(GET 请求,浏览器直接下载 zip) * @param purchaseId 采购申请ID diff --git a/src/components/Upload/index.vue b/src/components/Upload/index.vue index c778943..8b2f3e0 100644 --- a/src/components/Upload/index.vue +++ b/src/components/Upload/index.vue @@ -169,6 +169,7 @@ interface FileItem { url?: string; uid?: number; id?: string; // 文件ID + fileTitle?: string; // 文件标题(用于显示) } interface UploadFileItem { diff --git a/src/views/finance/purchasingrequisition/accept/AcceptBatchForm.vue b/src/views/finance/purchasingrequisition/accept/AcceptBatchForm.vue index e565a26..2a5487b 100644 --- a/src/views/finance/purchasingrequisition/accept/AcceptBatchForm.vue +++ b/src/views/finance/purchasingrequisition/accept/AcceptBatchForm.vue @@ -17,20 +17,12 @@ - -
- - - - 下载{{ lyysTemplateLabel }} - -
+ + + + + 下载{{ lyysTemplateLabel }} +
@@ -44,9 +36,10 @@ diff --git a/src/views/finance/purchasingrequisition/accept/PurchasingAcceptModal.vue b/src/views/finance/purchasingrequisition/accept/PurchasingAcceptModal.vue index b2b4784..f5baa16 100644 --- a/src/views/finance/purchasingrequisition/accept/PurchasingAcceptModal.vue +++ b/src/views/finance/purchasingrequisition/accept/PurchasingAcceptModal.vue @@ -59,7 +59,7 @@ v-show="String(b.batch) === activeTab" :key="b.id" :ref="(el) => setBatchFormRef(b.batch, el)" - v-model="batchForms[b.batch]" + :model-value="batchForms[b.batch]" :readonly="false" :purchase-id="String(purchaseId)" :project-type="acceptProjectType" @@ -221,11 +221,29 @@ const loadBatchDetails = async () => { // 仅当该期在服务端有验收日期时才视为已保存 const hasSaved = !!d.accept.acceptDate batchSavedFlags.value[b.batch] = hasSaved + // 优先使用 templateFiles(包含id和fileTitle),否则降级使用 templateFileIds + let fileIdsStr = '' + if (d.accept.templateFiles && d.accept.templateFiles.length > 0) { + // 使用 templateFiles,格式为 {id: string, fileTitle: string}[] + fileIdsStr = d.accept.templateFiles.map((f: any) => f.id).join(',') + } else if (d.accept.templateFileIds) { + // 降级使用 templateFileIds + const fileIds = d.accept.templateFileIds + fileIdsStr = Array.isArray(fileIds) ? fileIds.join(',') : (fileIds || '') + } batchForms[b.batch] = { acceptType: '2', // 固定为上传模式 acceptDate: d.accept.acceptDate || '', remark: d.accept.remark || '', - templateFileIds: d.accept.templateFileIds || [], + templateFileIds: fileIdsStr, + // 保存文件信息用于显示 + _templateFiles: d.accept.templateFiles || [], + } + // 通知子组件初始化数据 + await nextTick() + const batchFormRef = batchFormRefMap.value[b.batch] + if (batchFormRef?.initData) { + batchFormRef.initData() } } } catch (_) {} @@ -275,23 +293,39 @@ const saveCurrentBatch = async () => { const b = batches.value.find((x: any) => String(x.batch) === activeTab.value) if (!b?.id) return - const form = batchForms[curBatch] - if (!form) return - if (!form.acceptDate) { + // 从子组件获取表单数据 + const formData = batchFormRef?.getFormData?.() || batchFormRef?.form + if (!formData) return + + if (!formData.acceptDate) { useMessage().error('请选择验收日期') return } + // templateFileIds: 提取ID数组 + let fileIds: string[] = [] + if (formData.templateFileIds) { + if (Array.isArray(formData.templateFileIds)) { + fileIds = formData.templateFileIds.map((item: any) => { + if (typeof item === 'string') return item + if (item && item.id) return item.id + return null + }).filter(Boolean) + } else if (typeof formData.templateFileIds === 'string') { + fileIds = formData.templateFileIds.split(',').map((s: string) => s.trim()).filter(Boolean) + } + } + saving.value = true try { await updateBatch({ id: b.id, purchaseId: String(purchaseId.value), acceptType: '2', // 固定为上传模式 - acceptDate: form.acceptDate, - remark: form.remark, - templateFileIds: form.templateFileIds || [], + acceptDate: formData.acceptDate, + remark: formData.remark, + templateFileIds: fileIds, }) useMessage().success('保存成功') batchSavedFlags.value[curBatch] = true diff --git a/src/views/finance/purchasingrequisition/add.vue b/src/views/finance/purchasingrequisition/add.vue index 8cae6fc..5c73bae 100644 --- a/src/views/finance/purchasingrequisition/add.vue +++ b/src/views/finance/purchasingrequisition/add.vue @@ -211,10 +211,9 @@ {{ item.label }} - - + diff --git a/src/views/finance/purchasingrequisition/implement.vue b/src/views/finance/purchasingrequisition/implement.vue index 5741ffc..a0fdb2d 100644 --- a/src/views/finance/purchasingrequisition/implement.vue +++ b/src/views/finance/purchasingrequisition/implement.vue @@ -8,33 +8,37 @@ - - 采购文件版本 -
- - - - - - - - - - - - - -
-
可继续上传新版本(保留原文件,格式 doc/docx/pdf,单文件不超过 5MB):
- + + diff --git a/src/views/finance/purchasingrequisition/index.vue b/src/views/finance/purchasingrequisition/index.vue index d876537..4d4625f 100644 --- a/src/views/finance/purchasingrequisition/index.vue +++ b/src/views/finance/purchasingrequisition/index.vue @@ -292,63 +292,52 @@ - + + + + - - - - 指定 - 随机 + + + + 指定采购代表人 + 部门多人系统抽取 - + - + - - {{ assignAgentCurrentRow.agentName }} + + + + - - - @@ -356,14 +345,19 @@ import { ref, reactive, defineAsyncComponent, onMounted, computed } from 'vue' import { useRouter } from 'vue-router' import { BasicTableProps, useTable } from "/@/hooks/table"; -import { getPage, delObj, submitObj, getArchiveDownloadUrl, getApplyTemplateDownloadUrl, getFileApplyTemplateDownloadUrl, assignAgent } from "/@/api/finance/purchasingrequisition"; -import { getPage as getAgentPage } from '/@/api/finance/purchaseagent'; +import { getPage, delObj, submitObj, getArchiveDownloadUrl, getApplyTemplateDownloadUrl, getFileApplyTemplateDownloadUrl, getDeptMembers, saveRepresentor } from "/@/api/finance/purchasingrequisition"; import { useMessage, useMessageBox } from "/@/hooks/message"; import { useAuth } from '/@/hooks/auth'; import { getDicts } from '/@/api/admin/dict'; import { getTree } from '/@/api/finance/purchasingcategory'; -import { List, Document, DocumentCopy, Search, Collection, Money, CircleCheck, InfoFilled, Calendar, OfficeBuilding, Warning, DocumentChecked, Edit, Delete, Upload, FolderOpened, Download } from '@element-plus/icons-vue' +import { List, Document, DocumentCopy, Search, Money, CircleCheck, InfoFilled, Calendar, OfficeBuilding, Warning, DocumentChecked, Edit, Delete, Upload, FolderOpened, Download, User } from '@element-plus/icons-vue' import other from '/@/utils/other' +import { Session } from '/@/utils/storage' + +// 角色常量 +const PURCHASE_DEPT_AUDIT_ROLE_CODE = 'PURCHASE_DEPT_AUDIT' +const roleCode = computed(() => Session.getRoleCode() || '') +const isDeptAuditRole = computed(() => roleCode.value === PURCHASE_DEPT_AUDIT_ROLE_CODE) // 引入组件 const FormDialog = defineAsyncComponent(() => import('./form.vue')); @@ -400,72 +394,54 @@ const currFlowCommentType = ref<'apply' | 'file'>('apply') const implementFormRef = ref() -/** 分配代理弹窗 */ -const assignAgentDialogVisible = ref(false) -const assignAgentCurrentRow = ref(null) -const assignAgentForm = reactive({ mode: 'designated' as 'designated' | 'random', agentId: '' }) -const agentList = ref([]) -const agentListLoading = ref(false) -const assignAgentSubmitting = ref(false) +/** 采购代表弹窗 */ +const representorDialogVisible = ref(false) +const representorCurrentRow = ref(null) +const representorForm = reactive({ mode: 'single' as 'single' | 'multi', teacherNo: '', multiIds: [] as string[] }) +const representorDeptMembers = ref([]) +const representorSubmitting = ref(false) -const openAssignAgentDialog = async (row: any) => { - assignAgentCurrentRow.value = row - assignAgentForm.mode = 'designated' - assignAgentForm.agentId = '' - assignAgentDialogVisible.value = true - agentListLoading.value = true +const openRepresentorDialog = async (row: any) => { + representorCurrentRow.value = row + representorForm.mode = 'single' + representorForm.teacherNo = '' + representorForm.multiIds = [] + representorDialogVisible.value = true try { - const res = await getAgentPage({ size: 500, current: 1 }) - const records = res?.data?.records ?? res?.records ?? [] - agentList.value = Array.isArray(records) ? records : [] + const res = await getDeptMembers() + representorDeptMembers.value = res?.data || [] } catch (_) { - agentList.value = [] - } finally { - agentListLoading.value = false + representorDeptMembers.value = [] } } -const handleAssignAgentRandom = async () => { - const row = assignAgentCurrentRow.value +const handleSaveRepresentor = async () => { + const row = representorCurrentRow.value const id = row?.id ?? row?.purchaseId if (id == null || id === '') { useMessage().warning('无法获取申请单ID') return } - assignAgentSubmitting.value = true - try { - await assignAgent(Number(id), 'random') - useMessage().success('随机分配代理成功') - assignAgentDialogVisible.value = false - getDataList() - } catch (e: any) { - useMessage().error(e?.msg || '随机分配代理失败') - } finally { - assignAgentSubmitting.value = false - } -} - -const handleAssignAgentDesignated = async () => { - const row = assignAgentCurrentRow.value - const id = row?.id ?? row?.purchaseId - if (id == null || id === '') { - useMessage().warning('无法获取申请单ID') + if (representorForm.mode === 'single' && !representorForm.teacherNo) { + useMessage().warning('请选择采购代表人') return } - if (!assignAgentForm.agentId) { - useMessage().warning('请选择招标代理') + if (representorForm.mode === 'multi' && !representorForm.multiIds.length) { + useMessage().warning('请选择部门多人') return } - assignAgentSubmitting.value = true + representorSubmitting.value = true try { - await assignAgent(Number(id), 'designated', assignAgentForm.agentId) - useMessage().success('指定代理成功') - assignAgentDialogVisible.value = false + const teacherNo = representorForm.mode === 'single' ? representorForm.teacherNo : undefined + const multiIds = representorForm.mode === 'multi' ? representorForm.multiIds.join(',') : undefined + await saveRepresentor(Number(id), teacherNo, multiIds) + useMessage().success('保存采购代表成功') + representorDialogVisible.value = false getDataList() } catch (e: any) { - useMessage().error(e?.msg || '指定代理失败') + useMessage().error(e?.msg || '保存采购代表失败') } finally { - assignAgentSubmitting.value = false + representorSubmitting.value = false } } @@ -648,18 +624,18 @@ const getActionMenuItems = (row: any) => { icon: Download, visible: () => true, }, + { + command: 'representor', + label: '采购代表', + icon: User, + visible: () => isDeptAuditRole.value, + }, // { // command: 'downloadFileApply', // label: '下载文件审批表', // icon: Download, // visible: () => true, // }, - { - command: 'assignAgent', - label: '分配代理', - icon: Collection, - visible: () => row?.purchaseMode === '2' || (row?.purchaseMode === '0' && row?.purchaseType === '4'), - } // { // command: 'docAudit', // label: '采购文件审核', @@ -703,12 +679,12 @@ const handleMoreCommand = (command: string, row: any) => { case 'downloadFileApply': handleDownloadFileApply(row); break; - case 'assignAgent': - openAssignAgentDialog(row); - break; case 'docAudit': handleDocAudit(row); break; + case 'representor': + openRepresentorDialog(row); + break; } };