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:
@@ -1,6 +1,7 @@
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useDidShow, useRouter } from '@tarojs/taro';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { useThrottledDidShow } from '@/hooks/useThrottledDidShow';
|
||||
import { BLEManager } from '@/services/ble/BLEManager';
|
||||
import { XiaomiBandAdapter } from '@/services/ble/adapters/XiaomiBandAdapter';
|
||||
import { BloodPressureAdapter } from '@/services/ble/adapters/BloodPressureAdapter';
|
||||
@@ -13,17 +14,14 @@ import type { BLEDevice, NormalizedReading } from '@/services/ble/types';
|
||||
import { useElderClass } from '../../hooks/useElderClass';
|
||||
import './index.scss';
|
||||
|
||||
const bleManager = new BLEManager({ scanTimeout: 10000, retryCount: 3 });
|
||||
bleManager.registerAdapter(XiaomiBandAdapter);
|
||||
bleManager.registerAdapter(BloodPressureAdapter);
|
||||
bleManager.registerAdapter(GlucoseMeterAdapter);
|
||||
bleManager.registerAdapter(CustomBandAdapter);
|
||||
/** liveReadings 最大保留条数,防止内存无限增长 */
|
||||
const MAX_LIVE_READINGS = 200;
|
||||
|
||||
type PageState = 'idle' | 'scanning' | 'connecting' | 'connected' | 'syncing' | 'done' | 'error';
|
||||
|
||||
export default function DeviceSync() {
|
||||
const modeClass = useElderClass();
|
||||
const { currentPatient } = useAuthStore();
|
||||
const currentPatient = useAuthStore((s) => s.currentPatient);
|
||||
const router = useRouter();
|
||||
const returnTo = router.params.returnTo || '';
|
||||
const [pageState, setPageState] = useState<PageState>('idle');
|
||||
@@ -39,10 +37,27 @@ export default function DeviceSync() {
|
||||
intervalMs: 60 * 60 * 1000,
|
||||
}), []);
|
||||
|
||||
useDidShow(() => {
|
||||
const bleManagerRef = useRef<BLEManager | null>(null);
|
||||
const getBleManager = useCallback(() => {
|
||||
if (!bleManagerRef.current) {
|
||||
const mgr = new BLEManager({ scanTimeout: 10000, retryCount: 3 });
|
||||
mgr.registerAdapter(XiaomiBandAdapter);
|
||||
mgr.registerAdapter(BloodPressureAdapter);
|
||||
mgr.registerAdapter(GlucoseMeterAdapter);
|
||||
mgr.registerAdapter(CustomBandAdapter);
|
||||
bleManagerRef.current = mgr;
|
||||
}
|
||||
return bleManagerRef.current;
|
||||
}, []);
|
||||
|
||||
useThrottledDidShow(() => {
|
||||
const bleManager = getBleManager();
|
||||
bleManager.setOnConnectionChange(() => {});
|
||||
bleManager.setOnReadings((readings) => {
|
||||
setLiveReadings((prev) => [...prev, ...readings]);
|
||||
setLiveReadings((prev) => {
|
||||
const merged = [...prev, ...readings];
|
||||
return merged.length > MAX_LIVE_READINGS ? merged.slice(-MAX_LIVE_READINGS) : merged;
|
||||
});
|
||||
});
|
||||
|
||||
// 显示上次同步时间
|
||||
@@ -65,19 +80,24 @@ export default function DeviceSync() {
|
||||
return { success: count > 0, uploadedCount: count };
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
scheduler.destroy();
|
||||
bleManager.destroy();
|
||||
if (bleManagerRef.current) {
|
||||
bleManagerRef.current.destroy();
|
||||
bleManagerRef.current = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
}, [scheduler]);
|
||||
|
||||
const handleScan = useCallback(async () => {
|
||||
setPageState('scanning');
|
||||
setDevices([]);
|
||||
setErrorMsg('');
|
||||
try {
|
||||
const found = await bleManager.scanDevices();
|
||||
const found = await getBleManager().scanDevices();
|
||||
setDevices(found);
|
||||
if (found.length === 0) {
|
||||
setErrorMsg('未发现支持的设备,请确认设备已开启蓝牙并靠近手机');
|
||||
@@ -94,7 +114,7 @@ export default function DeviceSync() {
|
||||
setPageState('connecting');
|
||||
setErrorMsg('');
|
||||
try {
|
||||
await bleManager.connect(device);
|
||||
await getBleManager().connect(device);
|
||||
setPageState('connected');
|
||||
} catch (e: any) {
|
||||
setErrorMsg(e.message || '连接失败');
|
||||
@@ -109,7 +129,7 @@ export default function DeviceSync() {
|
||||
setErrorMsg('');
|
||||
|
||||
try {
|
||||
const result = await bleManager.syncToServer(async (readings) => {
|
||||
const result = await getBleManager().syncToServer(async (readings) => {
|
||||
return uploadReadings(
|
||||
currentPatient.id,
|
||||
selectedDevice.deviceId,
|
||||
@@ -154,7 +174,7 @@ export default function DeviceSync() {
|
||||
}, [currentPatient, selectedDevice, liveReadings, returnTo]);
|
||||
|
||||
const handleDisconnect = useCallback(async () => {
|
||||
await bleManager.disconnect();
|
||||
await getBleManager().disconnect();
|
||||
setPageState('idle');
|
||||
setSelectedDevice(null);
|
||||
setLiveReadings([]);
|
||||
|
||||
Reference in New Issue
Block a user