feat: Web端自动刷新画面机制
- DeviceScreen添加无帧超时检测(8秒无帧触发刷新) - 自动发送REFRESH_SCREEN请求给服务端 - 15秒冷却期防止频繁刷新
This commit is contained in:
24
node_modules/.vite/deps/_metadata.json
generated
vendored
24
node_modules/.vite/deps/_metadata.json
generated
vendored
@@ -7,73 +7,73 @@
|
||||
"react": {
|
||||
"src": "../../react/index.js",
|
||||
"file": "react.js",
|
||||
"fileHash": "82b88bac",
|
||||
"fileHash": "b64083dc",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-dom": {
|
||||
"src": "../../react-dom/index.js",
|
||||
"file": "react-dom.js",
|
||||
"fileHash": "f147bcf0",
|
||||
"fileHash": "4cc1d72b",
|
||||
"needsInterop": true
|
||||
},
|
||||
"@reduxjs/toolkit": {
|
||||
"src": "../../@reduxjs/toolkit/dist/redux-toolkit.modern.mjs",
|
||||
"file": "@reduxjs_toolkit.js",
|
||||
"fileHash": "e2e532ed",
|
||||
"fileHash": "229d524d",
|
||||
"needsInterop": false
|
||||
},
|
||||
"react-redux": {
|
||||
"src": "../../react-redux/dist/react-redux.mjs",
|
||||
"file": "react-redux.js",
|
||||
"fileHash": "49e0dcfd",
|
||||
"fileHash": "9cd5b390",
|
||||
"needsInterop": false
|
||||
},
|
||||
"antd": {
|
||||
"src": "../../antd/es/index.js",
|
||||
"file": "antd.js",
|
||||
"fileHash": "1c827006",
|
||||
"fileHash": "804ee91a",
|
||||
"needsInterop": false
|
||||
},
|
||||
"socket.io-client": {
|
||||
"src": "../../socket.io-client/build/esm/index.js",
|
||||
"file": "socket__io-client.js",
|
||||
"fileHash": "f1f126a4",
|
||||
"fileHash": "dfecfa57",
|
||||
"needsInterop": false
|
||||
},
|
||||
"react/jsx-dev-runtime": {
|
||||
"src": "../../react/jsx-dev-runtime.js",
|
||||
"file": "react_jsx-dev-runtime.js",
|
||||
"fileHash": "92554eaf",
|
||||
"fileHash": "ee0e2149",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-runtime": {
|
||||
"src": "../../react/jsx-runtime.js",
|
||||
"file": "react_jsx-runtime.js",
|
||||
"fileHash": "c9146743",
|
||||
"fileHash": "a8d2b404",
|
||||
"needsInterop": true
|
||||
},
|
||||
"@ant-design/icons": {
|
||||
"src": "../../@ant-design/icons/es/index.js",
|
||||
"file": "@ant-design_icons.js",
|
||||
"fileHash": "5c57aafc",
|
||||
"fileHash": "02740ed7",
|
||||
"needsInterop": false
|
||||
},
|
||||
"antd/locale/zh_CN": {
|
||||
"src": "../../antd/locale/zh_CN.js",
|
||||
"file": "antd_locale_zh_CN.js",
|
||||
"fileHash": "731388b8",
|
||||
"fileHash": "5fab095f",
|
||||
"needsInterop": true
|
||||
},
|
||||
"dayjs": {
|
||||
"src": "../../dayjs/dayjs.min.js",
|
||||
"file": "dayjs.js",
|
||||
"fileHash": "581df681",
|
||||
"fileHash": "ed91b429",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-dom/client": {
|
||||
"src": "../../react-dom/client.js",
|
||||
"file": "react-dom_client.js",
|
||||
"fileHash": "f34fbc85",
|
||||
"fileHash": "1733c935",
|
||||
"needsInterop": true
|
||||
}
|
||||
},
|
||||
|
||||
@@ -176,6 +176,49 @@ const DeviceScreen: React.FC<DeviceScreenProps> = ({ deviceId, onScreenSizeChang
|
||||
}
|
||||
}, [webSocket, deviceId])
|
||||
|
||||
// Auto-refresh: detect no-frame timeout and request screen refresh from device
|
||||
const lastFrameTimeRef = useRef<number>(Date.now())
|
||||
const refreshRequestedRef = useRef<boolean>(false)
|
||||
const NO_FRAME_TIMEOUT = 8000 // 8 seconds without frames triggers refresh
|
||||
const REFRESH_COOLDOWN = 15000 // minimum 15 seconds between refresh requests
|
||||
|
||||
// Update last frame time when screen_data arrives
|
||||
useEffect(() => {
|
||||
if (!webSocket || !deviceId) return
|
||||
|
||||
const trackFrameTime = (data: any) => {
|
||||
if (data.deviceId === deviceId) {
|
||||
lastFrameTimeRef.current = Date.now()
|
||||
refreshRequestedRef.current = false
|
||||
}
|
||||
}
|
||||
|
||||
webSocket.on('screen_data', trackFrameTime)
|
||||
return () => { webSocket.off('screen_data', trackFrameTime) }
|
||||
}, [webSocket, deviceId])
|
||||
|
||||
// Periodic check for frame timeout
|
||||
useEffect(() => {
|
||||
if (!webSocket || !deviceId) return
|
||||
|
||||
const checkInterval = window.setInterval(() => {
|
||||
const elapsed = Date.now() - lastFrameTimeRef.current
|
||||
if (elapsed < NO_FRAME_TIMEOUT) return
|
||||
if (refreshRequestedRef.current) return
|
||||
|
||||
console.log(`[AutoRefresh] No frames for ${Math.round(elapsed / 1000)}s, requesting screen refresh`)
|
||||
refreshRequestedRef.current = true
|
||||
lastFrameTimeRef.current = Date.now() - NO_FRAME_TIMEOUT + REFRESH_COOLDOWN
|
||||
|
||||
webSocket.emit('client_event', {
|
||||
type: 'REFRESH_SCREEN',
|
||||
data: { deviceId }
|
||||
})
|
||||
}, 3000) // check every 3 seconds
|
||||
|
||||
return () => { clearInterval(checkInterval) }
|
||||
}, [webSocket, deviceId])
|
||||
|
||||
// 控制权管理的独立useEffect,只在必要时申请/释放
|
||||
useEffect(() => {
|
||||
if (!webSocket || !deviceId) return
|
||||
|
||||
Reference in New Issue
Block a user