feat: 完善文档中心与报销申请交互及侧边栏重构
后端优化编排器报销查询和本体检测精度,增强报销单草稿保 存和附件回填逻辑,前端重构侧边栏组件支持折叠和图标导 航,完善文档中心状态筛选和详情提示,报销创建和审批详情 页优化会话管理和费用明细交互,新增助手应用服务和预设动 作工具函数,补充单元测试覆盖。
This commit is contained in:
@@ -4,7 +4,12 @@ import test from 'node:test'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import {
|
||||
APPLICATION_WELCOME_QUICK_ACTIONS,
|
||||
APPROVAL_WELCOME_QUICK_ACTIONS,
|
||||
ASSISTANT_SESSION_MODE_OPTIONS,
|
||||
EXPENSE_WELCOME_QUICK_ACTIONS,
|
||||
SESSION_TYPE_APPLICATION,
|
||||
SESSION_TYPE_APPROVAL,
|
||||
SESSION_TYPE_EXPENSE,
|
||||
SESSION_TYPE_KNOWLEDGE,
|
||||
buildWelcomeQuickActions
|
||||
@@ -40,6 +45,10 @@ import {
|
||||
selectGuidedQueryMode,
|
||||
shouldConfirmGuidedInterruption
|
||||
} from '../src/views/scripts/travelReimbursementGuidedFlowModel.js'
|
||||
import {
|
||||
ASSISTANT_SCOPE_ACTION_SWITCH,
|
||||
resolveAssistantScopeGuard
|
||||
} from '../src/utils/assistantSessionScope.js'
|
||||
|
||||
const createViewScript = readFileSync(
|
||||
fileURLToPath(new URL('../src/views/scripts/TravelReimbursementCreateView.js', import.meta.url)),
|
||||
@@ -53,8 +62,16 @@ const sessionStateScript = readFileSync(
|
||||
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSessionState.js', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
const submitComposerScript = readFileSync(
|
||||
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSubmitComposer.js', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
test('welcome quick actions are reduced to three guided local actions', () => {
|
||||
test('assistant session modes expose independent quick actions', () => {
|
||||
assert.deepEqual(
|
||||
ASSISTANT_SESSION_MODE_OPTIONS.map((item) => item.label),
|
||||
['申请助手', '报销助手', '审核助手', '财务知识助手']
|
||||
)
|
||||
assert.deepEqual(
|
||||
EXPENSE_WELCOME_QUICK_ACTIONS.map((item) => item.label),
|
||||
['快速发起报销', '查询单据状态', '差旅计算器']
|
||||
@@ -69,6 +86,14 @@ test('welcome quick actions are reduced to three guided local actions', () => {
|
||||
)
|
||||
assert.ok(EXPENSE_WELCOME_QUICK_ACTIONS.every((item) => !item.prompt))
|
||||
assert.equal(buildWelcomeQuickActions(SESSION_TYPE_EXPENSE).length, 3)
|
||||
assert.deepEqual(
|
||||
buildWelcomeQuickActions(SESSION_TYPE_APPLICATION).map((item) => item.label),
|
||||
APPLICATION_WELCOME_QUICK_ACTIONS.map((item) => item.label)
|
||||
)
|
||||
assert.deepEqual(
|
||||
buildWelcomeQuickActions(SESSION_TYPE_APPROVAL).map((item) => item.label),
|
||||
APPROVAL_WELCOME_QUICK_ACTIONS.map((item) => item.label)
|
||||
)
|
||||
assert.notDeepEqual(
|
||||
buildWelcomeQuickActions(SESSION_TYPE_KNOWLEDGE).map((item) => item.label),
|
||||
EXPENSE_WELCOME_QUICK_ACTIONS.map((item) => item.label),
|
||||
@@ -76,6 +101,34 @@ test('welcome quick actions are reduced to three guided local actions', () => {
|
||||
)
|
||||
})
|
||||
|
||||
test('assistant session scope guard keeps business boundaries isolated', () => {
|
||||
const expenseInApplication = resolveAssistantScopeGuard('我想报销的士票', SESSION_TYPE_APPLICATION)
|
||||
assert.equal(expenseInApplication.targetSessionType, SESSION_TYPE_EXPENSE)
|
||||
assert.match(expenseInApplication.text, /申请助手/)
|
||||
assert.match(expenseInApplication.text, /报销助手/)
|
||||
assert.equal(expenseInApplication.suggestedActions[0].action_type, ASSISTANT_SCOPE_ACTION_SWITCH)
|
||||
assert.equal(expenseInApplication.suggestedActions[0].payload.session_type, SESSION_TYPE_EXPENSE)
|
||||
assert.equal(expenseInApplication.suggestedActions[0].payload.carry_text, '我想报销的士票')
|
||||
|
||||
assert.equal(resolveAssistantScopeGuard('我想发起一笔费用申请', SESSION_TYPE_APPLICATION), null)
|
||||
assert.equal(
|
||||
resolveAssistantScopeGuard('帮我查询待我审核的单据', SESSION_TYPE_EXPENSE).targetSessionType,
|
||||
SESSION_TYPE_APPROVAL
|
||||
)
|
||||
assert.equal(
|
||||
resolveAssistantScopeGuard('差旅住宿标准是多少', SESSION_TYPE_EXPENSE).targetSessionType,
|
||||
SESSION_TYPE_KNOWLEDGE
|
||||
)
|
||||
assert.equal(
|
||||
resolveAssistantScopeGuard('报销标准是多少', SESSION_TYPE_EXPENSE).targetSessionType,
|
||||
SESSION_TYPE_KNOWLEDGE
|
||||
)
|
||||
assert.equal(
|
||||
resolveAssistantScopeGuard('解释这张单据酒店超标风险', SESSION_TYPE_EXPENSE, { hasActiveReviewPayload: true }),
|
||||
null
|
||||
)
|
||||
})
|
||||
|
||||
test('guided reimbursement asks type first and walks travel fields in order', () => {
|
||||
const typeActions = buildGuidedExpenseTypeActions()
|
||||
assert.deepEqual(
|
||||
@@ -177,6 +230,9 @@ test('guided flow state is serializable and restored through session state', ()
|
||||
assert.match(sessionStateScript, /guidedFlowState,\s*\n\s*insightPanelCollapsed/)
|
||||
assert.match(sessionStateScript, /function refreshWelcomeQuickActions/)
|
||||
assert.match(sessionStateScript, /buildWelcomeQuickActions\(/)
|
||||
assert.match(sessionStateScript, /ASSISTANT_SESSION_TYPES\.reduce/)
|
||||
assert.match(sessionStateScript, /props\.entrySource === 'application' \? SESSION_TYPE_APPLICATION : SESSION_TYPE_EXPENSE/)
|
||||
assert.match(sessionStateScript, /const canRestorePersistedInitialState =[\s\S]*shouldPersistLocalSnapshot/)
|
||||
})
|
||||
|
||||
test('guided flow is local until final confirmation or collected query handoff', () => {
|
||||
@@ -184,6 +240,10 @@ test('guided flow is local until final confirmation or collected query handoff',
|
||||
assert.doesNotMatch(guidedFlowScript, /startExpenseClaimDraftFlowStep/)
|
||||
assert.doesNotMatch(guidedFlowScript, /review_action:\s*['"]save_draft['"]/)
|
||||
assert.match(createViewScript, /if \(await handleGuidedComposerSubmit\(options\)\) \{[\s\S]*return null[\s\S]*\}[\s\S]*return submitComposerInternal\(options\)/)
|
||||
assert.match(createViewScript, /ASSISTANT_SCOPE_ACTION_SWITCH/)
|
||||
assert.match(createViewScript, /actionPayload\.carry_text/)
|
||||
assert.match(submitComposerScript, /resolveAssistantScopeGuard/)
|
||||
assert.match(submitComposerScript, /skipScopeGuard/)
|
||||
assert.match(guidedFlowScript, /submitExistingComposer\(submitOptions\)/)
|
||||
assert.match(guidedFlowScript, /submitExistingComposer\(\{[\s\S]*pendingText:\s*'正在查询单据状态\.\.\.'/)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user