feat(离线预约): 新增离线预约记录和详情功能
添加离线预约记录列表和详情页面,重构离线数据缓存逻辑 修改弱网页面跳转逻辑,移除旧的离线预约码功能 新增离线预约缓存管理工具函数
Showing
13 changed files
with
502 additions
and
204 deletions
| 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: 2025-06-28 11:05:47 | 4 | + * @LastEditTime: 2026-01-13 14:56:43 |
| 5 | - * @FilePath: /myApp/src/app.config.js | 5 | + * @FilePath: /xyxBooking-weapp/src/app.config.js |
| 6 | - * @Description: 文件描述 | 6 | + * @Description: 小程序配置文件 |
| 7 | */ | 7 | */ |
| 8 | export default { | 8 | export default { |
| 9 | pages: [ | 9 | pages: [ |
| ... | @@ -26,6 +26,8 @@ export default { | ... | @@ -26,6 +26,8 @@ export default { |
| 26 | 'pages/verificationResult/index', | 26 | 'pages/verificationResult/index', |
| 27 | 'pages/weakNetwork/index', | 27 | 'pages/weakNetwork/index', |
| 28 | 'pages/offlineBookingCode/index', | 28 | 'pages/offlineBookingCode/index', |
| 29 | + 'pages/offlineBookingList/index', | ||
| 30 | + 'pages/offlineBookingDetail/index', | ||
| 29 | 'pages/nfcTest/index', | 31 | 'pages/nfcTest/index', |
| 30 | 'pages/tailwindTest/index', | 32 | 'pages/tailwindTest/index', |
| 31 | ], | 33 | ], | ... | ... |
| ... | @@ -11,29 +11,10 @@ import './utils/polyfill' | ... | @@ -11,29 +11,10 @@ import './utils/polyfill' |
| 11 | import './app.less' | 11 | 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 { qrcodeListAPI } from '@/api/index' | 14 | +import { refresh_offline_booking_cache, has_offline_booking_cache } from '@/composables/useOfflineBookingCache' |
| 15 | -import { formatDatetime } from '@/utils/tools' | ||
| 16 | 15 | ||
| 17 | let has_shown_network_modal = false | 16 | let has_shown_network_modal = false |
| 18 | 17 | ||
| 19 | -/** | ||
| 20 | - * 格式化支付记录,按 pay_id 分组,相同 pay_id 下的记录 sort 为 0,否则为 1 | ||
| 21 | - * @param {*} data 支付记录数组 | ||
| 22 | - * @returns 格式化后的支付记录数组 | ||
| 23 | - */ | ||
| 24 | -const formatGroup = (data) => { | ||
| 25 | - let lastPayId = null; | ||
| 26 | - for (let i = 0; i < data.length; i++) { | ||
| 27 | - if (data[i].pay_id !== lastPayId) { | ||
| 28 | - data[i].sort = 1; | ||
| 29 | - lastPayId = data[i].pay_id; | ||
| 30 | - } else { | ||
| 31 | - data[i].sort = 0; | ||
| 32 | - } | ||
| 33 | - } | ||
| 34 | - return data; | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | const App = createApp({ | 18 | const App = createApp({ |
| 38 | // 对应 onLaunch | 19 | // 对应 onLaunch |
| 39 | async onLaunch(options) { | 20 | async onLaunch(options) { |
| ... | @@ -51,49 +32,25 @@ const App = createApp({ | ... | @@ -51,49 +32,25 @@ const App = createApp({ |
| 51 | } | 32 | } |
| 52 | 33 | ||
| 53 | /** | 34 | /** |
| 54 | - * 预加载二维码数据 | 35 | + * 预加载离线预约记录数据(列表+详情) |
| 55 | - * - 仅在有网络连接时调用 | 36 | + * - 仅在有授权且网络可用时调用 |
| 56 | - * - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA) | 37 | + * - 成功后将数据存储到本地缓存(key: OFFLINE_BOOKING_DATA) |
| 57 | - * - 失败则移除缓存 | ||
| 58 | */ | 38 | */ |
| 59 | - const preloadQrData = async () => { | 39 | + const preloadBookingData = async () => { |
| 60 | try { | 40 | try { |
| 61 | - const { code, data } = await qrcodeListAPI(); | 41 | + await refresh_offline_booking_cache() |
| 62 | - if (code && data) { | ||
| 63 | - data.forEach(item => { | ||
| 64 | - item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time }) | ||
| 65 | - item.sort = 0; | ||
| 66 | - }); | ||
| 67 | - const validData = data.filter(item => item.qr_code !== ''); | ||
| 68 | - if (validData.length > 0) { | ||
| 69 | - const processed = formatGroup(validData); | ||
| 70 | - const offline_data = processed.map(item => ({ | ||
| 71 | - name: item.name, | ||
| 72 | - id_number: item.id_number, | ||
| 73 | - qr_code: item.qr_code, | ||
| 74 | - begin_time: item.begin_time, | ||
| 75 | - end_time: item.end_time, | ||
| 76 | - datetime: item.datetime, | ||
| 77 | - pay_id: item.pay_id, | ||
| 78 | - sort: item.sort, | ||
| 79 | - })); | ||
| 80 | - Taro.setStorageSync('OFFLINE_QR_DATA', offline_data); | ||
| 81 | - } else { | ||
| 82 | - Taro.removeStorageSync('OFFLINE_QR_DATA'); | ||
| 83 | - } | ||
| 84 | - } | ||
| 85 | } catch (e) { | 42 | } catch (e) { |
| 86 | - console.error('Preload QR failed', e); | 43 | + console.error('Preload booking cache failed', e) |
| 44 | + } | ||
| 87 | } | 45 | } |
| 88 | - }; | ||
| 89 | 46 | ||
| 90 | /** | 47 | /** |
| 91 | * 监听网络状态变化 | 48 | * 监听网络状态变化 |
| 92 | - * - 当网络连接且有授权时,调用 preloadQrData 预加载二维码数据 | 49 | + * - 当网络连接且有授权时,预加载离线预约记录数据 |
| 93 | */ | 50 | */ |
| 94 | Taro.onNetworkStatusChange((res) => { | 51 | Taro.onNetworkStatusChange((res) => { |
| 95 | if (res.isConnected && hasAuth()) { | 52 | if (res.isConnected && hasAuth()) { |
| 96 | - preloadQrData() | 53 | + preloadBookingData() |
| 97 | } | 54 | } |
| 98 | }) | 55 | }) |
| 99 | 56 | ||
| ... | @@ -120,23 +77,10 @@ const App = createApp({ | ... | @@ -120,23 +77,10 @@ const App = createApp({ |
| 120 | } | 77 | } |
| 121 | 78 | ||
| 122 | /** | 79 | /** |
| 123 | - * 检查是否有离线预约码缓存 | ||
| 124 | - * @returns {boolean} 如果有离线预约码缓存且有效,则返回 true;否则返回 false | ||
| 125 | - */ | ||
| 126 | - const has_offline_qr_cache = () => { | ||
| 127 | - try { | ||
| 128 | - const data = Taro.getStorageSync('OFFLINE_QR_DATA') | ||
| 129 | - return Array.isArray(data) && data.length > 0 | ||
| 130 | - } catch (e) { | ||
| 131 | - return false | ||
| 132 | - } | ||
| 133 | - } | ||
| 134 | - | ||
| 135 | - /** | ||
| 136 | * 处理在启动时出现的不良网络情况 | 80 | * 处理在启动时出现的不良网络情况 |
| 137 | - * - 当网络连接不良且有离线预约码缓存时,提示用户是否使用缓存预约码进入离线模式 | 81 | + * - 当网络连接不良且有离线预约记录缓存时,提示用户是否使用缓存进入离线模式 |
| 138 | - * - 当网络连接不良且无离线预约码缓存时,提示用户网络连接不畅 | 82 | + * - 当网络连接不良且无缓存时,提示用户网络连接不畅 |
| 139 | - * @returns {Promise<boolean>} 如果用户选择使用缓存预约码进入离线模式,则返回 true;否则返回 false | 83 | + * @returns {Promise<boolean>} 如果用户选择进入离线模式,则返回 true;否则返回 false |
| 140 | */ | 84 | */ |
| 141 | const handle_bad_network_on_launch = async () => { | 85 | const handle_bad_network_on_launch = async () => { |
| 142 | /** | 86 | /** |
| ... | @@ -153,16 +97,16 @@ const App = createApp({ | ... | @@ -153,16 +97,16 @@ const App = createApp({ |
| 153 | 97 | ||
| 154 | has_shown_network_modal = true | 98 | has_shown_network_modal = true |
| 155 | 99 | ||
| 156 | - if (has_offline_qr_cache()) { | 100 | + if (has_offline_booking_cache()) { |
| 157 | try { | 101 | try { |
| 158 | const modal_res = await Taro.showModal({ | 102 | const modal_res = await Taro.showModal({ |
| 159 | title: '网络连接不畅', | 103 | title: '网络连接不畅', |
| 160 | - content: '当前网络信号较弱,可使用已缓存的预约码进入离线模式', | 104 | + content: '当前网络信号较弱,可使用已缓存的预约记录进入离线模式', |
| 161 | - confirmText: '预约码', | 105 | + confirmText: '预约记录', |
| 162 | cancelText: '知道了', | 106 | cancelText: '知道了', |
| 163 | }) | 107 | }) |
| 164 | if (modal_res?.confirm) { | 108 | if (modal_res?.confirm) { |
| 165 | - await Taro.reLaunch({ url: '/pages/offlineBookingCode/index' }) | 109 | + await Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) |
| 166 | return true | 110 | return true |
| 167 | } | 111 | } |
| 168 | } catch (e) { | 112 | } catch (e) { |
| ... | @@ -183,10 +127,8 @@ const App = createApp({ | ... | @@ -183,10 +127,8 @@ const App = createApp({ |
| 183 | if (should_stop) return | 127 | if (should_stop) return |
| 184 | 128 | ||
| 185 | /** | 129 | /** |
| 186 | - * 尝试在网络可用时预加载二维码数据 | 130 | + * 尝试在网络可用时预加载离线预约记录数据 |
| 187 | * - 仅在有授权时调用 | 131 | * - 仅在有授权时调用 |
| 188 | - * - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA) | ||
| 189 | - * - 失败则移除缓存 | ||
| 190 | * @returns {Promise<void>} | 132 | * @returns {Promise<void>} |
| 191 | */ | 133 | */ |
| 192 | const try_preload_when_online = () => { | 134 | const try_preload_when_online = () => { |
| ... | @@ -194,7 +136,7 @@ const App = createApp({ | ... | @@ -194,7 +136,7 @@ const App = createApp({ |
| 194 | Taro.getNetworkType({ | 136 | Taro.getNetworkType({ |
| 195 | success: (res) => { | 137 | success: (res) => { |
| 196 | if (is_usable_network(res.networkType)) { | 138 | if (is_usable_network(res.networkType)) { |
| 197 | - preloadQrData() | 139 | + preloadBookingData() |
| 198 | } | 140 | } |
| 199 | } | 141 | } |
| 200 | }) | 142 | }) | ... | ... |
| 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-08 16:02:07 | 4 | + * @LastEditTime: 2026-01-13 15:18:07 |
| 5 | * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue | 5 | * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue |
| 6 | * @Description: 预约码卡组件 | 6 | * @Description: 预约码卡组件 |
| 7 | --> | 7 | --> |
| ... | @@ -187,23 +187,9 @@ const init = async () => { | ... | @@ -187,23 +187,9 @@ const init = async () => { |
| 187 | 187 | ||
| 188 | if (validData.length > 0) { | 188 | if (validData.length > 0) { |
| 189 | userList.value = formatGroup(validData); | 189 | userList.value = formatGroup(validData); |
| 190 | - // 缓存数据供离线模式使用 | ||
| 191 | - const offline_data = userList.value.map(item => ({ | ||
| 192 | - name: item.name, | ||
| 193 | - id_number: item.id_number, | ||
| 194 | - qr_code: item.qr_code, | ||
| 195 | - begin_time: item.begin_time, | ||
| 196 | - end_time: item.end_time, | ||
| 197 | - datetime: item.datetime, | ||
| 198 | - pay_id: item.pay_id, | ||
| 199 | - sort: item.sort, | ||
| 200 | - })); | ||
| 201 | - Taro.setStorageSync('OFFLINE_QR_DATA', offline_data); | ||
| 202 | refreshBtn(); | 190 | refreshBtn(); |
| 203 | } else { | 191 | } else { |
| 204 | userList.value = []; | 192 | userList.value = []; |
| 205 | - // 清空缓存 | ||
| 206 | - Taro.removeStorageSync('OFFLINE_QR_DATA'); | ||
| 207 | } | 193 | } |
| 208 | } | 194 | } |
| 209 | } catch (err) { | 195 | } catch (err) { | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-01-24 16:38:13 | 2 | * @Date: 2024-01-24 16:38:13 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-01-30 15:19:44 | 4 | + * @LastEditTime: 2026-01-13 15:04:21 |
| 5 | * @FilePath: /xyxBooking-weapp/src/components/reserveCard.vue | 5 | * @FilePath: /xyxBooking-weapp/src/components/reserveCard.vue |
| 6 | * @Description: 预约记录卡组件 | 6 | * @Description: 预约记录卡组件 |
| 7 | --> | 7 | --> |
| ... | @@ -9,7 +9,8 @@ | ... | @@ -9,7 +9,8 @@ |
| 9 | <view class="booking-list-item" @tap="goToDetail(reserve_info)"> | 9 | <view class="booking-list-item" @tap="goToDetail(reserve_info)"> |
| 10 | <view class="booking-list-item-header"> | 10 | <view class="booking-list-item-header"> |
| 11 | <view>{{ reserve_info.booking_time }}</view> | 11 | <view>{{ reserve_info.booking_time }}</view> |
| 12 | - <view :class="[formatStatus(reserve_info.status)?.key, 'status']">{{ formatStatus(reserve_info.status)?.value }}</view> | 12 | + <view v-if="is_offline" class="status offline">离线</view> |
| 13 | + <view v-else :class="[status_info.key, 'status']">{{ status_info.value }}</view> | ||
| 13 | </view> | 14 | </view> |
| 14 | <view class="booking-list-item-body"> | 15 | <view class="booking-list-item-body"> |
| 15 | <view class="booking-num"> | 16 | <view class="booking-num"> |
| ... | @@ -39,10 +40,20 @@ const props = defineProps({ | ... | @@ -39,10 +40,20 @@ const props = defineProps({ |
| 39 | type: Object, | 40 | type: Object, |
| 40 | default: () => ({}), | 41 | default: () => ({}), |
| 41 | }, | 42 | }, |
| 43 | + detail_path: { | ||
| 44 | + type: String, | ||
| 45 | + default: '/bookingDetail', | ||
| 46 | + }, | ||
| 47 | + is_offline: { | ||
| 48 | + type: Boolean, | ||
| 49 | + default: false, | ||
| 50 | + }, | ||
| 42 | }); | 51 | }); |
| 43 | 52 | ||
| 44 | const reserve_info = computed(() => props.data); | 53 | const reserve_info = computed(() => props.data); |
| 45 | 54 | ||
| 55 | +const is_offline = computed(() => props.is_offline); | ||
| 56 | + | ||
| 46 | const CodeStatus = { | 57 | const CodeStatus = { |
| 47 | APPLY: '1', | 58 | APPLY: '1', |
| 48 | PAYING: '2', | 59 | PAYING: '2', |
| ... | @@ -95,10 +106,14 @@ const formatStatus = (status) => { | ... | @@ -95,10 +106,14 @@ const formatStatus = (status) => { |
| 95 | } | 106 | } |
| 96 | } | 107 | } |
| 97 | 108 | ||
| 109 | +const status_info = computed(() => { | ||
| 110 | + return formatStatus(reserve_info.value?.status) || { key: '', value: '' } | ||
| 111 | +}) | ||
| 112 | + | ||
| 98 | const goToDetail = (item) => { | 113 | const goToDetail = (item) => { |
| 99 | // 只有成功、已使用、已取消(退款成功)才跳转详情 | 114 | // 只有成功、已使用、已取消(退款成功)才跳转详情 |
| 100 | if (item.status === CodeStatus.SUCCESS || item.status === CodeStatus.USED || item.status === CodeStatus.CANCEL) { | 115 | if (item.status === CodeStatus.SUCCESS || item.status === CodeStatus.USED || item.status === CodeStatus.CANCEL) { |
| 101 | - go('/bookingDetail', { pay_id: item.pay_id }); | 116 | + go(props.detail_path, { pay_id: item.pay_id }); |
| 102 | } | 117 | } |
| 103 | } | 118 | } |
| 104 | </script> | 119 | </script> |
| ... | @@ -128,6 +143,11 @@ const goToDetail = (item) => { | ... | @@ -128,6 +143,11 @@ const goToDetail = (item) => { |
| 128 | padding: 4rpx 12rpx; | 143 | padding: 4rpx 12rpx; |
| 129 | border-radius: 8rpx; | 144 | border-radius: 8rpx; |
| 130 | 145 | ||
| 146 | + &.offline { | ||
| 147 | + color: #999; | ||
| 148 | + background-color: #EEE; | ||
| 149 | + } | ||
| 150 | + | ||
| 131 | &.success { | 151 | &.success { |
| 132 | color: #A67939; | 152 | color: #A67939; |
| 133 | background-color: #FBEEDC; | 153 | background-color: #FBEEDC; | ... | ... |
src/composables/useOfflineBookingCache.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 刷新离线预约记录缓存 | ||
| 3 | + * - 仅在有授权且网络可用时调用 | ||
| 4 | + * - 成功后将数据存储到本地缓存(key: OFFLINE_BOOKING_DATA) | ||
| 5 | + * @param {boolean} force - 是否强制刷新,默认为 false | ||
| 6 | + * @returns {Promise<void>} | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +import Taro from '@tarojs/taro' | ||
| 10 | +import { billOfflineAllAPI } from '@/api/index' | ||
| 11 | +import { hasAuth } from '@/utils/authRedirect' | ||
| 12 | +import { formatDatetime } from '@/utils/tools' | ||
| 13 | + | ||
| 14 | +export const OFFLINE_BOOKING_CACHE_KEY = 'OFFLINE_BOOKING_DATA' | ||
| 15 | + | ||
| 16 | +let refresh_promise = null | ||
| 17 | + | ||
| 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 | +/** | ||
| 41 | + * 格式化预约记录项 | ||
| 42 | + * @param {Object} item - 原始预约记录项 | ||
| 43 | + * @returns {Object} 格式化后的预约记录项 | ||
| 44 | + */ | ||
| 45 | +const normalize_bill_item = (item) => { | ||
| 46 | + const data = item ? { ...item } : {} | ||
| 47 | + | ||
| 48 | + data.datetime = data.datetime || formatDatetime(data) | ||
| 49 | + data.booking_time = data.booking_time || data.datetime | ||
| 50 | + data.order_time = data.order_time || (data.created_time ? data.created_time.slice(0, -3) : '') | ||
| 51 | + | ||
| 52 | + return data | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/** | ||
| 56 | + * 获取离线预约记录缓存 | ||
| 57 | + * @returns {Array} 格式化后的预约记录项列表 | ||
| 58 | + */ | ||
| 59 | +export const get_offline_booking_cache = () => { | ||
| 60 | + try { | ||
| 61 | + const data = Taro.getStorageSync(OFFLINE_BOOKING_CACHE_KEY) | ||
| 62 | + return Array.isArray(data) ? data : [] | ||
| 63 | + } catch (e) { | ||
| 64 | + return [] | ||
| 65 | + } | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +/** | ||
| 69 | + * 检查是否存在离线预约记录缓存 | ||
| 70 | + * @returns {boolean} 是否存在缓存且非空 | ||
| 71 | + */ | ||
| 72 | +export const has_offline_booking_cache = () => { | ||
| 73 | + const list = get_offline_booking_cache() | ||
| 74 | + return Array.isArray(list) && list.length > 0 | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +/** | ||
| 78 | + * 根据支付ID获取离线预约记录 | ||
| 79 | + * @param {*} pay_id 支付ID | ||
| 80 | + * @returns {Object|null} 匹配的预约记录项或 null | ||
| 81 | + */ | ||
| 82 | +export const get_offline_booking_by_pay_id = (pay_id) => { | ||
| 83 | + const list = get_offline_booking_cache() | ||
| 84 | + const target_pay_id = String(pay_id || '') | ||
| 85 | + return list.find((item) => String(item?.pay_id || '') === target_pay_id) || null | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +/** | ||
| 89 | + * 获取预约记录中的人员列表 | ||
| 90 | + * @param {Object} bill - 预约记录项 | ||
| 91 | + * @returns {Array} 人员列表(包含姓名、身份证号、二维码等信息) | ||
| 92 | + */ | ||
| 93 | +export const get_offline_bill_person_list = (bill) => { | ||
| 94 | + if (!bill) return [] | ||
| 95 | + const candidate = | ||
| 96 | + bill.person_list || | ||
| 97 | + bill.bill_person_list || | ||
| 98 | + bill.persons || | ||
| 99 | + bill.qrcode_list || | ||
| 100 | + bill.qr_list || | ||
| 101 | + bill.detail_list || | ||
| 102 | + [] | ||
| 103 | + | ||
| 104 | + return Array.isArray(candidate) ? candidate : [] | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +/** | ||
| 108 | + * 构建预约记录中的二维码列表 | ||
| 109 | + * @param {Object} bill - 预约记录项 | ||
| 110 | + * @returns {Array} 二维码列表(包含姓名、身份证号、二维码、预约时间等信息) | ||
| 111 | + */ | ||
| 112 | +export const build_offline_qr_list = (bill) => { | ||
| 113 | + const list = get_offline_bill_person_list(bill) | ||
| 114 | + const datetime = bill?.datetime || formatDatetime(bill || {}) | ||
| 115 | + | ||
| 116 | + return list | ||
| 117 | + .filter((item) => item && item.qr_code !== '') | ||
| 118 | + .map((item) => { | ||
| 119 | + const begin_time = item.begin_time || bill?.begin_time | ||
| 120 | + const end_time = item.end_time || bill?.end_time | ||
| 121 | + return { | ||
| 122 | + name: item.name, | ||
| 123 | + id_number: item.id_number, | ||
| 124 | + qr_code: item.qr_code, | ||
| 125 | + begin_time, | ||
| 126 | + end_time, | ||
| 127 | + datetime: item.datetime || (begin_time && end_time ? formatDatetime({ begin_time, end_time }) : datetime), | ||
| 128 | + pay_id: bill?.pay_id, | ||
| 129 | + sort: 0, | ||
| 130 | + } | ||
| 131 | + }) | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +/** | ||
| 135 | + * 刷新离线预约记录缓存 | ||
| 136 | + * - 仅在有授权且网络可用时调用 | ||
| 137 | + * - 成功后将数据存储到本地缓存(key: OFFLINE_BOOKING_DATA) | ||
| 138 | + * @param {boolean} force - 是否强制刷新,默认为 false | ||
| 139 | + * @returns {Promise<void>} | ||
| 140 | + */ | ||
| 141 | +export const refresh_offline_booking_cache = async ({ force = false } = {}) => { | ||
| 142 | + if (!hasAuth()) return { code: 0, data: null, msg: '未授权' } | ||
| 143 | + | ||
| 144 | + if (refresh_promise && !force) return refresh_promise | ||
| 145 | + | ||
| 146 | + refresh_promise = (async () => { | ||
| 147 | + const network_type = await get_network_type() | ||
| 148 | + if (!is_usable_network(network_type)) { | ||
| 149 | + return { code: 0, data: null, msg: '网络不可用' } | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + const { code, data, msg } = await billOfflineAllAPI() | ||
| 153 | + if (code && Array.isArray(data)) { | ||
| 154 | + const normalized = data.map(normalize_bill_item).filter((item) => item && item.pay_id) | ||
| 155 | + if (normalized.length > 0) { | ||
| 156 | + Taro.setStorageSync(OFFLINE_BOOKING_CACHE_KEY, normalized) | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | + return { code, data, msg } | ||
| 160 | + })() | ||
| 161 | + | ||
| 162 | + try { | ||
| 163 | + return await refresh_promise | ||
| 164 | + } finally { | ||
| 165 | + refresh_promise = null | ||
| 166 | + } | ||
| 167 | +} |
| 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-07 22:27:24 | 4 | + * @LastEditTime: 2026-01-13 15:19:11 |
| 5 | * @FilePath: /xyxBooking-weapp/src/pages/bookingCode/index.vue | 5 | * @FilePath: /xyxBooking-weapp/src/pages/bookingCode/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -41,6 +41,7 @@ import icon_3 from '@/assets/images/首页01@2x.png' | ... | @@ -41,6 +41,7 @@ import icon_3 from '@/assets/images/首页01@2x.png' |
| 41 | import icon_4 from '@/assets/images/二维码icon.png' | 41 | 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 | 45 | ||
| 45 | const go = useGo(); | 46 | const go = useGo(); |
| 46 | 47 | ||
| ... | @@ -49,9 +50,11 @@ useDidShow(() => { | ... | @@ -49,9 +50,11 @@ useDidShow(() => { |
| 49 | success: (res) => { | 50 | success: (res) => { |
| 50 | const isConnected = ['wifi', '4g', '5g', '3g'].includes(res.networkType); | 51 | const isConnected = ['wifi', '4g', '5g', '3g'].includes(res.networkType); |
| 51 | if (!isConnected) { | 52 | if (!isConnected) { |
| 52 | - Taro.redirectTo({ | 53 | + if (has_offline_booking_cache()) { |
| 53 | - url: '/pages/weakNetwork/index' | 54 | + Taro.redirectTo({ url: '/pages/offlineBookingList/index' }) |
| 54 | - }) | 55 | + } else { |
| 56 | + Taro.redirectTo({ url: '/pages/weakNetwork/index' }) | ||
| 57 | + } | ||
| 55 | } | 58 | } |
| 56 | } | 59 | } |
| 57 | }); | 60 | }); | ... | ... |
| ... | @@ -6,121 +6,26 @@ | ... | @@ -6,121 +6,26 @@ |
| 6 | * @Description: 线下预约码页面 | 6 | * @Description: 线下预约码页面 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <view class="offline-booking-code-page"> | 9 | + <view class="offline-booking-code-page"></view> |
| 10 | - <view class="header-tip"> | ||
| 11 | - <IconFont name="tips" size="15" color="#A67939" /> | ||
| 12 | - <text>您当前处于离线模式,仅展示本地缓存的预约码</text> | ||
| 13 | - </view> | ||
| 14 | - | ||
| 15 | - <view style="padding: 32rpx;"> | ||
| 16 | - <offlineQrCode :list="qrList"></offlineQrCode> | ||
| 17 | - <view class="warning"> | ||
| 18 | - <view style="display: flex; align-items: center; justify-content: center;"><IconFont name="tips" /><text style="margin-left: 10rpx;">温馨提示</text></view> | ||
| 19 | - <view style="margin-top: 16rpx;">一人一码,扫码或识别身份证成功后进入</view> | ||
| 20 | - </view> | ||
| 21 | - </view> | ||
| 22 | - | ||
| 23 | - <view class="action-area"> | ||
| 24 | - <button class="home-btn" @tap="toHome">返回首页</button> | ||
| 25 | - </view> | ||
| 26 | - </view> | ||
| 27 | </template> | 10 | </template> |
| 28 | 11 | ||
| 29 | <script setup> | 12 | <script setup> |
| 30 | -import { ref, onMounted } from 'vue' | 13 | +import { onMounted } from 'vue' |
| 31 | import Taro from '@tarojs/taro' | 14 | import Taro from '@tarojs/taro' |
| 32 | -import offlineQrCode from '@/components/offlineQrCode'; | ||
| 33 | -import { IconFont } from '@nutui/icons-vue-taro' | ||
| 34 | import { useGo } from '@/hooks/useGo' | 15 | import { useGo } from '@/hooks/useGo' |
| 35 | 16 | ||
| 36 | const go = useGo(); | 17 | const go = useGo(); |
| 37 | -const qrList = ref([]); | ||
| 38 | - | ||
| 39 | -const toHome = () => { | ||
| 40 | - Taro.reLaunch({ url: '/pages/index/index' }); | ||
| 41 | -} | ||
| 42 | - | ||
| 43 | -// TODO: Mock Data as per requirement | ||
| 44 | -const getMockData = () => { | ||
| 45 | - return [ | ||
| 46 | - { | ||
| 47 | - name: '测试用户1', | ||
| 48 | - id_number: '110101199003078888', | ||
| 49 | - qr_code: 'OFFLINE_MOCK_QR_001', | ||
| 50 | - datetime: '2026-01-08 08:30-10:30', | ||
| 51 | - sort: 0 | ||
| 52 | - }, | ||
| 53 | - { | ||
| 54 | - name: '测试用户2', | ||
| 55 | - id_number: '110101199205126666', | ||
| 56 | - qr_code: 'OFFLINE_MOCK_QR_002', | ||
| 57 | - datetime: '2026-01-08 08:30-10:30', | ||
| 58 | - sort: 0 | ||
| 59 | - } | ||
| 60 | - ]; | ||
| 61 | -} | ||
| 62 | 18 | ||
| 63 | onMounted(() => { | 19 | onMounted(() => { |
| 64 | - try { | 20 | + Taro.nextTick(() => { |
| 65 | - const cachedData = Taro.getStorageSync('OFFLINE_QR_DATA'); | 21 | + go('/pages/offlineBookingList/index') |
| 66 | - if (cachedData && cachedData.length > 0) { | 22 | + }) |
| 67 | - qrList.value = cachedData; | ||
| 68 | - } else { | ||
| 69 | - // Requirement 4: Mock data if no data | ||
| 70 | - console.log('No cached data found, using mock data'); | ||
| 71 | - qrList.value = getMockData(); | ||
| 72 | - } | ||
| 73 | - } catch (e) { | ||
| 74 | - console.error('Read storage failed', e); | ||
| 75 | - qrList.value = getMockData(); | ||
| 76 | - } | ||
| 77 | }); | 23 | }); |
| 78 | 24 | ||
| 79 | </script> | 25 | </script> |
| 80 | 26 | ||
| 81 | <style lang="less"> | 27 | <style lang="less"> |
| 82 | .offline-booking-code-page { | 28 | .offline-booking-code-page { |
| 83 | - position: relative; | ||
| 84 | min-height: 100vh; | 29 | min-height: 100vh; |
| 85 | - background-color: #F6F6F6; | ||
| 86 | - | ||
| 87 | - .header-tip { | ||
| 88 | - background-color: #FEF8E8; | ||
| 89 | - color: #A67939; | ||
| 90 | - padding: 20rpx 32rpx; | ||
| 91 | - font-size: 26rpx; | ||
| 92 | - display: flex; | ||
| 93 | - align-items: center; | ||
| 94 | - | ||
| 95 | - text { | ||
| 96 | - margin-left: 10rpx; | ||
| 97 | - } | ||
| 98 | - } | ||
| 99 | - | ||
| 100 | - .warning { | ||
| 101 | - text-align: center; | ||
| 102 | - color: #A67939; | ||
| 103 | - margin-top: 32rpx; | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - .action-area { | ||
| 107 | - position: fixed; | ||
| 108 | - bottom: 60rpx; | ||
| 109 | - left: 0; | ||
| 110 | - width: 100%; | ||
| 111 | - display: flex; | ||
| 112 | - justify-content: center; | ||
| 113 | - | ||
| 114 | - .home-btn { | ||
| 115 | - width: 600rpx; | ||
| 116 | - height: 88rpx; | ||
| 117 | - line-height: 88rpx; | ||
| 118 | - background: #fff; | ||
| 119 | - color: #A67939; | ||
| 120 | - border: 2rpx solid #A67939; | ||
| 121 | - border-radius: 44rpx; | ||
| 122 | - font-size: 32rpx; | ||
| 123 | - } | ||
| 124 | - } | ||
| 125 | } | 30 | } |
| 126 | </style> | 31 | </style> | ... | ... |
src/pages/offlineBookingDetail/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="offline-booking-detail-page"> | ||
| 3 | + <view class="header-tip"> | ||
| 4 | + <IconFont name="tips" size="15" color="#A67939" /> | ||
| 5 | + <text>您当前处于离线模式,仅展示本地缓存的数据</text> | ||
| 6 | + </view> | ||
| 7 | + | ||
| 8 | + <view class="content"> | ||
| 9 | + <offlineQrCode :list="qr_list" /> | ||
| 10 | + | ||
| 11 | + <view v-if="bill_info && bill_info.pay_id" class="detail-wrapper"> | ||
| 12 | + <view class="detail-item"> | ||
| 13 | + <view>参访时间:</view> | ||
| 14 | + <view>{{ bill_info.datetime }}</view> | ||
| 15 | + </view> | ||
| 16 | + <view class="detail-item"> | ||
| 17 | + <view>参访人数:</view> | ||
| 18 | + <view>{{ bill_info.total_qty }} 人</view> | ||
| 19 | + </view> | ||
| 20 | + <view class="detail-item"> | ||
| 21 | + <view>支付金额:</view> | ||
| 22 | + <view>¥ {{ bill_info.total_amt }}</view> | ||
| 23 | + </view> | ||
| 24 | + <view class="detail-item"> | ||
| 25 | + <view>下单时间:</view> | ||
| 26 | + <view>{{ bill_info.order_time }}</view> | ||
| 27 | + </view> | ||
| 28 | + <view class="detail-item"> | ||
| 29 | + <view>订单编号:</view> | ||
| 30 | + <view>{{ bill_info.pay_id }}</view> | ||
| 31 | + </view> | ||
| 32 | + <view class="detail-item"> | ||
| 33 | + <view>订单状态:</view> | ||
| 34 | + <view>{{ status_text }}</view> | ||
| 35 | + </view> | ||
| 36 | + </view> | ||
| 37 | + </view> | ||
| 38 | + | ||
| 39 | + <view class="action-area"> | ||
| 40 | + <button class="back-btn" @tap="toList">返回列表</button> | ||
| 41 | + </view> | ||
| 42 | + </view> | ||
| 43 | +</template> | ||
| 44 | + | ||
| 45 | +<script setup> | ||
| 46 | +import { ref, computed } from 'vue' | ||
| 47 | +import Taro, { useDidShow, useRouter as useTaroRouter } from '@tarojs/taro' | ||
| 48 | +import { IconFont } from '@nutui/icons-vue-taro' | ||
| 49 | +import offlineQrCode from '@/components/offlineQrCode.vue' | ||
| 50 | +import { get_offline_booking_by_pay_id, build_offline_qr_list } from '@/composables/useOfflineBookingCache' | ||
| 51 | + | ||
| 52 | +const router = useTaroRouter() | ||
| 53 | +const bill_info = ref(null) | ||
| 54 | +const qr_list = ref([]) | ||
| 55 | + | ||
| 56 | +const CodeStatus = { | ||
| 57 | + APPLY: '1', | ||
| 58 | + PAYING: '2', | ||
| 59 | + SUCCESS: '3', | ||
| 60 | + CANCEL: '5', | ||
| 61 | + CANCELED: '7', | ||
| 62 | + USED: '9', | ||
| 63 | + REFUNDING: '11' | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +const status_text = computed(() => { | ||
| 67 | + const status = bill_info.value?.status | ||
| 68 | + switch (status) { | ||
| 69 | + case CodeStatus.APPLY: return '待支付' | ||
| 70 | + case CodeStatus.PAYING: return '支付中' | ||
| 71 | + case CodeStatus.SUCCESS: return '预约成功' | ||
| 72 | + case CodeStatus.CANCEL: return '已取消' | ||
| 73 | + case CodeStatus.CANCELED: return '已取消' | ||
| 74 | + case CodeStatus.USED: return '已使用' | ||
| 75 | + case CodeStatus.REFUNDING: return '退款中' | ||
| 76 | + default: return '未知状态' | ||
| 77 | + } | ||
| 78 | +}) | ||
| 79 | + | ||
| 80 | +const toList = () => { | ||
| 81 | + Taro.navigateBack({ | ||
| 82 | + fail: () => { | ||
| 83 | + Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) | ||
| 84 | + } | ||
| 85 | + }) | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +const load_cache = () => { | ||
| 89 | + const pay_id = router.params.pay_id | ||
| 90 | + const data = get_offline_booking_by_pay_id(pay_id) | ||
| 91 | + if (!data) { | ||
| 92 | + Taro.showToast({ title: '本地无该订单缓存', icon: 'none' }) | ||
| 93 | + Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) | ||
| 94 | + return | ||
| 95 | + } | ||
| 96 | + bill_info.value = data | ||
| 97 | + qr_list.value = build_offline_qr_list(data) | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +useDidShow(() => { | ||
| 101 | + load_cache() | ||
| 102 | +}) | ||
| 103 | +</script> | ||
| 104 | + | ||
| 105 | +<style lang="less"> | ||
| 106 | +.offline-booking-detail-page { | ||
| 107 | + min-height: 100vh; | ||
| 108 | + background-color: #F6F6F6; | ||
| 109 | + | ||
| 110 | + .header-tip { | ||
| 111 | + display: flex; | ||
| 112 | + align-items: center; | ||
| 113 | + padding: 20rpx 32rpx; | ||
| 114 | + color: #A67939; | ||
| 115 | + font-size: 26rpx; | ||
| 116 | + background: #FFF; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + .content { | ||
| 120 | + padding: 32rpx; | ||
| 121 | + padding-bottom: 180rpx; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + .detail-wrapper { | ||
| 125 | + background-color: #FFF; | ||
| 126 | + border-radius: 16rpx; | ||
| 127 | + padding: 32rpx; | ||
| 128 | + margin-top: 32rpx; | ||
| 129 | + box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.1); | ||
| 130 | + | ||
| 131 | + .detail-item { | ||
| 132 | + display: flex; | ||
| 133 | + justify-content: space-between; | ||
| 134 | + margin-bottom: 26rpx; | ||
| 135 | + color: #333; | ||
| 136 | + font-size: 30rpx; | ||
| 137 | + | ||
| 138 | + &:last-child { | ||
| 139 | + margin-bottom: 0; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + view:first-child { | ||
| 143 | + color: #999; | ||
| 144 | + width: 160rpx; | ||
| 145 | + } | ||
| 146 | + view:last-child { | ||
| 147 | + flex: 1; | ||
| 148 | + text-align: right; | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + .action-area { | ||
| 154 | + position: fixed; | ||
| 155 | + bottom: 0; | ||
| 156 | + left: 0; | ||
| 157 | + width: 750rpx; | ||
| 158 | + padding: 24rpx 32rpx; | ||
| 159 | + background: #FFF; | ||
| 160 | + box-sizing: border-box; | ||
| 161 | + box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.06); | ||
| 162 | + | ||
| 163 | + .back-btn { | ||
| 164 | + background-color: #A67939; | ||
| 165 | + color: #FFF; | ||
| 166 | + border-radius: 16rpx; | ||
| 167 | + font-size: 32rpx; | ||
| 168 | + padding: 22rpx 0; | ||
| 169 | + } | ||
| 170 | + } | ||
| 171 | +} | ||
| 172 | +</style> | ||
| 173 | + |
src/pages/offlineBookingList/index.config.js
0 → 100644
src/pages/offlineBookingList/index.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <view class="offline-booking-list-page"> | ||
| 3 | + <view class="header-tip"> | ||
| 4 | + <IconFont name="tips" size="15" color="#A67939" /> | ||
| 5 | + <text>您当前处于离线模式,仅展示本地缓存的预约记录</text> | ||
| 6 | + </view> | ||
| 7 | + | ||
| 8 | + <view class="list-wrapper"> | ||
| 9 | + <view v-for="(item, index) in booking_list" :key="index"> | ||
| 10 | + <reserveCard :data="item" detail_path="/offlineBookingDetail" is_offline /> | ||
| 11 | + </view> | ||
| 12 | + | ||
| 13 | + <view v-if="!booking_list.length" class="empty"> | ||
| 14 | + <text>本地无缓存预约记录</text> | ||
| 15 | + </view> | ||
| 16 | + </view> | ||
| 17 | + | ||
| 18 | + <view class="action-area"> | ||
| 19 | + <button class="home-btn" @tap="toHome">返回首页</button> | ||
| 20 | + </view> | ||
| 21 | + </view> | ||
| 22 | +</template> | ||
| 23 | + | ||
| 24 | +<script setup> | ||
| 25 | +import { ref } from 'vue' | ||
| 26 | +import Taro, { useDidShow } from '@tarojs/taro' | ||
| 27 | +import { IconFont } from '@nutui/icons-vue-taro' | ||
| 28 | +import reserveCard from '@/components/reserveCard.vue' | ||
| 29 | +import { get_offline_booking_cache } from '@/composables/useOfflineBookingCache' | ||
| 30 | + | ||
| 31 | +const booking_list = ref([]) | ||
| 32 | + | ||
| 33 | +const toHome = () => { | ||
| 34 | + Taro.reLaunch({ url: '/pages/index/index' }) | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +const load_cache = () => { | ||
| 38 | + booking_list.value = get_offline_booking_cache() | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +useDidShow(() => { | ||
| 42 | + load_cache() | ||
| 43 | +}) | ||
| 44 | +</script> | ||
| 45 | + | ||
| 46 | +<style lang="less"> | ||
| 47 | +.offline-booking-list-page { | ||
| 48 | + min-height: 100vh; | ||
| 49 | + background-color: #F6F6F6; | ||
| 50 | + | ||
| 51 | + .header-tip { | ||
| 52 | + display: flex; | ||
| 53 | + align-items: center; | ||
| 54 | + padding: 20rpx 32rpx; | ||
| 55 | + color: #A67939; | ||
| 56 | + font-size: 26rpx; | ||
| 57 | + background: #FFF; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + .list-wrapper { | ||
| 61 | + padding: 32rpx; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + .empty { | ||
| 65 | + padding: 120rpx 0; | ||
| 66 | + text-align: center; | ||
| 67 | + color: #A67939; | ||
| 68 | + font-size: 32rpx; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + .action-area { | ||
| 72 | + position: fixed; | ||
| 73 | + bottom: 0; | ||
| 74 | + left: 0; | ||
| 75 | + width: 750rpx; | ||
| 76 | + padding: 24rpx 32rpx; | ||
| 77 | + background: #FFF; | ||
| 78 | + box-sizing: border-box; | ||
| 79 | + box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.06); | ||
| 80 | + | ||
| 81 | + .home-btn { | ||
| 82 | + background-color: #A67939; | ||
| 83 | + color: #FFF; | ||
| 84 | + border-radius: 16rpx; | ||
| 85 | + font-size: 32rpx; | ||
| 86 | + padding: 22rpx 0; | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | +} | ||
| 90 | +</style> |
| ... | @@ -37,6 +37,7 @@ import { IconFont } from '@nutui/icons-vue-taro' | ... | @@ -37,6 +37,7 @@ import { IconFont } from '@nutui/icons-vue-taro' |
| 37 | import { useGo } from '@/hooks/useGo' | 37 | import { useGo } from '@/hooks/useGo' |
| 38 | import { billInfoAPI } from '@/api/index' | 38 | import { billInfoAPI } from '@/api/index' |
| 39 | import { formatDatetime } from '@/utils/tools'; | 39 | import { formatDatetime } from '@/utils/tools'; |
| 40 | +import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache' | ||
| 40 | 41 | ||
| 41 | const router = useTaroRouter(); | 42 | const router = useTaroRouter(); |
| 42 | const go = useGo(); | 43 | const go = useGo(); |
| ... | @@ -57,6 +58,7 @@ useDidShow(async () => { | ... | @@ -57,6 +58,7 @@ useDidShow(async () => { |
| 57 | data.datetime = data && formatDatetime(data); | 58 | data.datetime = data && formatDatetime(data); |
| 58 | billInfo.value = data; | 59 | billInfo.value = data; |
| 59 | } | 60 | } |
| 61 | + refresh_offline_booking_cache({ force: true }) | ||
| 60 | }) | 62 | }) |
| 61 | </script> | 63 | </script> |
| 62 | 64 | ... | ... |
| ... | @@ -17,7 +17,7 @@ | ... | @@ -17,7 +17,7 @@ |
| 17 | <view class="offline-entry" @tap="toOfflineCode"> | 17 | <view class="offline-entry" @tap="toOfflineCode"> |
| 18 | <view class="circle-btn"> | 18 | <view class="circle-btn"> |
| 19 | <image :src="icon_invite" style="width: 60rpx; height: 60rpx; margin-bottom: 16rpx;" /> | 19 | <image :src="icon_invite" style="width: 60rpx; height: 60rpx; margin-bottom: 16rpx;" /> |
| 20 | - <text>预约码</text> | 20 | + <text>预约记录</text> |
| 21 | </view> | 21 | </view> |
| 22 | </view> | 22 | </view> |
| 23 | 23 | ||
| ... | @@ -38,7 +38,7 @@ import icon_invite from '@/assets/images/二维码@2x2.png' | ... | @@ -38,7 +38,7 @@ import icon_invite from '@/assets/images/二维码@2x2.png' |
| 38 | const go = useGo(); | 38 | const go = useGo(); |
| 39 | 39 | ||
| 40 | const toOfflineCode = () => { | 40 | const toOfflineCode = () => { |
| 41 | - go('/pages/offlineBookingCode/index'); | 41 | + go('/pages/offlineBookingList/index'); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | const retry = () => { | 44 | const retry = () => { | ... | ... |
-
Please register or login to post a comment