feat(web): update composables

- useAppShell.js: update app shell composable
- useRequests.js: update requests composable
This commit is contained in:
caoxiaozhu
2026-05-13 06:48:27 +00:00
parent 8bc919386b
commit 6c8947f40f
2 changed files with 55 additions and 13 deletions

View File

@@ -77,7 +77,7 @@ export function useAppShell() {
}) })
const requestSummary = computed(() => const requestSummary = computed(() =>
requests.value.reduce( filteredRequests.value.reduce(
(summary, item) => { (summary, item) => {
const request = normalizeRequestForUi(item) const request = normalizeRequestForUi(item)
if (!request) { if (!request) {

View File

@@ -14,6 +14,15 @@ const EXPENSE_TYPE_LABELS = {
other: '其他费用' other: '其他费用'
} }
const LOCATION_REQUIRED_EXPENSE_TYPES = new Set([
'travel',
'hotel',
'transport',
'meal',
'meeting',
'entertainment'
])
const REIMBURSEMENT_PROGRESS_LABELS = [ const REIMBURSEMENT_PROGRESS_LABELS = [
'保存草稿', '保存草稿',
'待提交', '待提交',
@@ -73,6 +82,32 @@ function resolveTypeLabel(typeCode) {
return EXPENSE_TYPE_LABELS[String(typeCode || '').trim()] || EXPENSE_TYPE_LABELS.other return EXPENSE_TYPE_LABELS[String(typeCode || '').trim()] || EXPENSE_TYPE_LABELS.other
} }
function normalizeExpenseType(typeCode) {
return String(typeCode || '').trim() || 'other'
}
function isLocationRequiredExpenseType(typeCode) {
return LOCATION_REQUIRED_EXPENSE_TYPES.has(normalizeExpenseType(typeCode))
}
function resolveLocationDisplay(location, typeCode) {
const normalized = String(location || '').trim()
if (normalized) {
return normalized
}
return isLocationRequiredExpenseType(typeCode) ? '待补充' : '非必填'
}
function resolveAttachmentDisplayName(value) {
const normalized = String(value || '').trim()
if (!normalized) {
return ''
}
return normalized.split('/').filter(Boolean).pop() || normalized
}
function resolveApprovalMeta(status) { function resolveApprovalMeta(status) {
const normalized = String(status || '').trim().toLowerCase() const normalized = String(status || '').trim().toLowerCase()
@@ -261,28 +296,35 @@ function buildExpenseItems(claim, riskSummary) {
} }
return claim.items.map((item, index) => { return claim.items.map((item, index) => {
const attachments = String(item?.invoice_id || '').trim() ? [String(item.invoice_id).trim()] : [] const invoiceId = String(item?.invoice_id || '').trim()
const itemTypeLabel = resolveTypeLabel(item?.item_type || claim?.expense_type) const attachmentName = resolveAttachmentDisplayName(invoiceId)
const attachments = invoiceId ? [attachmentName || invoiceId] : []
const itemType = normalizeExpenseType(item?.item_type || claim?.expense_type)
const itemTypeLabel = resolveTypeLabel(itemType)
const itemLocation = String(item?.item_location || '').trim()
const itemReason = String(item?.item_reason || '').trim()
const itemAmount = parseNumber(item?.item_amount)
const itemAmountDisplay = itemAmount > 0 ? formatAmount(itemAmount) : '待补充'
return { return {
id: String(item?.id || `${claim?.id || 'claim'}-item-${index}`), id: String(item?.id || `${claim?.id || 'claim'}-item-${index}`),
time: formatDate(item?.item_date) || '待补充', time: formatDate(item?.item_date) || '待补充',
itemDate: formatDate(item?.item_date) || '', itemDate: formatDate(item?.item_date) || '',
itemType: String(item?.item_type || claim?.expense_type || '').trim() || 'other', itemType,
itemReason: String(item?.item_reason || claim?.reason || '').trim(), itemReason,
itemLocation: String(item?.item_location || claim?.location || '').trim(), itemLocation,
itemAmount: parseNumber(item?.item_amount), itemAmount,
invoiceId: String(item?.invoice_id || '').trim(), invoiceId,
dayLabel: claim?.expense_type === 'travel' ? `${index + 1}` : '业务发生项', dayLabel: claim?.expense_type === 'travel' ? `${index + 1}` : '业务发生项',
name: itemTypeLabel, name: itemTypeLabel,
category: itemTypeLabel, category: itemTypeLabel,
desc: String(item?.item_reason || claim?.reason || '').trim() || '待补充', desc: itemReason || '待补充',
detail: String(item?.item_location || claim?.location || '').trim() || '待补充', detail: resolveLocationDisplay(itemLocation, itemType),
amount: formatAmount(item?.item_amount), amount: itemAmountDisplay,
status: attachments.length ? '已识别' : '待补充', status: attachments.length ? '已识别' : '待补充',
tone: attachments.length ? 'ok' : 'bad', tone: attachments.length ? 'ok' : 'bad',
attachmentStatus: attachments.length ? `${attachments.length} 份附件` : '上传', attachmentStatus: attachments.length ? `${attachments.length} 份附件` : '上传',
attachmentHint: attachments.length ? attachments[0] : '暂无关联票据', attachmentHint: attachments.length ? attachments[0] : '支持上传 JPG、PNG、PDF未上传也可先保存草稿',
attachmentTone: attachments.length ? 'ok' : 'missing', attachmentTone: attachments.length ? 'ok' : 'missing',
attachments, attachments,
riskLabel: riskSummary === '无' ? '无' : '待关注', riskLabel: riskSummary === '无' ? '无' : '待关注',