feat(离线预约): 添加离线预约缓存轮询功能
实现离线预约缓存自动轮询刷新机制,提升离线状态下的数据同步能力 移除不再使用的支付相关API和等待页面
Showing
6 changed files
with
122 additions
and
12 deletions
| 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-13 20:55:13 | 4 | + * @LastEditTime: 2026-01-13 23:13:04 |
| 5 | * @FilePath: /xyxBooking-weapp/src/api/index.js | 5 | * @FilePath: /xyxBooking-weapp/src/api/index.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -14,8 +14,8 @@ const Api = { | ... | @@ -14,8 +14,8 @@ const Api = { |
| 14 | ADD_PERSON: '/srv/?a=api&t=add_person', | 14 | ADD_PERSON: '/srv/?a=api&t=add_person', |
| 15 | DEL_PERSON: '/srv/?a=api&t=del_person', | 15 | DEL_PERSON: '/srv/?a=api&t=del_person', |
| 16 | ADD_RESERVE: '/srv/?a=api&t=add_reserve', | 16 | ADD_RESERVE: '/srv/?a=api&t=add_reserve', |
| 17 | - PAY_PREPARE: '/srv/?a=api&t=pay_prepare', | 17 | + // PAY_PREPARE: '/srv/?a=api&t=pay_prepare', |
| 18 | - PAY_CALLBACK: '/srv/?a=api&t=pay_callback', | 18 | + // PAY_CALLBACK: '/srv/?a=api&t=pay_callback', |
| 19 | BILL_INFO: '/srv/?a=api&t=bill_info', | 19 | BILL_INFO: '/srv/?a=api&t=bill_info', |
| 20 | ON_AUTH_BILL_INFO: '/srv/?a=no_auth_api&t=bill_info', | 20 | ON_AUTH_BILL_INFO: '/srv/?a=no_auth_api&t=bill_info', |
| 21 | QRCODE_LIST: '/srv/?a=api&t=qrcode_list', | 21 | QRCODE_LIST: '/srv/?a=api&t=qrcode_list', |
| ... | @@ -24,7 +24,7 @@ const Api = { | ... | @@ -24,7 +24,7 @@ const Api = { |
| 24 | BILL_OFFLINE_ALL: '/srv/?a=api&t=bill_all_info', | 24 | BILL_OFFLINE_ALL: '/srv/?a=api&t=bill_all_info', |
| 25 | ICBC_REFUND: '/srv/?a=icbc_refund', | 25 | ICBC_REFUND: '/srv/?a=icbc_refund', |
| 26 | BILL_PREPARE: '/srv/?a=api&t=bill_person', | 26 | BILL_PREPARE: '/srv/?a=api&t=bill_person', |
| 27 | - BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', | 27 | + // BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', |
| 28 | QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', | 28 | QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', |
| 29 | ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', | 29 | ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', |
| 30 | WX_PAY: '/srv/?a=icbc_pay_wxamp', | 30 | WX_PAY: '/srv/?a=icbc_pay_wxamp', |
| ... | @@ -109,7 +109,7 @@ export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params)) | ... | @@ -109,7 +109,7 @@ export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params)) |
| 109 | * @param {String} bill_id | 109 | * @param {String} bill_id |
| 110 | * @returns {String} bill_id 预约单id | 110 | * @returns {String} bill_id 预约单id |
| 111 | */ | 111 | */ |
| 112 | -export const payPrepareAPI = (params) => fn(fetch.post(Api.PAY_PREPARE, params)); | 112 | +// export const payPrepareAPI = (params) => fn(fetch.post(Api.PAY_PREPARE, params)); |
| 113 | 113 | ||
| 114 | /** | 114 | /** |
| 115 | * @description: 支付回调(模拟) | 115 | * @description: 支付回调(模拟) |
| ... | @@ -117,7 +117,7 @@ export const payPrepareAPI = (params) => fn(fetch.post(Api.PAY_PREPARE, params)) | ... | @@ -117,7 +117,7 @@ export const payPrepareAPI = (params) => fn(fetch.post(Api.PAY_PREPARE, params)) |
| 117 | * @param {String} pay_status 支付状态,1为成功,0为失败(缺省) | 117 | * @param {String} pay_status 支付状态,1为成功,0为失败(缺省) |
| 118 | * @returns {String} bill_id 预约单id | 118 | * @returns {String} bill_id 预约单id |
| 119 | */ | 119 | */ |
| 120 | -export const payCallbackAPI = (params) => fn(fetch.post(Api.PAY_CALLBACK, params)); | 120 | +// export const payCallbackAPI = (params) => fn(fetch.post(Api.PAY_CALLBACK, params)); |
| 121 | 121 | ||
| 122 | /** | 122 | /** |
| 123 | * @description: 预约单详情,参观者列表 | 123 | * @description: 预约单详情,参观者列表 |
| ... | @@ -193,7 +193,7 @@ export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params)) | ... | @@ -193,7 +193,7 @@ export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params)) |
| 193 | * @param {String} | 193 | * @param {String} |
| 194 | * @returns {String} | 194 | * @returns {String} |
| 195 | */ | 195 | */ |
| 196 | -export const billPayStatusAPI = (params) => fn(fetch.get(Api.BILL_PAY_STATUS, params)); | 196 | +// export const billPayStatusAPI = (params) => fn(fetch.get(Api.BILL_PAY_STATUS, params)); |
| 197 | 197 | ||
| 198 | /** | 198 | /** |
| 199 | * @description: 身份证查询预约码 | 199 | * @description: 身份证查询预约码 | ... | ... |
| 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 14:56:43 | 4 | + * @LastEditTime: 2026-01-13 23:19:52 |
| 5 | * @FilePath: /xyxBooking-weapp/src/app.config.js | 5 | * @FilePath: /xyxBooking-weapp/src/app.config.js |
| 6 | * @Description: 小程序配置文件 | 6 | * @Description: 小程序配置文件 |
| 7 | */ | 7 | */ |
| ... | @@ -17,7 +17,6 @@ const pages = [ | ... | @@ -17,7 +17,6 @@ const pages = [ |
| 17 | 'pages/bookingList/index', | 17 | 'pages/bookingList/index', |
| 18 | 'pages/bookingDetail/index', | 18 | 'pages/bookingDetail/index', |
| 19 | 'pages/me/index', | 19 | 'pages/me/index', |
| 20 | - 'pages/waiting/index', | ||
| 21 | 'pages/callback/index', | 20 | 'pages/callback/index', |
| 22 | 'pages/search/index', | 21 | 'pages/search/index', |
| 23 | 'pages/visitorList/index', | 22 | 'pages/visitorList/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 15:22:40 | 4 | + * @LastEditTime: 2026-01-13 23:30:40 |
| 5 | * @FilePath: /xyxBooking-weapp/src/app.js | 5 | * @FilePath: /xyxBooking-weapp/src/app.js |
| 6 | * @Description: 应用入口文件 | 6 | * @Description: 应用入口文件 |
| 7 | */ | 7 | */ |
| ... | @@ -13,6 +13,7 @@ import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/util | ... | @@ -13,6 +13,7 @@ import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/util |
| 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 | import { is_usable_network, get_network_type } from '@/utils/network' |
| 16 | +import { start_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling' | ||
| 16 | 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' |
| 17 | 18 | ||
| 18 | let has_shown_network_modal = false | 19 | let has_shown_network_modal = false |
| ... | @@ -124,7 +125,10 @@ const App = createApp({ | ... | @@ -124,7 +125,10 @@ const App = createApp({ |
| 124 | * - 授权失败则跳转至授权页面 | 125 | * - 授权失败则跳转至授权页面 |
| 125 | */ | 126 | */ |
| 126 | if (hasAuth()) { | 127 | if (hasAuth()) { |
| 128 | + // 有授权时预加载数据 | ||
| 127 | try_preload_when_online() | 129 | try_preload_when_online() |
| 130 | + // 启动离线预约缓存轮询 | ||
| 131 | + start_offline_booking_cache_polling() | ||
| 128 | return | 132 | return |
| 129 | } | 133 | } |
| 130 | 134 | ||
| ... | @@ -135,6 +139,8 @@ const App = createApp({ | ... | @@ -135,6 +139,8 @@ const App = createApp({ |
| 135 | await silentAuth() | 139 | await silentAuth() |
| 136 | // 授权成功后预加载数据 | 140 | // 授权成功后预加载数据 |
| 137 | try_preload_when_online() | 141 | try_preload_when_online() |
| 142 | + // 启动离线预约缓存轮询 | ||
| 143 | + start_offline_booking_cache_polling() | ||
| 138 | } catch (error) { | 144 | } catch (error) { |
| 139 | console.error('静默授权失败:', error) | 145 | console.error('静默授权失败:', error) |
| 140 | // 授权失败则跳转至授权页面 | 146 | // 授权失败则跳转至授权页面 | ... | ... |
| 1 | +import { ref, onMounted, onUnmounted } from 'vue' | ||
| 2 | +import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache' | ||
| 3 | + | ||
| 4 | +let polling_timer_id = null | ||
| 5 | +let polling_running = false | ||
| 6 | +let polling_in_flight = false | ||
| 7 | +let polling_ref_count = 0 | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @description: 刷新离线预约缓存一次 | ||
| 11 | + * @param {Object} options 选项 | ||
| 12 | + * @param {Boolean} options.force 是否强制刷新 | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +const run_refresh_once = async (options) => { | ||
| 16 | + if (polling_in_flight) return | ||
| 17 | + polling_in_flight = true | ||
| 18 | + try { | ||
| 19 | + await refresh_offline_booking_cache({ force: !!options?.force }) | ||
| 20 | + } finally { | ||
| 21 | + polling_in_flight = false | ||
| 22 | + } | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * @description: 启动离线预约缓存轮询 | ||
| 27 | + * @param {Object} options 选项 | ||
| 28 | + * @param {Number} options.interval_ms 轮询间隔,单位毫秒 | ||
| 29 | + * @param {Boolean} options.immediate 是否立即刷新一次 | ||
| 30 | + */ | ||
| 31 | + | ||
| 32 | +export const start_offline_booking_cache_polling = (options) => { | ||
| 33 | + const interval_ms = Number(options?.interval_ms || 60000) | ||
| 34 | + if (polling_running) return | ||
| 35 | + | ||
| 36 | + polling_running = true | ||
| 37 | + | ||
| 38 | + if (options?.immediate !== false) { | ||
| 39 | + run_refresh_once(options) | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + polling_timer_id = setInterval(() => { | ||
| 43 | + run_refresh_once(options) | ||
| 44 | + }, interval_ms) | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +/** | ||
| 48 | + * @description: 停止离线预约缓存轮询 | ||
| 49 | + */ | ||
| 50 | + | ||
| 51 | +export const stop_offline_booking_cache_polling = () => { | ||
| 52 | + if (!polling_timer_id) { | ||
| 53 | + polling_running = false | ||
| 54 | + return | ||
| 55 | + } | ||
| 56 | + clearInterval(polling_timer_id) | ||
| 57 | + polling_timer_id = null | ||
| 58 | + polling_running = false | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +/** | ||
| 62 | + * @description: 用于管理离线预约缓存轮询的组合式函数 | ||
| 63 | + * @param {Object} options 选项 | ||
| 64 | + * @param {Boolean} options.enabled 是否启用轮询 | ||
| 65 | + * @param {Boolean} options.auto 是否自动启动轮询 | ||
| 66 | + * @param {Number} options.interval_ms 轮询间隔,单位毫秒 | ||
| 67 | + * @param {Boolean} options.immediate 是否立即刷新一次 | ||
| 68 | + */ | ||
| 69 | + | ||
| 70 | +export const use_offline_booking_cache_polling = (options) => { | ||
| 71 | + const is_running = ref(false) | ||
| 72 | + const enabled = options?.enabled !== false | ||
| 73 | + | ||
| 74 | + const start = () => { | ||
| 75 | + if (!enabled) return | ||
| 76 | + polling_ref_count += 1 | ||
| 77 | + start_offline_booking_cache_polling(options) | ||
| 78 | + is_running.value = true | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + const stop = () => { | ||
| 82 | + if (!is_running.value) return | ||
| 83 | + polling_ref_count = Math.max(0, polling_ref_count - 1) | ||
| 84 | + if (polling_ref_count === 0) { | ||
| 85 | + stop_offline_booking_cache_polling() | ||
| 86 | + } | ||
| 87 | + is_running.value = false | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + onMounted(() => { | ||
| 91 | + if (options?.auto !== false) start() | ||
| 92 | + }) | ||
| 93 | + | ||
| 94 | + onUnmounted(() => { | ||
| 95 | + stop() | ||
| 96 | + }) | ||
| 97 | + | ||
| 98 | + return { | ||
| 99 | + is_running, | ||
| 100 | + start, | ||
| 101 | + stop, | ||
| 102 | + } | ||
| 103 | +} |
| 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-13 21:23:30 | 4 | + * @LastEditTime: 2026-01-13 23:26:08 |
| 5 | * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue | 5 | * @FilePath: /xyxBooking-weapp/src/pages/index/index.vue |
| 6 | * @Description: 预约页首页 | 6 | * @Description: 预约页首页 |
| 7 | --> | 7 | --> |
| ... | @@ -58,6 +58,7 @@ import { ref } from 'vue' | ... | @@ -58,6 +58,7 @@ import { ref } from 'vue' |
| 58 | import { useGo } from '@/hooks/useGo' | 58 | import { useGo } from '@/hooks/useGo' |
| 59 | import { get_network_type, is_usable_network } from '@/utils/network' | 59 | import { get_network_type, is_usable_network } from '@/utils/network' |
| 60 | import { weak_network_text } from '@/utils/uiText' | 60 | import { weak_network_text } from '@/utils/uiText' |
| 61 | + | ||
| 61 | import icon_1 from '@/assets/images/立即预约@2x.png' | 62 | import icon_1 from '@/assets/images/立即预约@2x.png' |
| 62 | import icon_3 from '@/assets/images/首页02@2x.png' | 63 | import icon_3 from '@/assets/images/首页02@2x.png' |
| 63 | import icon_4 from '@/assets/images/二维码icon.png' | 64 | import icon_4 from '@/assets/images/二维码icon.png' | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-01-15 18:28:25 | 2 | * @Date: 2024-01-15 18:28:25 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-01-30 15:18:54 | 4 | + * @LastEditTime: 2026-01-13 23:20:10 |
| 5 | * @FilePath: /xyxBooking-weapp/src/pages/success/index.vue | 5 | * @FilePath: /xyxBooking-weapp/src/pages/success/index.vue |
| 6 | * @Description: 预约成功提示页面 | 6 | * @Description: 预约成功提示页面 |
| 7 | --> | 7 | --> |
| ... | @@ -58,6 +58,7 @@ useDidShow(async () => { | ... | @@ -58,6 +58,7 @@ useDidShow(async () => { |
| 58 | data.datetime = data && formatDatetime(data); | 58 | data.datetime = data && formatDatetime(data); |
| 59 | billInfo.value = data; | 59 | billInfo.value = data; |
| 60 | } | 60 | } |
| 61 | + // 刷新离线预约缓存 | ||
| 61 | refresh_offline_booking_cache({ force: true }) | 62 | refresh_offline_booking_cache({ force: true }) |
| 62 | }) | 63 | }) |
| 63 | </script> | 64 | </script> | ... | ... |
-
Please register or login to post a comment