fix: 修复员工服务、报销单审批及前端交互细节

- 修复员工创建时组织架构关联与邮箱校验逻辑
- 修复报销单API端点参数及预审流程调用
- 优化审批中心、差旅详情等前端页面交互
- 更新侧边栏导航与请求视图模型
- 补充员工服务与报销单相关测试用例
This commit is contained in:
caoxiaozhu
2026-05-20 14:32:35 +08:00
parent d7e98a58b9
commit f8b25a7ccc
14 changed files with 84 additions and 52 deletions

View File

@@ -428,9 +428,9 @@ export default {
actionBusy.value = true
try {
await returnExpenseClaim(row.claimId, {
reason: '审批中心退回,请申请人补充后重新提交。'
reason: '审批中心退回,请申请人调整后重新提交。'
})
toast(`${row.id} 已退回待补充`)
toast(`${row.id} 已退回待提交`)
returnDialogOpen.value = false
selectedClaimId.value = ''
await reload()

View File

@@ -264,21 +264,21 @@ function formatEmployeeHistoryTime(value) {
return ''
}
const matched = raw.match(
/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/
const chineseMatched = raw.match(
/^(\d{4})(\d{1,2})(\d{1,2})(\d{1,2})(\d{1,2})(?:\d{1,2}秒)?$/
)
if (!matched) {
return raw
if (chineseMatched) {
const [, year, month, day, hour, minute] = chineseMatched
return `${year}${Number(month)}${Number(day)}${Number(hour)}${Number(minute)}`
}
const year = Number.parseInt(matched[1], 10)
const month = Number.parseInt(matched[2], 10)
const day = Number.parseInt(matched[3], 10)
const hour = Number.parseInt(matched[4] || '0', 10)
const minute = Number.parseInt(matched[5] || '0', 10)
const second = Number.parseInt(matched[6] || '0', 10)
const isoMatched = raw.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}))?/)
if (isoMatched) {
const [, year, month, day, hour = '0', minute = '0'] = isoMatched
return `${year}${Number(month)}${Number(day)}${Number(hour)}${Number(minute)}`
}
return `${year}${month}${day}${hour}${minute}${second}`
return raw.replace(/(\d{1,2}分)\d{1,2}秒$/, '$1')
}
function resolveOrganizationUnitCode(employee) {

View File

@@ -454,8 +454,9 @@ export default {
const isTravelRequest = computed(() => request.value.detailVariant === 'travel')
const isDraftRequest = computed(() => request.value.approvalKey === 'draft')
const isEditableRequest = computed(() => ['draft', 'supplement'].includes(request.value.approvalKey))
const canManageCurrentClaim = computed(() => canManageExpenseClaims(currentUser.value))
const canDeleteRequest = computed(() => isDraftRequest.value || canManageCurrentClaim.value)
const canDeleteRequest = computed(() => isEditableRequest.value || canManageCurrentClaim.value)
const canReturnRequest = computed(() =>
canManageCurrentClaim.value
&& request.value.approvalKey === 'in_progress'
@@ -584,7 +585,7 @@ export default {
const uploadedExpenseCount = computed(() => expenseItems.value.filter((item) => item.attachments.length).length)
const hasExpenseRiskColumn = computed(() => expenseItems.value.some((item) => item.attachments.length))
const expenseTableColumnCount = computed(
() => 5 + (hasExpenseRiskColumn.value ? 1 : 0) + (isDraftRequest.value ? 1 : 0)
() => 5 + (hasExpenseRiskColumn.value ? 1 : 0) + (isEditableRequest.value ? 1 : 0)
)
const expenseSummaryText = computed(
() => request.value.expenseTableSummary || '请继续补充票据、说明和系统校验结果。'
@@ -595,9 +596,9 @@ export default {
|| '暂无附加说明。可在这里补充特殊背景、例外原因、补件计划或其他需要财务和审批人重点关注的信息。'
)
const draftBlockingIssues = computed(() =>
isDraftRequest.value ? buildDraftBlockingIssues(request.value, expenseItems.value) : []
isEditableRequest.value ? buildDraftBlockingIssues(request.value, expenseItems.value) : []
)
const canSubmit = computed(() => isDraftRequest.value && draftBlockingIssues.value.length === 0 && !actionBusy.value)
const canSubmit = computed(() => isEditableRequest.value && draftBlockingIssues.value.length === 0 && !actionBusy.value)
const locationInputPlaceholder = computed(() => resolveLocationInputPlaceholder(expenseEditor.itemType))
function applyLocalExpenseItemPatch(itemId, patch) {
@@ -807,7 +808,7 @@ export default {
})
function startExpenseEdit(item) {
if (!isDraftRequest.value || actionBusy.value) {
if (!isEditableRequest.value || actionBusy.value) {
return
}
@@ -850,7 +851,7 @@ export default {
}
async function handleAddExpenseItem() {
if (!isDraftRequest.value || actionBusy.value) {
if (!isEditableRequest.value || actionBusy.value) {
return
}
@@ -884,7 +885,7 @@ export default {
}
function triggerExpenseUpload(item) {
if (!isDraftRequest.value || actionBusy.value) {
if (!isEditableRequest.value || actionBusy.value) {
return
}
@@ -1198,10 +1199,10 @@ export default {
returnBusy.value = true
try {
await returnExpenseClaim(request.value.claimId, {
reason: '详情页退回,请申请人补充后重新提交。'
reason: '详情页退回,请申请人调整后重新提交。'
})
returnDialogOpen.value = false
toast(`${request.value.id} 已退回待补充`)
toast(`${request.value.id} 已退回待提交`)
emit('request-updated', { claimId: request.value.claimId })
} catch (error) {
toast(error?.message || '退回单据失败,请稍后重试。')
@@ -1270,6 +1271,7 @@ export default {
hasExpenseRiskColumn,
heroFactItems,
isDraftRequest,
isEditableRequest,
isTravelRequest,
locationInputPlaceholder,
openAiEntry,