feat: 添加管理端前端 (HMS 基座 React 管理面板)
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled

- 从 HMS 基座复制 apps/web/ (React + Ant Design + Vite + TypeScript)
- 管理端自动代理 API 到 localhost:3000 (vite.config.ts)
- 更新 scripts/dev.sh 支持三端启动: backend/admin/app
- 登录验证通过, 用户管理/角色权限/审计日志等页面正常
- 添加 .gitignore 排除 node_modules/dist
This commit is contained in:
iven
2026-06-02 10:03:13 +08:00
parent 181bfb1f3e
commit 8111471e93
341 changed files with 72102 additions and 1059 deletions

View File

@@ -0,0 +1,85 @@
import { describe, it, expect } from 'vitest'
import {
GENDER_OPTIONS,
BLOOD_TYPE_OPTIONS,
STATUS_OPTIONS,
} from './health'
describe('GENDER_OPTIONS', () => {
it('should be an array with 3 items', () => {
expect(GENDER_OPTIONS).toBeInstanceOf(Array)
expect(GENDER_OPTIONS).toHaveLength(3)
})
it('each item should have value and label string properties', () => {
for (const opt of GENDER_OPTIONS) {
expect(opt).toHaveProperty('value')
expect(opt).toHaveProperty('label')
expect(typeof opt.value).toBe('string')
expect(typeof opt.label).toBe('string')
}
})
it('should contain expected gender values', () => {
const values = GENDER_OPTIONS.map((o) => o.value)
expect(values).toEqual(['male', 'female', 'other'])
})
it('should contain expected Chinese labels', () => {
const labels = GENDER_OPTIONS.map((o) => o.label)
expect(labels).toEqual(['男', '女', '其他'])
})
})
describe('BLOOD_TYPE_OPTIONS', () => {
it('should be an array with 4 items', () => {
expect(BLOOD_TYPE_OPTIONS).toBeInstanceOf(Array)
expect(BLOOD_TYPE_OPTIONS).toHaveLength(4)
})
it('each item should have value and label string properties', () => {
for (const opt of BLOOD_TYPE_OPTIONS) {
expect(opt).toHaveProperty('value')
expect(opt).toHaveProperty('label')
expect(typeof opt.value).toBe('string')
expect(typeof opt.label).toBe('string')
}
})
it('should contain expected blood type values', () => {
const values = BLOOD_TYPE_OPTIONS.map((o) => o.value)
expect(values).toEqual(['A', 'B', 'AB', 'O'])
})
it('should contain expected Chinese labels', () => {
const labels = BLOOD_TYPE_OPTIONS.map((o) => o.label)
expect(labels).toEqual(['A 型', 'B 型', 'AB 型', 'O 型'])
})
})
describe('STATUS_OPTIONS', () => {
it('should be an array with 4 items', () => {
expect(STATUS_OPTIONS).toBeInstanceOf(Array)
expect(STATUS_OPTIONS).toHaveLength(4)
})
it('each item should have value and label string properties', () => {
for (const opt of STATUS_OPTIONS) {
expect(opt).toHaveProperty('value')
expect(opt).toHaveProperty('label')
expect(typeof opt.value).toBe('string')
expect(typeof opt.label).toBe('string')
}
})
it('should include an empty-string value for "all statuses" filter', () => {
const allOption = STATUS_OPTIONS.find((o) => o.value === '')
expect(allOption).toBeDefined()
expect(allOption!.label).toBe('全部状态')
})
it('should contain expected status values', () => {
const values = STATUS_OPTIONS.map((o) => o.value)
expect(values).toEqual(['', 'active', 'inactive', 'deceased'])
})
})

View File

@@ -0,0 +1,200 @@
/**
* 健康管理模块共享常量
*
* 集中定义性别、血型、患者状态、严重度、告警状态、设备类型等映射,
* 供各健康模块页面复用。避免在组件中重复定义。
*/
// --- 性别 ---
export const GENDER_OPTIONS = [
{ value: "male", label: "男" },
{ value: "female", label: "女" },
{ value: "other", label: "其他" },
];
export const GENDER_LABEL: Record<string, string> = {
male: "男",
female: "女",
other: "其他",
};
// --- 血型 ---
export const BLOOD_TYPE_OPTIONS = [
{ value: "A", label: "A 型" },
{ value: "B", label: "B 型" },
{ value: "AB", label: "AB 型" },
{ value: "O", label: "O 型" },
];
// --- 患者状态 ---
export const STATUS_OPTIONS = [
{ value: "", label: "全部状态" },
{ value: "active", label: "活跃" },
{ value: "inactive", label: "停用" },
{ value: "deceased", label: "已故" },
];
// --- 严重度(统一 5 处重复定义: AlertDashboard, AlertList, AlertRuleList, DoctorDashboard ---
export const SEVERITY_COLOR: Record<string, string> = {
info: "default",
warning: "orange",
critical: "red",
urgent: "magenta",
high: "red",
medium: "orange",
};
export const SEVERITY_LABEL: Record<string, string> = {
info: "提示",
warning: "警告",
critical: "严重",
urgent: "紧急",
high: "严重",
medium: "中等",
};
export const SEVERITY_OPTIONS = [
{ value: "info", label: "提示" },
{ value: "warning", label: "警告" },
{ value: "medium", label: "中等" },
{ value: "critical", label: "严重" },
{ value: "high", label: "严重" },
{ value: "urgent", label: "紧急" },
];
// --- 告警状态(统一 3 处: AlertDashboard, AlertList ---
export const ALERT_STATUS_COLOR: Record<string, string> = {
pending: "orange",
active: "gold",
acknowledged: "blue",
resolved: "green",
dismissed: "default",
};
export const ALERT_STATUS_LABEL: Record<string, string> = {
pending: "待处理",
active: "活跃",
acknowledged: "已确认",
resolved: "已恢复",
dismissed: "已忽略",
};
export const ALERT_STATUS_OPTIONS = [
{ value: "", label: "全部状态" },
{ value: "active", label: "活跃" },
{ value: "pending", label: "待处理" },
{ value: "acknowledged", label: "已确认" },
{ value: "resolved", label: "已恢复" },
{ value: "dismissed", label: "已忽略" },
];
// --- 设备类型(统一 3 处: DeviceManage, DeviceReadingsTab, AlertRuleList ---
export const DEVICE_TYPE_OPTIONS = [
{ value: "blood_pressure", label: "血压" },
{ value: "blood_glucose", label: "血糖" },
{ value: "heart_rate", label: "心率" },
{ value: "blood_oxygen", label: "血氧" },
{ value: "temperature", label: "体温" },
{ value: "steps", label: "步数" },
{ value: "sleep", label: "睡眠" },
{ value: "stress", label: "压力" },
];
export const DEVICE_TYPE_COLOR: Record<string, string> = {
blood_pressure: "red",
blood_glucose: "purple",
heart_rate: "volcano",
blood_oxygen: "blue",
temperature: "orange",
steps: "green",
sleep: "cyan",
stress: "geekblue",
};
// --- 告警规则条件类型 ---
export const CONDITION_TYPE_OPTIONS = [
{ value: "single_threshold", label: "单次阈值" },
{ value: "consecutive", label: "连续触发" },
{ value: "trend", label: "趋势变化" },
];
// --- 设备连接状态 ---
export const DEVICE_STATUS_OPTIONS = [
{ value: "", label: "全部状态" },
{ value: "online", label: "在线" },
{ value: "offline", label: "离线" },
{ value: "paired", label: "已配对" },
{ value: "error", label: "异常" },
];
export const DEVICE_STATUS_COLOR: Record<string, string> = {
online: "green",
offline: "default",
paired: "blue",
error: "red",
};
// --- 设备连接类型 ---
export const CONNECTION_TYPE_OPTIONS = [
{ value: "ble", label: "蓝牙" },
{ value: "gateway", label: "网关" },
{ value: "manual", label: "手动录入" },
];
// --- 实时监控卡片指标 ---
export const VITAL_CARD_METRICS = [
{ key: "heart_rate", label: "心率", unit: "bpm", color: "#ff4d4f" },
{ key: "blood_oxygen", label: "血氧", unit: "%", color: "#1890ff" },
{ key: "blood_pressure", label: "血压", unit: "mmHg", color: "#f5222d" },
{ key: "blood_glucose", label: "血糖", unit: "mg/dL", color: "#722ed1" },
{ key: "temperature", label: "体温", unit: "°C", color: "#fa8c16" },
{ key: "steps", label: "步数", unit: "步", color: "#52c41a" },
] as const;
// --- 告警标题中英文映射 ---
export const ALERT_TITLE_MAP: Record<string, string> = {
"BP Critical High": "血压严重偏高",
"BP Critical Low": "血压严重偏低",
"Heart Rate Abnormal": "心率异常",
"Blood Sugar Elevated": "血糖偏高",
"Blood Sugar Critical": "血糖危急值",
"Blood Sugar Low": "血糖偏低",
"Weight Gain Alert": "体重增长异常",
"Missed Medication": "漏服药物",
"SpO2 Low": "血氧偏低",
"Temperature High": "体温偏高",
"Temperature Low": "体温偏低",
"BP Trending High": "血压趋势偏高",
"BP Trending Low": "血压趋势偏低",
"Heart Rate High": "心率偏高",
"Heart Rate Low": "心率偏低",
};
/** 翻译告警标题:优先精确匹配,其次回退原文 */
export function translateAlertTitle(title: string): string {
return ALERT_TITLE_MAP[title] ?? title;
}
// --- 通用状态标签StatusTag 组件统一引用) ---
export const STATUS_TAG_CONFIG: Record<
string,
{ color: string; label: string }
> = {
// 预约状态
pending: { color: "gold", label: "待确认" },
confirmed: { color: "blue", label: "已确认" },
completed: { color: "green", label: "已完成" },
cancelled: { color: "default", label: "已取消" },
no_show: { color: "red", label: "未到诊" },
// 随访状态
overdue: { color: "red", label: "逾期" },
in_progress: { color: "processing", label: "进行中" },
// 咨询状态
waiting: { color: "gold", label: "等待中" },
active: { color: "green", label: "进行中" },
closed: { color: "default", label: "已关闭" },
// 患者状态
inactive: { color: "default", label: "停用" },
deceased: { color: "default", label: "已故" },
verified: { color: "green", label: "已认证" },
};