hookehuyr

refactor(网络请求): 重构弱网处理逻辑并移除组件中的超时代码

将弱网和超时处理逻辑集中到请求拦截器中
移除组件中冗余的超时处理代码
添加离线预约缓存检查功能
1 <!-- 1 <!--
2 * @Date: 2024-01-16 10:06:47 2 * @Date: 2024-01-16 10:06:47
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-13 15:18:07 4 + * @LastEditTime: 2026-01-13 16:00:44
5 * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue 5 * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue
6 * @Description: 预约码卡组件 6 * @Description: 预约码卡组件
7 --> 7 -->
...@@ -169,12 +169,7 @@ const formatGroup = (data) => { ...@@ -169,12 +169,7 @@ const formatGroup = (data) => {
169 const init = async () => { 169 const init = async () => {
170 if (!props.type) { 170 if (!props.type) {
171 try { 171 try {
172 - // TAG: 设置 5s 超时判定为弱网 172 + const { code, data } = await qrcodeListAPI();
173 - const timeoutPromise = new Promise((_, reject) => {
174 - setTimeout(() => reject(new Error('TIMEOUT')), 5000);
175 - });
176 -
177 - const { code, data } = await Promise.race([qrcodeListAPI(), timeoutPromise]);
178 173
179 if (code) { 174 if (code) {
180 data.forEach(item => { 175 data.forEach(item => {
...@@ -194,10 +189,6 @@ const init = async () => { ...@@ -194,10 +189,6 @@ const init = async () => {
194 } 189 }
195 } catch (err) { 190 } catch (err) {
196 console.error('Fetch QR List Failed:', err); 191 console.error('Fetch QR List Failed:', err);
197 - // 如果是超时,跳转弱网页面
198 - if (err.message === 'TIMEOUT') {
199 - go('/pages/weakNetwork/index');
200 - }
201 } 192 }
202 } else { 193 } else {
203 if (props.payId) { 194 if (props.payId) {
......
1 /* 1 /*
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-08 19:25:17 4 + * @LastEditTime: 2026-01-13 16:15:35
5 * @FilePath: /xyxBooking-weapp/src/utils/request.js 5 * @FilePath: /xyxBooking-weapp/src/utils/request.js
6 * @Description: 简单axios封装,后续按实际处理 6 * @Description: 简单axios封装,后续按实际处理
7 */ 7 */
...@@ -11,6 +11,7 @@ import Taro from '@tarojs/taro' ...@@ -11,6 +11,7 @@ import Taro from '@tarojs/taro'
11 // import qs from 'qs' 11 // import qs from 'qs'
12 // import { strExist } from './tools' 12 // import { strExist } from './tools'
13 import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect' 13 import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect'
14 +import { has_offline_booking_cache } from '@/composables/useOfflineBookingCache'
14 15
15 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress'; 16 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
16 // import store from '@/store' 17 // import store from '@/store'
...@@ -46,6 +47,95 @@ service.defaults.params = { ...@@ -46,6 +47,95 @@ service.defaults.params = {
46 ...REQUEST_DEFAULT_PARAMS, 47 ...REQUEST_DEFAULT_PARAMS,
47 }; 48 };
48 49
50 +let has_shown_timeout_modal = false
51 +
52 +/**
53 + * 判断是否为超时错误
54 + * @param {Error} error - 请求错误对象
55 + * @returns {boolean} 是否为超时错误
56 + */
57 +
58 +const is_timeout_error = (error) => {
59 + const msg = String(error?.message || error?.errMsg || '')
60 + if (error?.code === 'ECONNABORTED') return true
61 + return msg.toLowerCase().includes('timeout')
62 +}
63 +
64 +/**
65 + * 判断是否为网络错误(断网/弱网/请求失败等)
66 + * @param {Error} error - 请求错误对象
67 + * @returns {boolean} 是否为网络错误
68 + */
69 +const is_network_error = (error) => {
70 + const msg = String(error?.message || error?.errMsg || '')
71 + const raw = (() => {
72 + try {
73 + return JSON.stringify(error) || ''
74 + } catch (e) {
75 + return ''
76 + }
77 + })()
78 + const lower = (msg + ' ' + raw).toLowerCase()
79 + if (lower.includes('request:fail')) return true
80 + if (lower.includes('request fail')) return true
81 + if (lower.includes('network error')) return true
82 + if (lower.includes('failed to fetch')) return true
83 + if (lower.includes('the internet connection appears to be offline')) return true
84 + if (lower.includes('err_blocked_by_client')) return true
85 + if (lower.includes('blocked_by_client')) return true
86 + return false
87 +}
88 +
89 +/**
90 + * 是否需要触发弱网/断网降级逻辑
91 + * - 超时:直接触发
92 + * - 网络错误:直接触发(避免 wifi 但无网场景漏判)
93 + * @param {Error} error - 请求错误对象
94 + * @returns {Promise<boolean>} 是否需要触发降级
95 + */
96 +const should_handle_bad_network = async (error) => {
97 + if (is_timeout_error(error)) return true
98 + return is_network_error(error)
99 +}
100 +
101 +/**
102 + * 处理请求超时错误
103 + * - 显示超时提示 modal
104 + * - 若有离线预约记录缓存,则跳转至离线预约列表页
105 + * - 否则提示用户检查网络连接
106 + */
107 +const handle_request_timeout = async () => {
108 + if (has_shown_timeout_modal) return
109 + has_shown_timeout_modal = true
110 +
111 + const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []
112 + const current_page = pages && pages.length ? pages[pages.length - 1] : null
113 + const current_route = current_page?.route || ''
114 + if (String(current_route).includes('pages/offlineBookingList/index')) return
115 +
116 + // 若有离线预约记录缓存,则跳转至离线预约列表页
117 + if (has_offline_booking_cache()) {
118 + try {
119 + await Taro.reLaunch({ url: '/pages/offlineBookingList/index' })
120 + } catch (e) {
121 + console.error('reLaunch offlineBookingList failed:', e)
122 + }
123 + return
124 + }
125 +
126 + // 否则提示用户检查网络连接
127 + try {
128 + await Taro.showModal({
129 + title: '网络连接不畅',
130 + content: '当前网络信号较弱,暂无法使用小程序,请到网络更好的地方重试。',
131 + confirmText: '知道了',
132 + showCancel: false,
133 + })
134 + } catch (e) {
135 + console.error('show weak network modal failed:', e)
136 + }
137 +}
138 +
49 // request interceptor 139 // request interceptor
50 service.interceptors.request.use( 140 service.interceptors.request.use(
51 config => { 141 config => {
...@@ -144,12 +234,15 @@ service.interceptors.response.use( ...@@ -144,12 +234,15 @@ service.interceptors.response.use(
144 234
145 return response 235 return response
146 }, 236 },
147 - error => { 237 + async error => {
148 // Taro.showToast({ 238 // Taro.showToast({
149 // title: error.message, 239 // title: error.message,
150 // icon: 'none', 240 // icon: 'none',
151 // duration: 2000 241 // duration: 2000
152 // }) 242 // })
243 + if (await should_handle_bad_network(error)) {
244 + handle_request_timeout()
245 + }
153 return Promise.reject(error) 246 return Promise.reject(error)
154 } 247 }
155 ) 248 )
......