Files
hms/apps/miniprogram/src/app.tsx
iven 6d151bbfb1 refactor(mp): request.ts 模块级状态收编 + AbortSignal + Analytics 受控
- 提取 ConcurrencyLimiter 类(并发限制 8,可 reset)
- 提取 ResponseCache 类(GET 缓存 + 去重 + patientId 绑定)
- 新增 resetForTesting() 测试隔离函数
- api.get/post/put/delete 支持 AbortSignal 请求取消
- app.tsx Analytics 定时器改为 useDidShow/useDidHide 控制后台暂停
- 测试文件接入 resetForTesting()

构建通过,测试 74/75(1 个预存失败)。
2026-05-15 06:58:37 +08:00

63 lines
1.9 KiB
TypeScript

import { useEffect, useRef, PropsWithChildren } from 'react';
import Taro, { useDidShow, useDidHide } from '@tarojs/taro';
import ErrorBoundary from './components/ErrorBoundary';
import { flushEvents } from './services/analytics';
import { useAuthStore } from './stores/auth';
import { useUIStore } from './stores/ui';
import './app.scss';
function App({ children }: PropsWithChildren<Record<string, unknown>>) {
const restoreAuth = useAuthStore((s) => s.restore);
const restoreUI = useUIStore((s) => s.restore);
// useDidShow 在首次 mount 时也会触发,不需要 useEffect 重复调用
useDidShow(() => {
restoreAuth();
restoreUI();
});
// 暴露全局 bridge 供 MCP/自动化测试调用(仅 dev 模式)
useEffect(() => {
if (process.env.NODE_ENV === 'production') return;
(globalThis as any).__hms = {
restoreAuth: () => { restoreAuth(); return useAuthStore.getState(); },
restoreUI,
getAuthState: () => useAuthStore.getState(),
forceSetAuth: (state: Record<string, unknown>) => useAuthStore.setState(state),
};
return () => { delete (globalThis as any).__hms; };
}, []);
// Analytics 定时器:仅在页面可见时运行,后台时暂停以节省资源
const analyticsTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
const startAnalyticsTimer = () => {
if (analyticsTimerRef.current) return;
analyticsTimerRef.current = setInterval(flushEvents, 30000);
};
const stopAnalyticsTimer = () => {
if (analyticsTimerRef.current) {
clearInterval(analyticsTimerRef.current);
analyticsTimerRef.current = null;
}
};
useDidShow(() => {
startAnalyticsTimer();
});
useDidHide(() => {
stopAnalyticsTimer();
flushEvents();
});
useEffect(() => {
return () => { stopAnalyticsTimer(); };
}, []);
return <ErrorBoundary>{children}</ErrorBoundary>;
}
export default App;