feat(web): 工作台 AI 模式与差旅/风险建议交互优化
- 新增 PersonalWorkbenchAiMode 组件、AI 侧边栏与 orb 机器人视觉资源 - 新增 aiApplicationDraftModel / aiExpenseDraftModel / aiWorkbenchConversationStore 及业务准入 aiSidebarBusinessAccess,支撑 AI 模式下的申请与报销草稿 - 顶栏、侧边栏、工作台样式重构,适配 AI 模式切换与响应式布局 - 同步 steward plan/off_topic、差旅报销引导流、风险建议卡片等测试
This commit is contained in:
@@ -22,7 +22,7 @@ const OFF_TOPIC_PLAN = {
|
||||
attachment_groups: [],
|
||||
confirmation_groups: [],
|
||||
candidate_flows: [],
|
||||
summary: '这看起来跟财务任务没什么关系...',
|
||||
summary: '很抱歉主人,目前小财管家只能帮您整理**费用申请**和**费用报销**这两类事项。',
|
||||
suggested_prompts: [
|
||||
'我想要申请明天去北京出差3天,支撑客户现场实施',
|
||||
'我要报销上周去上海的高铁票',
|
||||
@@ -64,24 +64,60 @@ test('isOffTopicStewardPlan returns true only for off_topic plan status', () =>
|
||||
assert.equal(isOffTopicStewardPlan({}), false)
|
||||
})
|
||||
|
||||
test('buildStewardPlanMessageText renders friendly off_topic guidance', () => {
|
||||
test('buildStewardPlanMessageText renders backend-provided off_topic summary verbatim', () => {
|
||||
// off_topic 文案由后端(含 LLM)生成,前端只负责透传,不再拼接标题/引导
|
||||
const text = buildStewardPlanMessageText(OFF_TOPIC_PLAN)
|
||||
assert.match(text, /小财管家没看懂这件事/)
|
||||
assert.equal(text, OFF_TOPIC_PLAN.summary)
|
||||
// 推荐话术本身不在正文里展示,而是作为按钮单独渲染,避免重复。
|
||||
for (const prompt of OFF_TOPIC_PLAN.suggested_prompts) {
|
||||
assert.equal(text.includes(prompt), false, `正文不应包含推荐话术:${prompt}`)
|
||||
}
|
||||
})
|
||||
|
||||
test('buildStewardPlanMessageText keeps off_topic branch ahead of pending flow branch', () => {
|
||||
// 即使 summary 缺省,也走 off_topic 分支而非默认任务文案
|
||||
const text = buildStewardPlanMessageText({
|
||||
plan_id: 'p-off-topic-default',
|
||||
test('buildStewardPlanMessageText adapts greeting vs meaningless vs off_business summaries', () => {
|
||||
// 问候场景:礼貌回应主人
|
||||
const greetingText = buildStewardPlanMessageText({
|
||||
plan_id: 'p-greeting',
|
||||
plan_status: 'off_topic',
|
||||
next_action: 'none',
|
||||
suggested_prompts: ['申请出差']
|
||||
summary: '### 您好主人,很高兴为您服务\n\n请问您今天要办理什么业务?',
|
||||
suggested_prompts: ['我想要申请明天去北京出差3天']
|
||||
})
|
||||
assert.match(text, /小财管家没看懂这件事/)
|
||||
assert.match(greetingText, /您好主人/)
|
||||
assert.match(greetingText, /请问您今天要办理什么业务/)
|
||||
|
||||
// 无意义场景:温和解释 + 引导换种说法
|
||||
const meaninglessText = buildStewardPlanMessageText({
|
||||
plan_id: 'p-meaningless',
|
||||
plan_status: 'off_topic',
|
||||
next_action: 'none',
|
||||
summary: '### 这句话我暂时没识别到财务事项\n\n很抱歉主人,目前小财管家只能帮您整理**费用申请**和**费用报销**。',
|
||||
suggested_prompts: ['我想要申请明天去北京出差3天']
|
||||
})
|
||||
assert.match(meaninglessText, /这句话我暂时没识别到财务事项/)
|
||||
assert.match(meaninglessText, /很抱歉主人/)
|
||||
|
||||
// 有意义但非业务场景:LLM 生成的文案(这里 mock 模拟)
|
||||
const llmText = '### 抱歉主人,这句话我暂时帮不上忙\n\n主人聊的是天气,小财管家目前只能帮您整理**费用申请**和**费用报销**。'
|
||||
const offBusinessText = buildStewardPlanMessageText({
|
||||
plan_id: 'p-off-business',
|
||||
plan_status: 'off_topic',
|
||||
next_action: 'none',
|
||||
summary: llmText,
|
||||
suggested_prompts: ['我想要申请明天去北京出差3天']
|
||||
})
|
||||
assert.equal(offBusinessText, llmText)
|
||||
})
|
||||
|
||||
test('buildStewardPlanMessageText falls back to client template when summary is missing', () => {
|
||||
// 后端 summary 缺失时,前端有兜底文案保证体验不空白
|
||||
const text = buildStewardPlanMessageText({
|
||||
plan_id: 'p-empty',
|
||||
plan_status: 'off_topic',
|
||||
next_action: 'none',
|
||||
suggested_prompts: []
|
||||
})
|
||||
assert.match(text, /这句话我暂时没识别到财务事项/)
|
||||
assert.match(text, /费用申请.*费用报销|费用报销.*费用申请/)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user