fix(mp): T40 UI 审计修复 — 28 项设计系统合规 + 安全加固 + 讨论记录

T40 UI 审计修复(60 页面全覆盖):
- 新增 $acc-d/$wrn-d 渐变中间色变量,修复首页轮播渐变硬编码
- 替换 8 处裸 white 为 $white 设计变量(5 个 SCSS 文件)
- 修复 7 处触摸目标 40/44px → 48px(健康/消息/咨询/预约/首页)
- 3 页面新增 Loading 状态(体征录入/个人中心/就诊人添加)
- statusTag 移除硬编码布局值,改用 SCSS mixin 控制
- 医生端 14 页面架构 Hook 层补充(useThrottledDidShow 替换 useEffect)
- 移除 action-inbox 未使用 import

安全 P0 修复:
- JWT 中间件加固:token 类型校验 + 过期预检 + 类型别名简化
- 速率限制增强:滑动窗口 + 暴力破解防护
- analytics handler 错误处理完善

文档:
- T40 审计报告(24 PASS / 36 PASS_WITH_ISSUES / 0 NEEDS_WORK)
- 5 份 DevTools/性能审计讨论记录
- wiki 症状导航 + 小程序章节更新
This commit is contained in:
iven
2026-05-14 23:12:54 +08:00
parent 447126b6c5
commit 8f353946e1
90 changed files with 2089 additions and 830 deletions

View File

@@ -19,6 +19,7 @@ interface HealthState {
const CACHE_TTL = 5 * 60 * 1000;
const TODAY_SUMMARY_TTL = 60_000;
const MAX_TREND_KEYS = 20;
export const useHealthStore = create<HealthState>((set, get) => ({
todaySummary: null,
@@ -51,7 +52,16 @@ export const useHealthStore = create<HealthState>((set, get) => ({
try {
const resp = await healthApi.getTrend(indicator, range);
const points = resp.data_points || [];
set((s) => ({ trendData: { ...s.trendData, [cacheKey]: { data: points, cachedAt: Date.now() } } }));
set((s) => {
const updated = { ...s.trendData, [cacheKey]: { data: points, cachedAt: Date.now() } };
// 超过上限时淘汰最早的缓存
const keys = Object.keys(updated);
if (keys.length > MAX_TREND_KEYS) {
const oldest = keys.reduce((a, b) => updated[a].cachedAt < updated[b].cachedAt ? a : b);
delete updated[oldest];
}
return { trendData: updated };
});
return points;
} catch {
return [];

View File

@@ -30,7 +30,7 @@ export const useUIStore = create<UIState>((set, get) => ({
try {
const saved = Taro.getStorageSync(STORAGE_KEY);
if (saved === 'elder' || saved === 'normal') {
set({ mode: saved });
if (get().mode !== saved) set({ mode: saved });
}
} catch { /* storage 不可用时保持默认 */ }
},