hookehuyr

feat(网络状态): 添加网络从可用变为弱网/无网时的弹窗提示功能

在网络状态从可用变为弱网或无网时,新增弹窗提示用户并可一键进入离线模式
优化网络状态变化处理逻辑,避免重复提示并增加页面路由判断
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
26 * 离线预约记录详情/离线二维码 (`pages/offlineBookingDetail/index`) 26 * 离线预约记录详情/离线二维码 (`pages/offlineBookingDetail/index`)
27 * 离线预约码入口页 (`pages/offlineBookingCode/index`) 27 * 离线预约码入口页 (`pages/offlineBookingCode/index`)
28 * 离线预约缓存刷新与轮询 (`src/composables/useOfflineBookingCache.js`, `src/composables/useOfflineBookingCachePolling.js`) 28 * 离线预约缓存刷新与轮询 (`src/composables/useOfflineBookingCache.js`, `src/composables/useOfflineBookingCachePolling.js`)
29 + * 网络从可用变为弱网/无网时,弹窗提示并可一键进入离线模式(`src/app.js`
29 30
30 5. **义工核销** 31 5. **义工核销**
31 * 义工登录与权限预检 (`pages/volunteerLogin/index`) 32 * 义工登录与权限预检 (`pages/volunteerLogin/index`)
......
1 /* 1 /*
2 * @Date: 2025-06-28 10:33:00 2 * @Date: 2025-06-28 10:33:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-13 23:30:40 4 + * @LastEditTime: 2026-01-16 00:17:50
5 * @FilePath: /xyxBooking-weapp/src/app.js 5 * @FilePath: /xyxBooking-weapp/src/app.js
6 * @Description: 应用入口文件 6 * @Description: 应用入口文件
7 */ 7 */
...@@ -16,7 +16,10 @@ import { is_usable_network, get_network_type } from '@/utils/network' ...@@ -16,7 +16,10 @@ import { is_usable_network, get_network_type } from '@/utils/network'
16 import { enable_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling' 16 import { enable_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling'
17 import { weak_network_text, get_weak_network_modal_use_cache_options } from '@/utils/uiText' 17 import { weak_network_text, get_weak_network_modal_use_cache_options } from '@/utils/uiText'
18 18
19 +// 记录是否已展示过网络异常提示弹窗
19 let has_shown_network_modal = false 20 let has_shown_network_modal = false
21 +// 记录上一次网络是否可用,用于识别“从可用变为不可用”的场景
22 +let last_network_usable = null
20 23
21 const App = createApp({ 24 const App = createApp({
22 // 对应 onLaunch 25 // 对应 onLaunch
...@@ -48,32 +51,34 @@ const App = createApp({ ...@@ -48,32 +51,34 @@ const App = createApp({
48 } 51 }
49 52
50 /** 53 /**
51 - * 监听网络状态变化 54 + * 判断是否应该跳过网络异常提示弹窗
52 - * - 当网络连接且有授权时,预加载离线预约记录数据 55 + * - 仅在当前页面为离线预约列表/详情/核销码页时返回 true
53 */ 56 */
54 - Taro.onNetworkStatusChange((res) => { 57 +
55 - if (res.isConnected && hasAuth()) { 58 + const should_skip_network_prompt = () => {
56 - preloadBookingData() 59 + const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []
57 - } 60 + const current_page = pages && pages.length ? pages[pages.length - 1] : null
58 - }) 61 + const current_route = String(current_page?.route || '')
62 + if (!current_route) return false
63 + if (current_route.includes('pages/offlineBookingList/index')) return true
64 + if (current_route.includes('pages/offlineBookingDetail/index')) return true
65 + if (current_route.includes('pages/offlineBookingCode/index')) return true
66 + return false
67 + }
59 68
60 /** 69 /**
61 - * 处理在启动时出现的不良网络情况 70 + * 处理不良网络情况
62 - * - 当网络连接不良且有离线预约记录缓存时,提示用户是否使用缓存进入离线模式 71 + * - 仅在当前页面未跳过提示弹窗时调用
63 - * - 当网络连接不良且无缓存时,提示用户网络连接不畅 72 + * - 若有离线预约缓存,则展示弹窗询问是否使用缓存数据
64 - * @returns {Promise<boolean>} 如果用户选择进入离线模式,则返回 true;否则返回 false 73 + * - 否则展示简单提示弹窗
65 */ 74 */
66 - const handle_bad_network_on_launch = async () => { 75 +
67 - /** 76 + const handle_bad_network = async (network_type) => {
68 - * 避免重复提示用户
69 - * - 仅在首次启动时检查网络情况
70 - */
71 if (has_shown_network_modal) return false 77 if (has_shown_network_modal) return false
78 + if (should_skip_network_prompt()) return false
72 79
73 - const network_type = await get_network_type()
74 const is_none_network = network_type === 'none' 80 const is_none_network = network_type === 'none'
75 const is_weak_network = !is_usable_network(network_type) 81 const is_weak_network = !is_usable_network(network_type)
76 -
77 if (!is_weak_network) return false 82 if (!is_weak_network) return false
78 83
79 has_shown_network_modal = true 84 has_shown_network_modal = true
...@@ -99,8 +104,48 @@ const App = createApp({ ...@@ -99,8 +104,48 @@ const App = createApp({
99 return is_none_network 104 return is_none_network
100 } 105 }
101 106
102 - const should_stop = await handle_bad_network_on_launch() 107 + /**
103 - if (should_stop) return 108 + * 监听网络状态变化
109 + * - 当网络连接且有授权时,预加载离线预约记录数据
110 + */
111 + Taro.onNetworkStatusChange((res) => {
112 + const is_connected = res?.isConnected !== false
113 + const network_type = res?.networkType || 'none'
114 + const network_usable = is_connected && is_usable_network(network_type)
115 +
116 + if (network_usable) {
117 + has_shown_network_modal = false
118 + last_network_usable = true
119 + if (hasAuth()) preloadBookingData()
120 + return
121 + }
122 +
123 + const should_prompt = last_network_usable === true || last_network_usable === null
124 + last_network_usable = false
125 + if (should_prompt) {
126 + handle_bad_network(network_type)
127 + }
128 + return
129 + })
130 +
131 + /**
132 + * 处理在启动时出现的不良网络情况
133 + * - 当网络连接不良且有离线预约记录缓存时,提示用户是否使用缓存进入离线模式
134 + * - 当网络连接不良且无缓存时,提示用户网络连接不畅
135 + * @returns {Promise<boolean>} 如果用户选择进入离线模式,则返回 true;否则返回 false
136 + */
137 + const handle_bad_network_on_launch = async () => {
138 + /**
139 + * 避免重复提示用户
140 + * - 仅在首次启动时检查网络情况
141 + * - 如果用户已展示过提示弹窗,则直接返回 false
142 + */
143 + if (has_shown_network_modal) return false
144 +
145 + const network_type = await get_network_type()
146 + last_network_usable = is_usable_network(network_type)
147 + return handle_bad_network(network_type)
148 + }
104 149
105 /** 150 /**
106 * 尝试在网络可用时预加载离线预约记录数据 151 * 尝试在网络可用时预加载离线预约记录数据
...@@ -119,16 +164,28 @@ const App = createApp({ ...@@ -119,16 +164,28 @@ const App = createApp({
119 } 164 }
120 165
121 /** 166 /**
122 - * 尝试在有授权时预加载二维码数据 167 + * @description: 授权成功后的共用启动逻辑
168 + * - 尝试在网络可用时预加载离线预约数据
169 + * - 启动离线预约缓存轮询(会自行处理网络可用性与引用计数)
170 + */
171 + const bootstrap_after_auth = () => {
172 + try_preload_when_online()
173 + enable_offline_booking_cache_polling()
174 + }
175 +
176 + // 处理在启动时出现的不良网络情况
177 + const should_stop = await handle_bad_network_on_launch()
178 + // 如果用户选择进入离线模式,则直接返回
179 + if (should_stop) return
180 +
181 + /**
182 + * 尝试在有授权时预加载离线预约记录数据
123 * - 若无授权,则尝试静默授权 183 * - 若无授权,则尝试静默授权
124 - * - 授权成功后调用 try_preload_when_online 预加载数据 184 + * - 授权成功后调用 bootstrap_after_auth 启动共用逻辑
125 * - 授权失败则跳转至授权页面 185 * - 授权失败则跳转至授权页面
126 */ 186 */
127 if (hasAuth()) { 187 if (hasAuth()) {
128 - // 有授权时预加载数据 188 + bootstrap_after_auth()
129 - try_preload_when_online()
130 - // 启动离线预约缓存轮询
131 - enable_offline_booking_cache_polling()
132 return 189 return
133 } 190 }
134 191
...@@ -137,19 +194,18 @@ const App = createApp({ ...@@ -137,19 +194,18 @@ const App = createApp({
137 try { 194 try {
138 // 尝试静默授权 195 // 尝试静默授权
139 await silentAuth() 196 await silentAuth()
140 - // 授权成功后预加载数据 197 + // 授权成功后调用 bootstrap_after_auth 启动共用逻辑
141 - try_preload_when_online() 198 + bootstrap_after_auth()
142 - // 启动离线预约缓存轮询
143 - enable_offline_booking_cache_polling()
144 } catch (error) { 199 } catch (error) {
145 console.error('静默授权失败:', error) 200 console.error('静默授权失败:', error)
146 // 授权失败则跳转至授权页面 201 // 授权失败则跳转至授权页面
147 navigateToAuth(full_path || undefined) 202 navigateToAuth(full_path || undefined)
148 } 203 }
204 +
205 + return
149 }, 206 },
150 onShow() { 207 onShow() {
151 }, 208 },
152 - // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
153 }); 209 });
154 210
155 App.use(createPinia()) 211 App.use(createPinia())
......