refactor: ♻️ 优化请求工具类

This commit is contained in:
ray
2024-10-13 11:18:19 +08:00
parent a7757213f2
commit 3dec53af38
6 changed files with 90 additions and 46 deletions

36
pnpm-lock.yaml generated
View File

@@ -56,9 +56,6 @@ dependencies:
vue:
specifier: ^3.4.21
version: 3.5.6(typescript@4.9.5)
vue-i18n:
specifier: ^9.1.9
version: 9.14.0(vue@3.5.6)
wot-design-uni:
specifier: ^1.3.11
version: 1.3.11(vue@3.5.6)
@@ -2851,14 +2848,6 @@ packages:
'@intlify/shared': 9.1.9
'@intlify/vue-devtools': 9.1.9
/@intlify/core-base@9.14.0:
resolution: {integrity: sha512-zJn0imh9HIsZZUtt9v8T16PeVstPv6bP2YzlrYJwoF8F30gs4brZBwW2KK6EI5WYKFi3NeqX6+UU4gniz5TkGg==}
engines: {node: '>= 16'}
dependencies:
'@intlify/message-compiler': 9.14.0
'@intlify/shared': 9.14.0
dev: false
/@intlify/devtools-if@9.1.9:
resolution: {integrity: sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==}
engines: {node: '>= 10'}
@@ -2873,14 +2862,6 @@ packages:
'@intlify/shared': 9.1.9
source-map: 0.6.1
/@intlify/message-compiler@9.14.0:
resolution: {integrity: sha512-sXNsoMI0YsipSXW8SR75drmVK56tnJHoYbPXUv2Cf9lz6FzvwsosFm6JtC1oQZI/kU+n7qx0qRrEWkeYFTgETA==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 9.14.0
source-map-js: 1.2.1
dev: false
/@intlify/message-resolver@9.1.9:
resolution: {integrity: sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==}
engines: {node: '>= 10'}
@@ -2897,11 +2878,6 @@ packages:
resolution: {integrity: sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==}
engines: {node: '>= 10'}
/@intlify/shared@9.14.0:
resolution: {integrity: sha512-r+N8KRQL7LgN1TMTs1A2svfuAU0J94Wu9wWdJVJqYsoMMLIeJxrPjazihfHpmJqfgZq0ah3Y9Q4pgWV2O90Fyg==}
engines: {node: '>= 16'}
dev: false
/@intlify/vue-devtools@9.1.9:
resolution: {integrity: sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==}
engines: {node: '>= 10'}
@@ -9705,18 +9681,6 @@ packages:
- supports-color
dev: true
/vue-i18n@9.14.0(vue@3.5.6):
resolution: {integrity: sha512-LxmpRuCt2rI8gqU+kxeflRZMQn4D5+4M3oP3PWZdowW/ePJraHqhF7p4CuaME52mUxdw3Mmy2yAUKgfZYgCRjA==}
engines: {node: '>= 16'}
peerDependencies:
vue: ^3.0.0
dependencies:
'@intlify/core-base': 9.14.0
'@intlify/shared': 9.14.0
'@vue/devtools-api': 6.6.4
vue: 3.5.6(typescript@4.9.5)
dev: false
/vue-router@4.4.5(vue@3.5.6):
resolution: {integrity: sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==}
peerDependencies:

View File

@@ -0,0 +1,18 @@
/**
* 响应码枚举
*/
export const enum ResultCodeEnum {
/**
* 成功
*/
SUCCESS = "00000",
/**
* 错误
*/
ERROR = "B0001",
/**
* 令牌无效或过期
*/
TOKEN_INVALID = "A0230",
}

View File

@@ -1,6 +1,7 @@
import { defineStore } from "pinia";
import AuthAPI from "@/api/auth";
import UserAPI, { UserInfo } from "@/api/user";
import { setToken, clearToken } from "@/utils/auth";
export const useUserStore = defineStore("user", () => {
// 确保 token 是响应式的
@@ -8,10 +9,22 @@ export const useUserStore = defineStore("user", () => {
const userInfo = ref<UserInfo | null>(null);
// 登录
const login = async (username: string, password: string) => {
const { tokenType, accessToken } = await AuthAPI.login(username, password);
token.value = `${tokenType} ${accessToken}`; // Bearer token
uni.setStorageSync("token", token.value);
const login = (username: string, password: string) => {
AuthAPI.login(username, password)
.then((res) => {
token.value = ` ${res.accessToken}`; // Bearer token
setToken(token.value);
})
.catch((error) => {
if (error.action === "TOKEN_INVALID") {
// 处理 Token 失效,比如弹出登录提示框,而不是直接跳转
console.log("Token 已失效,请重新登录");
// 例如uni.navigateTo({ url: '/pages/login/index' });
} else {
// 处理其他错误
console.error("请求失败", error.message);
}
});
};
// 获取用户信息
@@ -25,7 +38,7 @@ export const useUserStore = defineStore("user", () => {
await AuthAPI.logout();
userInfo.value = null;
token.value = ""; // 清空 token
uni.removeStorageSync("token"); // 从本地缓存移除 token
clearToken(); // 从本地缓存移除 token
};
return {

19
src/utils/auth.ts Normal file
View File

@@ -0,0 +1,19 @@
const TOKEN_KEY = "app-token";
function getToken(): string {
return uni.getStorageSync(TOKEN_KEY) || "";
}
function setToken(token: string) {
return uni.setStorageSync(TOKEN_KEY, token);
}
function clearToken() {
return uni.removeStorageSync(TOKEN_KEY);
}
function isLogin(): boolean {
return !!getToken();
}
export { getToken, setToken, clearToken, isLogin };

View File

@@ -1,20 +1,48 @@
import { getToken, clearToken } from "@/utils/auth";
import { ResultCodeEnum } from "@/enums/ResultCodeEnum";
export default function request<T>(options: UniApp.RequestOptions): Promise<T> {
const token = uni.getStorageSync("token"); // 从本地缓存获取 token
// H5 使用 VITE_APP_BASE_API 作为代理路径,其他平台使用 VITE_APP_API_URL 作为请求路径
let baseApi = import.meta.env.VITE_APP_API_URL;
// #ifdef H5
baseApi = import.meta.env.VITE_APP_BASE_API;
// #endif
return new Promise((resolve, reject) => {
uni.request({
...options,
url: `${import.meta.env.VITE_APP_BASE_API}${options.url}`,
url: `${baseApi}${options.url}`,
header: {
...options.header,
Authorization: token,
Authorization: getToken() ? `Bearer ${getToken()}` : "", // 添加 Bearer 前缀
},
success: (response) => {
console.log("success response", response);
const resData = response.data as ResponseData<T>;
// 业务状态码 00000 表示成功
if (resData.code === "00000") {
if (resData.code === ResultCodeEnum.SUCCESS) {
resolve(resData.data);
} else {
}
// 令牌失效或过期处理
else if (resData.code === ResultCodeEnum.TOKEN_INVALID) {
uni.showToast({
title: resData.msg || "令牌无效或过期",
icon: "none",
duration: 2000,
});
clearToken();
// 此处不强制跳转到登录页,可以让调用方决定下一步操作
reject({
message: resData.msg || "令牌无效或过期",
code: resData.code,
action: "TOKEN_INVALID", // 提供一个 action 用于后续调用方判断
});
}
// 其他业务处理失败
else {
uni.showToast({
title: resData.msg || "业务处理失败",
icon: "none",
@@ -27,6 +55,7 @@ export default function request<T>(options: UniApp.RequestOptions): Promise<T> {
}
},
fail: (error) => {
console.log("fail error", error);
uni.showToast({
title: "网络请求失败",
icon: "none",

View File

@@ -11,6 +11,7 @@ export default defineConfig(async ({ mode }: ConfigEnv): Promise<UserConfig> =>
host: "0.0.0.0",
port: +env.VITE_APP_PORT,
open: true,
// 代理配置只在 H5浏览器开发时生效。 其他平台如小程序、App在开发时不使用 Vite 的开发服务器,它们直接运行在各自的环境中。
proxy: {
[env.VITE_APP_BASE_API]: {
changeOrigin: true,