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

@@ -805,6 +805,29 @@ test('application detail uses application labels instead of reimbursement labels
assert.match(detailViewTemplate, /当前申请单已进入流程,详情页仅展示状态与申请信息。/)
})
test('returned application detail can open assistant with editable prefill', () => {
assert.match(
detailViewTemplate,
/v-if="canModifyReturnedApplication"[\s\S]*@click="handleModifyApplication"[\s\S]*修改申请/
)
assert.match(
detailViewScript,
/const canModifyReturnedApplication = computed\(\(\) => \([\s\S]*isApplicationDocument\.value[\s\S]*isCurrentApplicant\.value[\s\S]*returned/
)
assert.match(detailViewScript, /function buildApplicationEditPreview\(\)/)
assert.match(detailViewScript, /applicationDetailFactItems\.value[\s\S]*sourceText:\s*'修改申请'/)
assert.match(detailViewScript, /fields:\s*\{[\s\S]*applicationType:[\s\S]*reason:[\s\S]*transportMode:/)
assert.match(detailViewScript, /function handleModifyApplication\(\)/)
assert.match(detailViewScript, /source:\s*'application'/)
assert.match(detailViewScript, /sessionType:\s*'application'/)
assert.match(detailViewScript, /prompt:\s*''/)
assert.match(detailViewScript, /applicationPreview:\s*buildApplicationEditPreview\(\)/)
assert.match(detailViewScript, /applicationEditMode:\s*true/)
assert.match(detailViewScript, /initialPromptAutoSubmit:\s*false/)
assert.match(detailViewScript, /canModifyReturnedApplication,/)
assert.match(detailViewScript, /handleModifyApplication,/)
})
test('application detail does not show optional travel receipt reminders', () => {
const request = {
documentTypeCode: 'application',
@@ -943,6 +966,34 @@ test('transport ticket items no longer generate business location completion adv
assert.doesNotMatch(detailViewScript, /完善第 1 条费用明细的业务地点/)
})
test('compliant attachment analysis does not create medium risk cards', () => {
const riskCards = buildAttachmentRiskCards({
expenseItems: [
{
id: 'item-001',
invoiceId: 'mock/invoice-001.txt',
itemReason: 'taxi',
itemType: 'transport'
}
],
attachmentMetaByItemId: {
'item-001': {
analysis: {
severity: 'success',
label: 'compliant',
headline: 'invoice fields match reimbursement item',
summary: 'mock OCR fields are consistent with the reimbursement detail',
points: ['amount and document type are consistent']
}
}
}
})
assert.deepEqual(riskCards, [])
assert.match(detailViewInsights, /success', 'ok', 'normal', 'none', 'compliant', 'approved'/)
assert.match(detailViewScript, /tone: normalizeRiskTone\(analysis\.severity \|\| 'low'\)/)
})
test('return reason dialog is wired into approval and detail return actions', () => {
assert.match(returnReasonDialog, /missing_attachment/)
assert.match(returnReasonDialog, /invoice_mismatch/)