299 lines
9.4 KiB
Vue
299 lines
9.4 KiB
Vue
<template>
|
||
<Dialog :options="{ title: '修改DNS服务器', size: 'lg' }" v-model="show">
|
||
<template #body-content>
|
||
<div class="p-4 sm:p-6">
|
||
<div class="space-y-4">
|
||
<!-- DNS1 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS1(主DNS服务器)<span class="text-red-500">*</span>
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns1"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns1 }"
|
||
@blur="validateDNSField('dns1', '主DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns1" class="mt-1 text-sm text-red-600">{{ errors.dns1 }}</p>
|
||
</div>
|
||
|
||
<!-- DNS2 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS2(辅DNS服务器)<span class="text-red-500">*</span>
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns2"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns2 }"
|
||
@blur="validateDNSField('dns2', '辅DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns2" class="mt-1 text-sm text-red-600">{{ errors.dns2 }}</p>
|
||
</div>
|
||
|
||
<!-- DNS3 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS3(可选)
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns3"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns3 }"
|
||
@blur="validateDNSField('dns3', '第三个DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns3" class="mt-1 text-sm text-red-600">{{ errors.dns3 }}</p>
|
||
</div>
|
||
|
||
<!-- DNS4 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS4(可选)
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns4"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns4 }"
|
||
@blur="validateDNSField('dns4', '第四个DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns4" class="mt-1 text-sm text-red-600">{{ errors.dns4 }}</p>
|
||
</div>
|
||
|
||
<!-- DNS5 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS5(可选)
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns5"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns5 }"
|
||
@blur="validateDNSField('dns5', '第五个DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns5" class="mt-1 text-sm text-red-600">{{ errors.dns5 }}</p>
|
||
</div>
|
||
|
||
<!-- DNS6 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||
DNS6(可选)
|
||
</label>
|
||
<input
|
||
v-model="dnsServers.dns6"
|
||
type="text"
|
||
class="w-full px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||
:class="{ 'border-red-300': errors.dns6 }"
|
||
@blur="validateDNSField('dns6', '第六个DNS服务器')"
|
||
/>
|
||
<p v-if="errors.dns6" class="mt-1 text-sm text-red-600">{{ errors.dns6 }}</p>
|
||
</div>
|
||
</div>
|
||
<div v-if="error" class="mt-4 p-3 bg-red-50 text-red-700 rounded-md text-sm">
|
||
{{ error }}
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template #actions>
|
||
<div class="w-full flex justify-end space-x-3">
|
||
<button
|
||
type="button"
|
||
class="px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none"
|
||
@click="cancel"
|
||
>
|
||
取消
|
||
</button>
|
||
<button
|
||
type="button"
|
||
class="px-4 py-2 bg-black border border-transparent rounded-md text-sm font-medium text-white hover:bg-gray-800 focus:outline-none disabled:bg-gray-300 disabled:cursor-not-allowed"
|
||
@click="modifyDNSServer"
|
||
:disabled="isLoading || !isValid"
|
||
>
|
||
{{ isLoading ? '修改中...' : '确定' }}
|
||
</button>
|
||
</div>
|
||
</template>
|
||
</Dialog>
|
||
</template>
|
||
|
||
<script>
|
||
import { toast } from 'vue-sonner';
|
||
import { Dialog } from 'jingrow-ui';
|
||
import { DashboardError } from '../utils/error';
|
||
|
||
export default {
|
||
name: 'JsiteDomainModifyDNSServerDialog',
|
||
components: {
|
||
Dialog
|
||
},
|
||
props: {
|
||
domain: {
|
||
type: String,
|
||
required: true
|
||
},
|
||
domainDoc: {
|
||
type: Object,
|
||
default: null
|
||
}
|
||
},
|
||
emits: ['success'],
|
||
data() {
|
||
return {
|
||
show: true,
|
||
dnsServers: {
|
||
dns1: '',
|
||
dns2: '',
|
||
dns3: '',
|
||
dns4: '',
|
||
dns5: '',
|
||
dns6: ''
|
||
},
|
||
errors: {},
|
||
error: null
|
||
};
|
||
},
|
||
computed: {
|
||
isLoading() {
|
||
return this.$resources.modifyDNSServer.loading;
|
||
},
|
||
isValid() {
|
||
return this.dnsServers.dns1 && this.dnsServers.dns2 && !this.hasErrors;
|
||
},
|
||
hasErrors() {
|
||
return Object.keys(this.errors).length > 0;
|
||
}
|
||
},
|
||
|
||
resources: {
|
||
modifyDNSServer() {
|
||
return {
|
||
url: 'jcloud.api.domain_west.west_domain_modify_dns_server',
|
||
validate() {
|
||
// 实时验证已经完成,这里只需要检查是否有错误
|
||
if (this.hasErrors) {
|
||
throw new DashboardError('请检查DNS服务器格式');
|
||
}
|
||
},
|
||
onSuccess(data) {
|
||
if (data.status === 'success') {
|
||
this.$emit('success', {
|
||
domain: this.domainDoc?.domain,
|
||
dnsServers: this.dnsServers,
|
||
message: data.message
|
||
});
|
||
this.show = false;
|
||
} else {
|
||
this.error = data.message || '修改DNS服务器失败';
|
||
}
|
||
},
|
||
onError(error) {
|
||
this.error = error.message || '修改DNS服务器失败';
|
||
}
|
||
};
|
||
}
|
||
},
|
||
mounted() {
|
||
},
|
||
methods: {
|
||
cancel() {
|
||
this.show = false;
|
||
},
|
||
modifyDNSServer() {
|
||
this.error = null;
|
||
this.$resources.modifyDNSServer.submit({
|
||
domain: this.domainDoc?.domain,
|
||
dns1: this.dnsServers.dns1?.trim() || '',
|
||
dns2: this.dnsServers.dns2?.trim() || '',
|
||
dns3: this.dnsServers.dns3?.trim() || undefined,
|
||
dns4: this.dnsServers.dns4?.trim() || undefined,
|
||
dns5: this.dnsServers.dns5?.trim() || undefined,
|
||
dns6: this.dnsServers.dns6?.trim() || undefined
|
||
});
|
||
},
|
||
validateDNSField(fieldName, fieldLabel) {
|
||
const value = this.dnsServers[fieldName];
|
||
|
||
// 清除该字段的错误
|
||
if (this.errors[fieldName]) {
|
||
delete this.errors[fieldName];
|
||
}
|
||
|
||
// 如果是必填字段且为空,不显示错误(让用户继续输入)
|
||
if ((fieldName === 'dns1' || fieldName === 'dns2') && !value) {
|
||
return;
|
||
}
|
||
|
||
// 检查是否有首尾空格
|
||
if (value && (value !== value.trim())) {
|
||
this.errors[fieldName] = `${fieldLabel}不能包含首尾空格`;
|
||
return;
|
||
}
|
||
|
||
// 如果字段有值但格式不正确,显示错误
|
||
if (value && !this.isValidDNSFormat(value)) {
|
||
this.errors[fieldName] = `${fieldLabel}格式不正确`;
|
||
}
|
||
},
|
||
isValidDNSFormat(dns) {
|
||
if (!dns) return false;
|
||
|
||
// 检查长度
|
||
if (dns.length < 3 || dns.length > 253) {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否包含至少一个点号(域名必须有点号分隔)
|
||
if (!dns.includes('.')) {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否以点号开头或结尾
|
||
if (dns.startsWith('.') || dns.endsWith('.')) {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否包含连续的点号
|
||
if (dns.includes('..')) {
|
||
return false;
|
||
}
|
||
|
||
// 分割域名部分进行详细验证
|
||
const parts = dns.split('.');
|
||
|
||
for (let part of parts) {
|
||
// 每个部分不能为空
|
||
if (!part) {
|
||
return false;
|
||
}
|
||
|
||
// 每个部分长度不能超过63个字符
|
||
if (part.length > 63) {
|
||
return false;
|
||
}
|
||
|
||
// 每个部分不能以连字符开头或结尾
|
||
if (part.startsWith('-') || part.endsWith('-')) {
|
||
return false;
|
||
}
|
||
|
||
// 每个部分只能包含字母、数字和连字符
|
||
if (!/^[a-zA-Z0-9-]+$/.test(part)) {
|
||
return false;
|
||
}
|
||
|
||
// 顶级域名(最后一部分)不能全是数字
|
||
if (parts.indexOf(part) === parts.length - 1 && /^\d+$/.test(part)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
};
|
||
</script> |