feat(health+miniprogram): 健康数据录入 + 趋势图
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

后端:
- 新增 GET /health/vital-signs/trend 小程序趋势查询 API
- 通过 JWT user_id 自动关联 patient,支持 range 参数 (7d/30d/90d)
- 新增 MiniTrendQueryParams, MiniTrendResp, DataPoint DTO

前端:
- 实现健康数据首页(今日概览 + 趋势入口 + 录入按钮)
- 实现健康数据录入页(指标选择 + 数值输入 + 提交)
- 实现趋势图页(时间范围切换 + 柱状图 + 数据列表)
- 新增 health service 和 store(趋势缓存 + 今日摘要)
- 修复所有页面相对路径引用问题
This commit is contained in:
iven
2026-04-24 00:36:30 +08:00
parent 0f84c881ef
commit affb3a5578
13 changed files with 714 additions and 15 deletions

View File

@@ -0,0 +1,41 @@
import { create } from 'zustand';
import * as healthApi from '../services/health';
interface HealthState {
todaySummary: healthApi.TodaySummary | null;
trendData: Record<string, { date: string; value: number }[]>;
loading: boolean;
refreshToday: () => Promise<void>;
getTrend: (indicator: string, range: string) => Promise<{ date: string; value: number }[]>;
}
export const useHealthStore = create<HealthState>((set, get) => ({
todaySummary: null,
trendData: {},
loading: false,
refreshToday: async () => {
set({ loading: true });
try {
const data = await healthApi.getTodaySummary();
set({ todaySummary: data, loading: false });
} catch {
set({ loading: false });
}
},
getTrend: async (indicator: string, range: string) => {
const cacheKey = `${indicator}_${range}`;
const cached = get().trendData[cacheKey];
if (cached) return cached;
try {
const resp = await healthApi.getTrend(indicator, range);
const points = resp.data_points || [];
set((s) => ({ trendData: { ...s.trendData, [cacheKey]: points } }));
return points;
} catch {
return [];
}
},
}));