From ce471426a1a52018678e2eb5bbb28084409e4c1d Mon Sep 17 00:00:00 2001 From: lijun Date: Thu, 18 Dec 2025 20:50:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E9=A1=B5=E9=9D=A2=EF=BC=8C=E4=B8=8E=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/vpn.ts | 5 + src/components/menu.ts | 6 + src/router/index.ts | 9 + src/store/permiss.ts | 3 +- src/utils/local_request.ts | 89 ++++++ src/views/system/vpn-online-connect.vue | 372 ++++++++++++++++++++++++ 6 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 src/utils/local_request.ts create mode 100644 src/views/system/vpn-online-connect.vue diff --git a/src/api/vpn.ts b/src/api/vpn.ts index b1f288b..3da51f8 100644 --- a/src/api/vpn.ts +++ b/src/api/vpn.ts @@ -1,4 +1,5 @@ import request from '@/utils/user_center_request'; +import local_request from '@/utils/local_request'; // myVPNGroup := router.Group("/vpn") // myVPNGroup.POST("/server_register", ServerRegisterHandler) @@ -76,3 +77,7 @@ export const SetVPNServerConfigHandler = (Data) => { export const DeleteVPNServerHandler = (Data) => { return request.delete('/vpn/delete_vpn_server', { data: Data }) } + +export const LocalClientConnectHandler = (Data) => { + return local_request.post('/vpn/connect', Data) +} \ No newline at end of file diff --git a/src/components/menu.ts b/src/components/menu.ts index 9e258bb..5ebfc5e 100644 --- a/src/components/menu.ts +++ b/src/components/menu.ts @@ -97,6 +97,12 @@ export const menuData: Menus[] = [ index: '/vpn-tunnel', title: '隧道配置', }, + { + id: '754', + pid: '75', + index: '/vpn-client', + title: 'VPN客户端UI', + } ], }, { diff --git a/src/router/index.ts b/src/router/index.ts index 8e88589..04e1c69 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -155,6 +155,15 @@ const routes: RouteRecordRaw[] = [ }, component: () => import(/* webpackChunkName: "system-user" */ '../views/system/vpn-tunnel.vue'), }, + { + path: '/vpn-client', + name: 'vpn-client', + meta: { + title: 'VPN客户端UI', + permiss: '754', + }, + component: () => import(/* webpackChunkName: "system-user" */ '../views/system/vpn-online-connect.vue'), + }, { path: '/callback', name: 'callback', diff --git a/src/store/permiss.ts b/src/store/permiss.ts index 57118d3..f47dea1 100644 --- a/src/store/permiss.ts +++ b/src/store/permiss.ts @@ -64,8 +64,9 @@ export const usePermissStore = defineStore("permiss", { "751", //VPN服务器配置管理 "752", //VPN地址池管理 "753", //VPN隧道管理 + "754", //VPN客户端UI ], - user: ["0", "8", "7", "9", "51" ,"53","55" ,"56", "57", "58", "59", "61", "71", "75"], + user: ["0", "8", "7", "9", "51" ,"53","55" ,"56", "57", "58", "59", "61", "71", "75", "754"], }, }; }, diff --git a/src/utils/local_request.ts b/src/utils/local_request.ts new file mode 100644 index 0000000..67b467e --- /dev/null +++ b/src/utils/local_request.ts @@ -0,0 +1,89 @@ +import axios from "axios"; +import router from "@/router/index.js"; +import { ElMessage } from 'element-plus'; + +const baseURL= "http://localhost:18086"; + + +let isRefreshing = false; +let requests = []; + +const request = axios.create({ + baseURL: baseURL, +}); + +// 请求拦截器 - 添加token +request.interceptors.request.use( + config => { + const token = localStorage.getItem("token"); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + config.headers.token = token; + } + return config; + } +); + +// 响应拦截器 +request.interceptors.response.use( + result => { + if(result.status !== 200) { + router.push("/login"); + } + + if(result.data.message === "NOT_LOGIN" || [2, 3, 4].includes(result.data.code)) { + // 检测到token过期 + if (isRefreshing == false) { + isRefreshing = true; + // 这里需要替换为实际的refresh token请求 + return axios.post('https://uc.ljsea.top/user/refresh_token', { + refresh_token: localStorage.getItem("refresh_token") + },{ + headers: { + 'Authorization': `Bearer ${localStorage.getItem("refresh_token")}` + } + }).then(res => { + const token = res.data["data"]["access_token"]; + localStorage.setItem("token", token); + //alert("token: " + token); + + // 重试所有挂起的请求 + requests.forEach(cb => cb(token)); + requests = []; + isRefreshing = false; + localStorage.setItem("refresh_time", Date.now().toString()); + + // 重试当前请求 + const config = result.config; + config.headers.Authorization = `Bearer ${token}`; + return request(config); + }).catch(err => { + // 刷新token失败,跳转登录 + ElMessage.error('登录已过期,请重新登录!'); + router.push("/login"); + return Promise.reject(err); + }); + } else if (isRefreshing) { + // 正在刷新token,将请求放入队列 + return new Promise(resolve => { + requests.push(token => { + resolve(request(result.config)); + }); + }); + } + } + + if(result.data.code == 7) { + ElMessage.error('该用户已存在,请重新输入!'); + return null; + } + + if(result.data.code == 1) { + ElMessage.error('请求失败,请稍后重试!'); + } else { + return result.data; + } + } +); + +export default request; \ No newline at end of file diff --git a/src/views/system/vpn-online-connect.vue b/src/views/system/vpn-online-connect.vue new file mode 100644 index 0000000..089c9ad --- /dev/null +++ b/src/views/system/vpn-online-connect.vue @@ -0,0 +1,372 @@ + + + + + \ No newline at end of file