From 6b0da7e397ba138d54fa24e338a3bf82b78534a3 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Tue, 11 Nov 2025 13:41:14 +0800 Subject: [PATCH] feat: api config --- apps/web-tdesign/src/api/request.ts | 82 +++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/apps/web-tdesign/src/api/request.ts b/apps/web-tdesign/src/api/request.ts index 86b181d33..3ecbee4d4 100644 --- a/apps/web-tdesign/src/api/request.ts +++ b/apps/web-tdesign/src/api/request.ts @@ -3,7 +3,7 @@ */ import type { RequestClientOptions } from '@vben/request'; -import { useAppConfig } from '@vben/hooks'; +import { isTenantEnable, useAppConfig } from '@vben/hooks'; import { preferences } from '@vben/preferences'; import { authenticateResponseInterceptor, @@ -12,6 +12,7 @@ import { RequestClient, } from '@vben/request'; import { useAccessStore } from '@vben/stores'; +import { createApiEncrypt } from '@vben/utils'; import { message } from '#/adapter/tdesign'; import { useAuthStore } from '#/store'; @@ -19,6 +20,8 @@ import { useAuthStore } from '#/store'; import { refreshTokenApi } from './core'; const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); +const tenantEnable = isTenantEnable(); +const apiEncrypt = createApiEncrypt(import.meta.env); function createRequestClient(baseURL: string, options?: RequestClientOptions) { const client = new RequestClient({ @@ -49,8 +52,16 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { */ async function doRefreshToken() { const accessStore = useAccessStore(); - const resp = await refreshTokenApi(); - const newToken = resp.data; + const refreshToken = accessStore.refreshToken as string; + if (!refreshToken) { + throw new Error('Refresh token is null!'); + } + const resp = await refreshTokenApi(refreshToken); + const newToken = resp?.data?.data?.accessToken; + // add by 芋艿:这里一定要抛出 resp.data,从而触发 authenticateResponseInterceptor 中,刷新令牌失败!!! + if (!newToken) { + throw resp.data; + } accessStore.setAccessToken(newToken); return newToken; } @@ -66,10 +77,54 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { config.headers.Authorization = formatToken(accessStore.accessToken); config.headers['Accept-Language'] = preferences.app.locale; + // 添加租户编号 + config.headers['tenant-id'] = tenantEnable + ? accessStore.tenantId + : undefined; + // 只有登录时,才设置 visit-tenant-id 访问租户 + config.headers['visit-tenant-id'] = tenantEnable + ? accessStore.visitTenantId + : undefined; + + // 是否 API 加密 + if ((config.headers || {}).isEncrypt) { + try { + // 加密请求数据 + if (config.data) { + config.data = apiEncrypt.encryptRequest(config.data); + // 设置加密标识头 + config.headers[apiEncrypt.getEncryptHeader()] = 'true'; + } + } catch (error) { + console.error('请求数据加密失败:', error); + throw error; + } + } return config; }, }); + // API 解密响应拦截器 + client.addResponseInterceptor({ + fulfilled: (response) => { + // 检查是否需要解密响应数据 + const encryptHeader = apiEncrypt.getEncryptHeader(); + const isEncryptResponse = + response.headers[encryptHeader] === 'true' || + response.headers[encryptHeader.toLowerCase()] === 'true'; + if (isEncryptResponse && typeof response.data === 'string') { + try { + // 解密响应数据 + response.data = apiEncrypt.decryptResponse(response.data); + } catch (error) { + console.error('响应数据解密失败:', error); + throw new Error(`响应数据解密失败: ${(error as Error).message}`); + } + } + return response; + }, + }); + // 处理返回的响应数据格式 client.addResponseInterceptor( defaultResponseInterceptor({ @@ -96,7 +151,12 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg // 当前mock接口返回的错误字段是 error 或者 message const responseData = error?.response?.data ?? {}; - const errorMessage = responseData?.error ?? responseData?.message ?? ''; + const errorMessage = + responseData?.error ?? responseData?.message ?? responseData.msg ?? ''; + // add by 芋艿:特殊:避免 401 “账号未登录”,重复提示。因为,此时会跳转到登录界面,只需提示一次!!! + if (error?.data?.code === 401) { + return; + } // 如果没有错误信息,则会根据状态码进行提示 message.error(errorMessage || msg); }), @@ -110,3 +170,17 @@ export const requestClient = createRequestClient(apiURL, { }); export const baseRequestClient = new RequestClient({ baseURL: apiURL }); +baseRequestClient.addRequestInterceptor({ + fulfilled: (config) => { + const accessStore = useAccessStore(); + // 添加租户编号 + config.headers['tenant-id'] = tenantEnable + ? accessStore.tenantId + : undefined; + // 只有登录时,才设置 visit-tenant-id 访问租户 + config.headers['visit-tenant-id'] = tenantEnable + ? accessStore.visitTenantId + : undefined; + return config; + }, +});