diff --git a/src/views/system/vpn-policy.vue b/src/views/system/vpn-policy.vue index 123469e..866bc37 100644 --- a/src/views/system/vpn-policy.vue +++ b/src/views/system/vpn-policy.vue @@ -91,7 +91,9 @@ v-loading="loading" stripe > - + + + {{ getSrcTypeText(scope.row.src_type) }} @@ -165,6 +167,11 @@ size="default" > + + + + + @@ -265,6 +272,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 匹配策略 + 重置 + + + + + 匹配结果: + + 策略ID: + {{ matchResult.ID>0? matchResult.ID : '未匹配到策略,使用服务器配置'}} + + + 策略名称: + {{ matchResult.name }} + + + 处置动作: + + {{ matchResult.action === 1 ? '允许' : '拒绝' }} + + + + + + + + 关闭 + + + @@ -277,11 +412,15 @@ import { GetMyVPNPolicyHandler, CreateMyVPNPolicyHandler, UpdateMyVPNPolicyHandler, - DeleteMyVPNPolicyHandler + DeleteMyVPNPolicyHandler, + MatchVPNPolicyHandler } from '@/api/vpn'; +import { match } from 'assert'; +import { el } from 'element-plus/es/locale'; // VPN策略基础接口定义 interface VPNPolicyBase { + name: string; server_id: string; ip_type: number; // 4, 6 src_type: number; // 0-ip,1-network, 2-userID, 3-groupID @@ -342,6 +481,25 @@ const matchDialogVisible = ref(false); const isEdit = ref(false); const policyFormRef = ref(); +// 匹配表单 +const matchForm = reactive({ + server_id: '', + ip_type: 4, + src_type: 0, + src_value: '', + dst_type: 0, + dst_value: '', + protocol: 0, + src_ip: '', + src_user_id: 0, + dst_ip: '', + dst_user_id: 0 +}); + +// 匹配结果 +const matchResult = ref(); +const matchLoading = ref(false); + // 搜索表单 const searchForm = reactive({ src_type: undefined as number | undefined, @@ -359,6 +517,7 @@ const pagination = reactive({ // 策略表单 const policyForm = reactive({ + name: '', id: undefined, server_id: '', ip_type: 4, @@ -478,6 +637,100 @@ const refreshPolicies = () => { //显示匹配对话框 const showMatchDialog = () => { matchDialogVisible.value = true; + // 默认选择当前选中的服务器 + if (selectedServer.value) { + matchForm.server_id = selectedServer.value.server_id; + } +}; + +// 匹配策略 +const matchPolicy = async () => { + if (!matchForm.server_id) { + ElMessage.warning('请选择服务器'); + return; + } + + // 根据类型设置对应的值 + switch (matchForm.src_type) { + case 0: + case 1: + matchForm.src_ip = matchForm.src_value; + matchForm.src_user_id = 0; + break; + case 2: + case 3: + matchForm.src_user_id = parseInt(matchForm.src_value) || 0; + matchForm.src_ip = ''; + break; + default: + break; + } + switch (matchForm.dst_type) { + case 0: + case 1: + matchForm.dst_ip = matchForm.dst_value; + matchForm.dst_user_id = 0; + break; + case 2: + case 3: + matchForm.dst_user_id = parseInt(matchForm.dst_value) || 0; + matchForm.dst_ip = ''; + break; + default: + break; + } + + matchLoading.value = true; + try { + const response = await MatchVPNPolicyHandler(matchForm); + if (response["code"] == 0) { + if (response["data"] === 0){ + if (!matchResult.value){ + matchResult.value = {} as VPNPolicy; + } + matchResult.value.ID = 0; + matchResult.value.name = '未匹配到策略'; + matchResult.value.action = serverList.value.find(item => item.server_id === matchForm.server_id)?.no_policy_action; + }else{ + matchResult.value = response.data; + } + ElMessage.success('策略匹配成功'); + } else { + ElMessage.error(response["message"] || '策略匹配失败'); + } + } catch (error) { + ElMessage.error('策略匹配失败'); + console.error(error); + } finally { + matchLoading.value = false; + } +}; + +// 重置匹配表单 +const resetMatchForm = () => { + matchForm.server_id = selectedServer.value?.server_id || ''; + matchForm.ip_type = 4; + matchForm.src_type = 0; + matchForm.src_value = ''; + matchForm.dst_type = 0; + matchForm.dst_value = ''; + matchForm.protocol = 0; + matchForm.src_ip = ''; + matchForm.src_user_id = 0; + matchForm.dst_ip = ''; + matchForm.dst_user_id = 0; +}; + +// 匹配表单源类型改变 +const onMatchSrcTypeChange = () => { + matchForm.src_ip = ''; + matchForm.src_user_id = 0; +}; + +// 匹配表单目标类型改变 +const onMatchDstTypeChange = () => { + matchForm.dst_ip = ''; + matchForm.dst_user_id = 0; }; // 显示新增对话框 @@ -970,4 +1223,25 @@ onMounted(() => { justify-content: flex-end; gap: 10px; } + +.match-form { + max-height: 500px; + overflow-y: auto; +} + +.match-actions { + margin: 20px 0; + text-align: center; +} + +.match-result h4 { + margin: 0 0 10px 0; + color: #303133; + font-weight: bold; +} + +.no-match-result { + margin-top: 20px; + text-align: center; +} \ No newline at end of file