hookehuyr

refactor(auth): 重构授权逻辑,优化会话管理和错误处理

- 将授权相关功能抽离到独立模块 authRedirect.js
- 实现静默续期和请求重放机制
- 优化授权失败后的降级处理
- 统一管理页面跳转和路径保存逻辑
- 移除未使用的代码和组件
......@@ -10,7 +10,6 @@ declare module 'vue' {
NutButton: typeof import('@nutui/nutui-taro')['Button']
NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox']
NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup']
NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider']
NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker']
NutInput: typeof import('@nutui/nutui-taro')['Input']
NutPicker: typeof import('@nutui/nutui-taro')['Picker']
......
......@@ -45,29 +45,19 @@
</template>
<script setup>
import { ref } from 'vue'
import Taro, { useDidShow, useShareAppMessage } from '@tarojs/taro'
import Taro, { useShareAppMessage } from '@tarojs/taro'
// import { showSuccessToast, showFailToast } from 'vant'; // NutUI 或 Taro API
import { billListAPI } from '@/api/index';
import { useGo } from '@/hooks/useGo'
import icon_1 from '@/assets/images/立即预约@2x.png'
import icon_2 from '@/assets/images/预约记录@2x.png'
import icon_3 from '@/assets/images/首页02@2x.png'
import icon_4 from '@/assets/images/二维码icon.png'
import icon_5 from '@/assets/images/我的01@2x.png'
import icon_6 from '@/assets/images/luru@2x.png'
const go = useGo();
const toBooking = () => { // 跳转到预约须知
go('/notice');
}
const toRecord = () => { // 跳转到预约记录
go('/bookingList');
}
const toSearch = () => { // 跳转到寺院录入
go('/search');
}
const toCode = () => { // 跳转到预约码
Taro.redirectTo({
url: '/pages/bookingCode/index'
......@@ -79,12 +69,6 @@ const toMy = () => { // 跳转到我的
})
}
useDidShow(async () => {
// TAG: 触发授权页面 (检查 session 或调用接口触发 401)
// 小程序中,request.js 拦截器会处理 401 跳转
await billListAPI({ page: 1, row_num: 1 });
});
useShareAppMessage(() => {
return {
title: '西园寺预约',
......
This diff is collapsed. Click to expand it.
/*
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-07 21:44:54
* @LastEditTime: 2026-01-08 16:27:50
* @FilePath: /xyxBooking-weapp/src/utils/request.js
* @Description: 简单axios封装,后续按实际处理
*/
......@@ -10,7 +10,7 @@ import axios from 'axios-miniprogram';
import Taro from '@tarojs/taro'
// import qs from 'qs'
// import { strExist } from './tools'
import { routerStore } from '@/stores/router'
import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect'
// import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
// import store from '@/store'
......@@ -30,25 +30,6 @@ const getSessionId = () => {
}
};
const getCurrentPageFullPath = () => {
try {
const pages = Taro.getCurrentPages()
if (!pages || pages.length === 0) return ''
const currentPage = pages[pages.length - 1]
const route = currentPage.route
const options = currentPage.options || {}
const queryParams = Object.keys(options)
.map(key => `${key}=${encodeURIComponent(options[key])}`)
.join('&')
return queryParams ? `${route}?${queryParams}` : route
} catch (error) {
return ''
}
}
// const isPlainObject = (value) => {
// if (value === null || typeof value !== 'object') return false
// return Object.prototype.toString.call(value) === '[object Object]'
......@@ -114,33 +95,49 @@ service.interceptors.request.use(
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
* 响应拦截器说明
* - 这里统一处理后端自定义 code(例如 401 未授权)
* - 如需拿到 headers/status 等原始信息,直接返回 response 即可
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
async response => {
const res = response.data
// 401 未授权处理
if (res.code === 401) {
// 跳转到授权页
// 避免死循环,如果已经在 auth 页则不跳
const config = response?.config || {}
/**
* 避免死循环/重复授权:
* - __is_auth_request:本次请求就是“换取会话”的授权请求,不应再次触发刷新
* - __is_retry:本次请求是 401 后的重试请求,如果仍 401,不再继续重试
*/
if (config.__is_auth_request || config.__is_retry) {
return response
}
/**
* 记录来源页:用于授权成功后回跳
* - 避免死循环:如果已经在 auth 页则不重复记录/跳转
*/
const pages = Taro.getCurrentPages();
const currentPage = pages[pages.length - 1];
if (currentPage && currentPage.route !== 'pages/auth/index') {
const router = routerStore()
const currentPath = getCurrentPageFullPath()
if (currentPath) {
router.add(currentPath)
}
// Taro.navigateTo({ url: '/pages/auth/index' });
saveCurrentPagePath()
}
try {
// 优先走静默续期:成功后重放原请求
await refreshSession()
const retry_config = { ...config, __is_retry: true }
return await service(retry_config)
} catch (error) {
// 静默续期失败:降级跳转到授权页(由授权页完成授权并回跳)
const pages_retry = Taro.getCurrentPages();
const current_page_retry = pages_retry[pages_retry.length - 1];
if (current_page_retry && current_page_retry.route !== 'pages/auth/index') {
navigateToAuth()
}
return response
}
return response; // 返回 response 以便业务代码处理(或者这里 reject)
}
if (['预约ID不存在'].includes(res.msg)) {
......