新建域名界面增加域名所有者选项框,增加新建域名所有者弹窗对话框,增加中国省市区3级联动的完整数据ts文件及调用接口

This commit is contained in:
jingrow 2025-08-01 20:15:12 +08:00
parent 44d44d6355
commit 9e8375574d
5 changed files with 6594 additions and 44 deletions

View File

@ -0,0 +1,441 @@
<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-xl max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<div class="p-6 border-b border-gray-200">
<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"
>
<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">
<!-- 重要提醒 -->
<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"
class="mr-2"
>
<span class="text-sm">个人</span>
</label>
<label class="flex items-center">
<input
type="radio"
v-model="formData.c_regtype"
value="E"
class="mr-2"
>
<span class="text-sm">企业/组织</span>
</label>
</div>
</div>
<!-- 国家选择 -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-2">国家/地区 *</label>
<select
v-model="selectedCountry"
@change="onCountryChange"
class="w-full border rounded px-3 py-2"
>
<option value="">请选择国家/地区</option>
<option v-for="country in countryList" :key="country.code" :value="country.code">
{{ country.name }}
</option>
</select>
</div>
<!-- 中文信息 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- 单位名称企业时显示 -->
<div v-if="formData.c_regtype === 'E'">
<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 px-3 py-2"
placeholder="请输入单位名称"
>
</div>
<!-- 姓名 -->
<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 px-3 py-2"
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 px-3 py-2"
placeholder="请输入名"
>
</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 px-3 py-2"
>
<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 px-3 py-2"
: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 px-3 py-2"
: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 px-3 py-2"
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 px-3 py-2"
placeholder="请输入城市"
>
</div>
<!-- 通讯地址 -->
<div class="md:col-span-2">
<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 px-3 py-2"
placeholder="请输入详细地址"
>
</div>
<!-- 邮编 -->
<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 px-3 py-2"
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-md">
+86
</span>
<input
v-model="formData.c_ph_num"
type="text"
class="flex-1 border rounded-r-md px-3 py-2"
placeholder="请输入手机号码"
>
</div>
</div>
<!-- 电子邮箱 -->
<div class="md:col-span-2">
<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 px-3 py-2"
placeholder="请输入邮箱地址"
>
</div>
<!-- 证件类型 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">证件类型 *</label>
<select
v-model="formData.c_idtype_gswl"
class="w-full border rounded px-3 py-2"
>
<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 px-3 py-2"
placeholder="请输入证件号码"
>
</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-4 py-2 border border-gray-300 bg-white text-gray-700 rounded hover:bg-gray-50"
>
取消
</button>
<button
type="submit"
:disabled="isLoading"
class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-300"
>
{{ 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_num: '', //
c_em: '', //
c_idtype_gswl: '', //
c_idnum_gswl: '' //
},
selectedCountry: 'CN',
selectedProvince: '',
selectedCity: '',
selectedDistrict: '',
countryList: getCountryList(),
chinaRegions: getChinaRegions()
};
},
methods: {
closeDialog() {
this.resetForm();
this.$emit('close');
},
handleSubmit() {
//
const errors = this.validateForm();
if (errors.length > 0) {
alert(errors[0]); //
return;
}
this.$emit('submit', this.formData);
},
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_num) {
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('请输入证件号码');
}
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_num: '',
c_em: '',
c_idtype_gswl: '',
c_idnum_gswl: ''
};
this.selectedCountry = 'CN';
this.selectedProvince = '';
this.selectedCity = '';
this.selectedDistrict = '';
},
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;
},
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: '身份证', label: '身份证' },
{ value: '护照', label: '护照' }
]
: [
{ value: '营业执照', label: '营业执照' },
{ value: '组织机构代码证', label: '组织机构代码证' }
];
}
}
};
</script>

View File

@ -145,6 +145,33 @@
</div>
<div v-if="domainCheckResult && domainCheckResult.available">
<!-- 域名所有者选择 -->
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">域名所有者 *</label>
<div class="flex gap-2">
<select
v-model="selectedDomainOwner"
class="flex-1 border rounded px-3 py-2"
required
>
<option value="">请选择域名所有者</option>
<option v-for="owner in domainOwners" :key="owner.name" :value="owner.name">
{{ owner.title }}
</option>
</select>
<button
@click="showNewOwnerDialog = true"
type="button"
class="px-4 py-2 border border-gray-300 bg-white text-gray-700 rounded hover:bg-gray-50 flex items-center gap-2"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
新建域名所有者
</button>
</div>
</div>
<label class="block text-sm font-medium text-gray-700 mb-2">购买时长</label>
<select v-model="period" class="w-full border rounded px-3 py-2">
<option v-for="p in periods" :key="p.value" :value="p.value">{{ p.label }}</option>
@ -324,6 +351,14 @@
</div>
</div>
</div>
<!-- 新建域名所有者对话框 -->
<DomainOwnerDialog
:visible="showNewOwnerDialog"
:is-loading="isCreatingOwner"
@close="showNewOwnerDialog = false"
@submit="handleOwnerSubmit"
/>
</div>
</template>
@ -332,13 +367,16 @@ import { toast } from 'vue-sonner';
import { DashboardError } from '../utils/error';
import AlipayLogo from '../logo/AlipayLogo.vue';
import WeChatPayLogo from '../logo/WeChatPayLogo.vue';
import DomainOwnerDialog from '../components/DomainOwnerDialog.vue';
import router from '../router';
import { getChinaRegions } from '../utils/regions';
export default {
name: 'NewJsiteDomain',
components: {
AlipayLogo,
WeChatPayLogo
WeChatPayLogo,
DomainOwnerDialog
},
data() {
return {
@ -373,6 +411,11 @@ export default {
suffixSort: 'default',
selectedCategory: 'popular',
showSuffixSelector: false,
//
selectedDomainOwner: '',
domainOwners: [],
showNewOwnerDialog: false,
isCreatingOwner: false,
suffixCategories: [
{ key: 'popular', label: '热门域名' },
{ key: 'gtd', label: '通用顶级域名' },
@ -898,10 +941,79 @@ export default {
}
};
},
//
getDomainOwners() {
return {
url: 'jcloud.api.domain_west.get_domain_owners',
onSuccess(response) {
if (response.status === "Success") {
this.domainOwners = response.data || [];
}
},
onError(error) {
console.error('获取域名所有者列表失败:', error);
}
};
},
//
createDomainOwner() {
return {
url: 'jcloud.api.domain_west.create_domain_owner',
validate() {
if (!this.newOwnerForm.c_regtype) {
throw new DashboardError('请选择所有者类型');
}
if (!this.newOwnerForm.c_ln_m || !this.newOwnerForm.c_fn_m) {
throw new DashboardError('请输入姓名');
}
if (!this.newOwnerForm.c_st_m || !this.newOwnerForm.c_ct_m) {
throw new DashboardError('请选择所属区域');
}
if (!this.newOwnerForm.c_adr_m) {
throw new DashboardError('请输入通讯地址');
}
if (!this.newOwnerForm.c_pc) {
throw new DashboardError('请输入邮编');
}
if (!this.newOwnerForm.c_ph_num) {
throw new DashboardError('请输入联系电话');
}
if (!this.newOwnerForm.c_em) {
throw new DashboardError('请输入电子邮箱');
}
if (!this.newOwnerForm.c_idtype_gswl) {
throw new DashboardError('请选择证件类型');
}
if (!this.newOwnerForm.c_idnum_gswl) {
throw new DashboardError('请输入证件号码');
}
},
onSuccess(response) {
if (response.status === "Success") {
toast.success('域名所有者创建成功');
this.showNewOwnerDialog = false;
this.isCreatingOwner = false;
//
this.$resources.getDomainOwners.submit();
} else {
toast.error(response.message || '创建失败');
this.isCreatingOwner = false;
}
},
onError(error) {
toast.error(error.message || '创建域名所有者失败');
this.isCreatingOwner = false;
}
};
},
},
mounted() {
//
document.addEventListener('click', this.handleClickOutside);
//
this.$resources.getDomainOwners.submit();
},
beforeUnmount() {
this.stopPaymentCheck();
@ -935,6 +1047,10 @@ export default {
this.error = '请先查询域名可用性';
return;
}
if (!this.selectedDomainOwner) {
this.error = '请选择域名所有者';
return;
}
if (!this.selectedPaymentMethod) {
this.error = '请选择支付方式';
return;
@ -946,7 +1062,8 @@ export default {
await this.$resources.createDomainOrder.submit({
domain: this.fullDomain,
period: this.period,
payment_method: this.selectedPaymentMethod
payment_method: this.selectedPaymentMethod,
domain_owner: this.selectedDomainOwner
});
this.isLoading = false;
@ -996,6 +1113,10 @@ export default {
goToDomainList() {
this.$router.push('/domains');
},
handleOwnerSubmit(formData) {
this.isCreatingOwner = true;
this.$resources.createDomainOwner.submit(formData);
},
getTotalAmount() {
const yearlyPrice = this.domainPrice || 0;
return (yearlyPrice * this.period).toFixed(2);
@ -1014,7 +1135,6 @@ export default {
}
}
},
},
};
</script>

File diff suppressed because it is too large Load Diff

View File

@ -79,6 +79,7 @@ ALLOWED_PAGETYPES = [
"Mpesa Payment Record",
"Jsite Server",
"Jsite Domain",
"Domain Owner",
]
ALLOWED_PAGETYPES_FOR_SUPPORT = [

View File

@ -679,7 +679,7 @@ def west_domain_get_template_detail(**data):
@jingrow.whitelist()
def create_domain_order(domain, period=1, payment_method='balance'):
def create_domain_order(domain, period=1, payment_method='balance', domain_owner=None):
"""创建域名注册订单"""
try:
# 获取当前用户团队
@ -689,6 +689,19 @@ def create_domain_order(domain, period=1, payment_method='balance'):
if not domain or '.' not in domain:
return {"success": False, "message": "域名格式不正确"}
# 验证域名所有者
if not domain_owner:
return {"success": False, "message": "请选择域名所有者"}
# 检查域名所有者是否存在
owner_exists = jingrow.get_all(
"Domain Owner",
{"name": domain_owner, "team": team.name},
["name"]
)
if not owner_exists:
return {"success": False, "message": "域名所有者不存在"}
# 查询域名价格
client = get_west_client()
if not client:
@ -709,6 +722,23 @@ def create_domain_order(domain, period=1, payment_method='balance'):
# 生成订单号
order_id = f"{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))}"
# 构建业务参数
biz_params = {
"domain": domain,
"period": period,
"domain_owner": domain_owner,
"yearly_price": yearly_price,
"domain_registrar": "西部数码",
"auto_renew": False,
"whois_protection": True,
# 注册域名所需参数
"regyear": period,
"dns_host1": "ns1.myhostadmin.net",
"dns_host2": "ns2.myhostadmin.net",
"c_sysid": "1681988",
"client_price": None
}
# 创建订单记录
order = jingrow.get_pg({
"pagetype": "Order",
@ -718,32 +748,17 @@ def create_domain_order(domain, period=1, payment_method='balance'):
"status": "待支付",
"total_amount": total_amount,
"title": domain,
"description": f"{period}"
"description": f"{period}",
"biz_params": json.dumps(biz_params, ensure_ascii=False)
})
order.insert(ignore_permissions=True)
# 创建域名记录
domain_doc = jingrow.get_pg({
"pagetype": "Jsite Domain",
"domain": domain,
"team": team.name,
"order_id": order_id,
"status": "Pending",
"price": yearly_price,
"period": period,
"domain_registrar": "西部数码",
"auto_renew": False,
"whois_protection": True
})
domain_doc.insert(ignore_permissions=True)
jingrow.db.commit()
return {
"success": True,
"message": "订单创建成功",
"order": order.as_dict(),
"domain": domain_doc.as_dict()
"order": order.as_dict()
}
except Exception as e:
@ -781,6 +796,20 @@ def create_domain_renew_order(**kwargs):
# 生成唯一订单号
order_id = f"{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))}"
# 构建业务参数
biz_params = {
"domain": domain_pg.domain,
"domain_name": domain, # 域名记录的名称
"renewal_years": renewal_years,
"yearly_price": yearly_price,
"domain_owner": domain_pg.domain_owner,
"domain_registrar": domain_pg.domain_registrar or "西部数码",
# 续费域名所需参数
"year": renewal_years,
"expire_date": None,
"client_price": None
}
# 创建订单记录
order = jingrow.get_pg({
"pagetype": "Order",
@ -790,7 +819,8 @@ def create_domain_renew_order(**kwargs):
"status": "待支付",
"total_amount": total_amount,
"title": domain_pg.domain,
"description": str(renewal_years) # 存储续费年数
"description": str(renewal_years), # 存储续费年数
"biz_params": json.dumps(biz_params, ensure_ascii=False)
})
order.insert(ignore_permissions=True)
@ -815,14 +845,18 @@ def register_domain_from_order(order_name):
if not order:
raise Exception("订单不存在")
# 查找对应的域名记录通过订单ID
domain = jingrow.get_pg("Jsite Domain", {"order_id": order.order_id})
if not domain:
raise Exception("找不到对应的域名记录")
# 从biz_params中读取业务参数
biz_params = json.loads(order.biz_params) if order.biz_params else {}
domain_name = biz_params.get("domain")
period = biz_params.get("period", 1)
domain_owner = biz_params.get("domain_owner")
yearly_price = biz_params.get("yearly_price", 0)
domain_registrar = biz_params.get("domain_registrar", "西部数码")
auto_renew = biz_params.get("auto_renew", False)
whois_protection = biz_params.get("whois_protection", True)
# 从域名记录中获取配置信息
domain_name = domain.domain
period = domain.period or 1
if not domain_name:
raise Exception("订单中缺少域名信息")
# 调用西部数码API注册域名
client = get_west_client()
@ -831,10 +865,11 @@ def register_domain_from_order(order_name):
result = client.register_domain(
domain=domain_name,
regyear=period,
dns_host1="ns1.myhostadmin.net",
dns_host2="ns2.myhostadmin.net",
c_sysid="1681988"
regyear=biz_params.get("regyear", period),
dns_host1=biz_params.get("dns_host1", "ns1.myhostadmin.net"),
dns_host2=biz_params.get("dns_host2", "ns2.myhostadmin.net"),
c_sysid=biz_params.get("c_sysid", "1681988"),
client_price=biz_params.get("client_price")
)
# 打印result到后台日志
@ -844,11 +879,23 @@ def register_domain_from_order(order_name):
error_msg = result.get('msg', result.get('message', '未知错误'))
raise Exception(f"域名注册失败: {error_msg}")
# 更新域名记录状态
domain.status = "Active"
domain.registration_date = jingrow.utils.nowdate()
domain.end_date = jingrow.utils.add_months(jingrow.utils.nowdate(), period * 12)
domain.save(ignore_permissions=True)
# 创建域名记录
domain_doc = jingrow.get_pg({
"pagetype": "Jsite Domain",
"domain": domain_name,
"team": order.team,
"order_id": order.order_id,
"status": "Active",
"price": yearly_price,
"period": period,
"domain_registrar": domain_registrar,
"domain_owner": domain_owner,
"auto_renew": auto_renew,
"whois_protection": whois_protection,
"registration_date": jingrow.utils.nowdate(),
"end_date": jingrow.utils.add_months(jingrow.utils.nowdate(), period * 12)
})
domain_doc.insert(ignore_permissions=True)
# 更新订单状态
order.status = "交易成功"
@ -870,12 +917,17 @@ def renew_domain_from_order(order_name):
if not order:
raise Exception("订单不存在")
# 从订单中获取信息
domain_name = order.title # 域名
renewal_years = int(order.description) # 续费年数
# 从biz_params中读取业务参数
biz_params = json.loads(order.biz_params) if order.biz_params else {}
domain_name = biz_params.get("domain")
renewal_years = biz_params.get("renewal_years", 1)
domain_record_name = biz_params.get("domain_name") # 域名记录的名称
if not domain_name:
raise Exception("订单中缺少域名信息")
# 查找域名记录
domain = jingrow.get_pg("Jsite Domain", {"domain": domain_name})
domain = jingrow.get_pg("Jsite Domain", domain_record_name)
if not domain:
raise Exception("找不到对应的域名记录")
@ -884,7 +936,12 @@ def renew_domain_from_order(order_name):
if not client:
raise Exception("API客户端初始化失败")
result = client.renew_domain(domain_name, renewal_years)
result = client.renew_domain(
domain_name,
biz_params.get("year", renewal_years),
biz_params.get("expire_date"),
biz_params.get("client_price")
)
# 打印result到后台日志
jingrow.log_error("西部数码域名续费结果", f"订单 {order_name} 的续费结果: {result}")
@ -989,3 +1046,200 @@ def delete_domain(pagetype, name):
jingrow.log_error("域名管理", f"删除域名记录失败: {str(e)}")
return {"success": False, "message": f"删除失败: {str(e)}"}
@jingrow.whitelist()
def get_domain_owners():
"""获取当前团队的域名所有者列表"""
try:
team = get_current_team()
if not team:
return {"status": "Error", "message": "未找到当前团队"}
# 获取当前团队的所有域名所有者
domain_owners = jingrow.get_all(
"Domain Owner",
{"team": team},
["name", "title", "fullname", "c_regtype", "c_org_m", "c_ln_m", "c_fn_m"]
)
return {
"status": "Success",
"data": domain_owners
}
except Exception as e:
jingrow.log_error("获取域名所有者列表失败", str(e))
return {"status": "Error", "message": f"获取域名所有者列表失败: {str(e)}"}
@jingrow.whitelist()
def create_domain_owner(data):
"""创建新的域名所有者"""
try:
team = get_current_team()
if not team:
return {"status": "Error", "message": "未找到当前团队"}
# 验证必填字段
required_fields = ['c_regtype', 'c_ln_m', 'c_fn_m', 'c_st_m', 'c_ct_m', 'c_adr_m', 'c_pc', 'c_ph_num', 'c_em']
for field in required_fields:
if not data.get(field):
return {"status": "Error", "message": f"字段 {field} 是必填项"}
# 生成英文信息
from pypinyin import lazy_pinyin
# 生成英文姓名
if data.get('c_ln_m') and data.get('c_fn_m'):
last_name_pinyin = ' '.join(lazy_pinyin(data['c_ln_m']))
first_name_pinyin = ' '.join(lazy_pinyin(data['c_fn_m']))
data['c_ln'] = last_name_pinyin.title()
data['c_fn'] = first_name_pinyin.title()
# 生成英文地址
if data.get('c_adr_m'):
address_pinyin = ' '.join(lazy_pinyin(data['c_adr_m']))
data['c_adr'] = address_pinyin.title()
# 生成英文省份和城市
if data.get('c_st_m'):
state_pinyin = ' '.join(lazy_pinyin(data['c_st_m']))
data['c_st'] = state_pinyin.title()
if data.get('c_ct_m'):
city_pinyin = ' '.join(lazy_pinyin(data['c_ct_m']))
data['c_ct'] = city_pinyin.title()
# 生成英文单位名称
if data.get('c_org_m'):
org_pinyin = ' '.join(lazy_pinyin(data['c_org_m']))
data['c_org'] = org_pinyin.title()
# 设置默认值
data['team'] = team
data['c_co'] = 'CN' # 中国
data['cocode'] = '+86'
data['c_ph_type'] = '0' # 手机
data['c_ph_code'] = '+86'
data['reg_contact_type'] = 'cg' # 常规
# 生成标题
if data['c_regtype'] == 'I': # 个人
data['title'] = f"{data['c_ln_m']}{data['c_fn_m']} - 个人"
else: # 企业
data['title'] = f"{data['c_org_m']} - 企业"
# 创建域名所有者记录
domain_owner = jingrow.get_pg({
"pagetype": "Domain Owner",
**data
})
domain_owner.insert()
return {
"status": "Success",
"message": "域名所有者创建成功",
"data": {
"name": domain_owner.name,
"title": domain_owner.title
}
}
except Exception as e:
jingrow.log_error("创建域名所有者失败", str(e))
return {"status": "Error", "message": f"创建域名所有者失败: {str(e)}"}
@jingrow.whitelist()
def get_china_regions():
"""获取中国省市县数据"""
provinces = [
{'code': '11', 'name': '北京市', 'cities': [
{'code': '1101', 'name': '北京市', 'districts': [
{'code': '110101', 'name': '东城区'},
{'code': '110102', 'name': '西城区'},
{'code': '110105', 'name': '朝阳区'},
{'code': '110106', 'name': '丰台区'},
{'code': '110107', 'name': '石景山区'},
{'code': '110108', 'name': '海淀区'},
{'code': '110109', 'name': '门头沟区'},
{'code': '110111', 'name': '房山区'},
{'code': '110112', 'name': '通州区'},
{'code': '110113', 'name': '顺义区'},
{'code': '110114', 'name': '昌平区'},
{'code': '110115', 'name': '大兴区'},
{'code': '110116', 'name': '怀柔区'},
{'code': '110117', 'name': '平谷区'},
{'code': '110118', 'name': '密云区'},
{'code': '110119', 'name': '延庆区'}
]}
]},
{'code': '12', 'name': '天津市', 'cities': [
{'code': '1201', 'name': '天津市', 'districts': [
{'code': '120101', 'name': '和平区'},
{'code': '120102', 'name': '河东区'},
{'code': '120103', 'name': '河西区'},
{'code': '120104', 'name': '南开区'},
{'code': '120105', 'name': '河北区'},
{'code': '120106', 'name': '红桥区'},
{'code': '120110', 'name': '东丽区'},
{'code': '120111', 'name': '西青区'},
{'code': '120112', 'name': '津南区'},
{'code': '120113', 'name': '北辰区'},
{'code': '120114', 'name': '武清区'},
{'code': '120115', 'name': '宝坻区'},
{'code': '120116', 'name': '滨海新区'},
{'code': '120117', 'name': '宁河区'},
{'code': '120118', 'name': '静海区'},
{'code': '120119', 'name': '蓟州区'}
]}
]},
{'code': '31', 'name': '上海市', 'cities': [
{'code': '3101', 'name': '上海市', 'districts': [
{'code': '310101', 'name': '黄浦区'},
{'code': '310104', 'name': '徐汇区'},
{'code': '310105', 'name': '长宁区'},
{'code': '310106', 'name': '静安区'},
{'code': '310107', 'name': '普陀区'},
{'code': '310109', 'name': '虹口区'},
{'code': '310110', 'name': '杨浦区'},
{'code': '310112', 'name': '闵行区'},
{'code': '310113', 'name': '宝山区'},
{'code': '310114', 'name': '嘉定区'},
{'code': '310115', 'name': '浦东新区'},
{'code': '310116', 'name': '金山区'},
{'code': '310117', 'name': '松江区'},
{'code': '310118', 'name': '青浦区'},
{'code': '310120', 'name': '奉贤区'},
{'code': '310151', 'name': '崇明区'}
]}
]},
{'code': '44', 'name': '广东省', 'cities': [
{'code': '4401', 'name': '广州市', 'districts': [
{'code': '440103', 'name': '荔湾区'},
{'code': '440104', 'name': '越秀区'},
{'code': '440105', 'name': '海珠区'},
{'code': '440106', 'name': '天河区'},
{'code': '440111', 'name': '白云区'},
{'code': '440112', 'name': '黄埔区'},
{'code': '440113', 'name': '番禺区'},
{'code': '440114', 'name': '花都区'},
{'code': '440115', 'name': '南沙区'},
{'code': '440117', 'name': '从化区'},
{'code': '440118', 'name': '增城区'}
]},
{'code': '4403', 'name': '深圳市', 'districts': [
{'code': '440303', 'name': '罗湖区'},
{'code': '440304', 'name': '福田区'},
{'code': '440305', 'name': '南山区'},
{'code': '440306', 'name': '宝安区'},
{'code': '440307', 'name': '龙岗区'},
{'code': '440308', 'name': '盐田区'},
{'code': '440309', 'name': '龙华区'},
{'code': '440310', 'name': '坪山区'},
{'code': '440311', 'name': '光明区'}
]}
]}
]
return {
"status": "Success",
"data": provinces
}