feat: 完善文档中心与报销申请交互及侧边栏重构

后端优化编排器报销查询和本体检测精度,增强报销单草稿保
存和附件回填逻辑,前端重构侧边栏组件支持折叠和图标导
航,完善文档中心状态筛选和详情提示,报销创建和审批详情
页优化会话管理和费用明细交互,新增助手应用服务和预设动
作工具函数,补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-25 13:35:39 +08:00
parent 50b1c3f9a9
commit d0e946cf47
59 changed files with 5117 additions and 416 deletions

View File

@@ -15,7 +15,9 @@ import {
} from '../src/views/scripts/travelRequestDetailInsights.js'
import {
buildExpenseItemViewModel,
buildDraftBlockingIssues
buildDraftBlockingIssues,
buildOptionalTravelReceiptRiskCards,
isApplicationDocumentRequest
} from '../src/views/scripts/travelRequestDetailExpenseModel.js'
const detailViewTemplate = readFileSync(
@@ -412,7 +414,7 @@ test('expense attachment actions keep preview as the only recognition entry poin
})
test('expense detail table shows the amount total below detail rows', () => {
assert.match(detailViewTemplate, /<div class="detail-expense-table">/)
assert.match(detailViewTemplate, /<div[^>]*class="detail-expense-table"/)
assert.match(detailViewTemplate, /当前还没有费用明细/)
assert.doesNotMatch(detailViewTemplate, /class="total-row"/)
assert.match(detailViewTemplate, /class="expense-total-under-table"[\s\S]*金额合计[\s\S]*\{\{ expenseTotal \}\}/)
@@ -421,7 +423,10 @@ test('expense detail table shows the amount total below detail rows', () => {
})
test('additional note is shown above expense details as travel purpose text', () => {
assert.ok(detailViewTemplate.indexOf('<h3>附加说明</h3>') < detailViewTemplate.indexOf('<h3>费用明细</h3>'))
assert.ok(
detailViewTemplate.indexOf('<h3>附加说明</h3>')
< detailViewTemplate.indexOf("isApplicationDocument ? '申请预算' : '费用明细'")
)
assert.match(detailViewTemplate, /用于说明本次出差或办事目的/)
assert.match(detailViewTemplate, /v-if="canEditDetailNote" class="detail-note-editor"/)
assert.match(detailViewTemplate, /v-else class="detail-note readonly"/)
@@ -514,6 +519,7 @@ test('expense detail edit keeps delete but removes cancel and allows draft place
test('travel detail AI advice adds low risk reminders for optional receipts', () => {
assert.match(detailViewScript, /function buildOptionalTravelReceiptRiskCards\(requestModel, items\)/)
assert.match(detailViewScript, /isApplicationDocumentRequest\(requestModel\)[\s\S]*return \[\]/)
assert.match(detailViewScript, /id: 'travel-optional-hotel-ticket'[\s\S]*tone: 'low'[\s\S]*住宿票据提醒/)
assert.match(detailViewScript, /不要忘记补充酒店住宿票据/)
assert.match(detailViewScript, /id: 'travel-optional-ride-ticket'[\s\S]*tone: 'low'[\s\S]*乘车票据提醒/)
@@ -539,6 +545,33 @@ test('expense detail save is blocked while attachment recognition is running', (
)
})
test('application detail uses application labels instead of reimbursement labels', () => {
assert.match(detailViewTemplate, /isApplicationDocument \? '申请进度'/)
assert.match(detailViewTemplate, /isApplicationDocument \? '申请预算' : '费用明细'/)
assert.match(detailViewTemplate, /无需补充任何报销票据/)
assert.match(detailViewTemplate, /isApplicationDocument \? '申请类型' : '报销类型'/)
assert.match(detailViewTemplate, /isApplicationDocument \? '预计金额' : '报销金额'/)
assert.match(detailViewTemplate, /isApplicationDocument \? '退回申请' : '退回单据'/)
assert.match(detailViewTemplate, /当前申请单已进入流程,详情页仅展示状态与申请信息。/)
})
test('application detail does not show optional travel receipt reminders', () => {
const request = {
documentTypeCode: 'application',
claimNo: 'APP-20260525-ABC123',
typeCode: 'travel_application',
detailVariant: 'travel'
}
assert.equal(isApplicationDocumentRequest(request), true)
assert.deepEqual(
buildOptionalTravelReceiptRiskCards(request, [
{ id: 'allowance', itemType: 'travel_allowance', isSystemGenerated: true, invoiceId: '' }
]),
[]
)
})
test('draft submit validation uses expense detail date and amount when claim summary is stale', () => {
const issues = buildDraftBlockingIssues(
{