diff --git a/.env.development b/.env.development
index 9c106c8..2a114bf 100644
--- a/.env.development
+++ b/.env.development
@@ -8,6 +8,8 @@ VITE_USE_MOCK=false
VITE_USE_PROXY=true
# base api
-VITE_BASE_API='/store'
+VITE_BASE_API='/api'
+VITE_BASE_API_1='/api1'
VITE_ADMIN_API='/admin'
+VITE_ADMIN_API_1='/admin1'
diff --git a/.env.production b/.env.production
index 91b5a7e..3f1e58d 100644
--- a/.env.production
+++ b/.env.production
@@ -6,8 +6,10 @@ VITE_USE_MOCK=false
# base api
VITE_BASE_API='//www.wanzhuanyongcheng.cn/store'
+VITE_BASE_API_1='//api.gxwzwh.com/store'
VITE_ADMIN_API='//www.wanzhuanyongcheng.cn'
+VITE_ADMIN_API_1='//api.gxwzwh.com'
# 是否启用压缩
VITE_USE_COMPRESS=true
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index bf2de99..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml
-# 基于编辑器的 HTTP 客户端请求
-/httpRequests/
diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml
deleted file mode 100644
index 04ede99..0000000
--- a/.idea/git_toolbox_blame.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/jdt-mer.iml b/.idea/jdt-mer.iml
deleted file mode 100644
index 0b872d8..0000000
--- a/.idea/jdt-mer.iml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 8aab5b9..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index c8397c9..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/constant.js b/build/constant.js
index 2aa3a0d..c95065a 100644
--- a/build/constant.js
+++ b/build/constant.js
@@ -2,37 +2,36 @@ export const OUTPUT_DIR = 'dist'
export const PROXY_CONFIG = {
/**
- * @desc 替换匹配值
- * @请求路径 http://localhost:3100/api/user
- * @转发路径 http://localhost:8080/user
+ * @desc 主接口代理
+ * @请求路径 http://localhost:3100/api/login
+ * @转发路径 http://localhost:3000/api/login
*/
- '/store': {
+ '/api': {
target: 'https://test.wanzhuanyongcheng.cn',
changeOrigin: true,
- // rewrite: (path) => path.replace(new RegExp('^/api'), ''),
+ rewrite: (path) => path.replace(/^\/api/, '/store'),
},
+ /**
+ * @desc 备用接口代理
+ * @请求路径 http://localhost:3100/api1/login
+ * @转发路径 http://localhost:3001/api/login
+ */
+ '/api1': {
+ target: 'https://api.gxwzwh.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api1/, '/store'),
+ },
+ /**
+ * @desc null
+ */
'/admin': {
target: 'https://test.wanzhuanyongcheng.cn',
changeOrigin: true,
- // rewrite: (path) => path.replace(new RegExp('^/admin'), ''),
+ rewrite: (path) => path.replace(/^\/admin/, ''),
+ },
+ '/admin1': {
+ target: 'https://api.gxwzwh.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/admin1/, ''),
},
- /**
- * @desc 不替换匹配值
- * @请求路径 http://localhost:3100/api/v2/user
- * @转发路径 http://localhost:8080/api/v2/user
- */
- // '/api/v2': {
- // target: 'http://localhost:8080',
- // changeOrigin: true,
- // },
- /**
- * @desc 替换部分匹配值
- * @请求路径 http://localhost:3100/api/v3/user
- * @转发路径 http://localhost:8080/user
- */
- // '/api/v3': {
- // target: 'http://localhost:8080',
- // changeOrigin: true,
- // rewrite: (path) => path.replace(new RegExp('^/api'), ''),
- // },
}
diff --git a/src/main.js b/src/main.js
index 2390124..82b6a92 100644
--- a/src/main.js
+++ b/src/main.js
@@ -9,10 +9,14 @@ import { setupRouter } from '@/router'
import { setupStore } from '@/store'
import App from './App.vue'
import { setupNaiveDiscreteApi } from './utils'
+import { initApiEndpoint } from '@/utils/api-config'
async function setupApp() {
const app = createApp(App)
+ // 初始化接口配置
+ initApiEndpoint()
+
setupStore(app)
setupNaiveDiscreteApi()
diff --git a/src/router/guard/permission-guard.js b/src/router/guard/permission-guard.js
index 165788e..26552c5 100644
--- a/src/router/guard/permission-guard.js
+++ b/src/router/guard/permission-guard.js
@@ -1,4 +1,5 @@
import { getToken, refreshAccessToken, isNullOrWhitespace } from '@/utils'
+import { addDynamicRoutes } from '@/router'
const WHITE_LIST = ['/login', '/404']
export function createPermissionGuard(router) {
@@ -17,6 +18,20 @@ export function createPermissionGuard(router) {
/** 有token的情况 */
if (to.path === '/login') return { path: '/' }
+ // 确保动态路由已加载
+ if (token && !router.hasRoute('Dashboard')) {
+ try {
+ await addDynamicRoutes()
+ // 如果当前路径不存在,重定向到工作台
+ if (to.path !== '/' && !router.hasRoute(to.name)) {
+ return { path: '/workbench' }
+ }
+ } catch (error) {
+ console.error('动态路由加载失败:', error)
+ return { path: '/login' }
+ }
+ }
+
refreshAccessToken()
return true
})
diff --git a/src/router/index.js b/src/router/index.js
index d5439a6..6ee0308 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -42,13 +42,45 @@ export async function addDynamicRoutes() {
const permissionStore = usePermissionStore()
!userStore.userId && (await userStore.getUserInfo())
const accessRoutes = permissionStore.generateRoutes(userStore.role)
+
+ // 确保路由按正确顺序添加
accessRoutes.forEach((route) => {
- !router.hasRoute(route.name) && router.addRoute(route)
+ if (!router.hasRoute(route.name)) {
+ router.addRoute(route)
+ }
})
- router.hasRoute(EMPTY_ROUTE.name) && router.removeRoute(EMPTY_ROUTE.name)
+
+ // 移除空路由,添加404路由
+ if (router.hasRoute(EMPTY_ROUTE.name)) {
+ router.removeRoute(EMPTY_ROUTE.name)
+ }
router.addRoute(NOT_FOUND_ROUTE)
+
+ // 确保根路径重定向到工作台
+ if (!router.hasRoute('Dashboard')) {
+ const workbenchRoute = {
+ name: 'Dashboard',
+ path: '/',
+ component: () => import('@/layout/index.vue'),
+ redirect: '/workbench',
+ children: [
+ {
+ name: 'Workbench',
+ path: 'workbench',
+ component: () => import('@/views/workbench/index.vue'),
+ meta: {
+ title: '工作台',
+ icon: 'mdi:index',
+ order: 0,
+ },
+ },
+ ],
+ }
+ router.addRoute(workbenchRoute)
+ }
} catch (error) {
console.error(error)
+ throw error
}
}
diff --git a/src/store/modules/user/index.js b/src/store/modules/user/index.js
index ee45919..aea7fc9 100644
--- a/src/store/modules/user/index.js
+++ b/src/store/modules/user/index.js
@@ -18,10 +18,7 @@ export const useUserStore = defineStore('user', {
return this.userInfo?.name
},
avatar() {
- return (
- this.userInfo?.avatar ||
- 'https://pic3.58cdn.com.cn/nowater/webim/big/n_v21bc7874294754e63a22b80febac9cf51.jpg'
- )
+ return this.userInfo?.avatar || 'https://v2.xxapi.cn/api/head?return=302'
},
role() {
return this.userInfo?.role || []
diff --git a/src/utils/api-config.js b/src/utils/api-config.js
new file mode 100644
index 0000000..0b6214b
--- /dev/null
+++ b/src/utils/api-config.js
@@ -0,0 +1,65 @@
+// 判断是否为开发环境
+const isDev = import.meta.env.DEV
+
+// API接口线路配置管理
+export const API_ENDPOINTS = {
+ primary: {
+ name: '主要线路',
+ baseURL: import.meta.env.VITE_BASE_API,
+ base_admin_url: import.meta.env.VITE_ADMIN_API,
+ timeout: 10000,
+ },
+ backup1: {
+ name: '备用线路',
+ baseURL: import.meta.env.VITE_BASE_API_1,
+ base_admin_url: import.meta.env.VITE_ADMIN_API_1,
+ timeout: 10000,
+ },
+}
+
+// 调试信息
+console.log('=== 多接口配置信息 ===')
+console.log('当前环境:', isDev ? '开发环境' : '生产环境')
+console.log('API配置:', API_ENDPOINTS)
+console.log('环境变量 VITE_BASE_API:', import.meta.env.VITE_BASE_API)
+console.log('环境变量 VITE_BASE_API_1:', import.meta.env.VITE_BASE_API_1)
+console.log('环境变量 VITE_BASE_ADMIN:', import.meta.env.VITE_ADMIN_API)
+console.log('环境变量 VITE_BASE_ADMIN_1:', import.meta.env.VITE_ADMIN_API_1)
+console.log('是否使用代理:', import.meta.env.VITE_USE_PROXY)
+
+// 当前使用的接口线路
+let currentEndpoint = 'primary'
+
+// 获取当前接口配置
+export function getCurrentEndpoint() {
+ return {
+ key: currentEndpoint,
+ ...API_ENDPOINTS[currentEndpoint],
+ }
+}
+
+// 设置当前接口
+export function setCurrentEndpoint(endpoint) {
+ if (API_ENDPOINTS[endpoint]) {
+ currentEndpoint = endpoint
+ localStorage.setItem('api_endpoint', endpoint)
+ return true
+ }
+ return false
+}
+
+// 获取所有可用接口
+export function getAvailableEndpoints() {
+ return Object.entries(API_ENDPOINTS).map(([key, config]) => ({
+ key,
+ ...config,
+ }))
+}
+
+// 初始化时从本地存储恢复接口选择
+export function initApiEndpoint() {
+ const savedEndpoint = localStorage.getItem('api_endpoint')
+ if (savedEndpoint && API_ENDPOINTS[savedEndpoint]) {
+ currentEndpoint = savedEndpoint
+ }
+}
diff --git a/src/utils/http/index.js b/src/utils/http/index.js
index 6fa57ef..f273c78 100644
--- a/src/utils/http/index.js
+++ b/src/utils/http/index.js
@@ -1,5 +1,6 @@
import axios from 'axios'
import { resReject, resResolve, reqReject, reqResolve } from './interceptors'
+import { getCurrentEndpoint, getAvailableEndpoints } from '../api-config'
export function createAxios(options = {}) {
const defaultOptions = {
@@ -14,6 +15,114 @@ export function createAxios(options = {}) {
return service
}
-export const request = createAxios({
- baseURL: import.meta.env.VITE_BASE_API,
-})
+// 检测是否为admin类接口
+function isAdminEndpoint(url) {
+ console.log('url', url)
+ // 检查URL是否包含admin相关路径
+ return url.includes('/admin')
+}
+
+// 根据URL类型选择对应的baseURL
+function getBaseURLByUrlType(endpoint, url) {
+ console.log('endpoint', endpoint)
+ console.log('url', url)
+ if (isAdminEndpoint(url)) {
+ return endpoint.base_admin_url || endpoint.baseURL
+ }
+ return endpoint.baseURL
+}
+
+// 创建支持多接口的请求实例
+export function createMultiEndpointRequest() {
+ let instances = null
+
+ // 延迟创建axios实例
+ function ensureInstances() {
+ if (!instances) {
+ instances = {}
+ const endpoints = getAvailableEndpoints()
+
+ console.log('创建axios实例,接口列表:', endpoints)
+
+ endpoints.forEach((endpoint) => {
+ console.log(`创建实例 ${endpoint.key}:`, endpoint.baseURL)
+ instances[endpoint.key] = createAxios({
+ baseURL: isAdminEndpoint(endpoint.baseURL) ? endpoint.base_admin_url : endpoint.baseURL,
+ timeout: endpoint.timeout,
+ })
+ })
+ }
+ return instances
+ }
+
+ return {
+ // 使用当前选中的接口发送请求
+ async request(config) {
+ const currentEndpoint = getCurrentEndpoint()
+ const url = config.url || ''
+
+ // 根据URL类型选择baseURL
+ const baseURL = getBaseURLByUrlType(currentEndpoint, url)
+
+ console.log('当前接口配置:', currentEndpoint)
+ console.log('请求URL:', url)
+ console.log('是否为admin接口:', isAdminEndpoint(url))
+ console.log('选择的baseURL:', baseURL)
+
+ // 创建临时axios实例
+ const instance = createAxios({
+ baseURL: baseURL,
+ timeout: currentEndpoint.timeout,
+ })
+
+ console.log('请求配置:', config)
+
+ return await instance(config)
+ },
+
+ // 获取当前接口实例
+ getCurrentInstance() {
+ const instances = ensureInstances()
+ const currentEndpoint = getCurrentEndpoint()
+ return instances[currentEndpoint.key]
+ },
+
+ // 获取所有接口实例
+ getAllInstances() {
+ return ensureInstances()
+ },
+ }
+}
+
+// export const request = createAxios({
+// baseURL: import.meta.env.VITE_BASE_API,
+// })
+
+// 支持多接口的请求实例
+export const multiRequest = createMultiEndpointRequest()
+
+// 创建自动适配多接口的request实例
+const multiEndpointInstance = createMultiEndpointRequest()
+
+// 创建支持axios方法的request实例
+export const request = {
+ // 基础请求方法
+ request: (config) => multiEndpointInstance.request(config),
+
+ // 自动适配axios方法
+ get: (url, config = {}) => multiEndpointInstance.request({ method: 'get', url, ...config }),
+ post: (url, data, config = {}) =>
+ multiEndpointInstance.request({ method: 'post', url, data, ...config }),
+ put: (url, data, config = {}) =>
+ multiEndpointInstance.request({ method: 'put', url, data, ...config }),
+ delete: (url, config = {}) => multiEndpointInstance.request({ method: 'delete', url, ...config }),
+ patch: (url, data, config = {}) =>
+ multiEndpointInstance.request({ method: 'patch', url, data, ...config }),
+ head: (url, config = {}) => multiEndpointInstance.request({ method: 'head', url, ...config }),
+ options: (url, config = {}) =>
+ multiEndpointInstance.request({ method: 'options', url, ...config }),
+
+ // 获取当前接口实例(用于直接访问axios实例)
+ getCurrentInstance: () => multiEndpointInstance.getCurrentInstance(),
+ getAllInstances: () => multiEndpointInstance.getAllInstances(),
+}
diff --git a/src/utils/http/interceptors.js b/src/utils/http/interceptors.js
index 44ad5e4..3fc651a 100644
--- a/src/utils/http/interceptors.js
+++ b/src/utils/http/interceptors.js
@@ -2,13 +2,11 @@ import { getToken } from '@/utils'
import { resolveResError } from './helpers'
export function reqResolve(config) {
- if (config.url.includes('/admin')) {
- config.url = config.url.replace(new RegExp('^/admin'), '')
- console.log(config)
- config.baseURL = import.meta.env.VITE_ADMIN_API
- } else {
- config.baseURL = import.meta.env.VITE_BASE_API
- }
+ // if (config.url.includes('/admin')) {
+ // config.url = config.url.replace(new RegExp('^/admin'), '')
+ // console.log(config)
+ // config.baseURL = import.meta.env.VITE_ADMIN_API
+ // }
// 处理不需要token的请求
if (config.noNeedToken) {
return config
diff --git a/src/views/login/api.js b/src/views/login/api.js
index 940f30b..5054509 100644
--- a/src/views/login/api.js
+++ b/src/views/login/api.js
@@ -1,5 +1,13 @@
-import { request } from '@/utils'
+import { request, multiRequest } from '@/utils'
export default {
login: (data) => request.post('/login', data, { noNeedToken: true }),
+ // 使用多接口的登录方法
+ loginWithMultiEndpoint: (data) =>
+ multiRequest.request({
+ method: 'post',
+ url: '/login',
+ data,
+ noNeedToken: true,
+ }),
}
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index 31e3c7f..838243a 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -14,7 +14,17 @@
{{ title }}
-
+
+
+
+
+
-
+
{
console.log(query)
$message.success('登录成功')
setToken(query.tk)
+ setCurrentEndpoint(query.api)
window.localStorage.setItem('type', query.type)
await addDynamicRoutes()
if (query.redirect) {
@@ -113,6 +130,39 @@ function initLoginInfo() {
const isRemember = useStorage('isRemember', false)
const loading = ref(false)
+
+// 接口线路相关
+const selectedEndpoint = ref('primary')
+const endpointOptions = ref([])
+
+// 初始化接口配置
+initApiEndpoint()
+const currentEndpoint = getCurrentEndpoint()
+selectedEndpoint.value = currentEndpoint.key
+
+// 加载接口选项
+function loadEndpointOptions() {
+ const endpoints = getAvailableEndpoints()
+ endpointOptions.value = endpoints.map((endpoint) => ({
+ label: endpoint.name,
+ value: endpoint.key,
+ }))
+}
+
+// 处理接口切换
+function handleEndpointChange(value) {
+ if (setCurrentEndpoint(value)) {
+ selectedEndpoint.value = value
+ $message.success(`已切换到${endpointOptions.value.find((opt) => opt.value === value)?.label}`)
+ } else {
+ $message.error('接口切换失败')
+ }
+}
+
+// 初始化
+onMounted(() => {
+ loadEndpointOptions()
+})
async function handleLogin() {
const { name, password } = loginInfo.value
if (!name || !password) {
@@ -122,7 +172,14 @@ async function handleLogin() {
try {
loading.value = true
$message.loading('正在验证...')
- const res = await api.login({ phone: name, password: password.toString() })
+
+ console.log('开始登录请求...')
+ console.log('登录数据:', { phone: name, password: password.toString() })
+ console.log('当前选中接口:', selectedEndpoint.value)
+
+ const res = await api.loginWithMultiEndpoint({ phone: name, password: password.toString() })
+
+ console.log('登录响应:', res)
$message.success('登录成功')
setToken(res.data.token)
window.localStorage.setItem('type', res.data.type)
@@ -140,7 +197,7 @@ async function handleLogin() {
router.push('/')
}
} catch (error) {
- console.error(error)
+ console.error('登录请求失败:', error)
$message.removeMessage()
}
loading.value = false
diff --git a/vite.config.js b/vite.config.js
index dcf1473..1575c2f 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -20,6 +20,14 @@ export default defineConfig(({ command, mode }) => {
VITE_SENTRY,
} = viteEnv
+ // 调试代理配置
+ console.log('=== Vite代理配置调试 ===')
+ console.log('VITE_USE_PROXY:', VITE_USE_PROXY)
+ console.log('VITE_BASE_API:', VITE_BASE_API)
+ console.log('VITE_ADMIN_API:', VITE_ADMIN_API)
+ console.log('PROXY_CONFIG:', PROXY_CONFIG)
+ console.log('所有环境变量:', viteEnv)
+
return {
base: VITE_PUBLIC_PATH || '/',
resolve: {
@@ -34,12 +42,12 @@ export default defineConfig(({ command, mode }) => {
https: false,
port: VITE_PORT,
open: false,
- proxy: VITE_USE_PROXY
- ? {
- [VITE_BASE_API]: PROXY_CONFIG[VITE_BASE_API],
- [VITE_ADMIN_API]: PROXY_CONFIG[VITE_ADMIN_API],
- }
- : undefined,
+ proxy: {
+ '/api1': PROXY_CONFIG['/api1'],
+ '/api': PROXY_CONFIG['/api'],
+ '/admin1': PROXY_CONFIG['/admin1'],
+ '/admin': PROXY_CONFIG['/admin'],
+ },
},
build: {
target: 'es2015',