添加策略匹配

This commit is contained in:
lijun 2026-01-28 21:33:40 +08:00
parent 9e706091d8
commit 6b1e37d9cd
1 changed files with 276 additions and 2 deletions

View File

@ -91,7 +91,9 @@
v-loading="loading"
stripe
>
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="ID" label="ID" width="80" />
<!-- 名称 -->
<el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip />
<el-table-column label="源信息" min-width="150">
<template #default="scope">
<div>{{ getSrcTypeText(scope.row.src_type) }}</div>
@ -165,6 +167,11 @@
size="default"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="策略名称" prop="name">
<el-input v-model="policyForm.name"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="服务器ID" prop="server_id">
<el-input v-model="policyForm.server_id" disabled />
@ -265,6 +272,134 @@
</span>
</template>
</el-dialog>
<!-- 策略匹配对话框 -->
<el-dialog
title="策略匹配测试"
v-model="matchDialogVisible"
width="900px"
@close="resetMatchForm"
>
<el-form
:model="matchForm"
ref="matchFormRef"
label-width="120px"
size="default"
class="match-form"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="服务器" prop="server_id">
<el-select v-model="matchForm.server_id" placeholder="请选择服务器" style="width: 100%;">
<el-option
v-for="server in serverList"
:key="server.server_id"
:label="server.name"
:value="server.server_id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="IP类型" prop="ip_type">
<el-select v-model="matchForm.ip_type" placeholder="请选择IP类型">
<el-option label="IPv4" :value="4" />
<el-option label="IPv6" :value="6" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="源类型" prop="src_type">
<el-select v-model="matchForm.src_type" placeholder="请选择源类型" @change="onMatchSrcTypeChange">
<el-option label="IP地址" :value="0" />
<el-option label="网段" :value="1" />
<el-option label="用户ID" :value="2" />
<el-option label="组ID" :value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="源值" prop="src_value">
<el-input
v-model="matchForm.src_value"
:placeholder="getSrcPlaceholder()"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="目标类型" prop="dst_type">
<el-select v-model="matchForm.dst_type" placeholder="请选择目标类型" @change="onMatchDstTypeChange">
<el-option label="IP地址" :value="0" />
<el-option label="网段" :value="1" />
<el-option label="用户ID" :value="2" />
<el-option label="组ID" :value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="目标值" prop="dst_value">
<el-input
v-model="matchForm.dst_value"
:placeholder="getDstPlaceholder()"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="协议" prop="protocol">
<el-select v-model="matchForm.protocol" placeholder="请选择协议">
<el-option label="全部协议" :value="0" />
<el-option label="ICMP" :value="1" />
<el-option label="TCP" :value="6" />
<el-option label="UDP" :value="17" />
<el-option label="其他" :value="255" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="match-actions">
<el-button type="primary" @click="matchPolicy" :loading="matchLoading">匹配策略</el-button>
<el-button @click="resetMatchForm">重置</el-button>
</div>
<!-- 匹配结果 -->
<div v-if="matchResult" class="match-result">
<h4>匹配结果:</h4>
<div class="match-result-item">
<span>策略ID:</span>
<span>{{ matchResult.ID>0? matchResult.ID : '未匹配到策略,使用服务器配置'}}</span>
</div>
<div class="match-result-item" v-if="matchResult.ID>0">
<span>策略名称:</span>
<span>{{ matchResult.name }}</span>
</div>
<div class="match-result-item">
<span>处置动作:</span>
<el-tag :type="matchResult.action === 1 ? 'success' : 'danger'" size="small">
{{ matchResult.action === 1 ? '允许' : '拒绝' }}
</el-tag>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="matchDialogVisible = false">关闭</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
@ -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<VPNPolicy>();
const matchLoading = ref(false);
//
const searchForm = reactive({
src_type: undefined as number | undefined,
@ -359,6 +517,7 @@ const pagination = reactive({
//
const policyForm = reactive<VPNPolicyBase & { id?: number }>({
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;
}
</style>