feat: 数字员工财务报告体系与定时提醒及看板快照调度

- 新增数字员工财务报告生成、邮件投递与渲染调度器
- 引入员工画像扫描调度与定时提醒任务
- 完善财务看板快照、排行口径与部门人员占比计算
- 优化数字员工工作看板仪表盘与技能目录
- 增强前端总览页图表、工作台摘要与顶部导航栏交互
- 新增差旅申请规划推动提醒与报销创建会话状态管理
- 补充财务报告、看板调度、数字员工工作记录测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-03 09:25:23 +08:00
parent 0c74b4ab4a
commit 15006a05a7
114 changed files with 7356 additions and 650 deletions

View File

@@ -35,6 +35,10 @@ const assistantSubmitComposerScript = readFileSync(
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSubmitComposer.js', import.meta.url)),
'utf8'
)
const assistantSessionStateScript = readFileSync(
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSessionState.js', import.meta.url)),
'utf8'
)
const assistantTemplate = readFileSync(
fileURLToPath(new URL('../src/views/TravelReimbursementCreateView.vue', import.meta.url)),
'utf8'
@@ -60,6 +64,17 @@ test('application and reimbursement entries open the same financial assistant mo
assert.doesNotMatch(appShellRouteView, /ExpenseApplicationDialog/)
})
test('documents center reloads immediately when entered or clicked again', () => {
assert.match(appShellRouteView, /:refresh-token="documentCenterRefreshToken"/)
assert.match(appShellRouteView, /@reload="reloadRequests"/)
assert.match(appShellComposable, /const documentCenterRefreshToken = ref\(0\)/)
assert.match(appShellComposable, /async function reloadDocumentCenterRequests\(\) \{[\s\S]*documentCenterRefreshToken\.value \+= 1[\s\S]*return reloadRequests\(\)/)
assert.match(appShellComposable, /if \(view === 'documents'\) \{[\s\S]*void reloadDocumentCenterRequests\(\)/)
assert.match(appShellComposable, /shouldRefreshCurrentDocumentCenter[\s\S]*route\.name === 'app-documents'[\s\S]*void reloadDocumentCenterRequests\(\)/)
assert.match(appShellComposable, /documentCenterRefreshToken,/)
assert.match(appShellComposable, /reloadDocumentCenterRequests,/)
})
test('application entry keeps its own assistant source without creating a separate dialog', () => {
assert.match(appShellComposable, /const SMART_ENTRY_SOURCE_APPLICATION = 'application'/)
assert.match(appShellComposable, /function openExpenseApplicationCreate\(\) \{[\s\S]*openFinancialAssistantCreate\(SMART_ENTRY_SOURCE_APPLICATION\)/)
@@ -68,6 +83,32 @@ test('application entry keeps its own assistant source without creating a separa
assert.match(assistantScript, /activeSessionType\.value === SESSION_TYPE_APPLICATION[\s\S]*我想先申请一笔差旅费用/)
})
test('application edit prefill opens assistant without auto submit', () => {
assert.match(appShellRouteView, /:initial-prompt-auto-submit="smartEntryContext\.initialPromptAutoSubmit"/)
assert.match(appShellRouteView, /:initial-application-preview="smartEntryContext\.initialApplicationPreview"/)
assert.match(appShellComposable, /initialPromptAutoSubmit:\s*true/)
assert.match(appShellComposable, /initialApplicationPreview:\s*null/)
assert.match(appShellComposable, /initialPromptAutoSubmit:\s*payload\.initialPromptAutoSubmit !== false/)
assert.match(appShellComposable, /initialApplicationPreview:\s*payload\.applicationPreview && typeof payload\.applicationPreview === 'object'/)
assert.match(
assistantScript,
/initialPromptAutoSubmit:\s*\{[\s\S]*type:\s*Boolean[\s\S]*default:\s*true/
)
assert.match(
assistantScript,
/initialApplicationPreview:\s*\{[\s\S]*type:\s*Object[\s\S]*default:\s*null/
)
assert.match(
assistantScript,
/props\.initialApplicationPreview[\s\S]*normalizeApplicationPreview\(props\.initialApplicationPreview\)[\s\S]*createMessage\('assistant', buildLocalApplicationPreviewMessage\(applicationPreview\)/
)
assert.match(assistantSessionStateScript, /&& !props\.initialApplicationPreview/)
assert.match(
assistantScript,
/if \(props\.initialPromptAutoSubmit !== false\) \{[\s\S]*submitComposer\(\)/
)
})
test('financial assistant toolbar renders four isolated assistant sessions', () => {
assert.match(assistantScript, /filterAssistantSessionModes\(ASSISTANT_SESSION_MODE_OPTIONS, currentUser\.value\)/)
assert.match(assistantScript, /visibleModes\.map/)