feat(web): 票据夹资产缓存接入与 AI 工作台附件流程完善
- ReceiptFolderView 删除票据后提示已关联附件副本保留,接入 useToast;fetchReceiptFolderAsset 加 no-store 避免预览缓存 - PersonalWorkbenchAiMode 附件区/对话气泡适配资产缓存,personal-workbench-ai-mode.css 调整布局 - usePersonalWorkbenchAiMode/useWorkbenchAiApplicationPreviewFlow/useWorkbenchAiAttachmentAssociationFlow/useWorkbenchAiStewardFlow 完善附件草稿选择与关联流程 - travelRequestDetailSmartEntryRecognition 智能识别增强,AppShellRouteView/PersonalWorkbenchView/useApplicationPreviewEditor/useTravelReimbursementSubmitComposer 等配套适配 - 新增 expense-attachment-draft-selection、receipt-folder-asset-cache、travel-request-detail-smart-entry-recognition 测试,更新 attachment-association-confirmation、expense-application-fast-preview、workbench-ai-mode-switch 测试
This commit is contained in:
90
web/tests/expense-attachment-draft-selection.test.mjs
Normal file
90
web/tests/expense-attachment-draft-selection.test.mjs
Normal file
@@ -0,0 +1,90 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import { useTravelReimbursementCreateViewControls } from '../src/views/scripts/useTravelReimbursementCreateViewControls.js'
|
||||
|
||||
function ref(value) {
|
||||
return { value }
|
||||
}
|
||||
|
||||
const submitComposerScript = readFileSync(
|
||||
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSubmitComposer.js', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
test('选择候选草稿时直接确认归集并带入附件原件', async () => {
|
||||
const submitCalls = []
|
||||
const attachedFiles = [{ name: '2月20 武汉-上海.pdf' }]
|
||||
const message = {
|
||||
queryPayload: {
|
||||
selectionMode: 'draft_association'
|
||||
}
|
||||
}
|
||||
|
||||
const controls = useTravelReimbursementCreateViewControls({
|
||||
activeSessionType: ref('expense'),
|
||||
attachedFiles: ref(attachedFiles),
|
||||
clearAssistantSessionSnapshot: () => {},
|
||||
closeAfterBusy: ref(false),
|
||||
conversationId: ref('conversation-1'),
|
||||
deleteConversation: async () => {},
|
||||
deleteSessionBusy: ref(false),
|
||||
deleteSessionDialogOpen: ref(false),
|
||||
draftClaimId: ref(''),
|
||||
emitClose: () => {},
|
||||
getExpenseQueryActivePage: () => 1,
|
||||
getExpenseQueryTotalPages: () => 1,
|
||||
persistSessionState: () => {},
|
||||
resetCurrentSessionState: () => {},
|
||||
reviewActionBusy: ref(false),
|
||||
router: { push: () => {} },
|
||||
resolveCurrentUserId: () => 'user-1',
|
||||
sessionSwitchBusy: ref(false),
|
||||
submitComposer: async (options) => {
|
||||
submitCalls.push(options)
|
||||
return { ok: true }
|
||||
},
|
||||
submitting: ref(false),
|
||||
toast: () => {},
|
||||
workbenchVisible: ref(true)
|
||||
})
|
||||
|
||||
await controls.handleExpenseQueryRecordClick(message, {
|
||||
claimId: 'claim-1',
|
||||
claimNo: 'R74CB7C2R'
|
||||
})
|
||||
|
||||
assert.equal(submitCalls.length, 1)
|
||||
assert.equal(submitCalls[0].associationConfirmed, true)
|
||||
assert.equal(submitCalls[0].skipDraftAssociationPrompt, true)
|
||||
assert.equal(submitCalls[0].uploadDisposition, 'continue_existing')
|
||||
assert.deepEqual(submitCalls[0].files, attachedFiles)
|
||||
assert.equal(submitCalls[0].files[0], attachedFiles[0])
|
||||
assert.equal(submitCalls[0].extraContext.review_action, 'link_to_existing_draft')
|
||||
assert.equal(submitCalls[0].extraContext.attachment_association_confirmed, true)
|
||||
assert.equal(submitCalls[0].extraContext.draft_claim_id, 'claim-1')
|
||||
assert.equal(message.queryPayload.selectionLocked, true)
|
||||
assert.equal(message.queryPayload.selectedClaimId, 'claim-1')
|
||||
})
|
||||
|
||||
test('确认归集到现有草稿时先同步附件再渲染最终结果', () => {
|
||||
assert.match(
|
||||
submitComposerScript,
|
||||
/let attachmentSyncCompleted = false/
|
||||
)
|
||||
assert.match(
|
||||
submitComposerScript,
|
||||
/if \(\s*reviewActionResult === 'link_to_existing_draft'[\s\S]*await persistComposerFilesToDraft\(\)[\s\S]*attachmentSyncCompleted = true[\s\S]*\}/
|
||||
)
|
||||
assert.ok(
|
||||
submitComposerScript.indexOf('await persistComposerFilesToDraft()') <
|
||||
submitComposerScript.indexOf('const assistantMessage = createMessage('),
|
||||
'附件同步应先于最终助手消息,避免详情页先展示空明细和旧风险'
|
||||
)
|
||||
assert.match(
|
||||
submitComposerScript,
|
||||
/if \(!attachmentSyncCompleted\) \{\s*const persistTask = persistComposerFilesToDraft\(\)/
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user