feat(outbound): 审批列表页增加完结按钮 + 优化缺货提示文案
- 去掉缺货提醒末尾的『是否查看?』(纯文案,保持强提醒但不承诺展示清单) - approval/index.vue 对已通过(status=1)的审批单新增「完结」按钮 库管/主管/超管可见,完结后从已通过列表移除 - 筛选区新增「已完结」状态选项,状态标签支持 status=4
This commit is contained in:
@ -819,7 +819,7 @@ const openBomSelect = async () => {
|
|||||||
const rec = bomShortageRecords.value[no]
|
const rec = bomShortageRecords.value[no]
|
||||||
return `• ${no}(${rec.items.length} 种缺货,${rec.time})`
|
return `• ${no}(${rec.items.length} 种缺货,${rec.time})`
|
||||||
}).join('\n') +
|
}).join('\n') +
|
||||||
`\n\n建议先补货后再出库,避免漏出。是否查看?`,
|
`\n\n建议先补货后再出库,避免漏出。`,
|
||||||
'存在未完成出库',
|
'存在未完成出库',
|
||||||
{ confirmButtonText: '知道了', cancelButtonText: '忽略', type: 'warning' }
|
{ confirmButtonText: '知道了', cancelButtonText: '忽略', type: 'warning' }
|
||||||
).catch(() => {})
|
).catch(() => {})
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
<el-radio-button :label="1">已通过</el-radio-button>
|
<el-radio-button :label="1">已通过</el-radio-button>
|
||||||
<el-radio-button :label="2">已驳回</el-radio-button>
|
<el-radio-button :label="2">已驳回</el-radio-button>
|
||||||
<el-radio-button :label="3">已完成</el-radio-button>
|
<el-radio-button :label="3">已完成</el-radio-button>
|
||||||
|
<el-radio-button :label="4">已完结</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-button type="primary" :icon="Refresh" @click="fetchData">刷新</el-button>
|
<el-button type="primary" :icon="Refresh" @click="fetchData">刷新</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -133,6 +134,19 @@
|
|||||||
驳回
|
驳回
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- ★ 已通过的申请单:库管/主管可手动完结 -->
|
||||||
|
<template v-else-if="row.status === 1">
|
||||||
|
<el-button
|
||||||
|
v-if="canCloseRequest"
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
size="small"
|
||||||
|
:loading="row._closing"
|
||||||
|
@click="handleCloseRequest(row)"
|
||||||
|
>
|
||||||
|
完结
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
<span v-else style="color: #c0c4cc;">-</span>
|
<span v-else style="color: #c0c4cc;">-</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -178,10 +192,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { Refresh, Warning } from '@element-plus/icons-vue'
|
import { Refresh, Warning } from '@element-plus/icons-vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { getApprovalRequestList, approveRequest } from '@/api/outbound'
|
import { getApprovalRequestList, approveRequest, closeRequest } from '@/api/outbound'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
@ -207,14 +221,14 @@ const userNameCache = ref<Record<number, string>>({})
|
|||||||
// --- 工具函数 ---
|
// --- 工具函数 ---
|
||||||
const statusText = (status: number) => {
|
const statusText = (status: number) => {
|
||||||
const map: Record<number, string> = {
|
const map: Record<number, string> = {
|
||||||
0: '待审批', 1: '已通过', 2: '已驳回', 3: '已完成'
|
0: '待审批', 1: '已通过', 2: '已驳回', 3: '已完成', 4: '已完结'
|
||||||
}
|
}
|
||||||
return map[status] ?? '-'
|
return map[status] ?? '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusTagType = (status: number) => {
|
const statusTagType = (status: number) => {
|
||||||
const map: Record<number, string> = {
|
const map: Record<number, string> = {
|
||||||
0: 'warning', 1: 'success', 2: 'danger', 3: 'info'
|
0: 'warning', 1: 'success', 2: 'danger', 3: 'info', 4: 'info'
|
||||||
}
|
}
|
||||||
return map[status] ?? 'info'
|
return map[status] ?? 'info'
|
||||||
}
|
}
|
||||||
@ -224,6 +238,40 @@ const getApplicantName = (id: number | null) => {
|
|||||||
return userNameCache.value[id] ?? `用户 #${id}`
|
return userNameCache.value[id] ?? `用户 #${id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ★ 完结权限:超级管理员 / 拥有出库操作权限(库管)或审批操作权限(主管)
|
||||||
|
const canCloseRequest = computed(() =>
|
||||||
|
userStore.role === 'SUPER_ADMIN' ||
|
||||||
|
userStore.hasPermission('outbound_create:operation') ||
|
||||||
|
userStore.hasPermission('outbound_approval:operation') ||
|
||||||
|
userStore.username === 'IRIS'
|
||||||
|
)
|
||||||
|
|
||||||
|
// ★ 完结已通过的审批单
|
||||||
|
const handleCloseRequest = async (row: any) => {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确定强制完结审批单【${row.request_no}】吗?\n\n` +
|
||||||
|
`此操作将使该单从「已通过」列表中移除,且不可恢复。\n` +
|
||||||
|
`若该单已部分出库,请确认无需再关联此单。`,
|
||||||
|
'⚠️ 强制完结确认',
|
||||||
|
{ confirmButtonText: '确认完结', cancelButtonText: '取消', type: 'warning' }
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
return // 用户取消
|
||||||
|
}
|
||||||
|
|
||||||
|
row._closing = true
|
||||||
|
try {
|
||||||
|
await closeRequest(row.id)
|
||||||
|
ElMessage.success(`审批单 ${row.request_no} 已完结`)
|
||||||
|
fetchData()
|
||||||
|
} catch (err: any) {
|
||||||
|
ElMessage.error(err?.msg || err?.message || '完结失败')
|
||||||
|
} finally {
|
||||||
|
row._closing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getApproverName = (id: number | null) => {
|
const getApproverName = (id: number | null) => {
|
||||||
if (!id) return '-'
|
if (!id) return '-'
|
||||||
return userNameCache.value[id] ?? `用户 #${id}`
|
return userNameCache.value[id] ?? `用户 #${id}`
|
||||||
|
|||||||
Reference in New Issue
Block a user