diff --git a/apps/src/api/request.ts b/apps/src/api/request.ts index 27e3cdb..5b1b17e 100644 --- a/apps/src/api/request.ts +++ b/apps/src/api/request.ts @@ -13,6 +13,7 @@ import { useAccessStore } from '@vben/stores'; import { message } from 'antdv-next'; +import { getDevApiBaseURL } from '#/config/dev-api-switch'; import { useAuthStore } from '#/store'; const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); @@ -48,6 +49,10 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) { // 请求头处理 client.addRequestInterceptor({ fulfilled: async (config) => { + const devBaseURL = getDevApiBaseURL(String(config.url ?? '')); + if (devBaseURL) { + config.baseURL = devBaseURL; + } const accessStore = useAccessStore(); const accessToken = accessStore.accessToken; if (accessToken) { diff --git a/apps/src/components/dev-api-switch.vue b/apps/src/components/dev-api-switch.vue new file mode 100644 index 0000000..ae4cd87 --- /dev/null +++ b/apps/src/components/dev-api-switch.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/apps/src/config/dev-api-switch.ts b/apps/src/config/dev-api-switch.ts new file mode 100644 index 0000000..2d1907e --- /dev/null +++ b/apps/src/config/dev-api-switch.ts @@ -0,0 +1,79 @@ +export const DEV_API_SWITCH_STORAGE_KEY = '__chatapp3_admin_dev_api_target__'; + +export const DEV_API_TARGETS = { + internal: 'internal', + prod: 'prod', +} as const; + +export type DevApiTarget = + (typeof DEV_API_TARGETS)[keyof typeof DEV_API_TARGETS]; + +export const DEV_API_OPTIONS: Array<{ + label: string; + value: DevApiTarget; +}> = [ + { + label: '内网 API', + value: DEV_API_TARGETS.internal, + }, + { + label: '线上 API', + value: DEV_API_TARGETS.prod, + }, +]; + +const DEV_API_PREFIX_MAP: Record = { + [DEV_API_TARGETS.internal]: '/__dev_api_internal__', + [DEV_API_TARGETS.prod]: '/__dev_api_prod__', +}; + +function canUseStorage() { + return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined'; +} + +export function isDevApiSwitchEnabled() { + return import.meta.env.DEV; +} + +export function normalizeDevApiTarget(value: null | string | undefined): DevApiTarget { + return value === DEV_API_TARGETS.prod + ? DEV_API_TARGETS.prod + : DEV_API_TARGETS.internal; +} + +export function getStoredDevApiTarget(): DevApiTarget { + if (!isDevApiSwitchEnabled() || !canUseStorage()) { + return DEV_API_TARGETS.internal; + } + return normalizeDevApiTarget( + window.localStorage.getItem(DEV_API_SWITCH_STORAGE_KEY), + ); +} + +export function setStoredDevApiTarget(target: DevApiTarget) { + if (!isDevApiSwitchEnabled() || !canUseStorage()) { + return; + } + window.localStorage.setItem( + DEV_API_SWITCH_STORAGE_KEY, + normalizeDevApiTarget(target), + ); +} + +export function getDevApiTargetLabel(target: DevApiTarget) { + return ( + DEV_API_OPTIONS.find((item) => item.value === target)?.label || + '内网 API' + ); +} + +export function getDevApiBaseURL(url?: string) { + if (!isDevApiSwitchEnabled()) { + return null; + } + const normalizedUrl = String(url || ''); + if (/^https?:\/\//.test(normalizedUrl)) { + return null; + } + return DEV_API_PREFIX_MAP[getStoredDevApiTarget()]; +} diff --git a/apps/src/layouts/basic.vue b/apps/src/layouts/basic.vue index 8ce249e..ae6f6bb 100644 --- a/apps/src/layouts/basic.vue +++ b/apps/src/layouts/basic.vue @@ -17,8 +17,10 @@ import { useAccessStore, useUserStore } from '@vben/stores'; import { $t } from '#/locales'; import { useAuthStore } from '#/store'; +import DevApiSwitch from '#/components/dev-api-switch.vue'; import LoginForm from '#/views/_core/authentication/login.vue'; +const isDev = import.meta.env.DEV; const notifications = ref([ { id: 1, @@ -141,6 +143,9 @@ watch(