Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
CFFP-HB
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chao Sun
CFFP-HB
Commits
5f9deeb6
Commit
5f9deeb6
authored
Oct 21, 2026
by
yuzhenWang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加一体机超时退出功能,已发布测试
parent
c6302b35
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
262 additions
and
1 deletions
+262
-1
App.vue
+36
-1
index.html
+47
-0
util/useH5IdleExit.js
+179
-0
No files found.
App.vue
View file @
5f9deeb6
...
@@ -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
:
{
// 检查用户状态的方法 防止多端操作导致此用户不存在
// 检查用户状态的方法 防止多端操作导致此用户不存在
...
...
index.html
View file @
5f9deeb6
...
@@ -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>
...
...
util/useH5IdleExit.js
0 → 100644
View file @
5f9deeb6
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment