2
0

feat:IP格式校验

This commit is contained in:
zhongzm
2025-06-19 13:56:32 +08:00
parent de7445cd99
commit 5f22ef60a9
3 changed files with 173 additions and 12 deletions

View File

@@ -939,6 +939,9 @@ const local: any = {
deletetitle:'Delete',
deletebody:'Are you sure you want to delete this record?',
ok:'confirm',
plenumber:'Please enter a valid number',
subnetMask:'Subnet mask must be between 0-32',
iperror:'ip is not right'
},
terminal:{

View File

@@ -940,6 +940,10 @@ const local:any = {
deletetitle:'确认删除',
deletebody:'确定要删除这条记录吗?',
ok:'确认',
plenumber:'请输入有效数字',
subnetMask:'子网掩码必须在0-32之间',
iperror:'ip地址格式不正确'
},
terminal:{
title:'终端设备',

View File

@@ -130,15 +130,48 @@
</a-form-item>
<a-form-item v-if="addPreAuthType === 1" label="IP">
<div style="display: flex; align-items: center; gap: 4px;">
<a-input v-model:value="addPreAuthIpParts[0]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addPreAuthIpParts[0]"
style="width: 56px;"
:maxlength="3"
@input="validateIpPart(0)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addPreAuthIpParts[1]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addPreAuthIpParts[1]"
style="width: 56px;"
:maxlength="3"
@input="validateIpPart(1)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addPreAuthIpParts[2]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addPreAuthIpParts[2]"
style="width: 56px;"
:maxlength="3"
@input="validateIpPart(2)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addPreAuthIpParts[3]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addPreAuthIpParts[3]"
style="width: 56px;"
:maxlength="3"
@input="validateIpPart(3)"
placeholder="0-255"
/>
<span>/</span>
<a-input v-model:value="addPreAuthIpParts[4]" style="width: 56px;" :maxlength="2" />
<a-input
v-model:value="addPreAuthIpParts[4]"
style="width: 56px;"
:maxlength="2"
@input="validateMaskPart"
placeholder="0-32"
/>
</div>
<div v-if="ipValidationError" style="color: #ff4d4f; font-size: 12px; margin-top: 4px;">
{{ ipValidationError }}
</div>
</a-form-item>
<a-form-item v-if="addPreAuthType === 2" label="URL">
@@ -166,13 +199,40 @@
</a-form-item>
<a-form-item v-if="addFreeClientType === 3" label="IP">
<div style="display: flex; align-items: center; gap: 4px;">
<a-input v-model:value="addFreeClientIpParts[0]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addFreeClientIpParts[0]"
style="width: 56px;"
:maxlength="3"
@input="validateFreeClientIpPart(0)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addFreeClientIpParts[1]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addFreeClientIpParts[1]"
style="width: 56px;"
:maxlength="3"
@input="validateFreeClientIpPart(1)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addFreeClientIpParts[2]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addFreeClientIpParts[2]"
style="width: 56px;"
:maxlength="3"
@input="validateFreeClientIpPart(2)"
placeholder="0-255"
/>
<span>.</span>
<a-input v-model:value="addFreeClientIpParts[3]" style="width: 56px;" :maxlength="3" />
<a-input
v-model:value="addFreeClientIpParts[3]"
style="width: 56px;"
:maxlength="3"
@input="validateFreeClientIpPart(3)"
placeholder="0-255"
/>
</div>
<div v-if="freeClientIpValidationError" style="color: #ff4d4f; font-size: 12px; margin-top: 4px;">
{{ freeClientIpValidationError }}
</div>
</a-form-item>
<a-form-item v-if="addFreeClientType === 4" label="MAC">
@@ -217,12 +277,14 @@ const addPreAuthVisible = ref(false)
const addPreAuthType = ref(1) // 1: IP, 2: URL
const addPreAuthValue = ref('')
const addPreAuthIpParts = ref(['', '', '', '', '']) // [ip1, ip2, ip3, ip4, mask]
const ipValidationError = ref('')
// 新增:添加免认证白名单弹窗相关变量
const addFreeClientVisible = ref(false)
const addFreeClientType = ref(3) // 3: IP, 4: MAC
const addFreeClientIpParts = ref(['', '', '', ''])
const addFreeClientMacParts = ref(['', '', '', '', '', ''])
const freeClientIpValidationError = ref('')
// 定义表格列配置
const preAuthColumns = [
@@ -241,7 +303,10 @@ const preAuthColumns = [
dataIndex: 'url',
key: 'url',
customRender: ({ record }: { record: any }) => {
if (record.type === 1) return record.ip
if (record.type === 1) {
const ipDisplay = record.subnetMask ? `${record.ip}/${record.subnetMask}` : record.ip
return ipDisplay
}
if (record.type === 2) return record.url
return '-'
}
@@ -341,6 +406,7 @@ const getAccessControl = async () => {
key: String(item.idInt),
type: item.type,
ip: item.ip,
subnetMask: item.subnetMask,
url: item.url,
...item
}))
@@ -368,6 +434,7 @@ const onAddPreAuth = () => {
addPreAuthType.value = 1
addPreAuthValue.value = ''
addPreAuthIpParts.value = ['', '', '', '', '']
ipValidationError.value = ''
addPreAuthVisible.value = true
}
@@ -376,11 +443,29 @@ const handleAddPreAuthOk = () => {
// 拼接IP
const ip = addPreAuthIpParts.value.slice(0, 4).join('.')
const mask = addPreAuthIpParts.value[4]
const ipValue = mask ? `${ip}/${mask}` : ip
// IP地址格式校验
const ipRegex = /\b((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\b/
if (!ipRegex.test(ip)) {
message.error(t('page.access.iperror'))
return
}
// 子网掩码校验(如果输入了掩码)
if (mask) {
const maskNum = parseInt(mask)
if (isNaN(maskNum) || maskNum < 0 || maskNum > 32) {
message.error(t('page.access.subnetMask'))
return
}
}
preAuthList.value.push({
key: Date.now() + Math.random(), // 简单唯一key
type: 1,
ip: ipValue,
ip: ip,
subnetMask: mask || undefined,
url: null
})
} else {
@@ -389,6 +474,7 @@ const handleAddPreAuthOk = () => {
key: Date.now() + Math.random(),
type: 2,
ip: null,
subnetMask: undefined,
url: addPreAuthValue.value
})
}
@@ -399,6 +485,7 @@ const onAddFreeClient = () => {
addFreeClientType.value = 3
addFreeClientIpParts.value = ['', '', '', '']
addFreeClientMacParts.value = ['', '', '', '', '', '']
freeClientIpValidationError.value = ''
addFreeClientVisible.value = true
}
@@ -406,6 +493,15 @@ const handleAddFreeClientOk = () => {
if (addFreeClientType.value === 3) {
// 拼接IP
const ip = addFreeClientIpParts.value.join('.')
// IP地址格式校验
const ipRegex = /\b((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\.((?!\d\d\d)\d+|1\d\d|2[0-4]\d|25[0-5])\b/
if (!ipRegex.test(ip)) {
message.error(t('page.access.iperror'))
return
}
freeClientList.value.push({
key: Date.now() + Math.random(),
type: 3,
@@ -470,6 +566,7 @@ const handleApply = async () => {
preAuthAccessPolicies: preAuthList.value.map(item => ({
type: item.type,
ip: item.type === 1 ? item.ip : undefined,
subnetMask: item.type === 1 ? item.subnetMask : undefined,
url: item.type === 2 ? item.url : undefined
})),
freeAuthClientPolicies: freeClientList.value.map(item => ({
@@ -510,6 +607,63 @@ const handleCancel = async () => {
}
}
const validateIpPart = (index: number) => {
const value = addPreAuthIpParts.value[index]
if (value && !/^\d+$/.test(value)) {
ipValidationError.value = t('page.access.plenumber')
return
}
if (value) {
const num = parseInt(value)
if (num < 0 || num > 255) {
ipValidationError.value = `IP${index + 1}must between 0-255`
return
}
}
// 清除错误信息
ipValidationError.value = ''
}
const validateMaskPart = () => {
const value = addPreAuthIpParts.value[4]
if (value && !/^\d+$/.test(value)) {
ipValidationError.value = t('page.access.plenumber')
return
}
if (value) {
const num = parseInt(value)
if (num < 0 || num > 32) {
ipValidationError.value = t('page.access.subnetMask')
return
}
}
// 清除错误信息
ipValidationError.value = ''
}
const validateFreeClientIpPart = (index: number) => {
const value = addFreeClientIpParts.value[index]
if (value && !/^\d+$/.test(value)) {
freeClientIpValidationError.value = t('page.access.plenumber')
return
}
if (value) {
const num = parseInt(value)
if (num < 0 || num > 255) {
freeClientIpValidationError.value = `IP${index + 1}must in 0-255`
return
}
}
// 清除错误信息
freeClientIpValidationError.value = ''
}
onMounted(async () => {
console.log('onMounted执行')
await getSiteList()