Browse Source

登陆权限相关

pull/97/head
pengda 1 month ago
parent
commit
34c21777a4
  1. 14
      src/components/Header.vue
  2. 1
      src/config/host.js
  3. 20
      src/main.js
  4. 4
      src/router/index.js
  5. 32
      src/utils/login.js
  6. 46
      src/utils/loginRefresh.js
  7. 13
      src/utils/request.js

14
src/components/Header.vue

@ -14,7 +14,7 @@
</div> </div>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item><a href="/agent/domainList" target="_blank">我的域名</a></el-dropdown-item> <el-dropdown-item><a href="/agent/domainList" target="_blank">我的域名</a></el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item> <el-dropdown-item><span @click="loginOut">退出</span></el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
@ -23,6 +23,18 @@
<script> <script>
export default { export default {
methods: { methods: {
loginOut(){
this.$http('POST', '/agentnew/login_out', {}).then(response => {
if(response.status){
localStorage.removeItem('token')
window.location.href = this.$host;
}else{
this.$message.error(response.data.info)
}
}).catch(error => {
console.error(error, 'error')
})
}
} }
} }
</script> </script>

1
src/config/host.js

@ -0,0 +1 @@
export const host = '//www.kuailelunwen.com';

20
src/main.js

@ -17,22 +17,28 @@ import HeaderIcon from './utils/headerIcon'
// 复制到粘贴板 // 复制到粘贴板
import clipboard from '@/utils/dirClipBoard'; import clipboard from '@/utils/dirClipBoard';
import { modernCopyToClipboard } from '@/utils/clipboard'; import { modernCopyToClipboard } from '@/utils/clipboard';
//登陆
import { autoLoginByToken } from '@/utils/login'
// 复制 // 复制
Vue.prototype.$copy = modernCopyToClipboard; Vue.prototype.$copy = modernCopyToClipboard;
Vue.prototype.$loadingFn = LoadingService; Vue.prototype.$loadingFn = LoadingService;
Vue.config.productionTip = false; Vue.config.productionTip = false;
// 请求 // 请求
import { host } from '@/config/host';
Vue.prototype.$host = host
Vue.prototype.$http = request; Vue.prototype.$http = request;
Vue.prototype.$token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3NTI2NDY1NDUsIm5iZiI6MTc1MjY0NjU0NSwiZXhwIjoxNzU1MjM4NTQ1LCJ1c2VyIjoic3VidXNlciIsImxvZ2luX3R5cGUiOjAsImFpZCI6IjEifQ.G-Is-x9qPMiV_urOlDPQVRjfAIozySxL5EK2k82d46k', Vue.prototype.$token = ''
Vue.use(ElementUI); Vue.use(ElementUI);
Vue.use(GuipMessage) Vue.use(GuipMessage)
Vue.use(clipboard); Vue.use(clipboard);
Vue.directive('clickaway', clickaway); Vue.directive('clickaway', clickaway);
Vue.mixin(HeaderIcon) Vue.mixin(HeaderIcon)
new Vue({ // ✅ 自动登录后再启动应用
router, autoLoginByToken().finally(() => {
store, new Vue({
render: h => h(App) router,
}).$mount('#app') store,
render: h => h(App)
}).$mount('#app')
})

4
src/router/index.js

@ -9,7 +9,7 @@ const whiteSecondSider = [
'/agent/siteAddFinally','/agent/siteServiceAdd' '/agent/siteAddFinally','/agent/siteServiceAdd'
]; ];
const blackSliderList = [ 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/domainList'
, '/agent/noticeList' , '/agent/noticeList'
]; ];
@ -310,7 +310,7 @@ const routes = [{
{ {
path: '/franchise', path: '/franchise',
name: '加盟', name: '加盟',
component: () => import( /* webpackChunkName: "franchise" */ '../views/Franchise.vue'), component: () => import( /* webpackChunkName: "franchise" */ '../views/agent/Franchise.vue'),
meta: { meta: {
hideBreadcrumb: true // 一级页面不显示面包屑 hideBreadcrumb: true // 一级页面不显示面包屑
} }

32
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
}

46
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)
}
}

13
src/utils/request.js

@ -1,5 +1,7 @@
// src/utils/request.js // src/utils/request.js
import axios from "axios"; import axios from "axios";
import { handleTokenRefresh } from '@/utils/loginRefresh';
import { host } from '@/config/host';
// 创建 axios 实例 // 创建 axios 实例
const service = axios.create({ const service = axios.create({
@ -8,6 +10,7 @@ const service = axios.create({
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
}, },
withCredentials: true
}); });
// 请求拦截器 // 请求拦截器
@ -50,7 +53,15 @@ service.interceptors.response.use(
switch (error.response.status) { switch (error.response.status) {
case 401: 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; break;
case 404: case 404:
// 资源未找到 // 资源未找到

Loading…
Cancel
Save