fix(expenses): refine operation record audit UI

This commit is contained in:
caoxiaozhu
2026-07-20 10:31:27 +08:00
parent 2a9b3e3273
commit 2a1a5991cb
5 changed files with 278 additions and 96 deletions

View File

@@ -6,7 +6,8 @@ import { effectScope, nextTick, ref } from 'vue'
import {
buildExpenseCaseTimelineViewModel,
isExpenseCaseNotAvailableError
isExpenseCaseNotAvailableError,
orderExpenseCaseEventsForDisplay
} from '../src/utils/expenseCaseTimeline.js'
import { fetchExpenseCaseTimeline } from '../src/services/expenseCases.js'
import { useExpenseCaseTimeline } from '../src/composables/requests/useExpenseCaseTimeline.js'
@@ -69,6 +70,7 @@ test('expense case timeline maps and sorts the real business event chain', () =>
assert.equal(timeline.linkCount, 2)
assert.deepEqual(timeline.events.map((event) => event.id), ['event-1', 'event-2'])
assert.equal(timeline.events[0].label, '费用申请已提交')
assert.equal(timeline.events[0].icon, 'mdi mdi-file-send-outline')
assert.match(timeline.events[0].summary, /草稿 → 已提交/)
assert.match(timeline.events[0].summary, /直属领导审批/)
assert.equal(timeline.events[0].actorLabel, 'employee@example.com')
@@ -139,6 +141,7 @@ test('expense case timeline explains receipt collection, association and AI pre-
assert.match(timeline.events[0].summary, /上海出差高铁票\.pdf/)
assert.match(timeline.events[1].summary, /BX-20260713-001/)
assert.equal(timeline.events[2].tone, 'warning')
assert.equal(timeline.events[2].icon, 'mdi mdi-shield-check-outline')
assert.match(timeline.events[2].summary, /1 条重大风险/)
})
@@ -246,6 +249,37 @@ test('expense case timeline keeps equal-time server order and hides unknown even
assert.doesNotMatch(JSON.stringify(timeline.events[0]), /private-correlation|pending/)
})
test('expense case records show newer events first and preserve equal-time server order', () => {
const timeline = buildExpenseCaseTimelineViewModel({
events: [
{
id: 'older',
event_type: 'application_submitted',
occurred_at: '2026-07-17T14:54:00Z'
},
{
id: 'newer-first',
event_type: 'application_pre_review_completed',
occurred_at: '2026-07-18T02:00:00Z'
},
{
id: 'newer-second',
event_type: 'claim_submitted',
occurred_at: '2026-07-18T02:00:00Z'
}
]
})
const displayedEvents = orderExpenseCaseEventsForDisplay(timeline.events)
assert.deepEqual(
displayedEvents.map((event) => event.id),
['newer-first', 'newer-second', 'older']
)
assert.equal(displayedEvents[0].icon, 'mdi mdi-shield-check-outline')
assert.deepEqual(timeline.events.map((event) => event.id), ['older', 'newer-first', 'newer-second'])
})
test('expense case service safely encodes claim identifiers', async () => {
const originalFetch = globalThis.fetch
let requestedUrl = ''
@@ -351,7 +385,11 @@ test('travel request detail consumes the real expense case endpoint', () => {
assert.match(detailView, /:refresh-key="expenseCaseTimelineRefreshKey"/)
assert.match(progressCard, /<TravelRequestExpenseCaseTimeline/)
assert.match(progressCard, /TravelRequestExpenseCaseTimeline/)
assert.match(timelineComponent, /费用事件时间线/)
assert.match(timelineComponent, /费用操作记录/)
assert.match(timelineComponent, /发生时间/)
assert.match(timelineComponent, /操作人/)
assert.doesNotMatch(timelineComponent, /expense-case-latest/)
assert.match(timelineComponent, /orderExpenseCaseEventsForDisplay/)
assert.match(timelineComponent, /当前单据尚未纳入统一费用事件/)
assert.match(expenseCaseService, /\/expense-cases\/by-claim\//)
})