diff --git a/src/components/Header.vue b/src/components/Header.vue index f508792..9fa7e44 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -14,7 +14,7 @@ 我的域名 - 退出 + 退出 @@ -23,6 +23,18 @@ diff --git a/src/config/host.js b/src/config/host.js new file mode 100644 index 0000000..04fefa3 --- /dev/null +++ b/src/config/host.js @@ -0,0 +1 @@ +export const host = '//www.kuailelunwen.com'; \ No newline at end of file diff --git a/src/main.js b/src/main.js index 2d49172..afa234b 100755 --- a/src/main.js +++ b/src/main.js @@ -17,22 +17,28 @@ import HeaderIcon from './utils/headerIcon' // 复制到粘贴板 import clipboard from '@/utils/dirClipBoard'; import { modernCopyToClipboard } from '@/utils/clipboard'; +//登陆 +import { autoLoginByToken } from '@/utils/login' // 复制 Vue.prototype.$copy = modernCopyToClipboard; Vue.prototype.$loadingFn = LoadingService; Vue.config.productionTip = false; // 请求 +import { host } from '@/config/host'; +Vue.prototype.$host = host Vue.prototype.$http = request; -Vue.prototype.$token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3NTI2NDY1NDUsIm5iZiI6MTc1MjY0NjU0NSwiZXhwIjoxNzU1MjM4NTQ1LCJ1c2VyIjoic3VidXNlciIsImxvZ2luX3R5cGUiOjAsImFpZCI6IjEifQ.G-Is-x9qPMiV_urOlDPQVRjfAIozySxL5EK2k82d46k', +Vue.prototype.$token = '' Vue.use(ElementUI); Vue.use(GuipMessage) Vue.use(clipboard); Vue.directive('clickaway', clickaway); Vue.mixin(HeaderIcon) -new Vue({ - router, - store, - render: h => h(App) -}).$mount('#app') - +// ✅ 自动登录后再启动应用 +autoLoginByToken().finally(() => { + new Vue({ + router, + store, + render: h => h(App) + }).$mount('#app') +}) diff --git a/src/router/index.js b/src/router/index.js index 21e5947..c97f1af 100755 --- a/src/router/index.js +++ b/src/router/index.js @@ -9,7 +9,7 @@ const whiteSecondSider = [ '/agent/siteAddFinally','/agent/siteServiceAdd' ]; const blackSliderList = [ - '/register', '/agent/siteAdd', '/franchise','/agent/siteServiceList', '/agent/siteTemplate','/agent/siteAddFinally','/agent/siteServiceAdd', '/agent/supplyList', + '/franchise', '/register', '/agent/siteAdd', '/agent/siteServiceList', '/agent/siteTemplate','/agent/siteAddFinally','/agent/siteServiceAdd', '/agent/supplyList', '/agent/domainList' , '/agent/noticeList' ]; @@ -310,7 +310,7 @@ const routes = [{ { path: '/franchise', name: '加盟', - component: () => import( /* webpackChunkName: "franchise" */ '../views/Franchise.vue'), + component: () => import( /* webpackChunkName: "franchise" */ '../views/agent/Franchise.vue'), meta: { hideBreadcrumb: true // 一级页面不显示面包屑 } diff --git a/src/utils/login.js b/src/utils/login.js new file mode 100644 index 0000000..269e119 --- /dev/null +++ b/src/utils/login.js @@ -0,0 +1,32 @@ +// utils/login.js + +import axios from 'axios' + +export async function autoLoginByToken() { + const urlParams = new URLSearchParams(window.location.search) + const token = urlParams.get('token') + + if (token) { + try { + const res = await axios.post('/agentnew/token_login', { token: token },{ + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + }) + if (res.data.status) { + // 可选:将 token 存入 localStorage + localStorage.setItem('token', res.data.data) + + const url = new URL(window.location.href); + url.searchParams.delete('token'); + window.location.replace(url.toString()); + return true + } else { + return false + } + } catch (e) { + console.error('请求异常', e) + } + } + return false +} diff --git a/src/utils/loginRefresh.js b/src/utils/loginRefresh.js new file mode 100644 index 0000000..5ec76bf --- /dev/null +++ b/src/utils/loginRefresh.js @@ -0,0 +1,46 @@ +let isRefreshing = false +let refreshSubscribers = [] + +function onRefreshed(newToken) { + refreshSubscribers.forEach(cb => cb(newToken)) + refreshSubscribers = [] +} + +function subscribeTokenRefresh(cb) { + refreshSubscribers.push(cb) +} + +/** + * 刷新 Token 并重新请求 + * @param {Object} originalRequest - 原始 axios 请求配置 + * @param {AxiosInstance} instance - axios 实例 + */ +export async function handleTokenRefresh(originalRequest, instance) { + if (isRefreshing) { + return new Promise(resolve => { + subscribeTokenRefresh(token => { + originalRequest.headers.Authorization = `Bearer ${token}` + resolve(instance(originalRequest)) + }) + }) + } + + isRefreshing = true + try { + const res = await instance.post('/agentnew/refresh_token') + const newToken = res.data + localStorage.setItem('token', newToken) + + isRefreshing = false + onRefreshed(newToken) + + originalRequest.headers.Authorization = `Bearer ${newToken}` + return instance(originalRequest) + } catch (err) { + isRefreshing = false + refreshSubscribers = [] + localStorage.removeItem('token') + window.location.href = this.$host; + return Promise.reject(err) + } +} diff --git a/src/utils/request.js b/src/utils/request.js index 2b81f4e..706c15c 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,5 +1,7 @@ // src/utils/request.js import axios from "axios"; +import { handleTokenRefresh } from '@/utils/loginRefresh'; +import { host } from '@/config/host'; // 创建 axios 实例 const service = axios.create({ @@ -8,6 +10,7 @@ const service = axios.create({ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + withCredentials: true }); // 请求拦截器 @@ -50,7 +53,15 @@ service.interceptors.response.use( switch (error.response.status) { case 401: // 未授权,跳转到登录页 - window.location.href = "/login"; + window.location.href = host; + break; + case 402: + // token失效 + // 防止无限刷新 + if (!error.config._retry) { + error.config._retry = true; + return handleTokenRefresh(error.config, service); // <<< 封装方法 + } break; case 404: // 资源未找到