hookehuyr

fix(auth): 优化授权逻辑和离线数据存储

重构授权检查函数从 needAuth 改为 hasAuth 以更清晰表达意图
优化离线数据存储结构,只保存必要字段
简化网络状态检查和预加载逻辑
/*
* @Date: 2025-06-28 10:33:00
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-08 19:36:25
* @LastEditTime: 2026-01-12 23:48:04
* @FilePath: /xyxBooking-weapp/src/app.js
* @Description: 文件描述
*/
......@@ -9,7 +9,7 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './utils/polyfill'
import './app.less'
import { saveCurrentPagePath, needAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
import Taro from '@tarojs/taro'
import { qrcodeListAPI } from '@/api/index'
import { formatDatetime } from '@/utils/tools'
......@@ -59,14 +59,23 @@ const App = createApp({
const { code, data } = await qrcodeListAPI();
if (code && data) {
data.forEach(item => {
item.qr_code_url = '/admin?m=srv&a=get_qrcode&key=' + item.qr_code;
item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time })
item.sort = 0;
});
const validData = data.filter(item => item.qr_code !== '');
if (validData.length > 0) {
const processed = formatGroup(validData);
Taro.setStorageSync('OFFLINE_QR_DATA', processed);
const offline_data = processed.map(item => ({
name: item.name,
id_number: item.id_number,
qr_code: item.qr_code,
begin_time: item.begin_time,
end_time: item.end_time,
datetime: item.datetime,
pay_id: item.pay_id,
sort: item.sort,
}));
Taro.setStorageSync('OFFLINE_QR_DATA', offline_data);
} else {
Taro.removeStorageSync('OFFLINE_QR_DATA');
}
......@@ -77,47 +86,58 @@ const App = createApp({
};
/**
* 检查网络状态并预加载二维码数据
* - 仅在有网络连接时调用
* 监听网络状态变化
* - 当网络连接且有授权时,调用 preloadQrData 预加载二维码数据
*/
Taro.onNetworkStatusChange((res) => {
if (res.isConnected && hasAuth()) {
preloadQrData()
}
})
const is_usable_network = (network_type) => {
return ['wifi', '4g', '5g', '3g'].includes(network_type)
}
/**
* 尝试在网络可用时预加载二维码数据
* - 仅在有授权时调用
* - 成功后将数据存储到本地缓存(key: OFFLINE_QR_DATA)
* - 失败则移除缓存
* @returns {Promise<void>}
*/
const checkNetworkAndPreload = () => {
const try_preload_when_online = () => {
if (!hasAuth()) return
Taro.getNetworkType({
success: (res) => {
const isConnected = ['wifi', '4g', '5g', '3g'].includes(res.networkType);
if (isConnected) {
preloadQrData();
if (is_usable_network(res.networkType)) {
preloadQrData()
}
}
});
};
})
}
/**
* 监听网络状态变化
* - 网络连接时预加载二维码数据
* 尝试在有授权时预加载二维码数据
* - 若无授权,则尝试静默授权
* - 授权成功后调用 try_preload_when_online 预加载数据
* - 授权失败则跳转至授权页面
*/
Taro.onNetworkStatusChange((res) => {
if (res.isConnected) {
preloadQrData();
if (hasAuth()) {
try_preload_when_online()
return
}
});
// 初始检查网络状态并预加载二维码数据
checkNetworkAndPreload();
if (!needAuth()) return
if (path === 'pages/auth/index') return
try {
// 静默授权
// 尝试静默授权
await silentAuth()
// 授权成功后检查网络状态并预加载二维码数据
checkNetworkAndPreload();
// 授权成功后预加载数据
try_preload_when_online()
} catch (error) {
console.error('静默授权失败:', error)
// 授权失败后跳转到授权页,携带当前页路径作为回跳目标
// 授权失败则跳转至授权页面
navigateToAuth(full_path || undefined)
}
},
......
......@@ -188,7 +188,17 @@ const init = async () => {
if (validData.length > 0) {
userList.value = formatGroup(validData);
// 缓存数据供离线模式使用
Taro.setStorageSync('OFFLINE_QR_DATA', userList.value);
const offline_data = userList.value.map(item => ({
name: item.name,
id_number: item.id_number,
qr_code: item.qr_code,
begin_time: item.begin_time,
end_time: item.end_time,
datetime: item.datetime,
pay_id: item.pay_id,
sort: item.sort,
}));
Taro.setStorageSync('OFFLINE_QR_DATA', offline_data);
refreshBtn();
} else {
userList.value = [];
......
<!--
* @Date: 2024-01-15 16:25:51
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-12 18:54:33
* @LastEditTime: 2026-01-12 22:23:03
* @FilePath: /xyxBooking-weapp/src/pages/submit/index.vue
* @Description: 预约人员信息
-->
......@@ -113,6 +113,9 @@ const goToVisitor = () => {
go('/addVisitor');
}
// 待支付订单ID
const pending_pay_id = ref(null);
const submitBtn = async () => {
if (!checked_visitors.value.length) {
Taro.showToast({ title: '请先添加参观者', icon: 'none' })
......@@ -121,8 +124,7 @@ const submitBtn = async () => {
let pay_id = pending_pay_id.value;
if (!pay_id) {
// TAG: 提交订单跳转到支付页面
if (!pay_id) { // TAG: 提交订单, 如果没有待支付订单ID, 则创建一个新的订单
Taro.showLoading({ title: '提交中...' });
const { code, data, msg } = await addReserveAPI({
reserve_date: date.value,
......@@ -144,19 +146,19 @@ const submitBtn = async () => {
// 如果金额大于零, 走微信支付, 如果等于零直接跳转成功页
if (total.value > 0) {
Taro.showLoading({ title: '支付准备中...' });
const payParams = await wxPayAPI({ pay_id: pay_id }); // 参数接口
const payParams = await wxPayAPI({ pay_id }); // 参数接口
Taro.hideLoading();
if (payParams.code) {
let pay = payParams.data;
let pay_params = payParams.data;
Taro.requestPayment({
timeStamp: pay.timeStamp,
nonceStr: pay.nonceStr,
package: pay.package,
signType: pay.signType,
paySign: pay.paySign,
timeStamp: pay_params.timeStamp,
nonceStr: pay_params.nonceStr,
package: pay_params.package,
signType: pay_params.signType,
paySign: pay_params.paySign,
success (res) {
go('/success', { pay_id: pay_id });
go('/success', { pay_id });
},
fail (res) {
// 支付取消或失败,保留 pending_pay_id,允许用户再次点击按钮尝试支付同一订单
......@@ -170,7 +172,7 @@ const submitBtn = async () => {
}
} else {
// 金额等于零, 直接跳转成功页
go('/success', { pay_id: pay_id });
go('/success', { pay_id });
}
}
......
......@@ -40,16 +40,16 @@ export const saveCurrentPagePath = (custom_path) => {
}
/**
* 判断是否需要授权
* @returns {boolean} true=需要授权,false=已存在 sessionid
* 判断是否授权
* @returns {boolean} true=已存在 sessionid,false=需要授权
*/
export const needAuth = () => {
export const hasAuth = () => {
try {
const sessionid = Taro.getStorageSync('sessionid')
return !sessionid || sessionid === ''
return !!sessionid && sessionid !== ''
} catch (error) {
console.error('检查授权状态失败:', error)
return true
return false
}
}
......@@ -96,7 +96,7 @@ export const refreshSession = async (options) => {
// 开发环境可按需手动传 openid(仅用于本地联调)
if (process.env.NODE_ENV === 'development') {
// request_data.openid = 'h-008';
// request_data.openid = 'waj';
// request_data.openid = 'h-009';
// request_data.openid = 'h-010';
// request_data.openid = 'h-011';
......@@ -112,7 +112,7 @@ export const refreshSession = async (options) => {
// 换取后端会话(服务端通过 Set-Cookie 返回会话信息)
const response = await Taro.request({
url: `${BASE_URL}/srv/?a=openid&f=${encodeURIComponent(REQUEST_DEFAULT_PARAMS.f)}&client_name=${encodeURIComponent(REQUEST_DEFAULT_PARAMS.client_name)}`,
url: `${BASE_URL}/srv/?a=openid_wxapp&f=${encodeURIComponent(REQUEST_DEFAULT_PARAMS.f)}&client_name=${encodeURIComponent(REQUEST_DEFAULT_PARAMS.client_name)}`,
method: 'POST',
data: request_data,
})
......@@ -154,7 +154,7 @@ export const refreshSession = async (options) => {
const do_silent_auth = async (show_loading) => {
// 已有 sessionid 时直接视为已授权
if (!needAuth()) {
if (hasAuth()) {
return { code: 1, msg: '已授权' }
}
......@@ -212,9 +212,9 @@ export const navigateToAuth = (return_path) => {
}
// TAG: navigateTo 失败时(例如页面栈满),降级为 redirectTo
Taro.navigateTo({ url: '/pages/auth/index' }).catch(() => {
return Taro.redirectTo({ url: '/pages/auth/index' })
})
// Taro.navigateTo({ url: '/pages/auth/index' }).catch(() => {
// return Taro.redirectTo({ url: '/pages/auth/index' })
// })
}
/**
......@@ -279,7 +279,7 @@ export const isFromShare = (options) => {
* @returns {Promise<boolean>} true=已处理且可继续,false=授权失败
*/
export const handleSharePageAuth = async (options, callback) => {
if (!needAuth()) {
if (hasAuth()) {
if (typeof callback === 'function') callback()
return true
}
......