提交
This commit is contained in:
1 parent
06956b742b
commit
e59b2aa6cb
104 files changed
+653227
-7621
No files matched your search
@@ -684,15 +684,40 @@ async function handleToolbarSubmit() {
|
||||
ElMessage.warning('请先勾选要提交的申请')
|
||||
return
|
||||
}
|
||||
|
||||
const validTargets = selectedRows.value.filter(isDraftEditable)
|
||||
const skippedCount = selectedRows.value.length - validTargets.length
|
||||
|
||||
if (!validTargets.length) {
|
||||
ElMessage.warning('所选申请均不是草稿或已驳回状态,无法提交审批')
|
||||
return
|
||||
}
|
||||
|
||||
if (skippedCount > 0) {
|
||||
ElMessage.warning(
|
||||
`已跳过 ${skippedCount} 条不可提交的申请(仅草稿或已驳回可提交),将继续提交其余 ${validTargets.length} 条`
|
||||
)
|
||||
}
|
||||
|
||||
loadingMap.submit = true
|
||||
try {
|
||||
for (const row of selectedRows.value) {
|
||||
await advanceApi.submit(row.id)
|
||||
const results = await Promise.allSettled(validTargets.map((row) => advanceApi.submit(row.id)))
|
||||
const successCount = results.filter((item) => item.status === 'fulfilled').length
|
||||
const failedCount = results.length - successCount
|
||||
const skipText = skippedCount > 0 ? `,跳过 ${skippedCount} 条` : ''
|
||||
|
||||
if (successCount === 0) {
|
||||
ElMessage.error(`提交失败${skipText}`)
|
||||
return
|
||||
}
|
||||
if (failedCount > 0) {
|
||||
ElMessage.warning(`成功提交 ${successCount} 条,失败 ${failedCount} 条${skipText}`)
|
||||
} else if (successCount === 1 && skippedCount === 0) {
|
||||
ElMessage.success('提交成功')
|
||||
} else {
|
||||
ElMessage.success(`成功提交 ${successCount} 条${skipText}`)
|
||||
}
|
||||
ElMessage.success('提交成功')
|
||||
await refreshList()
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || '提交失败')
|
||||
} finally {
|
||||
loadingMap.submit = false
|
||||
}
|
||||
|
||||
@@ -420,6 +420,22 @@
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-alert
|
||||
v-if="approveRows.length > 1"
|
||||
type="success"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="batch-action-alert batch-action-alert--success"
|
||||
:title="`将${approveAction === 'approve' ? '审批通过' : '审批驳回'} ${approveRows.length} 条申请(使用同一审批意见)`"
|
||||
/>
|
||||
<el-alert
|
||||
v-if="approveSkippedCount > 0"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="batch-action-alert batch-action-alert--danger"
|
||||
:title="`已跳过 ${approveSkippedCount} 条不可审批的申请`"
|
||||
/>
|
||||
<el-form label-position="top" class="bx-dialog-form">
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="审批时间">
|
||||
@@ -570,8 +586,32 @@ function formatNow() {
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
}
|
||||
|
||||
const approveSkippedCount = ref(0)
|
||||
|
||||
function isApprovableRow(row?: any) {
|
||||
if (!row) return false
|
||||
return !row.status || row.status === 'pending'
|
||||
}
|
||||
|
||||
function openApproveDialog(rows: any[], action: 'approve' | 'reject') {
|
||||
approveRows.value = rows
|
||||
const validRows = (rows || []).filter(isApprovableRow)
|
||||
const skippedCount = (rows || []).length - validRows.length
|
||||
|
||||
if (!validRows.length) {
|
||||
ElMessage.warning(
|
||||
action === 'approve' ? '所选申请均不可审批通过' : '所选申请均不可驳回'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (skippedCount > 0) {
|
||||
ElMessage.warning(
|
||||
`已跳过 ${skippedCount} 条不可审批的申请,将继续处理其余 ${validRows.length} 条`
|
||||
)
|
||||
}
|
||||
|
||||
approveRows.value = validRows
|
||||
approveSkippedCount.value = skippedCount
|
||||
approveAction.value = action
|
||||
approvalOpinion.value = action === 'approve' ? '审批通过' : '审批驳回'
|
||||
approveTime.value = formatNow()
|
||||
@@ -742,22 +782,61 @@ const pendingSummaryMethod = amountSummary
|
||||
const approvedSummaryMethod = amountSummary
|
||||
|
||||
async function handleConfirmApprove() {
|
||||
if (!approveRows.value.length) {
|
||||
ElMessage.warning('没有可审批的申请')
|
||||
return
|
||||
}
|
||||
|
||||
const key = approveAction.value === 'approve' ? 'approvePass' : 'approveReject'
|
||||
loadingMap[key] = true
|
||||
const apiFn = approveAction.value === 'approve' ? advanceApi.approve : advanceApi.reject
|
||||
const msg = approveAction.value === 'approve' ? '审批通过成功' : '驳回成功'
|
||||
const actionLabel = approveAction.value === 'approve' ? '审批通过' : '审批驳回'
|
||||
|
||||
try {
|
||||
for (const row of approveRows.value) {
|
||||
await apiFn(row.id, { approvalOpinion: approvalOpinion.value })
|
||||
const results = await Promise.allSettled(
|
||||
approveRows.value.map((row) => apiFn(row.id, { approvalOpinion: approvalOpinion.value }))
|
||||
)
|
||||
const successCount = results.filter((item) => item.status === 'fulfilled').length
|
||||
const failedCount = results.length - successCount
|
||||
const skipText = approveSkippedCount.value > 0 ? `,跳过 ${approveSkippedCount.value} 条` : ''
|
||||
|
||||
if (successCount === 0) {
|
||||
ElMessage.error(`${actionLabel}失败${skipText}`)
|
||||
return
|
||||
}
|
||||
ElMessage.success(approveRows.value.length > 1 ? `批量${msg}` : msg)
|
||||
if (failedCount > 0) {
|
||||
ElMessage.warning(`成功${actionLabel} ${successCount} 条,失败 ${failedCount} 条${skipText}`)
|
||||
} else if (successCount === 1 && approveSkippedCount.value === 0) {
|
||||
ElMessage.success(`${actionLabel}成功`)
|
||||
} else {
|
||||
ElMessage.success(`成功${actionLabel} ${successCount} 条${skipText}`)
|
||||
}
|
||||
|
||||
dialogs.approve = false
|
||||
await refreshPending()
|
||||
await refreshMenuBadges(menuStore.menuList)
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || '操作失败')
|
||||
} finally {
|
||||
loadingMap[key] = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.batch-action-alert {
|
||||
margin-bottom: 12px;
|
||||
|
||||
&--success {
|
||||
:deep(.el-alert__title),
|
||||
:deep(.el-alert__icon) {
|
||||
color: var(--primary, #10b981);
|
||||
}
|
||||
}
|
||||
|
||||
&--danger {
|
||||
:deep(.el-alert__title),
|
||||
:deep(.el-alert__icon) {
|
||||
color: #ef4444;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1107,13 +1107,22 @@ async function handleToolbarSubmit() {
|
||||
ElMessage.warning('请先勾选要提交的报销单')
|
||||
return
|
||||
}
|
||||
if (!selectedRows.value.every(isDraftEditable)) {
|
||||
ElMessage.warning('仅草稿或已驳回的报销单可提交')
|
||||
|
||||
const validTargets = selectedRows.value.filter(isDraftEditable)
|
||||
const skippedCount = selectedRows.value.length - validTargets.length
|
||||
|
||||
if (!validTargets.length) {
|
||||
ElMessage.warning('所选报销单均不是草稿或已驳回状态,无法提交审批')
|
||||
return
|
||||
}
|
||||
|
||||
if (skippedCount > 0) {
|
||||
ElMessage.warning(`已跳过 ${skippedCount} 条不可提交的报销单(仅草稿或已驳回可提交),将继续提交其余 ${validTargets.length} 条`)
|
||||
}
|
||||
|
||||
// 按申请人分别校验发票余额(代申请时用申请人额度)
|
||||
const needByApplicant = new Map<string, number>()
|
||||
for (const row of selectedRows.value) {
|
||||
for (const row of validTargets) {
|
||||
const aid = String(row.applicantId || currentUserId())
|
||||
needByApplicant.set(aid, (needByApplicant.get(aid) || 0) + Number(row.amount || 0))
|
||||
}
|
||||
@@ -1126,15 +1135,26 @@ async function handleToolbarSubmit() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
loadingMap.submit = true
|
||||
try {
|
||||
for (const row of selectedRows.value) {
|
||||
await reimburseApi.submit(row.id)
|
||||
const results = await Promise.allSettled(validTargets.map((row) => reimburseApi.submit(row.id)))
|
||||
const successCount = results.filter((item) => item.status === 'fulfilled').length
|
||||
const failedCount = results.length - successCount
|
||||
const skipText = skippedCount > 0 ? `,跳过 ${skippedCount} 条` : ''
|
||||
|
||||
if (successCount === 0) {
|
||||
ElMessage.error(`提交失败${skipText}`)
|
||||
return
|
||||
}
|
||||
if (failedCount > 0) {
|
||||
ElMessage.warning(`成功提交 ${successCount} 条,失败 ${failedCount} 条${skipText}`)
|
||||
} else if (successCount === 1 && skippedCount === 0) {
|
||||
ElMessage.success('提交成功')
|
||||
} else {
|
||||
ElMessage.success(`成功提交 ${successCount} 条${skipText}`)
|
||||
}
|
||||
ElMessage.success('提交成功')
|
||||
await refreshList()
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || '提交失败')
|
||||
} finally {
|
||||
loadingMap.submit = false
|
||||
}
|
||||
|
||||
@@ -551,6 +551,22 @@
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-alert
|
||||
v-if="approveRows.length > 1"
|
||||
type="success"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="batch-action-alert batch-action-alert--success"
|
||||
:title="`将${approveAction === 'approve' ? '审批通过' : '审批驳回'} ${approveRows.length} 条报销单(使用同一审批意见)`"
|
||||
/>
|
||||
<el-alert
|
||||
v-if="approveSkippedCount > 0"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="batch-action-alert batch-action-alert--danger"
|
||||
:title="`已跳过 ${approveSkippedCount} 条不可审批的报销单`"
|
||||
/>
|
||||
<el-form label-position="top" class="bx-dialog-form">
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="审批时间">
|
||||
@@ -741,8 +757,35 @@ function formatNow() {
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
}
|
||||
|
||||
const approveSkippedCount = ref(0)
|
||||
|
||||
function isApprovableRow(row?: any) {
|
||||
if (!row) return false
|
||||
// 待审批列表中的单据;若状态已变则不可再审
|
||||
return !row.status || row.status === 'pending'
|
||||
}
|
||||
|
||||
function openApproveDialog(rows: any[], action: 'approve' | 'reject') {
|
||||
approveRows.value = rows
|
||||
const validRows = (rows || []).filter(isApprovableRow)
|
||||
const skippedCount = (rows || []).length - validRows.length
|
||||
|
||||
if (!validRows.length) {
|
||||
ElMessage.warning(
|
||||
action === 'approve'
|
||||
? '所选报销单均不可审批通过'
|
||||
: '所选报销单均不可驳回'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (skippedCount > 0) {
|
||||
ElMessage.warning(
|
||||
`已跳过 ${skippedCount} 条不可审批的报销单,将继续处理其余 ${validRows.length} 条`
|
||||
)
|
||||
}
|
||||
|
||||
approveRows.value = validRows
|
||||
approveSkippedCount.value = skippedCount
|
||||
approveAction.value = action
|
||||
approvalOpinion.value = action === 'approve' ? '审批通过' : '审批驳回'
|
||||
approveTime.value = formatNow()
|
||||
@@ -943,20 +986,39 @@ async function openView(row: any) {
|
||||
}
|
||||
|
||||
async function handleConfirmApprove() {
|
||||
if (!approveRows.value.length) {
|
||||
ElMessage.warning('没有可审批的报销单')
|
||||
return
|
||||
}
|
||||
|
||||
const key = approveAction.value === 'approve' ? 'approvePass' : 'approveReject'
|
||||
loadingMap[key] = true
|
||||
const apiFn = approveAction.value === 'approve' ? reimburseApi.approve : reimburseApi.reject
|
||||
const msg = approveAction.value === 'approve' ? '审批通过成功' : '驳回成功'
|
||||
const actionLabel = approveAction.value === 'approve' ? '审批通过' : '审批驳回'
|
||||
|
||||
try {
|
||||
for (const row of approveRows.value) {
|
||||
await apiFn(row.id, { approvalOpinion: approvalOpinion.value })
|
||||
const results = await Promise.allSettled(
|
||||
approveRows.value.map((row) => apiFn(row.id, { approvalOpinion: approvalOpinion.value }))
|
||||
)
|
||||
const successCount = results.filter((item) => item.status === 'fulfilled').length
|
||||
const failedCount = results.length - successCount
|
||||
const skipText = approveSkippedCount.value > 0 ? `,跳过 ${approveSkippedCount.value} 条` : ''
|
||||
|
||||
if (successCount === 0) {
|
||||
ElMessage.error(`${actionLabel}失败${skipText}`)
|
||||
return
|
||||
}
|
||||
ElMessage.success(approveRows.value.length > 1 ? `批量${msg}` : msg)
|
||||
if (failedCount > 0) {
|
||||
ElMessage.warning(`成功${actionLabel} ${successCount} 条,失败 ${failedCount} 条${skipText}`)
|
||||
} else if (successCount === 1 && approveSkippedCount.value === 0) {
|
||||
ElMessage.success(`${actionLabel}成功`)
|
||||
} else {
|
||||
ElMessage.success(`成功${actionLabel} ${successCount} 条${skipText}`)
|
||||
}
|
||||
|
||||
dialogs.approve = false
|
||||
await refreshPending()
|
||||
await refreshMenuBadges(menuStore.menuList)
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.message || '操作失败')
|
||||
} finally {
|
||||
loadingMap[key] = false
|
||||
}
|
||||
@@ -987,3 +1049,23 @@ function viewDetailSummary({ columns, data }: { columns: any[]; data: any[] }) {
|
||||
return sums
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.batch-action-alert {
|
||||
margin-bottom: 12px;
|
||||
|
||||
&--success {
|
||||
:deep(.el-alert__title),
|
||||
:deep(.el-alert__icon) {
|
||||
color: var(--primary, #10b981);
|
||||
}
|
||||
}
|
||||
|
||||
&--danger {
|
||||
:deep(.el-alert__title),
|
||||
:deep(.el-alert__icon) {
|
||||
color: #ef4444;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -496,7 +496,7 @@ async function handleApprove(row: any) {
|
||||
loadingMap[key] = true
|
||||
try {
|
||||
const api = row.bizType === '备用金' ? advanceApi : reimburseApi
|
||||
await api.approve(row.id, { approvalOpinion: '' })
|
||||
await api.approve(row.id, { approvalOpinion: '审批通过' })
|
||||
ElMessage.success('审批通过')
|
||||
await loadData()
|
||||
await refreshSidebarBadges()
|
||||
@@ -509,7 +509,7 @@ async function handleApprove(row: any) {
|
||||
|
||||
function openRejectDialog(row: any) {
|
||||
currentRow.value = row
|
||||
approveOpinion.value = ''
|
||||
approveOpinion.value = '审批驳回'
|
||||
dialogs.approve = true
|
||||
}
|
||||
|
||||
@@ -518,7 +518,8 @@ async function handleDialogApprove() {
|
||||
loadingMap.approvePass = true
|
||||
try {
|
||||
const api = currentRow.value.bizType === '备用金' ? advanceApi : reimburseApi
|
||||
await api.approve(currentRow.value.id, { approvalOpinion: approveOpinion.value })
|
||||
const opinion = approveOpinion.value.trim() || '审批通过'
|
||||
await api.approve(currentRow.value.id, { approvalOpinion: opinion })
|
||||
ElMessage.success('审批通过')
|
||||
dialogs.approve = false
|
||||
await loadData()
|
||||
@@ -535,7 +536,8 @@ async function handleDialogReject() {
|
||||
loadingMap.approveReject = true
|
||||
try {
|
||||
const api = currentRow.value.bizType === '备用金' ? advanceApi : reimburseApi
|
||||
await api.reject(currentRow.value.id, { approvalOpinion: approveOpinion.value })
|
||||
const opinion = approveOpinion.value.trim() || '审批驳回'
|
||||
await api.reject(currentRow.value.id, { approvalOpinion: opinion })
|
||||
ElMessage.success('已驳回')
|
||||
dialogs.approve = false
|
||||
await loadData()
|
||||
@@ -562,7 +564,7 @@ async function handleBatchPass() {
|
||||
try {
|
||||
for (const row of selectedRows.value) {
|
||||
const api = row.bizType === '备用金' ? advanceApi : reimburseApi
|
||||
await api.approve(row.id, { approvalOpinion: '' })
|
||||
await api.approve(row.id, { approvalOpinion: '审批通过' })
|
||||
}
|
||||
ElMessage.success('批量审批通过成功')
|
||||
await loadData()
|
||||
@@ -583,7 +585,7 @@ async function handleBatchReject() {
|
||||
try {
|
||||
for (const row of selectedRows.value) {
|
||||
const api = row.bizType === '备用金' ? advanceApi : reimburseApi
|
||||
await api.reject(row.id, { approvalOpinion: '' })
|
||||
await api.reject(row.id, { approvalOpinion: '审批驳回' })
|
||||
}
|
||||
ElMessage.success('批量驳回成功')
|
||||
await loadData()
|
||||
|
||||
Reference in new issue
Block a user