app.js
8.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
* @Date: 2025-06-28 10:33:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-13 13:55:59
* @FilePath: /xyxBooking-weapp/src/app.js
* @Description: 应用入口文件
*/
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './utils/polyfill'
import './app.less'
import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
import Taro from '@tarojs/taro'
import { qrcodeListAPI } from '@/api/index'
import { formatDatetime } from '@/utils/tools'
let has_shown_network_modal = false
/**
* 格式化支付记录,按 pay_id 分组,相同 pay_id 下的记录 sort 为 0,否则为 1
* @param {*} data 支付记录数组
* @returns 格式化后的支付记录数组
*/
const formatGroup = (data) => {
let lastPayId = null;
for (let i = 0; i < data.length; i++) {
if (data[i].pay_id !== lastPayId) {
data[i].sort = 1;
lastPayId = data[i].pay_id;
} else {
data[i].sort = 0;
}
}
return data;
}
const App = createApp({
// 对应 onLaunch
async onLaunch(options) {
const path = options?.path || ''
const query = options?.query || {}
const query_string = Object.keys(query)
.map((key) => `${key}=${encodeURIComponent(query[key])}`)
.join('&')
const full_path = query_string ? `${path}?${query_string}` : path
// 保存当前页面路径,用于授权后跳转回原页面
if (full_path) {
saveCurrentPagePath(full_path)
}
/**
* 预加载二维码数据
* - 仅在有网络连接时调用
* - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA)
* - 失败则移除缓存
*/
const preloadQrData = async () => {
try {
const { code, data } = await qrcodeListAPI();
if (code && data) {
data.forEach(item => {
item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time })
item.sort = 0;
});
const validData = data.filter(item => item.qr_code !== '');
if (validData.length > 0) {
const processed = formatGroup(validData);
const offline_data = processed.map(item => ({
name: item.name,
id_number: item.id_number,
qr_code: item.qr_code,
begin_time: item.begin_time,
end_time: item.end_time,
datetime: item.datetime,
pay_id: item.pay_id,
sort: item.sort,
}));
Taro.setStorageSync('OFFLINE_QR_DATA', offline_data);
} else {
Taro.removeStorageSync('OFFLINE_QR_DATA');
}
}
} catch (e) {
console.error('Preload QR failed', e);
}
};
/**
* 监听网络状态变化
* - 当网络连接且有授权时,调用 preloadQrData 预加载二维码数据
*/
Taro.onNetworkStatusChange((res) => {
if (res.isConnected && hasAuth()) {
preloadQrData()
}
})
const is_usable_network = (network_type) => {
return ['wifi', '4g', '5g', '3g'].includes(network_type)
}
/**
* 获取当前网络类型
* @returns {string} 当前网络类型,如 wifi、4g、5g、3g、none 等
*/
const get_network_type = async () => {
try {
const result = await new Promise((resolve, reject) => {
Taro.getNetworkType({
success: resolve,
fail: reject,
})
})
return result?.networkType || 'unknown'
} catch (e) {
return 'unknown'
}
}
/**
* 检查是否有离线预约码缓存
* @returns {boolean} 如果有离线预约码缓存且有效,则返回 true;否则返回 false
*/
const has_offline_qr_cache = () => {
try {
const data = Taro.getStorageSync('OFFLINE_QR_DATA')
return Array.isArray(data) && data.length > 0
} catch (e) {
return false
}
}
/**
* 处理在启动时出现的不良网络情况
* - 当网络连接不良且有离线预约码缓存时,提示用户是否使用缓存预约码进入离线模式
* - 当网络连接不良且无离线预约码缓存时,提示用户网络连接不畅
* @returns {Promise<boolean>} 如果用户选择使用缓存预约码进入离线模式,则返回 true;否则返回 false
*/
const handle_bad_network_on_launch = async () => {
/**
* 避免重复提示用户
* - 仅在首次启动时检查网络情况
*/
if (has_shown_network_modal) return false
const network_type = await get_network_type()
const is_none_network = network_type === 'none'
const is_weak_network = !is_usable_network(network_type)
if (!is_weak_network) return false
has_shown_network_modal = true
if (has_offline_qr_cache()) {
try {
const modal_res = await Taro.showModal({
title: '网络连接不畅',
content: '当前网络信号较弱,可使用已缓存的预约码进入离线模式',
confirmText: '预约码',
cancelText: '知道了',
})
if (modal_res?.confirm) {
await Taro.reLaunch({ url: '/pages/offlineBookingCode/index' })
return true
}
} catch (e) {
return is_none_network
}
} else {
try {
await Taro.showToast({ title: '网络连接不畅', icon: 'none', duration: 2000 })
} catch (e) {
return is_none_network
}
}
return is_none_network
}
const should_stop = await handle_bad_network_on_launch()
if (should_stop) return
/**
* 尝试在网络可用时预加载二维码数据
* - 仅在有授权时调用
* - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA)
* - 失败则移除缓存
* @returns {Promise<void>}
*/
const try_preload_when_online = () => {
if (!hasAuth()) return
Taro.getNetworkType({
success: (res) => {
if (is_usable_network(res.networkType)) {
preloadQrData()
}
}
})
}
/**
* 尝试在有授权时预加载二维码数据
* - 若无授权,则尝试静默授权
* - 授权成功后调用 try_preload_when_online 预加载数据
* - 授权失败则跳转至授权页面
*/
if (hasAuth()) {
try_preload_when_online()
return
}
if (path === 'pages/auth/index') return
try {
// 尝试静默授权
await silentAuth()
// 授权成功后预加载数据
try_preload_when_online()
} catch (error) {
console.error('静默授权失败:', error)
// 授权失败则跳转至授权页面
navigateToAuth(full_path || undefined)
}
},
onShow() {
},
// 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
});
App.use(createPinia())
export default App