hookehuyr

refactor: 移除离线预约功能并添加授权模式开关

移除与离线预约相关的所有代码,包括缓存管理、轮询逻辑和弱网络提示模块
添加 ENABLE_AUTH_MODE 配置开关以控制授权功能的启用状态
简化网络超时处理逻辑,将弱网络弹窗改为 toast 提示
清理不再使用的示例页面和类型定义文件
1 +/* eslint-disable */
2 +/* prettier-ignore */
3 +// @ts-nocheck
4 +// Generated by unplugin-vue-components
5 +// Read more: https://github.com/vuejs/core/pull/3399
6 +export {}
7 +
8 +declare module 'vue' {
9 + export interface GlobalComponents {
10 + IndexNav: typeof import('./src/components/indexNav.vue')['default']
11 + Picker: typeof import('./src/components/time-picker-data/picker.vue')['default']
12 + PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default']
13 + QrCode: typeof import('./src/components/qrCode.vue')['default']
14 + QrCodeSearch: typeof import('./src/components/qrCodeSearch.vue')['default']
15 + RouterLink: typeof import('vue-router')['RouterLink']
16 + RouterView: typeof import('vue-router')['RouterView']
17 + }
18 +}
...@@ -3,9 +3,8 @@ ...@@ -3,9 +3,8 @@
3 * @Template: 在此定义您的业务 API 接口地址 3 * @Template: 在此定义您的业务 API 接口地址
4 */ 4 */
5 5
6 -import { fn, fetch } from '@/api/fn'; 6 +// import { fn, fetch } from '@/api/fn';
7 7
8 -const Api = {}
9 8
10 // ==================== 业务 API 接口示例 ==================== 9 // ==================== 业务 API 接口示例 ====================
11 // 请根据实际业务需求修改或添加接口 10 // 请根据实际业务需求修改或添加接口
......
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-17 12:14:16 4 + * @LastEditTime: 2026-01-29 18:29:57
5 - * @FilePath: /xyxBooking-weapp/src/app.js 5 + * @FilePath: /manulife-weapp/src/app.js
6 * @Description: 应用入口文件 6 * @Description: 应用入口文件
7 */ 7 */
8 import { createApp } from 'vue' 8 import { createApp } from 'vue'
...@@ -10,16 +10,6 @@ import { createPinia } from 'pinia' ...@@ -10,16 +10,6 @@ import { createPinia } from 'pinia'
10 import './utils/polyfill' 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'
14 -import { refresh_offline_booking_cache, has_offline_booking_cache } from '@/composables/useOfflineBookingCache'
15 -import { is_usable_network, get_network_type } from '@/utils/network'
16 -import { enable_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling'
17 -import { weak_network_text, get_weak_network_modal_use_cache_options } from '@/utils/uiText'
18 -
19 -// 记录是否已展示过网络异常提示弹窗
20 -let has_shown_network_modal = false
21 -// 记录上一次网络是否可用,用于识别“从可用变为不可用”的场景
22 -let last_network_usable = null
23 13
24 const App = createApp({ 14 const App = createApp({
25 // 对应 onLaunch 15 // 对应 onLaunch
...@@ -37,163 +27,8 @@ const App = createApp({ ...@@ -37,163 +27,8 @@ const App = createApp({
37 saveCurrentPagePath(full_path) 27 saveCurrentPagePath(full_path)
38 } 28 }
39 29
40 - /** 30 + // 如果用户已授权,则不需要额外操作
41 - * @description 预加载离线预约记录数据(列表+详情)
42 - * - 仅在有授权且网络可用时调用
43 - * - 成功后将数据存储到本地缓存(key: OFFLINE_BOOKING_DATA)
44 - * @returns {Promise<void>} 无返回值
45 - */
46 - const preloadBookingData = async () => {
47 - try {
48 - await refresh_offline_booking_cache()
49 - } catch (e) {
50 - console.error('Preload booking cache failed', e)
51 - }
52 - }
53 -
54 - /**
55 - * @description 判断是否应该跳过网络异常提示弹窗
56 - * - 仅在当前页面为离线预约列表/详情/核销码页时返回 true
57 - * @returns {boolean} true=跳过提示,false=不跳过
58 - */
59 -
60 - const should_skip_network_prompt = () => {
61 - const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []
62 - const current_page = pages && pages.length ? pages[pages.length - 1] : null
63 - const current_route = String(current_page?.route || '')
64 - if (!current_route) return false
65 - if (current_route.includes('pages/offlineBookingList/index')) return true
66 - if (current_route.includes('pages/offlineBookingDetail/index')) return true
67 - if (current_route.includes('pages/offlineBookingCode/index')) return true
68 - return false
69 - }
70 -
71 - /**
72 - * @description 处理不良网络情况
73 - * - 仅在当前页面未跳过提示弹窗时调用
74 - * - 若有离线预约缓存,则展示弹窗询问是否使用缓存数据
75 - * - 否则展示简单提示 toast
76 - * @param {string} network_type 网络类型(wifi/4g/5g/3g/none/unknown)
77 - * @returns {Promise<boolean>} true=需要中断后续启动流程,false=继续
78 - */
79 -
80 - const handle_bad_network = async (network_type) => {
81 - if (has_shown_network_modal) return false
82 - if (should_skip_network_prompt()) return false
83 -
84 - const is_none_network = network_type === 'none'
85 - const is_weak_network = !is_usable_network(network_type)
86 - if (!is_weak_network) return false
87 -
88 - has_shown_network_modal = true
89 -
90 - if (has_offline_booking_cache()) {
91 - try {
92 - const modal_res = await Taro.showModal(get_weak_network_modal_use_cache_options())
93 - if (modal_res?.confirm) {
94 - await Taro.reLaunch({ url: '/pages/offlineBookingList/index' })
95 - return true
96 - }
97 - } catch (e) {
98 - return is_none_network
99 - }
100 - } else {
101 - try {
102 - await Taro.showToast({ title: weak_network_text.toast_title, icon: 'none', duration: 2000 })
103 - } catch (e) {
104 - return is_none_network
105 - }
106 - }
107 -
108 - return is_none_network
109 - }
110 -
111 - /**
112 - * 监听网络状态变化
113 - * - 当网络连接且有授权时,预加载离线预约记录数据
114 - */
115 - Taro.onNetworkStatusChange((res) => {
116 - const is_connected = res?.isConnected !== false
117 - const network_type = res?.networkType || 'none'
118 - const network_usable = is_connected && is_usable_network(network_type)
119 -
120 - if (network_usable) {
121 - has_shown_network_modal = false
122 - last_network_usable = true
123 - if (hasAuth()) preloadBookingData()
124 - return
125 - }
126 -
127 - const should_prompt = last_network_usable === true || last_network_usable === null
128 - last_network_usable = false
129 - if (should_prompt) {
130 - handle_bad_network(network_type)
131 - }
132 - return
133 - })
134 -
135 - /**
136 - * @description 处理启动时的不良网络情况(只在启动阶段检查一次)
137 - * - 网络不可用且有离线缓存:询问是否进入离线模式
138 - * - 网络不可用且无缓存:toast 提示网络不佳
139 - * @returns {Promise<boolean>} true=进入离线模式并中断启动,false=继续启动
140 - */
141 - const handle_bad_network_on_launch = async () => {
142 - /**
143 - * 避免重复提示用户
144 - * - 仅在首次启动时检查网络情况
145 - * - 如果用户已展示过提示弹窗,则直接返回 false
146 - */
147 - if (has_shown_network_modal) return false
148 -
149 - const network_type = await get_network_type()
150 - last_network_usable = is_usable_network(network_type)
151 - return handle_bad_network(network_type)
152 - }
153 -
154 - /**
155 - * @description 尝试在网络可用时预加载离线预约记录数据
156 - * - 仅在有授权时调用
157 - * @returns {void} 无返回值
158 - */
159 - const try_preload_when_online = () => {
160 - if (!hasAuth()) return
161 - Taro.getNetworkType({
162 - success: (res) => {
163 - if (is_usable_network(res.networkType)) {
164 - preloadBookingData()
165 - }
166 - }
167 - })
168 - }
169 -
170 - /**
171 - * @description 授权成功后的共用启动逻辑
172 - * - 尝试在网络可用时预加载离线预约数据
173 - * - 启动离线预约缓存轮询(会自行处理网络可用性与引用计数)
174 - * @returns {void} 无返回值
175 - */
176 -
177 - const bootstrap_after_auth = () => {
178 - try_preload_when_online()
179 - enable_offline_booking_cache_polling({ interval_ms: 2 * 1000 * 60 })
180 - }
181 -
182 - // 处理在启动时出现的不良网络情况
183 - const should_stop = await handle_bad_network_on_launch()
184 - // 如果用户选择进入离线模式,则直接返回
185 - if (should_stop) return
186 -
187 - /**
188 - * 尝试在有授权时预加载离线预约记录数据
189 - * - 若无授权,则尝试静默授权
190 - * - 授权成功后调用 bootstrap_after_auth 启动共用逻辑
191 - * - 授权失败则跳转至授权页面
192 - */
193 -
194 - // 如果用户已授权,则直接调用 bootstrap_after_auth 启动共用逻辑
195 if (hasAuth()) { 31 if (hasAuth()) {
196 - bootstrap_after_auth()
197 return 32 return
198 } 33 }
199 34
...@@ -202,8 +37,6 @@ const App = createApp({ ...@@ -202,8 +37,6 @@ const App = createApp({
202 try { 37 try {
203 // 尝试静默授权 38 // 尝试静默授权
204 await silentAuth() 39 await silentAuth()
205 - // 授权成功后调用 bootstrap_after_auth 启动共用逻辑
206 - bootstrap_after_auth()
207 } catch (error) { 40 } catch (error) {
208 console.error('静默授权失败:', error) 41 console.error('静默授权失败:', error)
209 // 授权失败则跳转至授权页面 42 // 授权失败则跳转至授权页面
......
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 -import { is_usable_network, get_network_type } from '@/utils/network'
14 -
15 -export const OFFLINE_BOOKING_CACHE_KEY = 'OFFLINE_BOOKING_DATA'
16 -
17 -let refresh_promise = null
18 -
19 -/**
20 - * @description 兼容不同后端结构:从预约记录中提取可用数据载荷
21 - * - 部分接口会把字段塞到 bill.list 对象里,这里做一次展开合并
22 - * @param {Object} bill 原始预约记录
23 - * @returns {Object} 扁平化后的预约记录对象
24 - */
25 -const extract_bill_payload = (bill) => {
26 - if (!bill) return {}
27 -
28 - const data = { ...bill }
29 - const list = data.list
30 -
31 - if (list && typeof list === 'object' && !Array.isArray(list)) {
32 - return { ...list, ...data }
33 - }
34 -
35 - return data
36 -}
37 -
38 -/**
39 - * @description 从预约记录中提取人员列表
40 - * - 兼容不同字段名(person_list/bill_person_list/persons/qrcode_list/qr_list/detail_list)
41 - * - 保证返回数组类型
42 - * @param {Object} bill 预约记录
43 - * @returns {Array} 人员列表
44 - */
45 -const extract_person_list = (bill) => {
46 - if (!bill) return []
47 -
48 - /**
49 - * 从预约记录中提取人员列表
50 - * - 考虑不同字段名的情况(如 person_list, bill_person_list, persons, qrcode_list, qr_list, detail_list)
51 - * - 确保返回的是数组类型
52 - */
53 - const candidate =
54 - (Array.isArray(bill.list) ? bill.list : null) ||
55 - (Array.isArray(bill?.list?.list) ? bill.list.list : null) ||
56 - bill.person_list ||
57 - bill.bill_person_list ||
58 - bill.persons ||
59 - bill.qrcode_list ||
60 - bill.qr_list ||
61 - bill.detail_list ||
62 - []
63 -
64 - return Array.isArray(candidate) ? candidate : []
65 -}
66 -
67 -/**
68 - * @description 格式化预约记录项(统一字段与展示用时间)
69 - * @param {Object} item 原始预约记录项
70 - * @returns {Object} 格式化后的预约记录项
71 - */
72 -const normalize_bill_item = (item) => {
73 - const data = extract_bill_payload(item)
74 -
75 - data.datetime = data.datetime || formatDatetime(data)
76 - data.booking_time = data.booking_time || data.datetime
77 - data.order_time = data.order_time || (data.created_time ? data.created_time.slice(0, -3) : '')
78 -
79 - if (!data.person_name) {
80 - const person_list = extract_person_list(item)
81 - const first = person_list[0]
82 - const name = first?.name || first?.person_name
83 - if (name) data.person_name = name
84 - }
85 -
86 - return data
87 -}
88 -
89 -/**
90 - * 获取离线预约记录缓存
91 - * @returns {Array} 格式化后的预约记录项列表
92 - */
93 -export const get_offline_booking_cache = () => {
94 - try {
95 - const data = Taro.getStorageSync(OFFLINE_BOOKING_CACHE_KEY)
96 - return Array.isArray(data) ? data : []
97 - } catch (e) {
98 - return []
99 - }
100 -}
101 -
102 -/**
103 - * 检查是否存在离线预约记录缓存
104 - * @returns {boolean} 是否存在缓存且非空
105 - */
106 -export const has_offline_booking_cache = () => {
107 - const list = get_offline_booking_cache()
108 - return Array.isArray(list) && list.length > 0
109 -}
110 -
111 -/**
112 - * 根据支付ID获取离线预约记录
113 - * @param {*} pay_id 支付ID
114 - * @returns {Object|null} 匹配的预约记录项或 null
115 - */
116 -export const get_offline_booking_by_pay_id = (pay_id) => {
117 - const list = get_offline_booking_cache()
118 - const target_pay_id = String(pay_id || '')
119 - return list.find((item) => String(item?.pay_id || '') === target_pay_id) || null
120 -}
121 -
122 -/**
123 - * 获取预约记录中的人员列表
124 - * @param {Object} bill - 预约记录项
125 - * @returns {Array} 人员列表(包含姓名、身份证号、二维码等信息)
126 - */
127 -export const get_offline_bill_person_list = (bill) => {
128 - return extract_person_list(bill)
129 -}
130 -
131 -/**
132 - * 构建预约记录中的二维码列表
133 - * @param {Object} bill - 预约记录项
134 - * @returns {Array} 二维码列表(包含姓名、身份证号、二维码、预约时间等信息)
135 - */
136 -export const build_offline_qr_list = (bill) => {
137 - const list = get_offline_bill_person_list(bill)
138 - const datetime = bill?.datetime || formatDatetime(bill || {})
139 -
140 - return list
141 - .filter((item) => item && (item.qr_code || item.qrcode || item.qrCode) && (item.qr_code || item.qrcode || item.qrCode) !== '')
142 - .map((item) => {
143 - const begin_time = item.begin_time || bill?.begin_time
144 - const end_time = item.end_time || bill?.end_time
145 - const qr_code = item.qr_code || item.qrcode || item.qrCode
146 - const name = item.name || item.person_name || item.real_name
147 - const id_number = item.id_number || item.idcard || item.idCard || item.id
148 - return {
149 - name,
150 - id_number,
151 - qr_code,
152 - begin_time,
153 - end_time,
154 - datetime: item.datetime || (begin_time && end_time ? formatDatetime({ begin_time, end_time }) : datetime),
155 - pay_id: bill?.pay_id,
156 - sort: 0,
157 - }
158 - })
159 -}
160 -
161 -/**
162 - * 刷新离线预约记录缓存
163 - * - 仅在有授权且网络可用时调用
164 - * - 成功后将数据存储到本地缓存(key: OFFLINE_BOOKING_DATA)
165 - * @param {boolean} force - 是否强制刷新,默认为 false. force 参数的核心作用是控制是否忽略 “正在进行的缓存请求”, 管的是 “是否允许重复发起请求”,不管 “请求能不能成功执行缓存”。
166 - * @returns 不同情况返回值不一样
167 - * - 成功时包含格式化后的预约记录项列表
168 - * - 失败时包含错误信息(如网络错误、授权失败等)
169 - */
170 -
171 -export const refresh_offline_booking_cache = async ({ force = false } = {}) => {
172 - // 1. 检查是否有正在进行的刷新请求
173 - // 2. 如果有,且 force 为 false,则直接返回该 Promise
174 - // 3. 如果没有,或 force 为 true,则继续执行刷新逻辑
175 - // 4. 刷新完成后,将结果存储到本地缓存(key: OFFLINE_BOOKING_CACHE_KEY)
176 - // 5. 返回刷新结果 Promise
177 -
178 - if (!hasAuth()) return { code: 0, data: null, msg: '未授权' }
179 -
180 - if (refresh_promise && !force) return refresh_promise
181 -
182 - // 核心逻辑:
183 - // 1. 立刻触发异步逻辑,同时捕获 Promise 状态
184 - // 2. 保证 refresh_promise 始终是 Promise 类型,适配 await
185 - // 3. 隔离作用域,避免变量污染
186 - // 加 () 是为了 “让异步逻辑立刻跑起来”,并把 “跑的结果(Promise)” 存起来,供后续复用和等待。
187 - refresh_promise = (async () => {
188 - const network_type = await get_network_type()
189 - if (!is_usable_network(network_type)) {
190 - return { code: 0, data: null, msg: '网络不可用' }
191 - }
192 -
193 - const { code, data, msg } = await billOfflineAllAPI()
194 - if (code && Array.isArray(data)) {
195 - // 过滤出状态为3(已完成)的记录
196 - const normalized = data.map(normalize_bill_item).filter((item) => item && item.pay_id && item.status == 3)
197 - if (normalized.length > 0) {
198 - // TAG: 核心逻辑:将过滤后的记录存储到本地缓存
199 - Taro.setStorageSync(OFFLINE_BOOKING_CACHE_KEY, normalized)
200 - }
201 - }
202 - return { code, data, msg }
203 - })()
204 -
205 - try {
206 - return await refresh_promise
207 - } finally {
208 - refresh_promise = null
209 - }
210 -}
This diff is collapsed. Click to expand it.
1 -<template>
2 - <view class="api-demo">
3 - <nut-cell-group>
4 - <nut-cell title="API 生成器演示" />
5 - </nut-cell-group>
6 -
7 - <!-- 用户信息模块 -->
8 - <nut-cell-group title="用户模块">
9 - <nut-cell>
10 - <template #title>
11 - <view>获取用户信息</view>
12 - </template>
13 - <template #link>
14 - <nut-button
15 - size="small"
16 - type="primary"
17 - @click="fetchUserInfo"
18 - :loading="userLoading"
19 - >
20 - 调用
21 - </nut-button>
22 - </template>
23 - </nut-cell>
24 -
25 - <nut-cell v-if="userInfo" title="用户数据">
26 - <view class="user-info">
27 - <text>姓名: {{ userInfo?.name || '-' }}</text>
28 - <text>手机: {{ userInfo?.mobile || '-' }}</text>
29 - </view>
30 - </nut-cell>
31 - </nut-cell-group>
32 -
33 - <!-- 订单模块 -->
34 - <nut-cell-group title="订单模块">
35 - <nut-cell>
36 - <template #title>
37 - <view>获取订单列表</view>
38 - </template>
39 - <template #link>
40 - <nut-button
41 - size="small"
42 - type="primary"
43 - @click="fetchOrderList"
44 - :loading="orderLoading"
45 - >
46 - 调用
47 - </nut-button>
48 - </template>
49 - </nut-cell>
50 -
51 - <nut-cell v-if="orderList.length > 0" title="订单列表">
52 - <view class="order-list">
53 - <view
54 - v-for="order in orderList"
55 - :key="order.id"
56 - class="order-item"
57 - >
58 - <text>订单号: {{ order.order_no }}</text>
59 - <text>状态: {{ order.status }}</text>
60 - <text>金额: ¥{{ order.total_amount }}</text>
61 - </view>
62 - </view>
63 - </nut-cell>
64 -
65 - <nut-cell>
66 - <template #title>
67 - <view>获取订单详情</view>
68 - </template>
69 - <template #link>
70 - <nut-button
71 - size="small"
72 - type="primary"
73 - @click="fetchOrderDetail"
74 - :loading="detailLoading"
75 - >
76 - 调用
77 - </nut-button>
78 - </template>
79 - </nut-cell>
80 -
81 - <nut-cell v-if="orderDetail" title="订单详情">
82 - <view class="order-detail">
83 - <text>订单号: {{ orderDetail.order_no }}</text>
84 - <text>商品数: {{ orderDetail.items?.length || 0 }}</text>
85 - </view>
86 - </nut-cell>
87 - </nut-cell-group>
88 -
89 - <!-- 使用说明 -->
90 - <nut-cell-group title="使用说明">
91 - <nut-cell>
92 - <view class="instructions">
93 - <text>1. 点击上方按钮调用 API</text>
94 - <text>2. API 文件位于 src/api/ 目录</text>
95 - <text>3. 由 docs/api-specs/ 文档自动生成</text>
96 - <text>4. 运行 pnpm api:generate 生成新 API</text>
97 - </view>
98 - </nut-cell>
99 - </nut-cell-group>
100 - </view>
101 -</template>
102 -
103 -<script setup>
104 -import { ref } from 'vue';
105 -import Taro from '@tarojs/taro';
106 -import { getUserInfoAPI } from '@/api/user';
107 -import { getListAPI, getDetailAPI } from '@/api/order';
108 -
109 -// 用户模块
110 -const userInfo = ref(null);
111 -const userLoading = ref(false);
112 -
113 -// 订单模块
114 -const orderList = ref([]);
115 -const orderLoading = ref(false);
116 -const orderDetail = ref(null);
117 -const detailLoading = ref(false);
118 -
119 -/**
120 - * 获取用户信息
121 - */
122 -const fetchUserInfo = async () => {
123 - userLoading.value = true;
124 - try {
125 - const result = await getUserInfoAPI();
126 -
127 - if (result.code === 1) {
128 - userInfo.value = result.data.user;
129 - Taro.showToast({
130 - title: '获取成功',
131 - icon: 'success',
132 - duration: 2000,
133 - });
134 - } else {
135 - Taro.showToast({
136 - title: result.msg || '获取失败',
137 - icon: 'error',
138 - duration: 2000,
139 - });
140 - }
141 - } catch (error) {
142 - console.error('获取用户信息失败:', error);
143 - Taro.showToast({
144 - title: '网络异常',
145 - icon: 'error',
146 - duration: 2000,
147 - });
148 - } finally {
149 - userLoading.value = false;
150 - }
151 -};
152 -
153 -/**
154 - * 获取订单列表
155 - */
156 -const fetchOrderList = async () => {
157 - orderLoading.value = true;
158 - try {
159 - const result = await getListAPI({
160 - page: 1,
161 - pageSize: 10,
162 - });
163 -
164 - if (result.code === 1) {
165 - orderList.value = result.data.list || [];
166 - Taro.showToast({
167 - title: '获取成功',
168 - icon: 'success',
169 - duration: 2000,
170 - });
171 - } else {
172 - Taro.showToast({
173 - title: result.msg || '获取失败',
174 - icon: 'error',
175 - duration: 2000,
176 - });
177 - }
178 - } catch (error) {
179 - console.error('获取订单列表失败:', error);
180 - Taro.showToast({
181 - title: '网络异常',
182 - icon: 'error',
183 - duration: 2000,
184 - });
185 - } finally {
186 - orderLoading.value = false;
187 - }
188 -};
189 -
190 -/**
191 - * 获取订单详情
192 - */
193 -const fetchOrderDetail = async () => {
194 - detailLoading.value = true;
195 - try {
196 - const result = await getDetailAPI({
197 - id: 123, // 示例订单ID
198 - });
199 -
200 - if (result.code === 1) {
201 - orderDetail.value = result.data.order;
202 - Taro.showToast({
203 - title: '获取成功',
204 - icon: 'success',
205 - duration: 2000,
206 - });
207 - } else {
208 - Taro.showToast({
209 - title: result.msg || '获取失败',
210 - icon: 'error',
211 - duration: 2000,
212 - });
213 - }
214 - } catch (error) {
215 - console.error('获取订单详情失败:', error);
216 - Taro.showToast({
217 - title: '网络异常',
218 - icon: 'error',
219 - duration: 2000,
220 - });
221 - } finally {
222 - detailLoading.value = false;
223 - }
224 -};
225 -</script>
226 -
227 -<style lang="less" scoped>
228 -.api-demo {
229 - padding: 20px;
230 - background-color: #f5f5f5;
231 - min-height: 100vh;
232 -
233 - .user-info,
234 - .order-list,
235 - .order-detail,
236 - .instructions {
237 - display: flex;
238 - flex-direction: column;
239 - gap: 10px;
240 - font-size: 14px;
241 - color: #666;
242 -
243 - text {
244 - display: block;
245 - }
246 - }
247 -
248 - .order-item {
249 - padding: 10px;
250 - background-color: #f9f9f9;
251 - border-radius: 4px;
252 - margin-bottom: 10px;
253 - }
254 -}
255 -</style>
1 import Taro from '@tarojs/taro' 1 import Taro from '@tarojs/taro'
2 import { routerStore } from '@/stores/router' 2 import { routerStore } from '@/stores/router'
3 import { buildApiUrl } from './tools' 3 import { buildApiUrl } from './tools'
4 +import { ENABLE_AUTH_MODE } from './config'
4 5
5 // 改进:添加全局状态变量注释 6 // 改进:添加全局状态变量注释
6 /** 7 /**
...@@ -58,6 +59,9 @@ export const saveCurrentPagePath = (custom_path) => { ...@@ -58,6 +59,9 @@ export const saveCurrentPagePath = (custom_path) => {
58 * @returns {boolean} true=已存在 sessionid,false=需要授权 59 * @returns {boolean} true=已存在 sessionid,false=需要授权
59 */ 60 */
60 export const hasAuth = () => { 61 export const hasAuth = () => {
62 + // 如果禁用了授权模式,直接视为已授权
63 + if (!ENABLE_AUTH_MODE) return true
64 +
61 try { 65 try {
62 const sessionid = Taro.getStorageSync('sessionid') 66 const sessionid = Taro.getStorageSync('sessionid')
63 return !!sessionid && sessionid !== '' 67 return !!sessionid && sessionid !== ''
...@@ -93,6 +97,11 @@ const extractCookie = (response) => { ...@@ -93,6 +97,11 @@ const extractCookie = (response) => {
93 * @returns {Promise<{code:number,msg?:string,data?:any,cookie?:string}>} 授权结果(会把 cookie 写入 storage 的 sessionid) 97 * @returns {Promise<{code:number,msg?:string,data?:any,cookie?:string}>} 授权结果(会把 cookie 写入 storage 的 sessionid)
94 */ 98 */
95 export const refreshSession = async (options) => { 99 export const refreshSession = async (options) => {
100 + // 如果禁用了授权模式,直接返回模拟成功
101 + if (!ENABLE_AUTH_MODE) {
102 + return { code: 1, msg: '授权模式已禁用', cookie: 'mock_session_id' }
103 + }
104 +
96 const show_loading = options?.show_loading !== false 105 const show_loading = options?.show_loading !== false
97 106
98 // 已有授权进行中时,直接复用同一个 Promise 107 // 已有授权进行中时,直接复用同一个 Promise
...@@ -254,6 +263,9 @@ const NAVIGATING_RESET_DELAY_MS = 300 ...@@ -254,6 +263,9 @@ const NAVIGATING_RESET_DELAY_MS = 300
254 * @returns {Promise<void>} 无返回值 263 * @returns {Promise<void>} 无返回值
255 */ 264 */
256 export const navigateToAuth = async (return_path) => { 265 export const navigateToAuth = async (return_path) => {
266 + // 如果禁用了授权模式,直接返回不跳转
267 + if (!ENABLE_AUTH_MODE) return
268 +
257 const pages = Taro.getCurrentPages() 269 const pages = Taro.getCurrentPages()
258 const current_page = pages[pages.length - 1] 270 const current_page = pages[pages.length - 1]
259 const current_route = current_page?.route 271 const current_route = current_page?.route
......
1 /* 1 /*
2 + * @Date: 2026-01-29 10:48:35
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2026-01-29 17:56:45
5 + * @FilePath: /manulife-weapp/src/utils/config.js
6 + * @Description: 文件描述
7 + */
8 +/*
2 * @Description: 服务器环境配置 9 * @Description: 服务器环境配置
3 * @Template: 请根据实际项目修改 BASE_URL 和 REQUEST_DEFAULT_PARAMS 10 * @Template: 请根据实际项目修改 BASE_URL 和 REQUEST_DEFAULT_PARAMS
4 */ 11 */
...@@ -23,4 +30,11 @@ export const REQUEST_DEFAULT_PARAMS = { ...@@ -23,4 +30,11 @@ export const REQUEST_DEFAULT_PARAMS = {
23 client_name: 'YOUR_APP', // 🔧 修改为应用名称 30 client_name: 'YOUR_APP', // 🔧 修改为应用名称
24 } 31 }
25 32
33 +/**
34 + * @description 是否启用授权模式
35 + * - true: 启用授权检查、自动跳转登录、401自动续期
36 + * - false: 禁用所有授权相关功能(所有授权检查直接通过,不跳转登录页)
37 + */
38 +export const ENABLE_AUTH_MODE = false
39 +
26 export default BASE_URL 40 export default BASE_URL
......
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-13 21:29:43 4 + * @LastEditTime: 2026-01-29 18:35:55
5 - * @FilePath: /xyxBooking-weapp/src/utils/request.js 5 + * @FilePath: /manulife-weapp/src/utils/request.js
6 * @Description: 简单axios封装,后续按实际处理 6 * @Description: 简单axios封装,后续按实际处理
7 */ 7 */
8 // import axios from 'axios' 8 // import axios from 'axios'
...@@ -11,8 +11,6 @@ import Taro from '@tarojs/taro' ...@@ -11,8 +11,6 @@ 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'
15 -import { get_weak_network_modal_no_cache_options } from '@/utils/uiText'
16 import { parseQueryString } from './tools' 14 import { parseQueryString } from './tools'
17 15
18 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress'; 16 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
...@@ -136,34 +134,22 @@ const should_handle_bad_network = async (error) => { ...@@ -136,34 +134,22 @@ const should_handle_bad_network = async (error) => {
136 134
137 /** 135 /**
138 * @description 处理请求超时/弱网错误 136 * @description 处理请求超时/弱网错误
139 - * - 优先:若存在离线预约记录缓存,直接跳转离线预约列表页 137 + * - 弹出弱网提示(统一文案由 uiText 管理)
140 - * - 否则:弹出弱网提示(统一文案由 uiText 管理)
141 * @returns {Promise<void>} 无返回值 138 * @returns {Promise<void>} 无返回值
142 */ 139 */
143 const handle_request_timeout = async () => { 140 const handle_request_timeout = async () => {
144 if (has_shown_timeout_modal) return 141 if (has_shown_timeout_modal) return
145 has_shown_timeout_modal = true 142 has_shown_timeout_modal = true
146 143
147 - const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [] 144 + // 提示用户检查网络连接
148 - const current_page = pages && pages.length ? pages[pages.length - 1] : null
149 - const current_route = current_page?.route || ''
150 - if (String(current_route).includes('pages/offlineBookingList/index')) return
151 -
152 - // 若有离线预约记录缓存,则跳转至离线预约列表页
153 - if (has_offline_booking_cache()) {
154 - try {
155 - await Taro.reLaunch({ url: '/pages/offlineBookingList/index' })
156 - } catch (e) {
157 - console.error('reLaunch offlineBookingList failed:', e)
158 - }
159 - return
160 - }
161 -
162 - // 否则提示用户检查网络连接
163 try { 145 try {
164 - await Taro.showModal(get_weak_network_modal_no_cache_options()) 146 + await Taro.showToast({
147 + title: '网络连接异常,请检查网络设置',
148 + icon: 'none',
149 + duration: 2000
150 + })
165 } catch (e) { 151 } catch (e) {
166 - console.error('show weak network modal failed:', e) 152 + console.error('show weak network toast failed:', e)
167 } 153 }
168 } 154 }
169 155
...@@ -239,7 +225,7 @@ service.interceptors.response.use( ...@@ -239,7 +225,7 @@ service.interceptors.response.use(
239 const res = response.data 225 const res = response.data
240 226
241 // 401 未授权处理 227 // 401 未授权处理
242 - if (res.code === 401) { 228 + if (res.code === 401 && ENABLE_AUTH_MODE) {
243 const config = response?.config || {} 229 const config = response?.config || {}
244 /** 230 /**
245 * 避免死循环/重复重试: 231 * 避免死循环/重复重试:
......
1 -/*
2 - * @Date: 2026-01-13 21:28:45
3 - * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-15 19:24:57
5 - * @FilePath: /xyxBooking-weapp/src/utils/uiText.js
6 - * @Description: 弱网络提示文本
7 - */
8 -/**
9 - * @description 弱网/断网统一文案
10 - * - toast/modal/banner 等入口统一引用,避免多处硬编码
11 - */
12 -export const weak_network_text = {
13 - title: '网络连接不畅',
14 - toast_title: '网络连接不畅',
15 - banner_desc: '网络开小差啦!请检查网络设置,或更换位置后重新进入小程序~',
16 - offline_page_desc: '当前网络信号较弱,已自动为您切换至离线模式',
17 - modal_no_cache_content: '当前网络信号较弱,暂无法使用小程序,请检查网络设置,或更换位置后重新进入小程序~',
18 - modal_use_cache_content: '当前网络信号较弱,可使用已缓存的预约记录进入离线模式',
19 - modal_go_offline_records_content: '当前网络信号较弱,是否进入离线预约记录?',
20 - offline_mode_no_booking_toast: '当前为离线模式,无法预约',
21 - confirm_ok: '知道了',
22 - confirm_booking_records: '预约记录',
23 - confirm_offline_records: '离线记录',
24 -}
25 -
26 -/**
27 - * @description: 获取弱网络提示弹窗配置(无缓存)
28 - * @returns {Object}
29 - */
30 -export const get_weak_network_modal_no_cache_options = () => {
31 - return {
32 - title: weak_network_text.title,
33 - content: weak_network_text.modal_no_cache_content,
34 - confirmText: weak_network_text.confirm_ok,
35 - showCancel: false,
36 - }
37 -}
38 -
39 -/**
40 - * @description: 获取弱网络提示弹窗配置(有缓存)
41 - * @returns {Object}
42 - */
43 -export const get_weak_network_modal_use_cache_options = () => {
44 - return {
45 - title: weak_network_text.title,
46 - content: weak_network_text.modal_use_cache_content,
47 - confirmText: weak_network_text.confirm_booking_records,
48 - cancelText: weak_network_text.confirm_ok,
49 - }
50 -}
51 -
52 -/**
53 - * @description: 获取弱网络提示弹窗配置(进入离线预约记录)
54 - * @returns {Object}
55 - */
56 -export const get_weak_network_modal_go_offline_records_options = () => {
57 - return {
58 - title: weak_network_text.title,
59 - content: weak_network_text.modal_go_offline_records_content,
60 - confirmText: weak_network_text.confirm_offline_records,
61 - cancelText: weak_network_text.confirm_ok,
62 - }
63 -}