feat(web): Vitest 测试基建与首批单测(#27)+ 公共格式化函数

This commit is contained in:
weijuesen
2026-08-13 14:51:57 +08:00
parent e9991a2954
commit 0e6dc007f3
6 changed files with 1241 additions and 17 deletions
+1185 -1
View File
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -7,6 +7,7 @@
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "oxlint",
"test": "vitest run",
"preview": "vite preview"
},
"dependencies": {
@@ -24,12 +25,16 @@
"react-router-dom": "^7.18.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.2",
"@types/node": "^24.13.2",
"@types/react": "^18.3.27",
"@types/react-dom": "^18.3.7",
"@vitejs/plugin-react": "^6.0.3",
"jsdom": "^30.0.1",
"oxlint": "^1.71.0",
"typescript": "~6.0.2",
"vite": "^8.1.1"
"vite": "^8.1.1",
"vitest": "^4.1.10"
}
}
+10 -14
View File
@@ -3,17 +3,13 @@ import { Drawer, Image, Tag, Typography } from 'antd';
import { ProTable, type ProColumns } from '@ant-design/pro-components';
import dayjs from 'dayjs';
import { listInspections, type AIDetection, type InspectionRecord } from '../dal/inspections';
import { aiClassLabel, riskLevelLabel } from '../utils/format';
const CLASS_LABELS: Record<string, string> = {
healthy: '健康',
sick: '疑似异常',
};
const RISK_LABELS: Record<string, { color: string; text: string }> = {
green: { color: 'green', text: '绿' },
yellow: { color: 'gold', text: '黄' },
orange: { color: 'orange', text: '橙' },
red: { color: 'red', text: '红' },
const RISK_LABELS: Record<string, { color: string }> = {
green: { color: 'green' },
yellow: { color: 'gold' },
orange: { color: 'orange' },
red: { color: 'red' },
};
const aiClassOf = (rec: InspectionRecord) =>
@@ -36,7 +32,7 @@ export default function InspectionsPage() {
render: (_, r) => {
const c = aiClassOf(r);
return c ? (
<Tag color={c === 'sick' ? 'red' : 'green'}>{CLASS_LABELS[c]}</Tag>
<Tag color={c === 'sick' ? 'red' : 'green'}>{aiClassLabel(c)}</Tag>
) : (
'-'
);
@@ -50,7 +46,7 @@ export default function InspectionsPage() {
const l = RISK_LABELS[r.riskLevel || ''] || RISK_LABELS.green;
return r.riskScore !== undefined ? (
<Tag color={l.color}>
{l.text}{Math.round(r.riskScore!)}
{riskLevelLabel(r.riskLevel || '')}{Math.round(r.riskScore!)}
</Tag>
) : (
'-'
@@ -106,13 +102,13 @@ export default function InspectionsPage() {
{detail.aiStatus === 'done' ? '检测成功' : '检测失败'}
<br />
{detail.riskScore !== undefined ? Math.round(detail.riskScore) : '-'}
{detail.riskLevel ? RISK_LABELS[detail.riskLevel]?.text || detail.riskLevel : '-'}
{detail.riskLevel ? riskLevelLabel(detail.riskLevel) : '-'}
</Typography.Paragraph>
<Typography.Title level={5}></Typography.Title>
{detail.detections && detail.detections.length > 0 ? (
detail.detections.map((d: AIDetection, i: number) => (
<div key={i} style={{ padding: '6px 0', borderBottom: '1px solid #f0f0f0' }}>
<Tag color={d.class === 'healthy' ? 'green' : 'red'}>{CLASS_LABELS[d.class] || d.class}</Tag>
<Tag color={d.class === 'healthy' ? 'green' : 'red'}>{aiClassLabel(d.class)}</Tag>
<span> {(d.confidence * 100).toFixed(1)}%</span>
<span style={{ marginLeft: 12, color: '#999' }}>
x:{Math.round(d.bbox.x)} y:{Math.round(d.bbox.y)} w:{Math.round(d.bbox.w)} h:{Math.round(d.bbox.h)}
+21
View File
@@ -0,0 +1,21 @@
import { describe, expect, it } from 'vitest';
import { aiClassLabel, riskLevelLabel } from './format';
describe('aiClassLabel', () => {
it('映射 healthy/sick 为中文', () => {
expect(aiClassLabel('healthy')).toBe('健康');
expect(aiClassLabel('sick')).toBe('疑似异常');
});
it('未知类别原样返回', () => {
expect(aiClassLabel('unknown')).toBe('unknown');
});
});
describe('riskLevelLabel', () => {
it('映射四级风险', () => {
expect(riskLevelLabel('green')).toBe('绿');
expect(riskLevelLabel('yellow')).toBe('黄');
expect(riskLevelLabel('orange')).toBe('橙');
expect(riskLevelLabel('red')).toBe('红');
});
});
+15
View File
@@ -0,0 +1,15 @@
const AI_CLASS_LABELS: Record<string, string> = {
healthy: '健康',
sick: '疑似异常',
};
const RISK_LEVEL_LABELS: Record<string, string> = {
green: '绿',
yellow: '黄',
orange: '橙',
red: '红',
};
export const aiClassLabel = (cls: string) => AI_CLASS_LABELS[cls] || cls;
export const riskLevelLabel = (level: string) => RISK_LEVEL_LABELS[level] || level;
+4 -1
View File
@@ -1,4 +1,4 @@
import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
@@ -27,6 +27,9 @@ export default defineConfig({
},
},
},
test: {
environment: 'jsdom',
},
server: {
host: '0.0.0.0',
port: 5174,