Files
hms/apps/miniprogram/src/pages/health/trend/index.tsx
iven 0bf1822fa9
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
fix: QA 第二轮修复 — PatientDetail 重构/测试覆盖/id_number 列宽/小程序 URL 规范化
- refactor(web): PatientDetail.tsx 拆分为 4 个子组件(737→334行)
- refactor(web): 提取 usePaginatedData hook 消除重复分页状态
- feat(db): patient.id_number varchar(20)→varchar(255) 容纳加密值
- test(health): 添加预约模块集成测试(创建/列表/租户隔离)
- test(plugin): 添加 6 个 SQL 注入 sanitize 测试
- fix(miniprogram): 7 个 service 文件 URL 构建规范化(params 对象)
- fix(miniprogram): 跨平台字段名对齐(birth_date/start_time/end_time)
2026-04-25 10:22:44 +08:00

77 lines
2.6 KiB
TypeScript

import { useState, useEffect } from 'react';
import { View, Text } from '@tarojs/components';
import { useRouter } from '@tarojs/taro';
import { useHealthStore } from '@/stores/health';
import TrendChart from '@/components/TrendChart';
import './index.scss';
const RANGE_OPTIONS = [
{ value: '7d', label: '7天' },
{ value: '30d', label: '30天' },
{ value: '90d', label: '90天' },
];
const INDICATOR_META: Record<string, { label: string; unit: string; refMin?: number; refMax?: number }> = {
blood_pressure_systolic: { label: '收缩压', unit: 'mmHg', refMin: 90, refMax: 140 },
blood_pressure_diastolic: { label: '舒张压', unit: 'mmHg', refMin: 60, refMax: 90 },
heart_rate: { label: '心率', unit: 'bpm', refMin: 60, refMax: 100 },
blood_sugar_fasting: { label: '空腹血糖', unit: 'mmol/L', refMin: 3.9, refMax: 6.1 },
blood_sugar_postprandial: { label: '餐后血糖', unit: 'mmol/L', refMin: 3.9, refMax: 7.8 },
weight: { label: '体重', unit: 'kg' },
};
export default function Trend() {
const router = useRouter();
const indicator = router.params.indicator || 'heart_rate';
const [range, setRange] = useState('7d');
const [points, setPoints] = useState<{ date: string; value: number }[]>([]);
const { getTrend } = useHealthStore();
useEffect(() => {
getTrend(indicator, range).then(setPoints);
}, [indicator, range]);
const meta = INDICATOR_META[indicator] || { label: indicator, unit: '' };
return (
<View className='trend-page'>
<View className='trend-header'>
<Text className='trend-title'>{meta.label} </Text>
<View className='trend-tabs'>
{RANGE_OPTIONS.map((opt) => (
<View
key={opt.value}
className={`trend-tab ${range === opt.value ? 'active' : ''}`}
onClick={() => setRange(opt.value)}
>
<Text className='trend-tab-text'>{opt.label}</Text>
</View>
))}
</View>
</View>
{/* ECharts 折线图 */}
<View className='trend-chart-container'>
<TrendChart
data={points}
referenceMin={meta.refMin}
referenceMax={meta.refMax}
unit={meta.unit}
/>
</View>
{/* 数据列表 */}
{points.length > 0 && (
<View className='trend-list'>
{points.slice().reverse().map((p, i) => (
<View className='trend-item' key={i}>
<Text className='trend-item-date'>{p.date}</Text>
<Text className='trend-item-value'>{p.value}{meta.unit ? ` ${meta.unit}` : ''}</Text>
</View>
))}
</View>
)}
</View>
);
}