555 lines
21 KiB
Vue
555 lines
21 KiB
Vue
<template>
|
||
<div v-if="visible" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||
<div class="bg-white rounded-lg shadow-2xl max-w-4xl w-full mx-4 max-h-[90vh] flex flex-col overflow-hidden">
|
||
<!-- 固定标题栏 -->
|
||
<div class="p-6 border-b border-gray-200 bg-white rounded-t-lg flex-shrink-0">
|
||
<div class="flex items-center justify-between">
|
||
<h3 class="text-lg font-medium text-gray-900">新建域名所有者</h3>
|
||
<button
|
||
@click="closeDialog"
|
||
class="text-gray-400 hover:text-gray-600 transition-colors duration-200"
|
||
>
|
||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 可滚动内容区域 -->
|
||
<div class="p-6 overflow-y-auto flex-1">
|
||
<!-- 重要提醒 -->
|
||
<div class="mb-6 p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||
<div class="flex">
|
||
<svg class="w-5 h-5 text-yellow-400 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
|
||
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
|
||
</svg>
|
||
<div class="ml-3">
|
||
<p class="text-sm text-yellow-800">
|
||
域名所有者名称代表域名的所有权。请按照证件上的企业名称或个人姓名准确填写。如果域名需要备案,请确保域名所有者名称与备案主体名称一致,并完成域名实名认证。实名认证后所有者不可修改。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<form @submit.prevent="handleSubmit" class="space-y-6">
|
||
<!-- 所有者类型 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">所有者类型 *</label>
|
||
<div class="flex gap-4">
|
||
<label class="flex items-center">
|
||
<input
|
||
type="radio"
|
||
v-model="formData.c_regtype"
|
||
value="I"
|
||
@change="onRegTypeChange"
|
||
class="mr-2"
|
||
>
|
||
<span class="text-sm">个人</span>
|
||
</label>
|
||
<label class="flex items-center">
|
||
<input
|
||
type="radio"
|
||
v-model="formData.c_regtype"
|
||
value="E"
|
||
@change="onRegTypeChange"
|
||
class="mr-2"
|
||
>
|
||
<span class="text-sm">企业/组织</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 中文信息 -->
|
||
<div class="space-y-4">
|
||
<!-- 单位名称(企业时显示)- 单独一行 -->
|
||
<div v-if="formData.c_regtype === 'E'" class="w-full">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">所有者单位名称 *</label>
|
||
<input
|
||
v-model="formData.c_org_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入单位名称"
|
||
>
|
||
</div>
|
||
|
||
<!-- 姓名部分 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">姓 *</label>
|
||
<input
|
||
v-model="formData.c_ln_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入姓"
|
||
>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">名 *</label>
|
||
<input
|
||
v-model="formData.c_fn_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入名"
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 区域选择 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||
<!-- 国家/地区选择 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">国家/地区 *</label>
|
||
<select
|
||
v-model="selectedCountry"
|
||
@change="onCountryChange"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
>
|
||
<option value="">请选择国家/地区</option>
|
||
<option v-for="country in countryList" :key="country.code" :value="country.code">
|
||
{{ country.name }}
|
||
</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 所属区域 - 仅中国显示 -->
|
||
<div v-if="selectedCountry === 'CN'">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">所属省份 *</label>
|
||
<select
|
||
v-model="selectedProvince"
|
||
@change="onProvinceChange"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
>
|
||
<option value="">请选择省份</option>
|
||
<option v-for="province in chinaRegions" :key="province.code" :value="province.name">
|
||
{{ province.name }}
|
||
</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div v-if="selectedCountry === 'CN'">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">所属城市 *</label>
|
||
<select
|
||
v-model="selectedCity"
|
||
@change="onCityChange"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
:disabled="!selectedProvince"
|
||
>
|
||
<option value="">请选择城市</option>
|
||
<option v-for="city in getCurrentCities()" :key="city.code" :value="city.name">
|
||
{{ city.name }}
|
||
</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div v-if="selectedCountry === 'CN'">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">所属区县</label>
|
||
<select
|
||
v-model="selectedDistrict"
|
||
@change="onDistrictChange"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
:disabled="!selectedCity"
|
||
>
|
||
<option value="">请选择区县</option>
|
||
<option v-for="district in getCurrentDistricts()" :key="district.code" :value="district.name">
|
||
{{ district.name }}
|
||
</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 非中国地区的省份/州输入框 -->
|
||
<div v-if="selectedCountry && selectedCountry !== 'CN'">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">省份/州 *</label>
|
||
<input
|
||
v-model="formData.c_st_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入省份/州"
|
||
>
|
||
</div>
|
||
|
||
<!-- 非中国地区的城市输入框 -->
|
||
<div v-if="selectedCountry && selectedCountry !== 'CN'">
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">城市 *</label>
|
||
<input
|
||
v-model="formData.c_ct_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入城市"
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 通讯地址 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">通讯地址 *</label>
|
||
<input
|
||
v-model="formData.c_adr_m"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入详细地址"
|
||
>
|
||
</div>
|
||
|
||
<!-- 联系信息 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<!-- 邮编 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">邮编 *</label>
|
||
<input
|
||
v-model="formData.c_pc"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入邮编"
|
||
>
|
||
</div>
|
||
|
||
<!-- 手机号码 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">手机号码 *</label>
|
||
<div class="flex">
|
||
<span class="inline-flex items-center px-3 py-2 border border-r-0 border-gray-300 bg-gray-50 text-gray-500 text-sm rounded-l-lg">
|
||
+86
|
||
</span>
|
||
<input
|
||
v-model="formData.c_ph"
|
||
type="text"
|
||
class="flex-1 border rounded-r-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入手机号码"
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 电子邮箱 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">电子邮箱 *</label>
|
||
<input
|
||
v-model="formData.c_em"
|
||
type="email"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
placeholder="请输入邮箱地址"
|
||
>
|
||
</div>
|
||
|
||
<!-- 证件信息 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<!-- 证件类型 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">证件类型 *</label>
|
||
<select
|
||
v-model="formData.c_idtype_gswl"
|
||
@change="onCertificateTypeChange"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
>
|
||
<option value="">请选择证件类型</option>
|
||
<option v-for="option in getCertificateTypeOptions()" :key="option.value" :value="option.value">
|
||
{{ option.label }}
|
||
</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 证件号码 -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-gray-700 mb-2">证件号码 *</label>
|
||
<input
|
||
v-model="formData.c_idnum_gswl"
|
||
type="text"
|
||
class="w-full border rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
:placeholder="getCertificatePlaceholder()"
|
||
@input="validateIdNumber"
|
||
>
|
||
<div v-if="idNumberError" class="text-red-500 text-xs mt-1">
|
||
{{ idNumberError }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 红色警告 -->
|
||
<div class="p-4 bg-red-50 border border-red-200 rounded-lg">
|
||
<p class="text-sm text-red-800">
|
||
根据《互联网域名管理办法》,请提供真实、准确、完整的身份信息。域名信息模板中的电话号码必须与域名所有者一致,否则可能被认定为虚假注册,导致域名被注销。严禁代理持有,联系电话在修改后90天内不可变更。
|
||
</p>
|
||
</div>
|
||
|
||
<!-- 按钮 -->
|
||
<div class="flex justify-end gap-3 pt-4 border-t border-gray-200">
|
||
<button
|
||
type="button"
|
||
@click="closeDialog"
|
||
class="px-6 py-2 border border-gray-300 bg-white text-gray-700 rounded-lg hover:bg-gray-50 transition-colors duration-200"
|
||
>
|
||
取消
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
:disabled="isLoading"
|
||
class="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-300 transition-colors duration-200"
|
||
>
|
||
{{ isLoading ? '创建中...' : '立即保存' }}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { getCountryList, getChinaRegions, getCitiesByProvince, getDistrictsByCity } from '../utils/regions';
|
||
|
||
export default {
|
||
name: 'DomainOwnerDialog',
|
||
props: {
|
||
visible: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
isLoading: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
emits: ['close', 'submit'],
|
||
data() {
|
||
return {
|
||
formData: {
|
||
c_regtype: 'I', // I: 个人, E: 企业
|
||
c_org_m: '', // 中文单位名称
|
||
c_ln_m: '', // 中文姓
|
||
c_fn_m: '', // 中文名
|
||
c_st_m: '', // 中文省份
|
||
c_ct_m: '', // 中文城市
|
||
c_dt_m: '', // 中文区县
|
||
c_adr_m: '', // 中文地址
|
||
c_pc: '', // 邮编
|
||
c_ph_type: '0', // 电话类型:0-手机(固定值)
|
||
c_ph: '', // 手机号码
|
||
c_em: '', // 邮箱
|
||
c_idtype_gswl: 'SFZ', // 证件类型,个人默认身份证
|
||
c_idnum_gswl: '' // 证件号码
|
||
},
|
||
selectedCountry: 'CN',
|
||
selectedProvince: '',
|
||
selectedCity: '',
|
||
selectedDistrict: '',
|
||
countryList: getCountryList(),
|
||
chinaRegions: getChinaRegions(),
|
||
idNumberError: ''
|
||
};
|
||
},
|
||
methods: {
|
||
closeDialog() {
|
||
this.resetForm();
|
||
this.$emit('close');
|
||
},
|
||
async handleSubmit() {
|
||
// 验证表单
|
||
const errors = this.validateForm();
|
||
if (errors.length > 0) {
|
||
alert(errors[0]); // 可以改为更友好的提示方式
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const submitData = { ...this.formData };
|
||
submitData.c_co = this.selectedCountry;
|
||
submitData.cocode = this.selectedCountry === 'CN' ? '+86' : '';
|
||
const response = await this.$resources.createDomainOwner.submit(submitData);
|
||
if (response.status === 'Success') {
|
||
alert('域名所有者创建成功!');
|
||
this.$emit('submit', response.data);
|
||
this.closeDialog();
|
||
} else {
|
||
alert(`创建失败: ${response.message}`);
|
||
}
|
||
} catch (error) {
|
||
alert('创建失败,请检查网络连接或联系管理员');
|
||
}
|
||
},
|
||
validateForm() {
|
||
const errors = [];
|
||
|
||
if (!this.formData.c_regtype) {
|
||
errors.push('请选择所有者类型');
|
||
}
|
||
if (!this.formData.c_ln_m || !this.formData.c_fn_m) {
|
||
errors.push('请输入姓名');
|
||
}
|
||
if (!this.selectedCountry) {
|
||
errors.push('请选择国家/地区');
|
||
}
|
||
if (this.selectedCountry === 'CN' && (!this.formData.c_st_m || !this.formData.c_ct_m)) {
|
||
errors.push('请选择所属区域');
|
||
}
|
||
if (this.selectedCountry !== 'CN' && (!this.formData.c_st_m || !this.formData.c_ct_m)) {
|
||
errors.push('请输入省份/州和城市');
|
||
}
|
||
if (!this.formData.c_adr_m) {
|
||
errors.push('请输入通讯地址');
|
||
}
|
||
if (!this.formData.c_pc) {
|
||
errors.push('请输入邮编');
|
||
}
|
||
// 验证手机号码
|
||
if (!this.formData.c_ph) {
|
||
errors.push('请输入手机号码');
|
||
}
|
||
|
||
// 企业类型验证
|
||
if (this.formData.c_regtype === 'E' && !this.formData.c_org_m) {
|
||
errors.push('企业类型必须填写单位名称');
|
||
}
|
||
if (!this.formData.c_em) {
|
||
errors.push('请输入电子邮箱');
|
||
}
|
||
if (!this.formData.c_idtype_gswl) {
|
||
errors.push('请选择证件类型');
|
||
}
|
||
if (!this.formData.c_idnum_gswl) {
|
||
errors.push('请输入证件号码');
|
||
} else if (this.formData.c_idtype_gswl === 'SFZ') {
|
||
const idNum = this.formData.c_idnum_gswl;
|
||
if (idNum.length !== 18) {
|
||
errors.push('身份证号码必须是18位');
|
||
} else if (!(idNum.slice(0, 17).match(/^\d+$/) && (idNum[17].match(/^\d$/) || idNum[17].toUpperCase() === 'X'))) {
|
||
errors.push('身份证号码格式不正确');
|
||
}
|
||
}
|
||
|
||
return errors;
|
||
},
|
||
resetForm() {
|
||
this.formData = {
|
||
c_regtype: 'I',
|
||
c_org_m: '',
|
||
c_ln_m: '',
|
||
c_fn_m: '',
|
||
c_st_m: '',
|
||
c_ct_m: '',
|
||
c_dt_m: '',
|
||
c_adr_m: '',
|
||
c_pc: '',
|
||
c_ph_type: '0',
|
||
c_ph: '',
|
||
c_em: '',
|
||
c_idtype_gswl: 'SFZ', // 个人默认证件类型
|
||
c_idnum_gswl: ''
|
||
};
|
||
this.selectedCountry = 'CN';
|
||
this.selectedProvince = '';
|
||
this.selectedCity = '';
|
||
this.selectedDistrict = '';
|
||
this.idNumberError = '';
|
||
},
|
||
onCountryChange() {
|
||
// 重置省市区选择
|
||
this.selectedProvince = '';
|
||
this.selectedCity = '';
|
||
this.selectedDistrict = '';
|
||
this.formData.c_st_m = '';
|
||
this.formData.c_ct_m = '';
|
||
this.formData.c_dt_m = '';
|
||
},
|
||
onProvinceChange() {
|
||
this.selectedCity = '';
|
||
this.selectedDistrict = '';
|
||
this.formData.c_st_m = this.selectedProvince;
|
||
this.formData.c_ct_m = '';
|
||
this.formData.c_dt_m = '';
|
||
},
|
||
onCityChange() {
|
||
this.selectedDistrict = '';
|
||
this.formData.c_ct_m = this.selectedCity;
|
||
this.formData.c_dt_m = '';
|
||
},
|
||
onDistrictChange() {
|
||
this.formData.c_dt_m = this.selectedDistrict;
|
||
},
|
||
onCertificateTypeChange() {
|
||
// 清空证件号码和错误信息
|
||
this.formData.c_idnum_gswl = '';
|
||
this.idNumberError = '';
|
||
},
|
||
onRegTypeChange() {
|
||
// 根据所有者类型设置默认证件类型
|
||
if (this.formData.c_regtype === 'I') {
|
||
this.formData.c_idtype_gswl = 'SFZ'; // 个人默认身份证
|
||
} else {
|
||
this.formData.c_idtype_gswl = 'YYZZ'; // 企业默认营业执照
|
||
}
|
||
// 清空证件号码和错误信息
|
||
this.formData.c_idnum_gswl = '';
|
||
this.idNumberError = '';
|
||
},
|
||
getCurrentCities() {
|
||
if (!this.selectedProvince) return [];
|
||
return getCitiesByProvince(this.selectedProvince);
|
||
},
|
||
getCurrentDistricts() {
|
||
if (!this.selectedCity || !this.selectedProvince) return [];
|
||
return getDistrictsByCity(this.selectedProvince, this.selectedCity);
|
||
},
|
||
getCertificateTypeOptions() {
|
||
return this.formData.c_regtype === 'I'
|
||
? [
|
||
{ value: 'SFZ', label: '身份证' },
|
||
{ value: 'HZ', label: '护照' }
|
||
]
|
||
: [
|
||
{ value: 'YYZZ', label: '营业执照' },
|
||
{ value: 'ORG', label: '组织机构代码证' }
|
||
];
|
||
},
|
||
getCertificatePlaceholder() {
|
||
if (this.formData.c_idtype_gswl === 'SFZ') {
|
||
return '请输入18位身份证号码';
|
||
} else if (this.formData.c_idtype_gswl === 'HZ') {
|
||
return '请输入护照号码';
|
||
} else if (this.formData.c_idtype_gswl === 'YYZZ') {
|
||
return '请输入营业执照号码';
|
||
} else if (this.formData.c_idtype_gswl === 'ORG') {
|
||
return '请输入组织机构代码证号码';
|
||
}
|
||
return '请输入证件号码';
|
||
},
|
||
validateIdNumber() {
|
||
this.idNumberError = '';
|
||
|
||
if (!this.formData.c_idnum_gswl) {
|
||
return;
|
||
}
|
||
|
||
if (this.formData.c_idtype_gswl === 'SFZ') {
|
||
const idNum = this.formData.c_idnum_gswl;
|
||
if (idNum.length !== 18) {
|
||
this.idNumberError = `身份证号码必须是18位,当前为${idNum.length}位`;
|
||
return;
|
||
}
|
||
|
||
// 验证格式:前17位为数字,最后一位可能是数字或X
|
||
if (!(idNum.slice(0, 17).match(/^\d+$/) && (idNum[17].match(/^\d$/) || idNum[17].toUpperCase() === 'X'))) {
|
||
this.idNumberError = '身份证号码格式不正确';
|
||
return;
|
||
}
|
||
}
|
||
},
|
||
|
||
},
|
||
resources: {
|
||
createDomainOwner() {
|
||
return {
|
||
url: 'jcloud.api.domain_west.create_domain_owner_with_template',
|
||
onSuccess(response) {
|
||
return response;
|
||
},
|
||
onError(error) {
|
||
throw error;
|
||
}
|
||
};
|
||
}
|
||
}
|
||
};
|
||
</script> |