feat(dashboard): polish risk and digital employee boards

This commit is contained in:
caoxiaozhu
2026-06-03 09:41:32 +08:00
parent 15006a05a7
commit 0d6327a990
11 changed files with 716 additions and 100 deletions

View File

@@ -4,6 +4,13 @@ import test from 'node:test'
import { fileURLToPath } from 'node:url'
import { normalizeRiskObservationDashboard } from '../src/services/riskObservations.js'
import {
formatExpenseTypeLabel,
formatRiskDimensionLabel,
formatRiskObservationTitle,
formatRiskSignalLabel,
formatRiskSourceLabel
} from '../src/utils/riskLabels.js'
const dashboardComponent = readFileSync(
fileURLToPath(new URL('../src/components/dashboard/RiskObservationDashboard.vue', import.meta.url)),
@@ -17,6 +24,10 @@ const overviewTemplate = readFileSync(
fileURLToPath(new URL('../src/views/OverviewView.vue', import.meta.url)),
'utf8'
)
const riskLabels = readFileSync(
fileURLToPath(new URL('../src/utils/riskLabels.js', import.meta.url)),
'utf8'
)
test('risk dashboard normalizes amount, distributions, and ranking fields', () => {
const dashboard = normalizeRiskObservationDashboard({
@@ -68,6 +79,35 @@ test('risk dashboard renders overview amount and multi-dimension panels', () =>
assert.match(dashboardComponent, /topRules/)
})
test('risk dashboard localizes backend metric keys before rendering', () => {
assert.equal(formatRiskSignalLabel('duplicate_invoice'), '重复发票')
assert.equal(formatRiskSignalLabel('policy.duplicate_invoice'), '重复发票')
assert.equal(formatExpenseTypeLabel('travel'), '差旅费')
assert.equal(formatRiskSourceLabel('rule_center'), '规则中心')
assert.equal(formatRiskSourceLabel('financial_risk_graph'), '风险图谱')
assert.equal(formatRiskDimensionLabel('policy.duplicate_invoice', 'rule'), '重复发票规则')
assert.equal(
formatRiskObservationTitle({ title: 'policy.duplicate_invoice', riskSignal: 'duplicate_invoice' }),
'重复发票'
)
assert.match(riskLabels, /travel: '差旅费'/)
assert.match(riskLabels, /rule_center: '规则中心'/)
assert.match(overviewViewModel, /formatRiskSignalLabel/)
assert.match(overviewViewModel, /formatRiskSourceLabel/)
assert.match(dashboardComponent, /formatRiskObservationTitle/)
assert.doesNotMatch(dashboardComponent, /text\.replace\(\s*\/_\/g/)
})
test('risk dashboard renders exception ranking as chart-led visual summary', () => {
assert.match(dashboardComponent, /rankingChartItems/)
assert.match(dashboardComponent, /rankingDetailGroups/)
assert.match(dashboardComponent, /risk-ranking-visual/)
assert.match(dashboardComponent, /risk-ranking-detail-grid/)
assert.match(dashboardComponent, /:items="rankingChartItems"/)
assert.match(dashboardComponent, /value-suffix="项"/)
assert.doesNotMatch(dashboardComponent, /risk-ranking-grid/)
})
test('risk dashboard wires window filter to trend, ranking, and cards data source', () => {
assert.match(overviewViewModel, /const activeRiskWindowDays = ref\(30\)/)
assert.match(overviewViewModel, /windowDays: activeRiskWindowDays\.value/)
@@ -84,6 +124,8 @@ test('risk dashboard wires window filter to trend, ranking, and cards data sourc
})
test('risk dashboard shows loading overlay and realtime refresh status', () => {
assert.match(overviewTemplate, /dashboard-loading-overlay/)
assert.match(overviewTemplate, /activeDashboardLoadingText/)
assert.match(dashboardComponent, /risk-dashboard-loading-overlay/)
assert.match(dashboardComponent, /loadingLabel/)
assert.match(dashboardComponent, /lastUpdatedLabel/)
@@ -95,3 +137,16 @@ test('risk dashboard shows loading overlay and realtime refresh status', () => {
assert.match(overviewViewModel, /riskDashboardRequestSeq/)
assert.match(overviewTemplate, /:last-updated-at="riskDashboardLastUpdatedAt"/)
})
test('overview dashboards are loaded on demand instead of all at once', () => {
assert.match(overviewViewModel, /const activeDashboardKey = computed/)
assert.match(overviewViewModel, /const loadActiveDashboard = \(\) =>/)
assert.doesNotMatch(
overviewViewModel,
/onMounted\(\(\) => \{\s*void loadFinanceDashboard\(\)\s*void loadSystemDashboard\(\)\s*void loadRiskDashboard\(\)\s*void loadDigitalEmployeeDashboard\(\)/
)
assert.match(overviewViewModel, /watch\(activeDashboardKey/)
assert.match(overviewViewModel, /activeDashboardKey\.value === 'risk'/)
assert.match(overviewViewModel, /startRiskDashboardRealtimeRefresh\(\)/)
assert.match(overviewViewModel, /stopRiskDashboardRealtimeRefresh\(\)/)
})