采购更新

This commit is contained in:
吴红兵
2026-02-28 13:36:47 +08:00
parent 45ea9af8f6
commit eafa255359
4 changed files with 63 additions and 469 deletions

View File

@@ -1,15 +1,6 @@
<template>
<el-form ref="formRef" :model="form" :rules="rules" label-width="160px" >
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="验收方式" prop="acceptType">
<el-radio-group v-model="form.acceptType" :disabled="readonly">
<el-radio label="1" :disabled="!canFill">填写履约验收评价表</el-radio>
<el-radio label="2">上传履约验收评价表</el-radio>
</el-radio-group>
<div v-if="!canFill" class="el-form-item__tip">金额30万仅支持上传模版</div>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="验收日期" prop="acceptDate">
<el-date-picker
@@ -24,54 +15,10 @@
</el-form-item>
</el-col>
<!-- 填报方式验收内容表格 -->
<template v-if="form.acceptType === '1' && canFill">
<el-col :span="12" class="mb20">
<el-form-item label="验收内容" prop="acceptContents">
<el-table :data="form.acceptContents" border size="small" class="accept-content-table">
<el-table-column prop="itemName" label="验收项" >
<template #default="{ row }">
<div>
<span>{{row.itemName}}</span>
<el-input
v-if="row.type === 'input'"
v-model="row.remark"
placeholder="请输入"
size="small"
:disabled="readonly"
/>
</div>
</template>
</el-table-column>
<el-table-column prop="isQualified" label="合格/不合格" align="center">
<template #default="{ row }">
<el-radio-group v-model="row.isQualified" size="small" :disabled="readonly">
<el-radio label="1">合格</el-radio>
<el-radio label="0">不合格</el-radio>
</el-radio-group>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</template>
<!-- 上传方式先模版下载再上传 -->
<template v-if="form.acceptType === '2'">
<el-col :span="12" class="mb20">
<el-form-item label="模版下载">
<el-link type="primary" :href="lyysTemplateUrl" :download="lyysTemplateDownloadName" target="_blank">
<el-icon><Download /></el-icon>
{{ lyysTemplateLabel }}
</el-link>
<!-- <div class="el-form-item__tip">下载后填写并上传模板文件templates/lyys-template-{{ projectTypeKey }}.docx</div>-->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="履约验收模版" prop="templateFileIds">
<!-- 上传履约验收模版 -->
<el-col :span="12" class="mb20">
<el-form-item label="履约验收模版" prop="templateFileIds">
<div class="upload-with-template">
<UploadFile
v-model="templateFileIdsStr"
:limit="1"
@@ -79,84 +26,10 @@
upload-file-url="/purchase/purchasingfiles/upload"
:disabled="readonly"
/>
</el-form-item>
</el-col>
</template>
<el-col :span="12" class="mb20">
<el-form-item label="验收地点" prop="acceptAddress">
<el-input v-model="form.acceptAddress" placeholder="请输入验收地点" :disabled="readonly" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="存在问题及改进意见" prop="question">
<el-input
v-model="form.question"
type="textarea"
:rows="2"
placeholder="请输入存在问题及改进意见"
:disabled="readonly"
/>
</el-form-item>
</el-col>
<!-- 验收小组 -->
<el-col :span="12">
<el-form-item label="验收小组" prop="acceptTeam">
<div class="team-list">
<div v-for="(m, idx) in form.acceptTeam" :key="idx" class="team-row">
<el-select
v-model="m.roleType"
placeholder="身份"
size="small"
style="width: 130px; margin-right: 8px"
:disabled="readonly"
@change="(val) => onRoleChange(idx, val as string)"
>
<el-option label="组长(校内)" value="LEADER_IN" />
<el-option label="组长(校外)" value="LEADER_OUT" />
<el-option label="组员(校内)" value="MEMBER_IN" />
<el-option label="组员(校外)" value="MEMBER_OUT" />
</el-select>
<template v-if="m.roleType === 'LEADER_IN' || m.roleType === 'MEMBER_IN'">
<org-selector
v-model:orgList="m.userList"
type="user"
:multiple="false"
@update:orgList="(list: any[]) => onTeamUserChange(idx, list)"
/>
</template>
<template v-else>
<el-input v-model="m.name" placeholder="姓名" size="small" style="width:120px" :disabled="readonly" />
<el-input v-model="m.deptName" placeholder="单位/部门" size="small" style="width:160px" :disabled="readonly" />
</template>
<el-button v-if="!readonly && form.acceptTeam.length > 3" type="danger" link size="small" @click="removeTeam(idx)">删除</el-button>
</div>
<el-button v-if="!readonly" type="primary" link size="small" @click="addTeam">+ 增加成员</el-button>
</div>
<div class="el-form-item__tip">
至少3人且为单数
<template v-if="(previousBatchesTeams || []).length > 0">
<span class="copy-from-inline">
从往期带入
<el-select
v-model="copyFromBatch"
placeholder="同第N期"
clearable
size="small"
style="width: 100px"
@change="onCopyFromBatch"
>
<el-option
v-for="item in (previousBatchesTeams || [])"
:key="item.batch"
:label="`同第${item.batch}期`"
:value="item.batch"
/>
</el-select>
</span>
</template>
<el-link 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>
</el-link>
</div>
</el-form-item>
</el-col>
@@ -175,7 +48,7 @@ import { ref, reactive, computed, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { Download } from '@element-plus/icons-vue'
/** 项目类型 A:货物 B:工程 C:服务,与 public/templates/lyys-template-A|B|C.docx 对应 */
/** 项目类型 A:货物 B:工程 C:服务 */
const LYYS_TEMPLATE_MAP: Record<string, { label: string }> = {
A: { label: '履约验收表模板(货物)' },
B: { label: '履约验收表模板(工程)' },
@@ -185,23 +58,19 @@ const LYYS_TEMPLATE_MAP: Record<string, { label: string }> = {
const props = withDefaults(
defineProps<{
modelValue: Record<string, any>
canFill: boolean
readonly?: boolean
purchaseId?: string
/** 项目类型 A:货物 B:工程 C:服务,用于模版下载 */
projectType?: string
acceptanceItems?: any[]
batchNum?: number
previousBatchesTeams?: { batch: number; team: any[] }[]
}>(),
{ readonly: false, canFill: true, purchaseId: '', projectType: 'A', batchNum: 1, previousBatchesTeams: () => [] }
{ readonly: false, purchaseId: '', projectType: 'A', batchNum: 1 }
)
const emit = defineEmits(['update:modelValue'])
const formRef = ref<FormInstance>()
const templateFileIdsStr = ref('')
const copyFromBatch = ref<number | null>(null)
const projectTypeKey = computed(() => (props.projectType === 'A' || props.projectType === 'B' || props.projectType === 'C' ? props.projectType : 'A'))
const lyysTemplateLabel = computed(() => LYYS_TEMPLATE_MAP[projectTypeKey.value]?.label || LYYS_TEMPLATE_MAP.A.label)
@@ -209,56 +78,20 @@ const lyysTemplateDownloadName = computed(() => `${lyysTemplateLabel.value}.docx
const lyysTemplateUrl = computed(() => `/templates/lyys-template-${projectTypeKey.value}.docx`)
const form = reactive({
acceptType: '1',
acceptType: '2', // 固定为上传模式
acceptDate: '',
acceptContents: [] as any[],
acceptTeam: [
{ name: '', deptCode: '', deptName: '', teacherNo: '', roleType: '' },
{ name: '', deptCode: '', deptName: '', teacherNo: '', roleType: '' },
{ name: '', deptCode: '', deptName: '', teacherNo: '', roleType: '' },
] as any[],
templateFileIds: [] as string[],
acceptAddress: '',
question: '',
remark: '',
...props.modelValue,
})
// 确保acceptType始终为'2'
watch(() => props.modelValue, (val) => {
Object.assign(form, val || {})
// 金额≥30万时强制上传
if (!props.canFill && form.acceptType === '1') {
form.acceptType = '2'
}
// 编辑回显:校内成员根据 name/deptCode/deptName/teacherNo 构建 userList 供 org-selector 显示
if (Array.isArray(form.acceptTeam)) {
form.acceptTeam.forEach((m: any) => {
const isIn = m.roleType === 'LEADER_IN' || m.roleType === 'MEMBER_IN'
if (isIn && (m.name || m.teacherNo) && !(m.userList && m.userList.length)) {
m.userList = buildUserListFromTeamItem(m)
}
})
}
form.acceptType = '2' // 强制上传
}, { deep: true })
watch(form, () => emit('update:modelValue', { ...form }), { deep: true })
// 金额≥30万时默认选中上传方式
watch(() => props.canFill, (val) => {
if (!val && form.acceptType === '1') {
form.acceptType = '2'
}
}, { immediate: true })
watch(() => props.acceptanceItems, (items) => {
if (items?.length && form.acceptContents.length === 0) {
form.acceptContents = items.map((it: any) => ({
configId: it.id,
itemName: it.itemName,
type: it.type,
isQualified: '1',
remark: '',
}))
}
}, { immediate: true })
watch(form, () => emit('update:modelValue', { ...form }), { deep: true })
watch(templateFileIdsStr, (s) => {
const arr = s ? s.split(',').map((x: string) => x.trim()).filter(Boolean) : []
@@ -271,84 +104,10 @@ watch(() => form.templateFileIds, (arr) => {
if (Array.isArray(arr) && arr.length) templateFileIdsStr.value = arr.join(',')
}, { immediate: true, deep: true })
const addTeam = () => {
form.acceptTeam.push({ name: '', deptCode: '', deptName: '', teacherNo: '', roleType: '' })
}
const removeTeam = (idx: number) => {
form.acceptTeam.splice(idx, 1)
}
const onCopyFromBatch = (n: number | null) => {
if (!n) return
const item = props.previousBatchesTeams?.find((x) => x.batch === n)
if (item?.team?.length) {
form.acceptTeam = item.team.map((m: any) => ({
name: m.name || '',
deptCode: m.deptCode || '',
deptName: m.deptName || '',
teacherNo: m.teacherNo || '',
roleType: m.roleType || '',
userList: buildUserListFromTeamItem(m),
}))
}
copyFromBatch.value = null
}
const rules: FormRules = {
acceptType: [{ required: true, message: '请选择验收方式', trigger: 'change' }],
acceptDate: [{ required: true, message: '请选择验收日期', trigger: 'change' }],
}
const onRoleChange = (idx: number, val: string) => {
const isLeader = val === 'LEADER_IN' || val === 'LEADER_OUT'
if (isLeader) {
const hasOtherLeader = form.acceptTeam.some((m, i) =>
i !== idx && (m.roleType === 'LEADER_IN' || m.roleType === 'LEADER_OUT')
)
if (hasOtherLeader) {
// 只能有一个组长
form.acceptTeam[idx].roleType = ''
return
}
}
}
/** 从接口返回的成员项构建 org-selector 所需的 userList编辑回显用 */
const buildUserListFromTeamItem = (t: any) => {
if (!t?.name && !t?.teacherNo) return []
return [
{
id: t.teacherNo || t.name,
name: t.name || '',
type: 'user',
deptCode: t.deptCode,
deptName: t.deptName,
teacherNo: t.teacherNo,
realName: t.name,
},
]
}
const onTeamUserChange = (idx: number, list: any[]) => {
const m = form.acceptTeam[idx]
if (!m) return
if (list && list.length) {
const u = list[0]
m.name = u.name || u.realName || ''
m.deptCode = u.deptCode || u.commonDeptCode || ''
m.deptName = u.deptName || u.commonDeptName || ''
m.teacherNo = u.teacherNo ?? u.username ?? u.id ?? ''
m.userList = list
} else {
m.name = ''
m.deptCode = ''
m.deptName = ''
m.teacherNo = ''
m.userList = []
}
}
const validate = () => formRef.value?.validate()
defineExpose({ validate, form })
@@ -358,13 +117,9 @@ defineExpose({ validate, form })
.mb20 {
margin-bottom: 20px;
}
.copy-from-inline {
display: inline-flex;
align-items: center;
gap: 6px;
margin-left: 4px;
}
.copy-from-inline :deep(.el-select) {
vertical-align: middle;
.upload-with-template {
display: flex;
flex-direction: column;
gap: 8px;
}
</style>

View File

@@ -60,13 +60,10 @@
:key="b.id"
:ref="(el) => setBatchFormRef(b.batch, el)"
v-model="batchForms[b.batch]"
:can-fill="canFillForm"
:readonly="false"
:purchase-id="String(purchaseId)"
:project-type="acceptProjectType"
:acceptance-items="acceptanceItems"
:batch-num="b.batch"
:previous-batches-teams="getPreviousBatchesTeams(b.batch)"
/>
</div>
</div>
@@ -83,26 +80,6 @@
<template #footer>
<span>
<el-button @click="handleClose"> </el-button>
<!-- 仅填写履约验收评价表模式可导出单期 docx全部期数 zip -->
<el-dropdown
v-if="showExportDropdown"
split-button
type="primary"
@click="handleDownloadTemplate"
@command="handleDownloadTemplateCommand"
>
导出履约验收评价表
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="current" :disabled="!canExportCurrentBatch">
下载当前期({{ activeTab }})
</el-dropdown-item>
<el-dropdown-item command="all" :disabled="!canExportAllBatches">
下载全部期数(zip)
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button
v-if="mainTab === 'common' || batches.length === 0"
type="primary"
@@ -125,17 +102,13 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ref, reactive, computed, nextTick } from 'vue'
import { useMessage } from '/@/hooks/message'
import { handleBlobFile } from '/@/utils/other'
import {
saveCommonConfig as apiSaveCommonConfig,
getCommonConfigWithBatches,
updateBatch,
canFillForm as apiCanFillForm,
getAcceptanceItems,
getDetail,
downloadPerformanceAcceptanceTemplate,
} from '/@/api/purchase/purchasingAccept'
import AcceptCommonForm from './AcceptCommonForm.vue'
import AcceptBatchForm from './AcceptBatchForm.vue'
@@ -148,8 +121,6 @@ const saving = ref(false)
const purchaseId = ref<string | number>('')
const applyInfo = ref<any>(null)
const rowProjectType = ref<string>('A')
const canFillForm = ref(true)
const acceptanceItems = ref<any[]>([])
const batches = ref<any[]>([])
const mainTab = ref('common')
const activeTab = ref('1')
@@ -160,7 +131,7 @@ const commonForm = ref<Record<string, any>>({})
/** 每次打开自增,用于强制 AcceptCommonForm 重新挂载,确保公共信息彻底清空 */
const openToken = ref(0)
const batchForms = reactive<Record<number, any>>({})
/** 记录哪些期已保存到服务器,用于控制下一期可填”:只有上一期已保存才允许填下一期 */
/** 记录哪些期已保存到服务器,用于控制下一期可填”:只有上一期已保存才允许填下一期 */
const batchSavedFlags = ref<Record<number, boolean>>({})
const setBatchFormRef = (batch: number, el: any) => {
@@ -175,28 +146,6 @@ const activeBatchId = computed(() => {
/** 项目类型 A:货物 B:工程 C:服务,用于批次表单模版下载 */
const acceptProjectType = computed(() => applyInfo.value?.projectType || rowProjectType.value || 'A')
/** 当前期是否为「填写履约验收评价表」模式,仅此模式可导出 */
const canExportCurrentBatch = computed(() => batchForms[Number(activeTab.value)]?.acceptType === '1')
/** 是否存在任一批次为填写模式(可导出全部期数 zip */
const canExportAllBatches = computed(() =>
batches.value.some((b: any) => batchForms[b.batch]?.acceptType === '1')
)
/** 仅在有批次且至少一期为填写模式时显示导出下拉 */
const showExportDropdown = computed(
() => mainTab.value === 'batch' && batches.value.length > 0 && (canExportCurrentBatch.value || canExportAllBatches.value)
)
const getPreviousBatchesTeams = (batchNum: number) => {
const list: { batch: number; team: any[] }[] = []
for (let n = 1; n < batchNum; n++) {
const team = batchForms[n]?.acceptTeam
if (Array.isArray(team) && team.length > 0) {
list.push({ batch: n, team })
}
}
return list
}
/** 是否允许编辑该期:第 1 期始终可编辑;第 N 期仅当第 1N-1 期均已保存后才可编辑 */
const canEditBatch = (batch: number) => {
if (batch === 1) return true
@@ -220,15 +169,11 @@ const loadData = async () => {
const currentId = String(purchaseId.value)
loading.value = true
try {
const [configRes, canFillRes] = await Promise.all([
getCommonConfigWithBatches(currentId),
apiCanFillForm(currentId),
])
const configRes = await getCommonConfigWithBatches(currentId)
// 防止快速切换:若已打开其他申请单,忽略本次结果
if (String(purchaseId.value) !== currentId) return
const config = configRes?.data
canFillForm.value = !!canFillRes?.data
if (config?.common) {
applyInfo.value = config.common
@@ -245,13 +190,6 @@ const loadData = async () => {
}
}
const projectType = applyInfo.value?.projectType || rowProjectType.value || 'A'
const typeMap: Record<string, string> = { A: 'A', B: 'B', C: 'C' }
const at = typeMap[projectType] || 'A'
const itemsRes = await getAcceptanceItems(at)
if (String(purchaseId.value) !== currentId) return
acceptanceItems.value = itemsRes?.data || []
if (config?.batches?.length) {
batches.value = config.batches.sort((a: any, b: any) => (a.batch || 0) - (b.batch || 0))
activeTab.value = String(batches.value[0]?.batch || '1')
@@ -280,51 +218,14 @@ const loadBatchDetails = async () => {
const res = await getDetail(String(purchaseId.value), b.batch)
const d = res?.data
if (d?.accept) {
// 仅当该期在服务端有验收日期(且验收方式)时才视为已保存,避免空结构被当成“已填”
const hasSaved = !!(d.accept.acceptDate && d.accept.acceptType)
// 仅当该期在服务端有验收日期时才视为已保存
const hasSaved = !!d.accept.acceptDate
batchSavedFlags.value[b.batch] = hasSaved
const itemMap = (acceptanceItems.value || []).reduce((acc: any, it: any) => {
acc[it.id] = it
return acc
}, {})
batchForms[b.batch] = {
acceptType: d.accept.acceptType || '1',
acceptType: '2', // 固定为上传模式
acceptDate: d.accept.acceptDate || '',
acceptAddress: d.accept.acceptAddress || '',
question: d.accept.question || '',
remark: d.accept.remark || '',
templateFileIds: d.accept.templateFileIds || [],
acceptContents: (d.contents || []).map((c: any) => {
const cfg = itemMap[c.configId]
return {
configId: c.configId,
itemName: cfg?.itemName || '',
type: cfg?.type,
isQualified: c.isQualified || '1',
remark: c.remark || '',
}
}),
acceptTeam: (d.team || []).map((t: any) => ({
name: t.name,
deptCode: t.deptCode,
deptName: t.deptName,
teacherNo: t.teacherNo || '',
roleType: t.roleType || '',
})),
}
if (batchForms[b.batch].acceptTeam.length < 3) {
while (batchForms[b.batch].acceptTeam.length < 3) {
batchForms[b.batch].acceptTeam.push({ name: '', deptCode: '', deptName: '', teacherNo: '', roleType: '' })
}
}
if (acceptanceItems.value.length && (!batchForms[b.batch].acceptContents || batchForms[b.batch].acceptContents.length === 0)) {
batchForms[b.batch].acceptContents = acceptanceItems.value.map((it: any) => ({
configId: it.id,
itemName: it.itemName,
type: it.type,
isQualified: '1',
remark: '',
}))
}
}
} catch (_) {}
@@ -377,34 +278,20 @@ const saveCurrentBatch = async () => {
const form = batchForms[curBatch]
if (!form) return
if (!form.acceptType) {
useMessage().error('请选择验收方式')
return
}
if (!form.acceptDate) {
useMessage().error('请选择验收日期')
return
}
const team = (form.acceptTeam || []).filter((m: any) => m?.name)
if (team.length < 3 || team.length % 2 === 0) {
useMessage().error('验收小组至少3人且为单数')
return
}
saving.value = true
try {
await updateBatch({
id: b.id,
purchaseId: String(purchaseId.value),
acceptType: form.acceptType,
acceptType: '2', // 固定为上传模式
acceptDate: form.acceptDate,
acceptAddress: form.acceptAddress,
question: form.question,
remark: form.remark,
templateFileIds: form.templateFileIds || [],
acceptContents: form.acceptContents || [],
acceptTeam: team,
})
useMessage().success('保存成功')
batchSavedFlags.value[curBatch] = true
@@ -421,64 +308,6 @@ const handleClose = () => {
emit('refresh')
}
// 导出履约验收评价表(仅填写模式可导出)
const handleDownloadTemplate = async () => {
if (!purchaseId.value) {
useMessage().error('请先选择采购项目')
return
}
if (!canExportCurrentBatch.value) {
useMessage().error('仅填写履约验收评价表模式可导出,请先选择该模式并保存')
return
}
await downloadTemplateForBatch(Number(activeTab.value))
}
const handleDownloadTemplateCommand = async (command: string) => {
if (!purchaseId.value) {
useMessage().error('请先选择采购项目')
return
}
if (command === 'current') {
if (!canExportCurrentBatch.value) {
useMessage().error('当前期未选择填写履约验收评价表模式,无法导出')
return
}
await downloadTemplateForBatch(Number(activeTab.value))
} else if (command === 'all') {
if (!canExportAllBatches.value) {
useMessage().error('没有填写模式的分期可导出')
return
}
await downloadAllBatchesAsZip()
}
}
const downloadTemplateForBatch = async (batchNum: number) => {
try {
const response = await downloadPerformanceAcceptanceTemplate(String(purchaseId.value), batchNum)
const fileName = `履约验收表-${purchaseId.value}-第${batchNum}期.docx`
handleBlobFile(response, fileName)
useMessage().success(`${batchNum}期导出成功`)
} catch (error: any) {
console.error('导出失败:', error)
useMessage().error(error?.msg || '导出失败')
}
}
const downloadAllBatchesAsZip = async () => {
try {
const response = await downloadPerformanceAcceptanceTemplate(String(purchaseId.value), undefined, true)
const fileName = `履约验收表-${purchaseId.value}-全部期数.zip`
handleBlobFile(response, fileName)
const count = batches.value.filter((b: any) => batchForms[b.batch]?.acceptType === '1').length
useMessage().success(`已导出${count}期,请查收 zip 文件`)
} catch (error: any) {
console.error('导出全部期数失败:', error)
useMessage().error(error?.msg || '导出全部期数失败')
}
}
const DEFAULT_COMMON_FORM = {
hasContract: '0',
contractId: '',
@@ -501,8 +330,6 @@ const resetAllToDefault = () => {
activeTab.value = '1'
batchFormRefMap.value = {}
batches.value = []
acceptanceItems.value = []
canFillForm.value = true
Object.keys(batchForms).forEach((k) => delete batchForms[Number(k)])
batchSavedFlags.value = {}
}

View File

@@ -228,13 +228,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12">
<el-form-item label="校党委" prop="schoolLeaderUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.schoolLeaderUserId" placeholder="请选择校党委" clearable filterable @change="handleSchoolLeaderChange" style="width: 100%" :disabled="flowFieldDisabled('schoolLeaderUserId')">
<el-option v-for="item in schoolLeaderList" :key="item.id" :label="item.name" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<!-- 非特殊情况显示业务分管校领导 -->
<el-col :span="8" class="mb12" v-if="!isSpecialCase">
<el-form-item label="业务分管校领导" prop="schoolBusinessLeaderUserId" :required="!isDeptPurchase">
@@ -243,8 +237,16 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="mb12">
<el-form-item label="校党委" prop="schoolLeaderUserId" v-if="isSpecialCase" :required="!isDeptPurchase && isSpecialCase">
<el-select v-model="dataForm.schoolLeaderUserId" placeholder="请选择校党委" clearable filterable @change="handleSchoolLeaderChange" style="width: 100%" :disabled="flowFieldDisabled('schoolLeaderUserId')">
<el-option v-for="item in schoolLeaderList" :key="item.id" :label="item.name" :value="item.userId" />
</el-select>
</el-form-item>
</el-col>
<!-- 特殊情况显示采购分管校领导 -->
<el-col :span="8" class="mb12" v-if="isSpecialCase">
<el-col :span="8" class="mb12">
<el-form-item label="采购分管校领导" prop="purchaseManagerUserId" :required="!isDeptPurchase">
<el-select v-model="dataForm.purchaseManagerUserId" placeholder="请选择采购分管校领导" clearable filterable @change="handlePurchaseManagerChange" style="width: 100%" :disabled="flowFieldDisabled('purchaseManagerUserId')">
<el-option v-for="item in purchasingManagerList" :key="item.id" :label="item.name" :value="item.userId" />

View File

@@ -353,12 +353,13 @@
</template>
<script setup lang="ts" name="PurchasingRequisition">
import { ref, reactive, defineAsyncComponent, onMounted } from 'vue'
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 { 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'
@@ -391,6 +392,7 @@ const acceptModalRef = ref()
const searchFormRef = ref()
const showSearch = ref(true)
const docAuditDialogRef = ref()
const { hasAuth } = useAuth()
/** 审批过程弹窗:是否显示、当前行对应的流程 job供 Comment 组件用)、类型(申请单/文件) */
const showFlowComment = ref(false)
const currFlowJob = ref<{ id?: number; flowInstId?: number } | null>(null)
@@ -603,7 +605,7 @@ const handleSubmit = async (row: any) => {
/** 操作栏「更多」菜单项配置 */
const getActionMenuItems = (row: any) => {
const isTemp = row?.status === '-1';
return [
const items = [
{
command: 'edit',
label: '编辑',
@@ -626,18 +628,19 @@ const getActionMenuItems = (row: any) => {
command: 'accept',
label: '履约验收',
icon: DocumentChecked,
visible: () => true,
visible: () => hasAuth('purchase_accept'),
},
{
command: 'implement',
label: '实施采购',
icon: Upload
icon: Upload,
visible: () => hasAuth('purchase_implement'),
},
{
command: 'archive',
label: '文件归档',
icon: FolderOpened,
visible: () => true,
visible: () => hasAuth('purchase_archive'),
},
{
command: 'downloadApply',
@@ -645,25 +648,32 @@ const getActionMenuItems = (row: any) => {
icon: Download,
visible: () => true,
},
{
command: 'downloadFileApply',
label: '下载文件审批表',
icon: Download,
visible: () => true,
},
// {
// 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: '采购文件审核',
icon: DocumentChecked,
visible: () => row?.implementType === '2' && row?.agentId,
},
}
// {
// command: 'docAudit',
// label: '采购文件审核',
// icon: DocumentChecked,
// visible: () => row?.implementType === '2' && row?.agentId,
// },
];
// 过滤出有权限且可见的菜单项
return items.filter(item => {
if (item.visible === undefined) return true;
if (typeof item.visible === 'boolean') return item.visible;
if (typeof item.visible === 'function') return item.visible();
return false;
});
};
/** 处理更多操作下拉菜单命令 */