Commit 5f9deeb6 by yuzhenWang

添加一体机超时退出功能,已发布测试

parent c6302b35
...@@ -6,6 +6,18 @@ ...@@ -6,6 +6,18 @@
import api from './api/api'; import api from './api/api';
import {hshare} from '@/util/fiveshare'; import {hshare} from '@/util/fiveshare';
import dataHandling from "@/util/dataHandling"; import dataHandling from "@/util/dataHandling";
import { useH5IdleExit } from '@/util/useH5IdleExit'
const idleExit = useH5IdleExit()
let isAllInOneEnv = false
function resolveAllInOne(options) {
const fromQuery = options?.query?.bagType || ''
if (fromQuery) return fromQuery === 'allinone'
const q = window.location.search || ''
const m = q.match(/[?&]bagType=([^&]+)/)
return m ? decodeURIComponent(m[1]) === 'allinone' : false
}
export default { export default {
data() { data() {
return { return {
...@@ -14,8 +26,16 @@ ...@@ -14,8 +26,16 @@
loginType:'' loginType:''
} }
}, },
onLaunch: function() { onLaunch: function(options) {
console.log('App Launch'); console.log('App Launch');
//----嵌入一体机开启超时自动退出-----
isAllInOneEnv = resolveAllInOne(options)
window.addEventListener('pagehide', () => idleExit.stop())
window.addEventListener('beforeunload', () => idleExit.stop())
//----嵌入一体机开启超时自动退出-----
if(uni.getStorageSync('loginType')){ if(uni.getStorageSync('loginType')){
this.loginType = uni.getStorageSync('loginType') this.loginType = uni.getStorageSync('loginType')
} }
...@@ -73,6 +93,16 @@ ...@@ -73,6 +93,16 @@
}, },
onShow: function(options) { onShow: function(options) {
//----嵌入一体机开启超时自动退出-----
isAllInOneEnv = resolveAllInOne(options)
if (isAllInOneEnv) {
idleExit.start()
idleExit.reset()
}
//----嵌入一体机开启超时自动退出-----
console.log('App Show', options); console.log('App Show', options);
// 每次进应用显示时检查用户状态 // 每次进应用显示时检查用户状态
this.checkUserStatus(); this.checkUserStatus();
...@@ -84,8 +114,13 @@ ...@@ -84,8 +114,13 @@
// #endif // #endif
}, },
onHide: function() { onHide: function() {
// 切后台/息屏/H5 被隐藏:停掉,避免后台跑定时器
idleExit.stop()
console.log('App Hide') console.log('App Hide')
}, },
onUnload() {
idleExit.stop()
},
methods: { methods: {
// 检查用户状态的方法 防止多端操作导致此用户不存在 // 检查用户状态的方法 防止多端操作导致此用户不存在
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
} }
}); });
</script> </script>
<title>银盾家办</title> <title>银盾家办</title>
<link rel="stylesheet" href="./static/font/iconfont.css"> <link rel="stylesheet" href="./static/font/iconfont.css">
<link rel="shortcut icon" href="./static/suplogo.ico"> <link rel="shortcut icon" href="./static/suplogo.ico">
...@@ -70,6 +71,52 @@ ...@@ -70,6 +71,52 @@
<div id="app"> <div id="app">
<!--app-html--> <!--app-html-->
</div> </div>
<script>
(function() {
// 1. 判断是否在 App WebView 中
function isAppWebView() {
// 检测 5+ App(plus 对象)
if (typeof window.plus !== 'undefined') {
return true;
}
// 检测 UserAgent
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('html5plus') !== -1 || ua.indexOf('uni-app') !== -1) {
return true;
}
// 检测 uni-app 注入的全局对象(部分版本)
if (typeof window.__uni__ !== 'undefined') {
return true;
}
return false;
}
if (isAppWebView()) {
console.log('[环境] 检测到 App WebView,开始加载 uni.webview.js');
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/appYdhomeoffice/static/uni.webview.1.5.4.js';
script.onload = function() {
// 脚本加载成功后,执行原有逻辑(挂载 webViewJs)
var webViewJs = window.uni?.webView;
if (!webViewJs) {
console.error('uni.webview.js 加载成功但 webViewJs 不存在');
} else {
console.log('uni.webview.js 加载成功', webViewJs);
window.webViewJs = webViewJs;
console.log('window.webViewJs 已挂载', window);
}
};
script.onerror = function() {
console.error('uni.webview.js 加载失败,请检查路径');
};
document.head.appendChild(script);
} else {
console.log('[环境] 非 App WebView,跳过加载 uni.webview.js');
}
})();
</script>
<script type="module" src="/main.js"></script> <script type="module" src="/main.js"></script>
</body> </body>
......
const IDLE_TIMEOUT = 30 * 60 * 1000
// const IDLE_TIMEOUT = 3 * 1000
const EXIT_COUNTDOWN = 30
const WATCH_INTERVAL = 10 * 1000
const ACTIVITY_THROTTLE = 300
const POSTER_URL = '/pages/index/launch'
const ACTIVITY_EVENTS = [
{ type: 'touchstart', opts: { passive: true } },
{ type: 'pointerdown', opts: { passive: true } },
{ type: 'click', opts: { passive: true } },
{ type: 'input', opts: { capture: true, passive: true } },
{ type: 'focusin', opts: { capture: true, passive: true } },
{ type: 'change', opts: { capture: true, passive: true } },
{ type: 'keydown', opts: { capture: true, passive: true } },
{ type: 'wheel', opts: { passive: true } },
{ type: 'scroll', opts: { capture: true, passive: true } }
]
export function useH5IdleExit() {
let idleTimer = null
let exitTimer = null
let watcher = null
let lastActive = Date.now()
let lastActivityCall = 0
let modalShowing = false
let started = false
const clearTimers = () => {
if (idleTimer) { clearTimeout(idleTimer); idleTimer = null }
if (exitTimer) { clearTimeout(exitTimer); exitTimer = null }
if (watcher) { clearInterval(watcher); watcher = null }
}
const resetIdle = () => {
lastActive = Date.now()
if (idleTimer) clearTimeout(idleTimer)
idleTimer = setTimeout(showIdleModal, IDLE_TIMEOUT)
}
const doExit = () => {
clearTimers()
modalShowing = false
try { uni.clearStorageSync() } catch (e) {}
const bridge = window.webViewJs
if (bridge && typeof bridge.reLaunch === 'function') {
bridge.reLaunch({ url: POSTER_URL })
} else {
console.warn('[useH5IdleExit] window.webViewJs 不存在,无法跳转海报页')
try { uni.reLaunch({ url: POSTER_URL }) } catch (e) {}
}
}
const showIdleModal = () => {
if (modalShowing) return
modalShowing = true
let settled = false
exitTimer = setTimeout(() => {
if (settled) return
settled = true
doExit()
}, EXIT_COUNTDOWN * 1000)
uni.showModal({
title: '温馨提示',
content: `系统检测到您长时间未操作,系统将在 ${EXIT_COUNTDOWN} 秒后自动退出`,
confirmText: '立即退出',
cancelText: '继续使用',
confirmColor: '#e74c3c',
success: (res) => {
if (settled) return
settled = true
if (exitTimer) { clearTimeout(exitTimer); exitTimer = null }
modalShowing = false
if (res.confirm) doExit()
else resetIdle()
},
fail: () => {
if (exitTimer) { clearTimeout(exitTimer); exitTimer = null }
modalShowing = false
}
})
}
const onActivity = () => {
if (modalShowing) return
const now = Date.now()
if (now - lastActivityCall < ACTIVITY_THROTTLE) return
lastActivityCall = now
resetIdle()
}
const startWatcher = () => {
if (watcher) clearInterval(watcher)
watcher = setInterval(() => {
if (!started || modalShowing) return
if (Date.now() - lastActive >= IDLE_TIMEOUT) showIdleModal()
}, WATCH_INTERVAL)
}
const onVisibilityChange = () => {
if (document.hidden) {
clearTimers()
} else {
if (!started) return
modalShowing = false
resetIdle()
startWatcher()
}
}
const onWindowFocus = () => {
if (!started || modalShowing) return
resetIdle()
}
const bindActivityEvents = () => {
ACTIVITY_EVENTS.forEach(({ type, opts }) => document.addEventListener(type, onActivity, opts))
window.addEventListener('focus', onWindowFocus)
window.addEventListener('pageshow', onWindowFocus)
}
const unbindActivityEvents = () => {
ACTIVITY_EVENTS.forEach(({ type, opts }) => {
document.removeEventListener(type, onActivity, opts.capture ? { capture: true } : false)
})
window.removeEventListener('focus', onWindowFocus)
window.removeEventListener('pageshow', onWindowFocus)
}
const start = () => {
if (started) return
started = true
bindActivityEvents()
document.addEventListener('visibilitychange', onVisibilityChange)
resetIdle()
startWatcher()
window.__h5StopIdle = () => {
if (!started) return 'not-started'
clearTimers()
modalShowing = false
console.log('[H5] __h5StopIdle 已执行')
return 'stopped'
}
window.__h5ResetIdle = () => {
if (!started) return 'not-started'
modalShowing = false
resetIdle()
startWatcher()
console.log('[H5] __h5ResetIdle 已执行')
return 'reset'
}
} // <--- ⚠️ 就是这里,补上了缺失的大括号!
const stop = () => {
clearTimers()
started = false
modalShowing = false
unbindActivityEvents()
document.removeEventListener('visibilitychange', onVisibilityChange)
window.__h5StopIdle = null
window.__h5ResetIdle = null
}
const reset = () => {
if (!started) return
modalShowing = false
resetIdle()
startWatcher()
}
return { start, stop, reset }
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment