From 9e706091d80d574e7212c55e7f16e194e428cf57 Mon Sep 17 00:00:00 2001 From: lijun Date: Wed, 28 Jan 2026 20:22:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AD=96=E7=95=A5=E5=8C=B9?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components.d.ts | 41 + src/api/vpn.ts | 55 ++ src/components/menu.ts | 8 +- src/router/index.ts | 9 + src/store/permiss.ts | 1 + src/views/system/vpn-policy.vue | 973 ++++++++++++++++++++ src/views/system/vpn-server-config.vue | 10 +- src/views/system/vpn-server-online-user.vue | 1 + 8 files changed, 1092 insertions(+), 6 deletions(-) create mode 100644 src/views/system/vpn-policy.vue diff --git a/components.d.ts b/components.d.ts index 3d4fba0..aa1814f 100644 --- a/components.d.ts +++ b/components.d.ts @@ -8,6 +8,44 @@ export {} declare module '@vue/runtime-core' { export interface GlobalComponents { Countup: typeof import('./src/components/countup.vue')['default'] + ElAvatar: typeof import('element-plus/es')['ElAvatar'] + ElButton: typeof import('element-plus/es')['ElButton'] + ElCard: typeof import('element-plus/es')['ElCard'] + ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCol: typeof import('element-plus/es')['ElCol'] + ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] + ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] + ElDialog: typeof import('element-plus/es')['ElDialog'] + ElDivider: typeof import('element-plus/es')['ElDivider'] + ElDropdown: typeof import('element-plus/es')['ElDropdown'] + ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] + ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + ElEmpty: typeof import('element-plus/es')['ElEmpty'] + ElForm: typeof import('element-plus/es')['ElForm'] + ElFormItem: typeof import('element-plus/es')['ElFormItem'] + ElIcon: typeof import('element-plus/es')['ElIcon'] + ElInput: typeof import('element-plus/es')['ElInput'] + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] + ElLink: typeof import('element-plus/es')['ElLink'] + ElMenu: typeof import('element-plus/es')['ElMenu'] + ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] + ElOption: typeof import('element-plus/es')['ElOption'] + ElPagination: typeof import('element-plus/es')['ElPagination'] + ElProgress: typeof import('element-plus/es')['ElProgress'] + ElRadio: typeof import('element-plus/es')['ElRadio'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] + ElRow: typeof import('element-plus/es')['ElRow'] + ElSelect: typeof import('element-plus/es')['ElSelect'] + ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] + ElSwitch: typeof import('element-plus/es')['ElSwitch'] + ElTable: typeof import('element-plus/es')['ElTable'] + ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTabPane: typeof import('element-plus/es')['ElTabPane'] + ElTabs: typeof import('element-plus/es')['ElTabs'] + ElTag: typeof import('element-plus/es')['ElTag'] + ElTimeline: typeof import('element-plus/es')['ElTimeline'] + ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] + ElTooltip: typeof import('element-plus/es')['ElTooltip'] Header: typeof import('./src/components/header.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] @@ -20,4 +58,7 @@ declare module '@vue/runtime-core' { Upload_file2: typeof import('./src/components/upload_file2.vue')['default'] UploadFile: typeof import('./src/components/upload-file.vue')['default'] } + export interface ComponentCustomProperties { + vLoading: typeof import('element-plus/es')['ElLoadingDirective'] + } } diff --git a/src/api/vpn.ts b/src/api/vpn.ts index 5526f57..1e1529c 100644 --- a/src/api/vpn.ts +++ b/src/api/vpn.ts @@ -103,4 +103,59 @@ export const LocalClientDisConnectHandler = (Data) => { //获取本地客户端连接状态 export const LocalClientStatusHandler = () => { return local_request.get('/vpn/get_status') +} + +// VPN Policy Management APIs +// myVPNPolicyGroup := router.Group("/vpn_policy") +// myVPNPolicyGroup.GET("/get", GetMyVPNPolicyHandler) +// myVPNPolicyGroup.POST("/create", CreateMyVPNPolicyHandler) +// myVPNPolicyGroup.POST("/update", UpdateMyVPNPolicyHandler) +// myVPNPolicyGroup.DELETE("/delete", DeleteMyVPNPolicyHandler) + +/** + * 获取VPN策略列表 + * @param {Object} params 查询参数,包含server_id等 + * @returns {Promise} 包含VPN策略列表的Promise对象 + */ +export const GetMyVPNPolicyHandler = (params) => { + return request.get('/vpn_policy/get', { params }) +} + +/** + * 创建VPN策略 + * @param {Object} data VPN策略数据 + * @returns {Promise} 创建结果的Promise对象 + */ +export const CreateMyVPNPolicyHandler = (data) => { + return request.post('/vpn_policy/create', data) +} + +/** + * 更新VPN策略 + * @param {Object} data VPN策略更新数据,包含id + * @returns {Promise} 更新结果的Promise对象 + */ +export const UpdateMyVPNPolicyHandler = (data) => { + return request.post('/vpn_policy/update', data) +} + +/** + * 删除VPN策略 + * @param {Object} data 删除参数,包含id和server_id + * @returns {Promise} 删除结果的Promise对象 + */ +export const DeleteMyVPNPolicyHandler = (data) => { + let url = '/vpn_policy/delete'; + + if (data.id){ + url += "?id="+data.id + } + if (data.server_id){ + url += "&server_id=" + data.server_id + } + return request.delete(url) +} + +export const MatchVPNPolicyHandler = (data) => { + return request.post('/vpn_policy/match', data) } \ No newline at end of file diff --git a/src/components/menu.ts b/src/components/menu.ts index bf74c28..3b9818b 100644 --- a/src/components/menu.ts +++ b/src/components/menu.ts @@ -102,7 +102,13 @@ export const menuData: Menus[] = [ pid: '75', index: '/vpn-online-user', title: '在线用户', - } + }, + { + id: '756', + pid: '75', + index: '/vpn-policy', + title: 'VPN策略', + }, ], }, { diff --git a/src/router/index.ts b/src/router/index.ts index 6eb9d27..18d4fb8 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -173,6 +173,15 @@ const routes: RouteRecordRaw[] = [ }, component: () => import(/* webpackChunkName: "system-user" */ '../views/system/vpn-server-online-user.vue'), }, + { + path: '/vpn-policy', + name: 'vpn-policy', + meta: { + title: 'VPN策略', + permiss: '755', + }, + component: () => import(/* webpackChunkName: "system-user" */ '../views/system/vpn-policy.vue'), + }, { path: '/callback', diff --git a/src/store/permiss.ts b/src/store/permiss.ts index 0de974e..9ee785b 100644 --- a/src/store/permiss.ts +++ b/src/store/permiss.ts @@ -66,6 +66,7 @@ export const usePermissStore = defineStore("permiss", { "753", //VPN隧道管理 "754", //VPN客户端UI "755", //VPN在线用户连接 + "756", //VPN策略 ], user: ["0", "8", "7", "9", "51" ,"53","55" ,"56", "57", "58", "59", "61", "71", "754"], }, diff --git a/src/views/system/vpn-policy.vue b/src/views/system/vpn-policy.vue new file mode 100644 index 0000000..123469e --- /dev/null +++ b/src/views/system/vpn-policy.vue @@ -0,0 +1,973 @@ + + + + + \ No newline at end of file diff --git a/src/views/system/vpn-server-config.vue b/src/views/system/vpn-server-config.vue index 1a217d7..d885634 100644 --- a/src/views/system/vpn-server-config.vue +++ b/src/views/system/vpn-server-config.vue @@ -103,11 +103,10 @@ - - - - - + + + + @@ -360,6 +359,7 @@ interface ServerConfig { allow_user_id: UserID[]; encryption: string; hash: string; + no_policy_action:number; user_max_device: number; duration_time: number; ipv4_router: VPNRouter[]; diff --git a/src/views/system/vpn-server-online-user.vue b/src/views/system/vpn-server-online-user.vue index 563809e..c72cede 100644 --- a/src/views/system/vpn-server-online-user.vue +++ b/src/views/system/vpn-server-online-user.vue @@ -106,6 +106,7 @@ interface ServerConfig { allow_user_id: any[]; encryption: string; hash: string; + no_policy_action:number; user_max_device: number; duration_time: number; ipv4_router: any[];