hookehuyr

feat(offline): 添加离线模式支持并优化网络检测功能

新增离线预约记录页面和网络工具函数
将网络检测逻辑提取到独立工具模块
优化页面跳转时的网络状态检查
1 /* 1 /*
2 * @Date: 2023-08-24 09:42:27 2 * @Date: 2023-08-24 09:42:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-12 18:38:52 4 + * @LastEditTime: 2026-01-13 14:52:29
5 * @FilePath: /xyxBooking-weapp/src/api/index.js 5 * @FilePath: /xyxBooking-weapp/src/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -21,6 +21,7 @@ const Api = { ...@@ -21,6 +21,7 @@ const Api = {
21 QRCODE_LIST: '/srv/?a=api&t=qrcode_list', 21 QRCODE_LIST: '/srv/?a=api&t=qrcode_list',
22 QRCODE_STATUS: '/srv/?a=api&t=qrcode_status', 22 QRCODE_STATUS: '/srv/?a=api&t=qrcode_status',
23 BILL_LIST: '/srv/?a=api&t=bill_list', 23 BILL_LIST: '/srv/?a=api&t=bill_list',
24 + BILL_OFFLINE_ALL: '/srv/?a=api&t=bill_offline_all',
24 ICBC_REFUND: '/srv/?a=icbc_refund', 25 ICBC_REFUND: '/srv/?a=icbc_refund',
25 BILL_PREPARE: '/srv/?a=api&t=bill_person', 26 BILL_PREPARE: '/srv/?a=api&t=bill_person',
26 BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', 27 BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status',
...@@ -182,6 +183,12 @@ export const qrcodeStatusAPI = (params) => fn(fetch.get(Api.QRCODE_STATUS, param ...@@ -182,6 +183,12 @@ export const qrcodeStatusAPI = (params) => fn(fetch.get(Api.QRCODE_STATUS, param
182 export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params)); 183 export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params));
183 184
184 /** 185 /**
186 + * @description: 离线预约记录全量数据(列表+详情)
187 + * @returns {String}
188 + */
189 +export const billOfflineAllAPI = (params) => fn(fetch.get(Api.BILL_OFFLINE_ALL, params));
190 +
191 +/**
185 * @description: 取消预约 192 * @description: 取消预约
186 * @param {String} pay_id 193 * @param {String} pay_id
187 * @returns {String} 194 * @returns {String}
......
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 13:55:59 4 + * @LastEditTime: 2026-01-13 15:22:40
5 * @FilePath: /xyxBooking-weapp/src/app.js 5 * @FilePath: /xyxBooking-weapp/src/app.js
6 * @Description: 应用入口文件 6 * @Description: 应用入口文件
7 */ 7 */
...@@ -12,6 +12,7 @@ import './app.less' ...@@ -12,6 +12,7 @@ import './app.less'
12 import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect' 12 import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
13 import Taro from '@tarojs/taro' 13 import Taro from '@tarojs/taro'
14 import { refresh_offline_booking_cache, has_offline_booking_cache } from '@/composables/useOfflineBookingCache' 14 import { refresh_offline_booking_cache, has_offline_booking_cache } from '@/composables/useOfflineBookingCache'
15 +import { is_usable_network, get_network_type } from '@/utils/network'
15 16
16 let has_shown_network_modal = false 17 let has_shown_network_modal = false
17 18
...@@ -54,28 +55,6 @@ const App = createApp({ ...@@ -54,28 +55,6 @@ const App = createApp({
54 } 55 }
55 }) 56 })
56 57
57 - const is_usable_network = (network_type) => {
58 - return ['wifi', '4g', '5g', '3g'].includes(network_type)
59 - }
60 -
61 - /**
62 - * 获取当前网络类型
63 - * @returns {string} 当前网络类型,如 wifi、4g、5g、3g、none 等
64 - */
65 - const get_network_type = async () => {
66 - try {
67 - const result = await new Promise((resolve, reject) => {
68 - Taro.getNetworkType({
69 - success: resolve,
70 - fail: reject,
71 - })
72 - })
73 - return result?.networkType || 'unknown'
74 - } catch (e) {
75 - return 'unknown'
76 - }
77 - }
78 -
79 /** 58 /**
80 * 处理在启动时出现的不良网络情况 59 * 处理在启动时出现的不良网络情况
81 * - 当网络连接不良且有离线预约记录缓存时,提示用户是否使用缓存进入离线模式 60 * - 当网络连接不良且有离线预约记录缓存时,提示用户是否使用缓存进入离线模式
......
...@@ -10,33 +10,12 @@ import Taro from '@tarojs/taro' ...@@ -10,33 +10,12 @@ import Taro from '@tarojs/taro'
10 import { billOfflineAllAPI } from '@/api/index' 10 import { billOfflineAllAPI } from '@/api/index'
11 import { hasAuth } from '@/utils/authRedirect' 11 import { hasAuth } from '@/utils/authRedirect'
12 import { formatDatetime } from '@/utils/tools' 12 import { formatDatetime } from '@/utils/tools'
13 +import { is_usable_network, get_network_type } from '@/utils/network'
13 14
14 export const OFFLINE_BOOKING_CACHE_KEY = 'OFFLINE_BOOKING_DATA' 15 export const OFFLINE_BOOKING_CACHE_KEY = 'OFFLINE_BOOKING_DATA'
15 16
16 let refresh_promise = null 17 let refresh_promise = null
17 18
18 -const is_usable_network = (network_type) => {
19 - return ['wifi', '4g', '5g', '3g'].includes(network_type)
20 -}
21 -
22 -/**
23 - * 获取当前网络类型
24 - * @returns {Promise<string>} 网络类型(wifi, 4g, 5g, 3g, unknown)
25 - */
26 -const get_network_type = async () => {
27 - try {
28 - const result = await new Promise((resolve, reject) => {
29 - Taro.getNetworkType({
30 - success: resolve,
31 - fail: reject,
32 - })
33 - })
34 - return result?.networkType || 'unknown'
35 - } catch (e) {
36 - return 'unknown'
37 - }
38 -}
39 -
40 /** 19 /**
41 * 格式化预约记录项 20 * 格式化预约记录项
42 * @param {Object} item - 原始预约记录项 21 * @param {Object} item - 原始预约记录项
......
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:19:11 4 + * @LastEditTime: 2026-01-13 15:24:06
5 * @FilePath: /xyxBooking-weapp/src/pages/bookingCode/index.vue 5 * @FilePath: /xyxBooking-weapp/src/pages/bookingCode/index.vue
6 - * @Description: 文件描述 6 + * @Description: 预约码页面
7 --> 7 -->
8 <template> 8 <template>
9 <view class="booking-code-page"> 9 <view class="booking-code-page">
...@@ -42,13 +42,14 @@ import icon_4 from '@/assets/images/二维码icon.png' ...@@ -42,13 +42,14 @@ import icon_4 from '@/assets/images/二维码icon.png'
42 import icon_5 from '@/assets/images/我的01@2x.png' 42 import icon_5 from '@/assets/images/我的01@2x.png'
43 import { useGo } from '@/hooks/useGo' 43 import { useGo } from '@/hooks/useGo'
44 import { has_offline_booking_cache } from '@/composables/useOfflineBookingCache' 44 import { has_offline_booking_cache } from '@/composables/useOfflineBookingCache'
45 +import { is_usable_network } from '@/utils/network'
45 46
46 const go = useGo(); 47 const go = useGo();
47 48
48 useDidShow(() => { 49 useDidShow(() => {
49 Taro.getNetworkType({ 50 Taro.getNetworkType({
50 success: (res) => { 51 success: (res) => {
51 - const isConnected = ['wifi', '4g', '5g', '3g'].includes(res.networkType); 52 + const isConnected = is_usable_network(res.networkType);
52 if (!isConnected) { 53 if (!isConnected) {
53 if (has_offline_booking_cache()) { 54 if (has_offline_booking_cache()) {
54 Taro.redirectTo({ url: '/pages/offlineBookingList/index' }) 55 Taro.redirectTo({ url: '/pages/offlineBookingList/index' })
......
1 <!-- 1 <!--
2 * @Date: 2023-06-21 10:23:09 2 * @Date: 2023-06-21 10:23:09
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-09 18:08:03 4 + * @LastEditTime: 2026-01-13 15:35:17
5 * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue 5 * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue
6 * @Description: 预约页首页 6 * @Description: 预约页首页
7 --> 7 -->
......
1 <template> 1 <template>
2 <view class="my-page"> 2 <view class="my-page">
3 - <view v-for="(item, index) in menu_list" :key="index" class="my-item" @tap="go(item.to)"> 3 + <view v-for="(item, index) in menu_list" :key="index" class="my-item" @tap="on_menu_tap(item)">
4 <view class="left"> 4 <view class="left">
5 <image :src="item.icon" style="width: 38rpx; height: 38rpx; margin-right: 16rpx;" /> 5 <image :src="item.icon" style="width: 38rpx; height: 38rpx; margin-right: 16rpx;" />
6 {{ item.name }} 6 {{ item.name }}
...@@ -35,6 +35,8 @@ import { IconFont } from '@nutui/icons-vue-taro' ...@@ -35,6 +35,8 @@ import { IconFont } from '@nutui/icons-vue-taro'
35 import icon_3 from '@/assets/images/首页01@2x.png' 35 import icon_3 from '@/assets/images/首页01@2x.png'
36 import icon_4 from '@/assets/images/二维码icon.png' 36 import icon_4 from '@/assets/images/二维码icon.png'
37 import icon_5 from '@/assets/images/我的02@2x.png' 37 import icon_5 from '@/assets/images/我的02@2x.png'
38 +import { has_offline_booking_cache } from '@/composables/useOfflineBookingCache'
39 +import { is_usable_network, get_network_type } from '@/utils/network'
38 40
39 import icon_booking from '@/assets/images/预约记录@2x.png' 41 import icon_booking from '@/assets/images/预约记录@2x.png'
40 import icon_visitor from '@/assets/images/我的01@2x.png' 42 import icon_visitor from '@/assets/images/我的01@2x.png'
...@@ -42,6 +44,33 @@ import icon_invite from '@/assets/images/二维码@2x2.png' ...@@ -42,6 +44,33 @@ import icon_invite from '@/assets/images/二维码@2x2.png'
42 44
43 const go = useGo(); 45 const go = useGo();
44 46
47 +const on_menu_tap = async (item) => {
48 + if (!item?.to) return
49 +
50 + if (item.to === '/pages/bookingList/index') {
51 + const network_type = await get_network_type()
52 + const is_weak_network = !is_usable_network(network_type)
53 + if (is_weak_network) {
54 + if (has_offline_booking_cache()) {
55 + const modal_res = await Taro.showModal({
56 + title: '网络连接不畅',
57 + content: '当前网络信号较弱,是否进入离线预约记录?',
58 + confirmText: '离线记录',
59 + cancelText: '知道了',
60 + })
61 + if (modal_res?.confirm) {
62 + go('/pages/offlineBookingList/index')
63 + }
64 + return
65 + }
66 + Taro.showToast({ title: '网络连接不畅', icon: 'none', duration: 2000 })
67 + return
68 + }
69 + }
70 +
71 + go(item.to)
72 +}
73 +
45 const toCode = () => { // 跳转到预约码 74 const toCode = () => { // 跳转到预约码
46 Taro.redirectTo({ 75 Taro.redirectTo({
47 url: '/pages/bookingCode/index' 76 url: '/pages/bookingCode/index'
......
1 +<!--
2 + * @Date: 2026-01-13 14:55:05
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2026-01-13 15:25:25
5 + * @FilePath: /xyxBooking-weapp/src/pages/offlineBookingList/index.vue
6 + * @Description: 离线预约记录页面
7 +-->
1 <template> 8 <template>
2 <view class="offline-booking-list-page"> 9 <view class="offline-booking-list-page">
3 <view class="header-tip"> 10 <view class="header-tip">
4 - <IconFont name="tips" size="15" color="#A67939" /> 11 + <IconFont name="tips" size="15" color="#A67939" /> &nbsp;
5 <text>您当前处于离线模式,仅展示本地缓存的预约记录</text> 12 <text>您当前处于离线模式,仅展示本地缓存的预约记录</text>
6 </view> 13 </view>
7 14
...@@ -83,7 +90,7 @@ useDidShow(() => { ...@@ -83,7 +90,7 @@ useDidShow(() => {
83 color: #FFF; 90 color: #FFF;
84 border-radius: 16rpx; 91 border-radius: 16rpx;
85 font-size: 32rpx; 92 font-size: 32rpx;
86 - padding: 22rpx 0; 93 + padding: 12rpx 0;
87 } 94 }
88 } 95 }
89 } 96 }
......
1 +/*
2 + * @Date: 2026-01-13 15:34:47
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2026-01-13 15:36:37
5 + * @FilePath: /xyxBooking-weapp/src/utils/network.js
6 + * @Description: 网络相关工具函数
7 + */
8 +import Taro from '@tarojs/taro'
9 +
10 +/**
11 + * @description: 判断网络是否可用(wifi, 4g, 5g, 3g)
12 + * @param {string} network_type - 网络类型
13 + * @returns {boolean} 是否可用
14 + */
15 +export const is_usable_network = (network_type) => {
16 + return ['wifi', '4g', '5g', '3g'].includes(network_type)
17 +}
18 +
19 +/**
20 + * @description: 获取当前网络类型
21 + * @returns {Promise<string>} 网络类型(wifi, 4g, 5g, 3g, unknown)
22 + */
23 +export const get_network_type = async () => {
24 + try {
25 + const result = await new Promise((resolve, reject) => {
26 + Taro.getNetworkType({
27 + success: resolve,
28 + fail: reject,
29 + })
30 + })
31 + return result?.networkType || 'unknown'
32 + } catch (e) {
33 + return 'unknown'
34 + }
35 +}