更新采购申请
This commit is contained in:
704
src/views/purchase/purchasingrequisition/implement.vue
Normal file
704
src/views/purchase/purchasingrequisition/implement.vue
Normal file
@@ -0,0 +1,704 @@
|
||||
<template>
|
||||
<div class="implement-page">
|
||||
<div class="implement-form">
|
||||
<!-- 步骤一:选择实施采购方式 -->
|
||||
<div class="step-section">
|
||||
<div class="step-header">
|
||||
<span class="step-number" :class="{ completed: step1Completed && !isEditingStep1 }">1</span>
|
||||
<span class="step-title">选择实施采购方式</span>
|
||||
<el-tag v-if="step1Completed && !isEditingStep1" type="success" size="small">已完成</el-tag>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<el-form-item label="实施采购方式" required>
|
||||
<el-radio-group v-model="implementType" :disabled="step1Completed && !isEditingStep1">
|
||||
<el-radio :label="IMPLEMENT_TYPE.SELF_ORGANIZED">自行组织采购</el-radio>
|
||||
<el-radio :label="IMPLEMENT_TYPE.ENTRUST_AGENT">委托代理采购</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 步骤一未完成:显示保存按钮 -->
|
||||
<el-form-item v-if="!step1Completed">
|
||||
<el-button type="primary" :loading="saveTypeSubmitting" :disabled="!implementType" @click="handleSaveImplementType">保存</el-button>
|
||||
</el-form-item>
|
||||
<!-- 步骤一已完成但正在编辑:显示修改确认按钮 -->
|
||||
<el-form-item v-else-if="isEditingStep1">
|
||||
<el-button type="primary" :loading="saveTypeSubmitting" :disabled="!implementType" @click="handleReSaveImplementType">确认修改</el-button>
|
||||
<el-button @click="cancelEditStep1">取消</el-button>
|
||||
</el-form-item>
|
||||
<!-- 步骤一已完成且未在编辑:显示修改按钮 -->
|
||||
<el-form-item v-else>
|
||||
<el-button type="default" @click="startEditStep1">修改</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 步骤二:分配代理(仅委托代理采购且步骤一完成时显示) -->
|
||||
<div v-if="showStep2" class="step-section">
|
||||
<div class="step-header">
|
||||
<span class="step-number" :class="{ completed: step2Completed }">2</span>
|
||||
<span class="step-title">分配代理机构</span>
|
||||
<el-tag v-if="step2Completed" type="success" size="small">已完成</el-tag>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<el-form-item label="分配方式">
|
||||
<el-radio-group v-model="agentMode">
|
||||
<el-radio label="designated">指定代理</el-radio>
|
||||
<el-radio label="random">随机分配</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="agentMode === 'designated'" label="选择代理">
|
||||
<el-select v-model="selectedAgentId" placeholder="请选择招标代理" filterable style="width: 100%" :loading="agentListLoading">
|
||||
<el-option v-for="item in agentList" :key="item.id" :label="item.agentName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="agentMode === 'random'" label="随机结果">
|
||||
<div class="agent-roller">
|
||||
<span v-if="rollingAgentName" class="rolling">{{ rollingAgentName }}</span>
|
||||
<span v-else-if="assignedAgentName" class="assigned">已分配:{{ assignedAgentName }}</span>
|
||||
<span v-else class="placeholder">点击下方按钮进行随机分配</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="applyRow?.agentName" label="当前代理">
|
||||
<el-tag>{{ applyRow.agentName }}</el-tag>
|
||||
<!-- 发送状态 -->
|
||||
<el-tag v-if="applyRow?.agentSent === YES_NO.YES" type="success" style="margin-left: 8px;">已发送</el-tag>
|
||||
<el-tag v-else type="info" style="margin-left: 8px;">未发送</el-tag>
|
||||
</el-form-item>
|
||||
<!-- 指定代理按钮:未发送招标代理时可操作 -->
|
||||
<el-form-item v-if="agentMode === 'designated' && canReassignAgent">
|
||||
<el-button type="primary" :loading="assignAgentSubmitting" :disabled="!selectedAgentId" @click="handleAssignAgentDesignated">{{ step2Completed ? '重新指定' : '指定代理' }}</el-button>
|
||||
</el-form-item>
|
||||
<!-- 随机分配按钮:未发送招标代理时可操作 -->
|
||||
<el-form-item v-if="agentMode === 'random' && canReassignAgent">
|
||||
<el-button type="primary" :loading="assignAgentSubmitting" @click="handleAssignAgentRandom">随机分配</el-button>
|
||||
</el-form-item>
|
||||
<!-- 发送招标代理按钮 -->
|
||||
<el-form-item v-if="canSendToAgent">
|
||||
<el-button type="success" :loading="sendToAgentSubmitting" @click="handleSendToAgent">发送招标代理</el-button>
|
||||
</el-form-item>
|
||||
<!-- 撤回招标代理按钮 -->
|
||||
<el-form-item v-if="canRevokeAgent">
|
||||
<el-button type="warning" :loading="revokeAgentSubmitting" @click="handleRevokeAgent">撤回</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部按钮:编辑步骤一时隐藏 -->
|
||||
<div v-if="!isEditingStep1" class="implement-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<!-- 只有步骤一完成后才显示确定按钮 -->
|
||||
<el-button v-if="step1Completed" type="primary" :loading="implementSubmitting" @click="handleImplementSubmit">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingImplement">
|
||||
import { ref, computed, onMounted, watch, onUnmounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getDeptMembers, getObj, assignAgent, sendToAgent, revokeAgent, saveImplementType } from '/@/api/purchase/purchasingrequisition'
|
||||
import { getPage as getAgentPage } from '/@/api/purchase/purchaseagent'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import * as orderVue from '/@/api/order/order-key-vue'
|
||||
|
||||
// ==================== 常量定义(与后端枚举保持一致) ====================
|
||||
|
||||
/** 部门审核角色编码:仅该角色下显示采购代表相关页面和功能,流转至部门审核时需填写采购代表 */
|
||||
const PURCHASE_DEPT_AUDIT_ROLE_CODE = 'PURCHASE_DEPT_AUDIT'
|
||||
|
||||
/** 实施采购方式(与后端 ImplementTypeEnum 一致) */
|
||||
const IMPLEMENT_TYPE = {
|
||||
/** 自行组织采购 */
|
||||
SELF_ORGANIZED: '1',
|
||||
/** 委托代理采购 */
|
||||
ENTRUST_AGENT: '2',
|
||||
} as const
|
||||
|
||||
/** 采购形式(与后端 PurchaseModeEnum 一致) */
|
||||
const PURCHASE_MODE = {
|
||||
/** 部门自行采购 */
|
||||
DEPT_SELF: '1',
|
||||
/** 学校统一采购 */
|
||||
SCHOOL_UNIFIED: '2',
|
||||
} as const
|
||||
|
||||
/** 采购途径(与后端 PurchaseChannelEnum 一致) */
|
||||
const PURCHASE_CHANNEL = {
|
||||
/** 自行采购 */
|
||||
SELF: '1',
|
||||
/** 委托采购中心采购 */
|
||||
ENTRUST_CENTER: '2',
|
||||
} as const
|
||||
|
||||
/** 是否标识(与后端 CommonConstants.YES/NO 一致) */
|
||||
const YES_NO = {
|
||||
NO: '0',
|
||||
YES: '1',
|
||||
} as const
|
||||
|
||||
const roleCode = computed(() => Session.getRoleCode() || '')
|
||||
const isDeptAuditRole = computed(() => roleCode.value === PURCHASE_DEPT_AUDIT_ROLE_CODE)
|
||||
|
||||
// 与编辑界面一致:支持流程 dynamic-link 传入 currJob/currElTab,申请单 ID 优先取 currJob.orderId
|
||||
const props = defineProps({
|
||||
currJob: { type: Object, default: null },
|
||||
currElTab: { type: Object, default: null }
|
||||
})
|
||||
const emit = defineEmits(['handleJob'])
|
||||
|
||||
/** 是否被流程 handle 页面通过 dynamic-link 嵌入 */
|
||||
const isFlowEmbed = computed(() => !!props.currJob)
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
/** 申请单 ID(数值,用于 getObj 等):与 add 一致,优先流程 currJob.orderId,否则 route.query.id */
|
||||
const applyId = computed(() => {
|
||||
const raw = applyIdRaw.value
|
||||
if (raw == null || raw === '') return null
|
||||
const n = Number(raw)
|
||||
return Number.isNaN(n) ? null : n
|
||||
})
|
||||
|
||||
/** 申请单 ID 原始字符串(用于 getApplyFiles 的 purchaseId,与编辑页一致,避免类型/精度问题) */
|
||||
const applyIdRaw = computed(() => {
|
||||
if (props.currJob?.orderId != null && props.currJob?.orderId !== '') {
|
||||
return String(props.currJob.orderId)
|
||||
}
|
||||
const id = route.query.id
|
||||
return id != null && id !== '' ? String(id) : ''
|
||||
})
|
||||
|
||||
const applyRow = ref<any>(null)
|
||||
const implementType = ref<string>(IMPLEMENT_TYPE.SELF_ORGANIZED)
|
||||
const implementSubmitting = ref(false)
|
||||
|
||||
/** 步骤控制 */
|
||||
const step1Completed = ref(false)
|
||||
const saveTypeSubmitting = ref(false)
|
||||
const isEditingStep1 = ref(false)
|
||||
const originalImplementType = ref<string>('')
|
||||
|
||||
const representorMode = ref<'single' | 'multi'>('single')
|
||||
const representorTeacherNo = ref<string>('')
|
||||
const representorsMulti = ref<string[]>([])
|
||||
const deptMembers = ref<any[]>([])
|
||||
|
||||
/** 分配代理相关 */
|
||||
const agentMode = ref<'designated' | 'random'>('designated')
|
||||
const selectedAgentId = ref<string>('')
|
||||
const agentList = ref<any[]>([])
|
||||
const agentListLoading = ref(false)
|
||||
const assignAgentSubmitting = ref(false)
|
||||
const rollingAgentName = ref<string>('')
|
||||
const assignedAgentName = ref<string>('')
|
||||
const sendToAgentSubmitting = ref(false)
|
||||
const revokeAgentSubmitting = ref(false)
|
||||
let rollInterval: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
/** 是否可以分配代理:委托代理采购 且 (学校统一采购 或 部门自行采购且委托采购中心采购) 且 步骤一已完成 */
|
||||
const canAssignAgent = computed(() => {
|
||||
// 自行组织采购不需要分配代理
|
||||
if (implementType.value !== IMPLEMENT_TYPE.ENTRUST_AGENT) return false
|
||||
// 步骤一必须完成
|
||||
if (!step1Completed.value) return false
|
||||
const row = applyRow.value
|
||||
if (!row) return false
|
||||
// 学校统一采购 或 部门自行采购且委托采购中心采购
|
||||
return row.purchaseMode === PURCHASE_MODE.SCHOOL_UNIFIED
|
||||
|| (row.purchaseMode === PURCHASE_MODE.DEPT_SELF && row.purchaseChannel === PURCHASE_CHANNEL.ENTRUST_CENTER)
|
||||
})
|
||||
|
||||
/** 是否显示步骤二:委托代理采购 且 步骤一已完成 且 不在编辑步骤一 */
|
||||
const showStep2 = computed(() => {
|
||||
return step1Completed.value && !isEditingStep1.value && implementType.value === IMPLEMENT_TYPE.ENTRUST_AGENT
|
||||
})
|
||||
|
||||
/** 步骤二是否完成:已分配代理 */
|
||||
const step2Completed = computed(() => {
|
||||
return !!applyRow.value?.agentId
|
||||
})
|
||||
|
||||
/** 是否可以发送招标代理:委托代理采购 且 已分配代理 且 未发送 */
|
||||
const canSendToAgent = computed(() => {
|
||||
// 自行组织采购不需要发送
|
||||
if (implementType.value !== IMPLEMENT_TYPE.ENTRUST_AGENT) return false
|
||||
const row = applyRow.value
|
||||
if (!row) return false
|
||||
// 已分配代理 且 未发送
|
||||
return !!row.agentId && row.agentSent !== YES_NO.YES
|
||||
})
|
||||
|
||||
/** 是否可以重新分配代理:未发送招标代理时可操作 */
|
||||
const canReassignAgent = computed(() => {
|
||||
const row = applyRow.value
|
||||
if (!row) return false
|
||||
// 未发送招标代理时可重新分配
|
||||
return row.agentSent !== YES_NO.YES
|
||||
})
|
||||
|
||||
/** 是否可以撤回招标代理:已发送招标代理时可撤回 */
|
||||
const canRevokeAgent = computed(() => {
|
||||
const row = applyRow.value
|
||||
if (!row) return false
|
||||
// 已分配代理 且 已发送招标代理时可撤回
|
||||
return !!row.agentId && row.agentSent === YES_NO.YES
|
||||
})
|
||||
|
||||
const loadAgentList = async () => {
|
||||
agentListLoading.value = true
|
||||
try {
|
||||
const res = await getAgentPage({ size: 500, current: 1 })
|
||||
const records = res?.data?.records ?? res?.records ?? []
|
||||
agentList.value = Array.isArray(records) ? records : []
|
||||
} catch (_) {
|
||||
agentList.value = []
|
||||
} finally {
|
||||
agentListLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 随机分配代理 - 滚动动画 */
|
||||
const startRollingAnimation = (finalAgentName: string) => {
|
||||
if (agentList.value.length === 0) return
|
||||
|
||||
// 清除之前的动画
|
||||
if (rollInterval) {
|
||||
clearInterval(rollInterval)
|
||||
rollInterval = null
|
||||
}
|
||||
|
||||
rollingAgentName.value = ''
|
||||
assignedAgentName.value = ''
|
||||
|
||||
let currentIndex = 0
|
||||
const totalDuration = 2000 // 总动画时间 2秒
|
||||
const intervalTime = 80 // 滚动间隔
|
||||
|
||||
rollInterval = setInterval(() => {
|
||||
rollingAgentName.value = agentList.value[currentIndex].agentName
|
||||
currentIndex = (currentIndex + 1) % agentList.value.length
|
||||
}, intervalTime)
|
||||
|
||||
// 2秒后停止并显示最终结果
|
||||
setTimeout(() => {
|
||||
if (rollInterval) {
|
||||
clearInterval(rollInterval)
|
||||
rollInterval = null
|
||||
}
|
||||
rollingAgentName.value = ''
|
||||
assignedAgentName.value = finalAgentName
|
||||
}, totalDuration)
|
||||
}
|
||||
|
||||
const handleAssignAgentRandom = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
assignAgentSubmitting.value = true
|
||||
try {
|
||||
const res = await assignAgent(Number(id), 'random')
|
||||
// 后端返回分配结果后,展示滚动动画
|
||||
const finalAgentName = res?.data?.agentName || res?.agentName || ''
|
||||
if (finalAgentName) {
|
||||
startRollingAnimation(finalAgentName)
|
||||
} else {
|
||||
useMessage().success('随机分配代理成功')
|
||||
await loadData()
|
||||
}
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '随机分配代理失败')
|
||||
} finally {
|
||||
assignAgentSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleAssignAgentDesignated = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
if (!selectedAgentId.value) {
|
||||
useMessage().warning('请选择招标代理')
|
||||
return
|
||||
}
|
||||
assignAgentSubmitting.value = true
|
||||
try {
|
||||
await assignAgent(Number(id), 'designated', selectedAgentId.value)
|
||||
useMessage().success('指定代理成功')
|
||||
await loadData()
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '指定代理失败')
|
||||
} finally {
|
||||
assignAgentSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 发送招标代理 */
|
||||
const handleSendToAgent = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
sendToAgentSubmitting.value = true
|
||||
try {
|
||||
await sendToAgent(Number(id))
|
||||
useMessage().success('已发送招标代理')
|
||||
await loadData()
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '发送招标代理失败')
|
||||
} finally {
|
||||
sendToAgentSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 撤回招标代理 */
|
||||
const handleRevokeAgent = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
revokeAgentSubmitting.value = true
|
||||
try {
|
||||
await revokeAgent(Number(id))
|
||||
useMessage().success('已撤回招标代理')
|
||||
await loadData()
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '撤回招标代理失败')
|
||||
} finally {
|
||||
revokeAgentSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 步骤一:保存实施采购方式 */
|
||||
const handleSaveImplementType = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
if (!implementType.value) {
|
||||
useMessage().warning('请选择实施采购方式')
|
||||
return
|
||||
}
|
||||
saveTypeSubmitting.value = true
|
||||
try {
|
||||
await saveImplementType(Number(id), implementType.value)
|
||||
useMessage().success('保存成功')
|
||||
step1Completed.value = true
|
||||
originalImplementType.value = implementType.value
|
||||
// 流程嵌入场景:通知流程 Tab 已保存
|
||||
if (isFlowEmbed.value && props.currJob && props.currElTab?.id) {
|
||||
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emit)
|
||||
}
|
||||
// 如果是委托代理采购,加载代理列表
|
||||
if (implementType.value === IMPLEMENT_TYPE.ENTRUST_AGENT) {
|
||||
await loadAgentList()
|
||||
}
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '保存失败')
|
||||
} finally {
|
||||
saveTypeSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 开始编辑步骤一 */
|
||||
const startEditStep1 = () => {
|
||||
originalImplementType.value = implementType.value
|
||||
isEditingStep1.value = true
|
||||
}
|
||||
|
||||
/** 取消编辑步骤一 */
|
||||
const cancelEditStep1 = () => {
|
||||
implementType.value = originalImplementType.value
|
||||
isEditingStep1.value = false
|
||||
}
|
||||
|
||||
/** 重新保存实施采购方式(修改后确认) */
|
||||
const handleReSaveImplementType = async () => {
|
||||
const id = applyRow.value?.id ?? applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取申请单ID')
|
||||
return
|
||||
}
|
||||
if (!implementType.value) {
|
||||
useMessage().warning('请选择实施采购方式')
|
||||
return
|
||||
}
|
||||
saveTypeSubmitting.value = true
|
||||
try {
|
||||
await saveImplementType(Number(id), implementType.value)
|
||||
useMessage().success('修改成功')
|
||||
isEditingStep1.value = false
|
||||
originalImplementType.value = implementType.value
|
||||
// 如果从委托代理采购改为自行组织采购,清空代理相关状态
|
||||
if (implementType.value === IMPLEMENT_TYPE.SELF_ORGANIZED) {
|
||||
assignedAgentName.value = ''
|
||||
selectedAgentId.value = ''
|
||||
}
|
||||
// 如果改为委托代理采购,加载代理列表
|
||||
if (implementType.value === IMPLEMENT_TYPE.ENTRUST_AGENT) {
|
||||
await loadAgentList()
|
||||
}
|
||||
// 流程嵌入场景:通知流程 Tab 已保存
|
||||
if (isFlowEmbed.value && props.currJob && props.currElTab?.id) {
|
||||
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emit)
|
||||
}
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '修改失败')
|
||||
} finally {
|
||||
saveTypeSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const isInIframe = () => typeof window !== 'undefined' && window.self !== window.top
|
||||
|
||||
const postMessage = (type: string, payload?: any) => {
|
||||
if (typeof window !== 'undefined' && window.parent) {
|
||||
window.parent.postMessage({ type, ...payload }, '*')
|
||||
}
|
||||
}
|
||||
|
||||
const loadData = async () => {
|
||||
const id = applyId.value
|
||||
if (!id) {
|
||||
useMessage().warning('缺少申请单ID')
|
||||
return
|
||||
}
|
||||
const needDeptMembers = isDeptAuditRole.value
|
||||
try {
|
||||
const requests: [ReturnType<typeof getObj>, ReturnType<typeof getDeptMembers>?] = [getObj(id)]
|
||||
if (needDeptMembers) requests.push(getDeptMembers())
|
||||
const results = await Promise.all(requests)
|
||||
const detailRes = results[0]
|
||||
const membersRes = needDeptMembers ? results[1] : null
|
||||
|
||||
applyRow.value = detailRes?.data ? { ...detailRes.data, id: detailRes.data.id ?? id } : { id }
|
||||
const row = applyRow.value
|
||||
if (row?.implementType) {
|
||||
implementType.value = row.implementType
|
||||
originalImplementType.value = row.implementType
|
||||
// 已有 implementType 说明步骤一已完成
|
||||
step1Completed.value = true
|
||||
}
|
||||
// 回显需求部门初审-采购代表人方式与人员
|
||||
if (row?.representorTeacherNo) {
|
||||
representorMode.value = 'single'
|
||||
representorTeacherNo.value = row.representorTeacherNo ?? ''
|
||||
representorsMulti.value = []
|
||||
} else if (row?.representors) {
|
||||
representorMode.value = 'multi'
|
||||
representorTeacherNo.value = ''
|
||||
const parts = typeof row.representors === 'string' ? row.representors.split(',') : []
|
||||
representorsMulti.value = parts.map((s: string) => s.trim()).filter(Boolean)
|
||||
} else {
|
||||
representorTeacherNo.value = ''
|
||||
representorsMulti.value = []
|
||||
}
|
||||
deptMembers.value = needDeptMembers && membersRes?.data ? membersRes.data : []
|
||||
|
||||
// 加载代理列表并回显已分配代理(委托代理采购时)
|
||||
if (step1Completed.value && implementType.value === IMPLEMENT_TYPE.ENTRUST_AGENT) {
|
||||
// 先判断是否可以分配代理(学校统一采购 或 部门自行采购且委托采购中心采购)
|
||||
const canLoadAgent = row.purchaseMode === PURCHASE_MODE.SCHOOL_UNIFIED
|
||||
|| (row.purchaseMode === PURCHASE_MODE.DEPT_SELF && row.purchaseChannel === PURCHASE_CHANNEL.ENTRUST_CENTER)
|
||||
if (canLoadAgent) {
|
||||
await loadAgentList()
|
||||
// 回显已分配代理
|
||||
if (row?.agentId) {
|
||||
selectedAgentId.value = row.agentId
|
||||
assignedAgentName.value = row.agentName || ''
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
applyRow.value = { id }
|
||||
deptMembers.value = []
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
postMessage('purchasingimplement:close')
|
||||
if (!isInIframe()) {
|
||||
window.history.back()
|
||||
}
|
||||
}
|
||||
|
||||
const handleImplementSubmit = async () => {
|
||||
const row = applyRow.value
|
||||
if (!row?.id && !applyId.value) return
|
||||
const id = row?.id ?? applyId.value
|
||||
if (!id) return
|
||||
|
||||
// 步骤一未完成时,先保存步骤一
|
||||
if (!step1Completed.value) {
|
||||
if (!implementType.value) {
|
||||
useMessage().warning('请选择实施采购方式')
|
||||
return
|
||||
}
|
||||
// 自动保存步骤一
|
||||
saveTypeSubmitting.value = true
|
||||
try {
|
||||
await saveImplementType(Number(id), implementType.value)
|
||||
step1Completed.value = true
|
||||
} catch (e: any) {
|
||||
useMessage().error(e?.msg || '保存实施采购方式失败')
|
||||
return
|
||||
} finally {
|
||||
saveTypeSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
implementSubmitting.value = true
|
||||
try {
|
||||
useMessage().success('实施采购已保存')
|
||||
postMessage('purchasingimplement:saved')
|
||||
// 流程嵌入场景:通知流程当前 Tab 已保存
|
||||
if (isFlowEmbed.value && props.currJob && props.currElTab?.id) {
|
||||
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emit)
|
||||
}
|
||||
} catch (err: any) {
|
||||
useMessage().error(err?.msg || '实施采购失败')
|
||||
} finally {
|
||||
implementSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 流程嵌入时供 handle.vue 调用的"保存"回调:与页面按钮保存逻辑保持一致 */
|
||||
async function flowSubmitForm() {
|
||||
await handleImplementSubmit()
|
||||
}
|
||||
|
||||
// 流程切换工单时重新加载数据(与 add 编辑页一致)
|
||||
watch(
|
||||
() => props.currJob?.orderId ?? props.currJob?.id,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal !== oldVal && applyId.value) {
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
await loadData()
|
||||
if (isInIframe()) {
|
||||
document.documentElement.classList.add('iframe-mode')
|
||||
document.body.classList.add('iframe-mode')
|
||||
}
|
||||
// 流程嵌入:注册 tab 保存回调,供审批页调用(与采购申请编辑页保持一致)
|
||||
if (isFlowEmbed.value && props.currJob && props.currElTab?.id) {
|
||||
orderVue.currElTabIsExist(props.currJob, props.currElTab.id)
|
||||
await orderVue.currElTabIsView({}, props.currJob, props.currElTab.id, flowSubmitForm)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
// 清理滚动动画定时器
|
||||
if (rollInterval) {
|
||||
clearInterval(rollInterval)
|
||||
rollInterval = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.implement-page {
|
||||
padding: 20px;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.implement-form {
|
||||
flex: 1;
|
||||
.mb-2 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.implement-form-tip {
|
||||
margin-top: 12px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.implement-footer {
|
||||
margin-top: 24px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.step-section {
|
||||
margin-bottom: 24px;
|
||||
padding: 16px;
|
||||
background: var(--el-fill-color-lighter);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.step-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: var(--el-color-primary);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
|
||||
&.completed {
|
||||
background: var(--el-color-success);
|
||||
}
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.step-content {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.agent-roller {
|
||||
padding: 12px 16px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-radius: 4px;
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.rolling {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--el-color-primary);
|
||||
animation: blink 0.1s infinite;
|
||||
}
|
||||
|
||||
.assigned {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.7; }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user