refactor(web): 前端工程化 — 组件拆分 + 名称缓存统一
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

- useHealthStore 新增 batchResolvePatientNames/batchResolveDoctorNames
  批量解析方法(去重 → 过滤已缓存 → 5 并发批次加载)
- PointsOrderList 移除局部 nameCache,改用 useHealthStore 全局缓存
- PluginCRUDPage (871L) 拆分为 usePluginData + DetailDrawer +
  ImportModal + PluginCRUDPageInner,原文件改为 re-export
- PluginGraphPage (765L) 拆分为 useGraphData + useGraphCanvas hooks
- StatisticsDashboard (580L) 拆分为 useStatsData + HealthDataCenter
This commit is contained in:
iven
2026-04-27 20:56:27 +08:00
parent fdceed7284
commit 41af241238
13 changed files with 1624 additions and 1841 deletions

View File

@@ -11,6 +11,8 @@ interface HealthState {
resolveDoctorName: (id: string) => Promise<string>;
getPatientName: (id: string) => string;
getDoctorName: (id: string) => string;
batchResolvePatientNames: (ids: string[]) => Promise<void>;
batchResolveDoctorNames: (ids: string[]) => Promise<void>;
}
export const useHealthStore = create<HealthState>((set, get) => ({
@@ -72,4 +74,50 @@ export const useHealthStore = create<HealthState>((set, get) => ({
getPatientName: (id: string) => get().patientNames[id] || id.slice(0, 8),
getDoctorName: (id: string) => get().doctorNames[id] || id.slice(0, 8),
batchResolvePatientNames: async (ids: string[]) => {
const { patientNames } = get();
const uniqueIds = [...new Set(ids)];
const missing = uniqueIds.filter((id) => !patientNames[id]);
if (missing.length === 0) return;
const limit = 5;
for (let i = 0; i < missing.length; i += limit) {
const batch = missing.slice(i, i + limit);
const results = await Promise.allSettled(
batch.map(async (id) => {
const detail = await patientApi.get(id);
return { id, name: detail.name };
}),
);
const newEntries: Record<string, string> = {};
results.forEach((r, idx) => {
newEntries[batch[idx]] = r.status === 'fulfilled' ? r.value.name : batch[idx].slice(0, 8);
});
set((s) => ({ patientNames: { ...s.patientNames, ...newEntries } }));
}
},
batchResolveDoctorNames: async (ids: string[]) => {
const { doctorNames } = get();
const uniqueIds = [...new Set(ids)];
const missing = uniqueIds.filter((id) => !doctorNames[id]);
if (missing.length === 0) return;
const limit = 5;
for (let i = 0; i < missing.length; i += limit) {
const batch = missing.slice(i, i + limit);
const results = await Promise.allSettled(
batch.map(async (id) => {
const detail = await doctorApi.get(id);
return { id, name: detail.name };
}),
);
const newEntries: Record<string, string> = {};
results.forEach((r, idx) => {
newEntries[batch[idx]] = r.status === 'fulfilled' ? r.value.name : batch[idx].slice(0, 8);
});
set((s) => ({ doctorNames: { ...s.doctorNames, ...newEntries } }));
}
},
}));