From 30f5df220619ba5e0bc1289fc6f46893f5f37e96 Mon Sep 17 00:00:00 2001 From: 134 Date: Thu, 24 Sep 2026 13:15:53 +0800 Subject: [PATCH] fix: auto refresh MKH live data --- frontend/src/pages/MkhBomData/index.jsx | 35 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/MkhBomData/index.jsx b/frontend/src/pages/MkhBomData/index.jsx index 9e434cb..184de96 100644 --- a/frontend/src/pages/MkhBomData/index.jsx +++ b/frontend/src/pages/MkhBomData/index.jsx @@ -33,6 +33,9 @@ const number = (value, digits = 0) => (value === null || value === undefined || const text = (value) => (value === null || value === undefined || value === '' ? '--' : value); const EMPTY_FILTERS = { keyword: '', scope: 'warning' }; +// 页面长时打开时定期重读。后端共享 10 分钟索引缓存,因此多个页面的轮询 +// 会合并为每个缓存周期一次业务库读取,不会每 2 分钟重复扫远程大表。 +const AUTO_REFRESH_MS = 2 * 60 * 1000; // 预警等级 → 标签配色 const WARNING_TONE = { @@ -277,6 +280,8 @@ const MkhBomData = () => { const tableWrapRef = useRef(null); const listRequestGateRef = useRef(createRequestGate()); const detailGenerationRef = useRef(0); + const lastListRefreshAtRef = useRef(0); + const autoRefreshPendingRef = useRef(false); const [bodyHeight, setBodyHeight] = useState(420); useEffect(() => { @@ -313,10 +318,10 @@ const MkhBomData = () => { return params; }, [page, pageSize, sorter, filters]); - const load = useCallback(async () => { + const load = useCallback(async ({ background = false } = {}) => { const requestGeneration = listRequestGateRef.current.begin(); - setLoading(true); - setError(''); + if (!background) setLoading(true); + if (!background) setError(''); try { const result = await getMkhBomList({ ...query, live: 1, _refresh: Date.now() }); if (!listRequestGateRef.current.isCurrent(requestGeneration)) return; @@ -325,16 +330,38 @@ const MkhBomData = () => { return; } setData(result?.data || { rows: [], total: 0, page: 1, pageSize: 50 }); + lastListRefreshAtRef.current = Date.now(); + setError(''); } catch (requestError) { if (!listRequestGateRef.current.isCurrent(requestGeneration)) return; setError(requestError?.response?.data?.error || requestError?.message || '加载 MKH-BOM 资料失败'); } finally { - if (listRequestGateRef.current.isCurrent(requestGeneration)) setLoading(false); + if (!background && listRequestGateRef.current.isCurrent(requestGeneration)) setLoading(false); } }, [query]); useEffect(() => { load(); }, [load]); + // 页面保持打开时自动更新;从后台切回且数据已超过轮询周期时立即重读。 + // 后台刷新保留当前表格,不显示全页加载态;请求门仍会阻止旧响应覆盖新数据。 + useEffect(() => { + const refreshIfStale = () => { + if (document.visibilityState !== 'visible' || syncing || autoRefreshPendingRef.current) return; + if (Date.now() - lastListRefreshAtRef.current < AUTO_REFRESH_MS) return; + autoRefreshPendingRef.current = true; + load({ background: true }).finally(() => { + autoRefreshPendingRef.current = false; + }); + }; + + const timer = window.setInterval(refreshIfStale, AUTO_REFRESH_MS); + document.addEventListener('visibilitychange', refreshIfStale); + return () => { + window.clearInterval(timer); + document.removeEventListener('visibilitychange', refreshIfStale); + }; + }, [load, syncing]); + const changeFilter = (key) => (value) => { setFilters((old) => ({ ...old, [key]: value || '' })); setPage(1);