域名详情页实名认证检测通过
This commit is contained in:
parent
81d623b653
commit
b8ae5c7b3d
@ -9,7 +9,49 @@
|
|||||||
<div class="rounded-md border">
|
<div class="rounded-md border">
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="flex h-full flex-col sm:flex-row sm:items-center sm:justify-between">
|
<div class="flex h-full flex-col sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div class="mb-4 sm:mb-0">
|
<div class="mb-4 sm:mb-0">
|
||||||
|
<!-- 实名认证状态 -->
|
||||||
|
<div class="mb-4 p-4 bg-gradient-to-r from-gray-50 to-blue-50 rounded-xl border border-gray-200">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center space-x-3">
|
||||||
|
<div v-if="realNameStatus === 'verified'" class="flex items-center space-x-3">
|
||||||
|
<div class="inline-flex items-center rounded-full bg-gradient-to-r from-green-50 to-emerald-50 px-4 py-2 text-sm font-semibold text-green-800 border border-green-200 shadow-sm">
|
||||||
|
<svg class="mr-2 h-4 w-4 text-green-600" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
实名认证
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
@click="showRealNameInfo"
|
||||||
|
class="inline-flex items-center px-3 py-1.5 text-sm font-medium text-blue-700 bg-blue-100 hover:bg-blue-200 rounded-lg transition-colors duration-200 border border-blue-300"
|
||||||
|
>
|
||||||
|
<svg class="mr-1.5 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
查看认证信息
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex items-center space-x-3">
|
||||||
|
<div class="inline-flex items-center rounded-full bg-gradient-to-r from-amber-50 to-orange-50 px-4 py-2 text-sm font-semibold text-amber-800 border border-amber-200 shadow-sm">
|
||||||
|
<svg class="mr-2 h-4 w-4 text-amber-600" 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>
|
||||||
|
<button
|
||||||
|
@click="showUploadRealName"
|
||||||
|
class="inline-flex items-center px-3 py-1.5 text-sm font-medium text-white bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 rounded-lg transition-all duration-200 shadow-sm hover:shadow-md"
|
||||||
|
>
|
||||||
|
<svg class="mr-1.5 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
|
||||||
|
</svg>
|
||||||
|
上传实名资料
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="$domain.pg.end_date" class="mt-2 inline-flex items-center rounded-full bg-amber-50 px-4 py-2 text-sm font-medium text-amber-800">
|
<div v-if="$domain.pg.end_date" class="mt-2 inline-flex items-center rounded-full bg-amber-50 px-4 py-2 text-sm font-medium text-amber-800">
|
||||||
<ClockIcon class="mr-1.5 h-4 w-4 text-amber-500" />
|
<ClockIcon class="mr-1.5 h-4 w-4 text-amber-500" />
|
||||||
到期时间:{{ $format.date($domain.pg.end_date) }}
|
到期时间:{{ $format.date($domain.pg.end_date) }}
|
||||||
@ -158,6 +200,8 @@ export default {
|
|||||||
autoRenewLoading: false,
|
autoRenewLoading: false,
|
||||||
whoisProtectionLoading: false,
|
whoisProtectionLoading: false,
|
||||||
domainOwner: null,
|
domainOwner: null,
|
||||||
|
realNameStatus: 'unverified', // 实名认证状态:verified, unverified
|
||||||
|
realNameInfo: null, // 实名认证信息
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -196,6 +240,7 @@ export default {
|
|||||||
async getDomainOwner() {
|
async getDomainOwner() {
|
||||||
if (!this.$domain.pg?.domain_owner) {
|
if (!this.$domain.pg?.domain_owner) {
|
||||||
this.domainOwner = null;
|
this.domainOwner = null;
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,17 +253,33 @@ export default {
|
|||||||
onSuccess: (response) => {
|
onSuccess: (response) => {
|
||||||
if (response && response.status === "Success" && response.data) {
|
if (response && response.status === "Success" && response.data) {
|
||||||
this.domainOwner = response.data;
|
this.domainOwner = response.data;
|
||||||
|
// 根据域名所有者记录的r_status字段设置实名认证状态
|
||||||
|
// r_status是check字段类型,1表示已认证,0表示未认证
|
||||||
|
const rStatus = response.data.r_status;
|
||||||
|
|
||||||
|
// 对于check字段,将值转换为布尔值进行判断
|
||||||
|
const isVerified = Boolean(rStatus && (rStatus === 1 || rStatus === '1' || rStatus === true));
|
||||||
|
|
||||||
|
if (isVerified) {
|
||||||
|
this.realNameStatus = 'verified';
|
||||||
|
} else {
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error('获取域名所有者信息失败:', error);
|
console.error('获取域名所有者信息失败:', error);
|
||||||
this.domainOwner = null;
|
this.domainOwner = null;
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
getOwnerRequest.submit();
|
getOwnerRequest.submit();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取域名所有者信息失败:', error);
|
console.error('获取域名所有者信息失败:', error);
|
||||||
this.domainOwner = null;
|
this.domainOwner = null;
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renewDomain() {
|
renewDomain() {
|
||||||
@ -323,6 +384,58 @@ export default {
|
|||||||
toast.success('域名续费成功!');
|
toast.success('域名续费成功!');
|
||||||
this.$domain.reload();
|
this.$domain.reload();
|
||||||
},
|
},
|
||||||
|
// 显示实名认证信息
|
||||||
|
showRealNameInfo() {
|
||||||
|
const JsiteDomainRealNameInfoDialog = defineAsyncComponent(() => import('./JsiteDomainRealNameInfoDialog.vue'));
|
||||||
|
|
||||||
|
renderDialog(h(JsiteDomainRealNameInfoDialog, {
|
||||||
|
domain: this.domain,
|
||||||
|
domainDoc: this.$domain.pg,
|
||||||
|
realNameInfo: this.realNameInfo
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
// 显示上传实名资料
|
||||||
|
showUploadRealName() {
|
||||||
|
const JsiteDomainUploadRealNameDialog = defineAsyncComponent(() => import('./JsiteDomainUploadRealNameDialog.vue'));
|
||||||
|
|
||||||
|
renderDialog(h(JsiteDomainUploadRealNameDialog, {
|
||||||
|
domain: this.domain,
|
||||||
|
domainDoc: this.$domain.pg,
|
||||||
|
onSuccess: this.onUploadSuccess
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
// 上传成功回调
|
||||||
|
onUploadSuccess() {
|
||||||
|
toast.success('实名资料上传成功!');
|
||||||
|
this.getDomainOwner(); // 重新获取域名所有者信息(包含实名认证状态)
|
||||||
|
this.getRealNameInfo(); // 重新获取实名详细信息
|
||||||
|
},
|
||||||
|
// 获取域名实名认证信息
|
||||||
|
async getRealNameInfo() {
|
||||||
|
if (!this.$domain.pg?.domain) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const getRealNameRequest = createResource({
|
||||||
|
url: 'jcloud.api.domain_west.get_west_domain_real_info',
|
||||||
|
params: {
|
||||||
|
domain: this.$domain.pg.domain
|
||||||
|
},
|
||||||
|
onSuccess: (response) => {
|
||||||
|
if (response && response.status === "success" && response.data) {
|
||||||
|
this.realNameInfo = response.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error('获取域名实名信息失败:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getRealNameRequest.submit();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取域名实名信息失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
// 监听域名数据变化,重新获取所有者信息
|
// 监听域名数据变化,重新获取所有者信息
|
||||||
@ -332,6 +445,7 @@ export default {
|
|||||||
this.getDomainOwner();
|
this.getDomainOwner();
|
||||||
} else {
|
} else {
|
||||||
this.domainOwner = null;
|
this.domainOwner = null;
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
@ -366,7 +480,11 @@ export default {
|
|||||||
// 初始化时获取域名所有者信息
|
// 初始化时获取域名所有者信息
|
||||||
if (this.$domain.pg?.domain_owner) {
|
if (this.$domain.pg?.domain_owner) {
|
||||||
this.getDomainOwner();
|
this.getDomainOwner();
|
||||||
|
} else {
|
||||||
|
this.realNameStatus = 'unverified';
|
||||||
}
|
}
|
||||||
|
// 获取域名实名认证信息
|
||||||
|
this.getRealNameInfo();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
318
dashboard/src2/components/JsiteDomainRealNameInfoDialog.vue
Normal file
318
dashboard/src2/components/JsiteDomainRealNameInfoDialog.vue
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog v-bind="$attrs" :options="{ title: '实名认证信息', size: '3xl' }">
|
||||||
|
<template #body>
|
||||||
|
<div v-if="loading" class="flex justify-center items-center py-12">
|
||||||
|
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
||||||
|
<span class="ml-3 text-gray-600">加载中...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="error" class="text-center py-12">
|
||||||
|
<div class="text-red-500 mb-4">
|
||||||
|
<AlertTriangleIcon class="h-12 w-12 mx-auto" />
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-600">{{ error }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="realNameData" class="space-y-6">
|
||||||
|
<!-- 认证状态 -->
|
||||||
|
<div class="bg-gradient-to-r from-green-50 to-emerald-50 rounded-xl p-6 border border-green-200">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<CheckCircleIcon class="h-8 w-8 text-green-500" />
|
||||||
|
</div>
|
||||||
|
<div class="ml-4">
|
||||||
|
<h3 class="text-lg font-medium text-green-900">认证已通过</h3>
|
||||||
|
<p class="text-sm text-green-700">该域名已完成实名认证</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<div class="bg-white rounded-xl border border-gray-200 shadow-sm">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 flex items-center">
|
||||||
|
<FileTextIcon class="h-5 w-5 mr-2 text-blue-600" />
|
||||||
|
域名基本信息
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div class="space-y-4">
|
||||||
|
<InfoItem label="域名" :value="realNameData.domain" />
|
||||||
|
<InfoItem label="注册日期" :value="formatDate(realNameData.regdate)" />
|
||||||
|
<InfoItem label="到期日期" :value="formatDate(realNameData.rexpiredate)" />
|
||||||
|
<InfoItem label="认证状态" :value="getStatusText(realNameData.c_status)" />
|
||||||
|
</div>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<InfoItem label="模板ID" :value="realNameData.c_sysid" />
|
||||||
|
<InfoItem label="注册类型" :value="getRegTypeText(realNameData.c_regtype)" />
|
||||||
|
<InfoItem label="域名状态" :value="realNameData.status" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 所有者信息 -->
|
||||||
|
<div class="bg-white rounded-xl border border-gray-200 shadow-sm">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 flex items-center">
|
||||||
|
<UserIcon class="h-5 w-5 mr-2 text-blue-600" />
|
||||||
|
所有者信息
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div class="space-y-4">
|
||||||
|
<InfoItem label="中文姓名" :value="getFullChineseName()" />
|
||||||
|
<InfoItem label="英文姓名" :value="getFullEnglishName()" />
|
||||||
|
<InfoItem v-if="realNameData.owner.dom_org_m" label="中文单位" :value="realNameData.owner.dom_org_m" />
|
||||||
|
<InfoItem v-if="realNameData.owner.dom_org" label="英文单位" :value="realNameData.owner.dom_org" />
|
||||||
|
<InfoItem label="邮箱" :value="realNameData.owner.dom_em" />
|
||||||
|
</div>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<InfoItem label="电话" :value="realNameData.owner.dom_ph" />
|
||||||
|
<InfoItem label="传真" :value="realNameData.owner.dom_fax" />
|
||||||
|
<InfoItem label="国家/地区" :value="realNameData.owner.dom_co" />
|
||||||
|
<InfoItem label="省份" :value="realNameData.owner.dom_st_m || realNameData.owner.dom_st" />
|
||||||
|
<InfoItem label="城市" :value="realNameData.owner.dom_ct_m || realNameData.owner.dom_ct" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<InfoItem label="地址" :value="realNameData.owner.dom_adr_m || realNameData.owner.dom_adr1" />
|
||||||
|
<InfoItem label="邮编" :value="realNameData.owner.dom_pc" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 联系人信息 -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||||
|
<!-- 管理联系人 -->
|
||||||
|
<ContactCard
|
||||||
|
title="管理联系人"
|
||||||
|
icon="UserCircleIcon"
|
||||||
|
:contact="realNameData.admin"
|
||||||
|
type="admin"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 技术联系人 -->
|
||||||
|
<ContactCard
|
||||||
|
title="技术联系人"
|
||||||
|
icon="SettingsIcon"
|
||||||
|
:contact="realNameData.tech"
|
||||||
|
type="tech"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 缴费联系人 -->
|
||||||
|
<ContactCard
|
||||||
|
title="缴费联系人"
|
||||||
|
icon="CreditCardIcon"
|
||||||
|
:contact="realNameData.billing"
|
||||||
|
type="bill"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DNS服务器 -->
|
||||||
|
<div class="bg-white rounded-xl border border-gray-200 shadow-sm">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 flex items-center">
|
||||||
|
<GlobeIcon class="h-5 w-5 mr-2 text-blue-600" />
|
||||||
|
DNS服务器
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
<div v-for="(dns, index) in getDnsServers()" :key="index" class="bg-gray-50 rounded-lg p-4">
|
||||||
|
<div class="text-sm font-medium text-gray-600 mb-1">DNS{{ index + 1 }}</div>
|
||||||
|
<div class="font-mono text-sm text-gray-900">{{ dns || '未设置' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Dialog, createResource } from 'jingrow-ui';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import CheckCircleIcon from '~icons/lucide/check-circle';
|
||||||
|
import AlertTriangleIcon from '~icons/lucide/alert-triangle';
|
||||||
|
import FileTextIcon from '~icons/lucide/file-text';
|
||||||
|
import UserIcon from '~icons/lucide/user';
|
||||||
|
import UserCircleIcon from '~icons/lucide/user-circle';
|
||||||
|
import SettingsIcon from '~icons/lucide/settings';
|
||||||
|
import CreditCardIcon from '~icons/lucide/credit-card';
|
||||||
|
import GlobeIcon from '~icons/lucide/globe';
|
||||||
|
|
||||||
|
// 信息项组件
|
||||||
|
const InfoItem = {
|
||||||
|
props: ['label', 'value'],
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<dt class="text-sm font-medium text-gray-600">{{ label }}</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{ value || '未填写' }}</dd>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
// 联系人卡片组件
|
||||||
|
const ContactCard = {
|
||||||
|
props: ['title', 'icon', 'contact', 'type'],
|
||||||
|
components: { UserCircleIcon, SettingsIcon, CreditCardIcon },
|
||||||
|
template: `
|
||||||
|
<div class="bg-white rounded-xl border border-gray-200 shadow-sm">
|
||||||
|
<div class="px-4 py-3 border-b border-gray-100">
|
||||||
|
<h4 class="text-sm font-medium text-gray-900 flex items-center">
|
||||||
|
<component :is="icon" class="h-4 w-4 mr-2 text-blue-600" />
|
||||||
|
{{ title }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-3">
|
||||||
|
<div>
|
||||||
|
<div class="text-xs font-medium text-gray-600">姓名</div>
|
||||||
|
<div class="text-sm text-gray-900">{{ getContactName() }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-xs font-medium text-gray-600">邮箱</div>
|
||||||
|
<div class="text-sm text-gray-900">{{ contact[type + '_em'] || '未填写' }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-xs font-medium text-gray-600">电话</div>
|
||||||
|
<div class="text-sm text-gray-900">{{ contact[type + '_ph'] || '未填写' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
methods: {
|
||||||
|
getContactName() {
|
||||||
|
const chineseName = (this.contact[this.type + '_ln_m'] || '') + (this.contact[this.type + '_fn_m'] || '');
|
||||||
|
const englishName = (this.contact[this.type + '_ln'] || '') + ' ' + (this.contact[this.type + '_fn'] || '');
|
||||||
|
return chineseName || englishName.trim() || '未填写';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JsiteDomainRealNameInfoDialog',
|
||||||
|
components: {
|
||||||
|
Dialog,
|
||||||
|
CheckCircleIcon,
|
||||||
|
AlertTriangleIcon,
|
||||||
|
FileTextIcon,
|
||||||
|
UserIcon,
|
||||||
|
UserCircleIcon,
|
||||||
|
SettingsIcon,
|
||||||
|
CreditCardIcon,
|
||||||
|
GlobeIcon,
|
||||||
|
InfoItem,
|
||||||
|
ContactCard
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
domain: String,
|
||||||
|
domainDoc: Object,
|
||||||
|
realNameInfo: Object
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
realNameData: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadRealNameInfo() {
|
||||||
|
if (this.realNameInfo) {
|
||||||
|
this.realNameData = this.realNameInfo;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.domainDoc?.domain) {
|
||||||
|
this.error = '域名信息不存在';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const getRealNameRequest = createResource({
|
||||||
|
url: 'jcloud.api.domain_west.get_west_domain_real_info',
|
||||||
|
params: {
|
||||||
|
domain: this.domainDoc.domain
|
||||||
|
},
|
||||||
|
onSuccess: (response) => {
|
||||||
|
if (response && response.status === "success" && response.data) {
|
||||||
|
this.realNameData = response.data;
|
||||||
|
} else {
|
||||||
|
this.error = '获取实名认证信息失败';
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error('获取域名实名信息失败:', error);
|
||||||
|
this.error = '获取实名认证信息失败';
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getRealNameRequest.submit();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取域名实名信息失败:', error);
|
||||||
|
this.error = '获取实名认证信息失败';
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatDate(dateStr) {
|
||||||
|
if (!dateStr) return '未知';
|
||||||
|
try {
|
||||||
|
const date = new Date(dateStr);
|
||||||
|
return date.toLocaleDateString('zh-CN');
|
||||||
|
} catch {
|
||||||
|
return dateStr;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getStatusText(status) {
|
||||||
|
const statusMap = {
|
||||||
|
1: '已通过',
|
||||||
|
2: '审核中',
|
||||||
|
3: '审核失败',
|
||||||
|
4: '待上传'
|
||||||
|
};
|
||||||
|
return statusMap[status] || status || '未知';
|
||||||
|
},
|
||||||
|
getRegTypeText(regType) {
|
||||||
|
const typeMap = {
|
||||||
|
'I': '个人',
|
||||||
|
'E': '企业'
|
||||||
|
};
|
||||||
|
return typeMap[regType] || regType || '未知';
|
||||||
|
},
|
||||||
|
getFullChineseName() {
|
||||||
|
if (!this.realNameData?.owner) return '未填写';
|
||||||
|
const lastName = this.realNameData.owner.dom_ln_m || '';
|
||||||
|
const firstName = this.realNameData.owner.dom_fn_m || '';
|
||||||
|
return lastName + firstName || '未填写';
|
||||||
|
},
|
||||||
|
getFullEnglishName() {
|
||||||
|
if (!this.realNameData?.owner) return '未填写';
|
||||||
|
const lastName = this.realNameData.owner.dom_ln || '';
|
||||||
|
const firstName = this.realNameData.owner.dom_fn || '';
|
||||||
|
return (lastName + ' ' + firstName).trim() || '未填写';
|
||||||
|
},
|
||||||
|
getDnsServers() {
|
||||||
|
if (!this.realNameData?.dns_hosts) return [];
|
||||||
|
return [
|
||||||
|
this.realNameData.dns_hosts.dns_host1,
|
||||||
|
this.realNameData.dns_hosts.dns_host2,
|
||||||
|
this.realNameData.dns_hosts.dns_host3,
|
||||||
|
this.realNameData.dns_hosts.dns_host4,
|
||||||
|
this.realNameData.dns_hosts.dns_host5,
|
||||||
|
this.realNameData.dns_hosts.dns_host6
|
||||||
|
].filter(Boolean);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadRealNameInfo();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
468
dashboard/src2/components/JsiteDomainUploadRealNameDialog.vue
Normal file
468
dashboard/src2/components/JsiteDomainUploadRealNameDialog.vue
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog v-bind="$attrs" :options="{ title: '上传实名资料', size: '2xl' }">
|
||||||
|
<template #body>
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- 步骤指示器 -->
|
||||||
|
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl p-6 border border-blue-200">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<InfoIcon class="h-6 w-6 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
<div class="ml-4">
|
||||||
|
<h3 class="text-lg font-medium text-blue-900 mb-2">实名认证说明</h3>
|
||||||
|
<div class="text-sm text-blue-700 space-y-2">
|
||||||
|
<p>• 个人用户:请上传身份证正反面照片</p>
|
||||||
|
<p>• 企业用户:请上传营业执照和法人身份证</p>
|
||||||
|
<p>• 文件格式支持:JPG、PNG、PDF,单个文件不超过5MB</p>
|
||||||
|
<p>• 请确保证件信息清晰可见,避免反光或模糊</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form @submit.prevent="submitUpload" class="space-y-6">
|
||||||
|
<!-- 认证类型选择 -->
|
||||||
|
<div>
|
||||||
|
<label class="text-base font-medium text-gray-900 block mb-4">认证类型</label>
|
||||||
|
<div class="grid grid-cols-2 gap-4">
|
||||||
|
<label class="relative cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
v-model="formData.certType"
|
||||||
|
value="personal"
|
||||||
|
class="sr-only peer"
|
||||||
|
/>
|
||||||
|
<div class="border-2 border-gray-200 rounded-xl p-4 peer-checked:border-blue-500 peer-checked:bg-blue-50 transition-all duration-200 hover:border-gray-300">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<UserIcon class="h-6 w-6 text-gray-600 mr-3" />
|
||||||
|
<div>
|
||||||
|
<div class="font-medium text-gray-900">个人认证</div>
|
||||||
|
<div class="text-sm text-gray-600">使用个人身份证进行认证</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="relative cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
v-model="formData.certType"
|
||||||
|
value="enterprise"
|
||||||
|
class="sr-only peer"
|
||||||
|
/>
|
||||||
|
<div class="border-2 border-gray-200 rounded-xl p-4 peer-checked:border-blue-500 peer-checked:bg-blue-50 transition-all duration-200 hover:border-gray-300">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<BuildingIcon class="h-6 w-6 text-gray-600 mr-3" />
|
||||||
|
<div>
|
||||||
|
<div class="font-medium text-gray-900">企业认证</div>
|
||||||
|
<div class="text-sm text-gray-600">使用营业执照进行认证</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 个人认证文件上传 -->
|
||||||
|
<div v-if="formData.certType === 'personal'" class="space-y-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<!-- 身份证正面 -->
|
||||||
|
<FileUpload
|
||||||
|
label="身份证正面"
|
||||||
|
description="请上传身份证正面照片"
|
||||||
|
:files="formData.idCardFront"
|
||||||
|
@update:files="formData.idCardFront = $event"
|
||||||
|
accept="image/*,.pdf"
|
||||||
|
:maxSize="5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 身份证反面 -->
|
||||||
|
<FileUpload
|
||||||
|
label="身份证反面"
|
||||||
|
description="请上传身份证反面照片"
|
||||||
|
:files="formData.idCardBack"
|
||||||
|
@update:files="formData.idCardBack = $event"
|
||||||
|
accept="image/*,.pdf"
|
||||||
|
:maxSize="5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 企业认证文件上传 -->
|
||||||
|
<div v-if="formData.certType === 'enterprise'" class="space-y-6">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<!-- 营业执照 -->
|
||||||
|
<FileUpload
|
||||||
|
label="营业执照"
|
||||||
|
description="请上传营业执照照片或扫描件"
|
||||||
|
:files="formData.businessLicense"
|
||||||
|
@update:files="formData.businessLicense = $event"
|
||||||
|
accept="image/*,.pdf"
|
||||||
|
:maxSize="5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 法人身份证 -->
|
||||||
|
<FileUpload
|
||||||
|
label="法人身份证"
|
||||||
|
description="请上传法人身份证正面照片"
|
||||||
|
:files="formData.legalIdCard"
|
||||||
|
@update:files="formData.legalIdCard = $event"
|
||||||
|
accept="image/*,.pdf"
|
||||||
|
:maxSize="5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 联系信息 -->
|
||||||
|
<div class="bg-gray-50 rounded-xl p-6">
|
||||||
|
<h3 class="text-lg font-medium text-gray-900 mb-4">联系信息</h3>
|
||||||
|
<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
|
||||||
|
type="text"
|
||||||
|
v-model="formData.contactName"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="请输入联系人姓名"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">联系电话</label>
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
v-model="formData.contactPhone"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="请输入联系电话"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="md:col-span-2">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">邮箱地址</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
v-model="formData.contactEmail"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="请输入邮箱地址"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 备注 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">备注说明(可选)</label>
|
||||||
|
<textarea
|
||||||
|
v-model="formData.remark"
|
||||||
|
rows="3"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||||
|
placeholder="如有特殊情况请在此说明..."
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 提交按钮 -->
|
||||||
|
<div class="flex justify-end space-x-4 pt-6 border-t">
|
||||||
|
<Button variant="outline" @click="$emit('close')">
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
:loading="loading"
|
||||||
|
class="px-8 bg-blue-600 hover:bg-blue-700 text-white"
|
||||||
|
>
|
||||||
|
提交认证
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Dialog, Button, createResource } from 'jingrow-ui';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import InfoIcon from '~icons/lucide/info';
|
||||||
|
import UserIcon from '~icons/lucide/user';
|
||||||
|
import BuildingIcon from '~icons/lucide/building';
|
||||||
|
import UploadIcon from '~icons/lucide/upload';
|
||||||
|
import FileIcon from '~icons/lucide/file';
|
||||||
|
import XIcon from '~icons/lucide/x';
|
||||||
|
|
||||||
|
// 文件上传组件
|
||||||
|
const FileUpload = {
|
||||||
|
props: {
|
||||||
|
label: String,
|
||||||
|
description: String,
|
||||||
|
files: Array,
|
||||||
|
accept: String,
|
||||||
|
maxSize: Number,
|
||||||
|
required: Boolean
|
||||||
|
},
|
||||||
|
emits: ['update:files'],
|
||||||
|
components: { UploadIcon, FileIcon, XIcon },
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
{{ label }}
|
||||||
|
<span v-if="required" class="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<p class="text-sm text-gray-600 mb-3">{{ description }}</p>
|
||||||
|
|
||||||
|
<div class="space-y-3">
|
||||||
|
<!-- 文件上传区域 -->
|
||||||
|
<div
|
||||||
|
@click="triggerFileInput"
|
||||||
|
@dragover.prevent
|
||||||
|
@drop.prevent="handleDrop"
|
||||||
|
class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center cursor-pointer hover:border-blue-400 hover:bg-blue-50 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
<UploadIcon class="h-8 w-8 text-gray-400 mx-auto mb-2" />
|
||||||
|
<p class="text-sm text-gray-600">点击上传或拖拽文件到此处</p>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
支持 {{ accept }} 格式,最大 {{ maxSize }}MB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 已上传文件列表 -->
|
||||||
|
<div v-if="files && files.length > 0" class="space-y-2">
|
||||||
|
<div
|
||||||
|
v-for="(file, index) in files"
|
||||||
|
:key="index"
|
||||||
|
class="flex items-center justify-between bg-gray-50 rounded-lg p-3"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<FileIcon class="h-5 w-5 text-blue-600 mr-2" />
|
||||||
|
<div>
|
||||||
|
<div class="text-sm font-medium text-gray-900">{{ file.name }}</div>
|
||||||
|
<div class="text-xs text-gray-500">{{ formatFileSize(file.size) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
@click="removeFile(index)"
|
||||||
|
class="text-gray-400 hover:text-red-500 transition-colors"
|
||||||
|
>
|
||||||
|
<XIcon class="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
ref="fileInput"
|
||||||
|
type="file"
|
||||||
|
:accept="accept"
|
||||||
|
multiple
|
||||||
|
class="hidden"
|
||||||
|
@change="handleFileSelect"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
methods: {
|
||||||
|
triggerFileInput() {
|
||||||
|
this.$refs.fileInput.click();
|
||||||
|
},
|
||||||
|
handleFileSelect(event) {
|
||||||
|
const files = Array.from(event.target.files);
|
||||||
|
this.addFiles(files);
|
||||||
|
},
|
||||||
|
handleDrop(event) {
|
||||||
|
const files = Array.from(event.dataTransfer.files);
|
||||||
|
this.addFiles(files);
|
||||||
|
},
|
||||||
|
addFiles(newFiles) {
|
||||||
|
const validFiles = newFiles.filter(file => {
|
||||||
|
// 检查文件大小
|
||||||
|
if (file.size > this.maxSize * 1024 * 1024) {
|
||||||
|
toast.error(`文件 ${file.name} 超过 ${this.maxSize}MB 限制`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentFiles = this.files || [];
|
||||||
|
this.$emit('update:files', [...currentFiles, ...validFiles]);
|
||||||
|
},
|
||||||
|
removeFile(index) {
|
||||||
|
const currentFiles = [...this.files];
|
||||||
|
currentFiles.splice(index, 1);
|
||||||
|
this.$emit('update:files', currentFiles);
|
||||||
|
},
|
||||||
|
formatFileSize(bytes) {
|
||||||
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JsiteDomainUploadRealNameDialog',
|
||||||
|
components: {
|
||||||
|
Dialog,
|
||||||
|
Button,
|
||||||
|
InfoIcon,
|
||||||
|
UserIcon,
|
||||||
|
BuildingIcon,
|
||||||
|
FileUpload
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
domain: String,
|
||||||
|
domainDoc: Object
|
||||||
|
},
|
||||||
|
emits: ['success', 'close'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
formData: {
|
||||||
|
certType: 'personal',
|
||||||
|
idCardFront: [],
|
||||||
|
idCardBack: [],
|
||||||
|
businessLicense: [],
|
||||||
|
legalIdCard: [],
|
||||||
|
contactName: '',
|
||||||
|
contactPhone: '',
|
||||||
|
contactEmail: '',
|
||||||
|
remark: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async submitUpload() {
|
||||||
|
// 验证必填字段
|
||||||
|
if (!this.validateForm()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建FormData对象
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
// 添加基本信息
|
||||||
|
formData.append('domain', this.domainDoc.domain);
|
||||||
|
formData.append('certType', this.formData.certType);
|
||||||
|
formData.append('contactName', this.formData.contactName);
|
||||||
|
formData.append('contactPhone', this.formData.contactPhone);
|
||||||
|
formData.append('contactEmail', this.formData.contactEmail);
|
||||||
|
formData.append('remark', this.formData.remark);
|
||||||
|
|
||||||
|
// 添加文件
|
||||||
|
if (this.formData.certType === 'personal') {
|
||||||
|
if (this.formData.idCardFront.length > 0) {
|
||||||
|
this.formData.idCardFront.forEach((file, index) => {
|
||||||
|
formData.append(`idCardFront_${index}`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.formData.idCardBack.length > 0) {
|
||||||
|
this.formData.idCardBack.forEach((file, index) => {
|
||||||
|
formData.append(`idCardBack_${index}`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (this.formData.certType === 'enterprise') {
|
||||||
|
if (this.formData.businessLicense.length > 0) {
|
||||||
|
this.formData.businessLicense.forEach((file, index) => {
|
||||||
|
formData.append(`businessLicense_${index}`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.formData.legalIdCard.length > 0) {
|
||||||
|
this.formData.legalIdCard.forEach((file, index) => {
|
||||||
|
formData.append(`legalIdCard_${index}`, file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用后端上传API
|
||||||
|
const uploadRequest = createResource({
|
||||||
|
url: 'jcloud.api.domain_west.upload_domain_real_name_files',
|
||||||
|
method: 'POST',
|
||||||
|
params: formData,
|
||||||
|
onSuccess: (response) => {
|
||||||
|
if (response && response.status === "success") {
|
||||||
|
toast.success('实名资料上传成功,请等待审核');
|
||||||
|
this.$emit('success');
|
||||||
|
this.$emit('close');
|
||||||
|
} else {
|
||||||
|
toast.error(response.message || '上传失败,请重试');
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error('上传实名资料失败:', error);
|
||||||
|
toast.error('上传失败,请重试');
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadRequest.submit();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('上传实名资料失败:', error);
|
||||||
|
toast.error('上传失败,请重试');
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validateForm() {
|
||||||
|
if (!this.formData.certType) {
|
||||||
|
toast.error('请选择认证类型');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.formData.certType === 'personal') {
|
||||||
|
if (!this.formData.idCardFront.length) {
|
||||||
|
toast.error('请上传身份证正面');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.formData.idCardBack.length) {
|
||||||
|
toast.error('请上传身份证反面');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (this.formData.certType === 'enterprise') {
|
||||||
|
if (!this.formData.businessLicense.length) {
|
||||||
|
toast.error('请上传营业执照');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.formData.legalIdCard.length) {
|
||||||
|
toast.error('请上传法人身份证');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.formData.contactName.trim()) {
|
||||||
|
toast.error('请填写联系人姓名');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.formData.contactPhone.trim()) {
|
||||||
|
toast.error('请填写联系电话');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.formData.contactEmail.trim()) {
|
||||||
|
toast.error('请填写邮箱地址');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证邮箱格式
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!emailRegex.test(this.formData.contactEmail)) {
|
||||||
|
toast.error('请填写正确的邮箱地址');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -417,6 +417,83 @@ class WestDomain:
|
|||||||
}
|
}
|
||||||
return self._make_request('/audit/', 'POST', body_params=body_params)
|
return self._make_request('/audit/', 'POST', body_params=body_params)
|
||||||
|
|
||||||
|
def get_upload_token(self, c_sysid: str, f_type_org: str, f_code_org: str,
|
||||||
|
f_type_lxr: Optional[str] = None, f_code_lxr: Optional[str] = None) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
获取实名上传token
|
||||||
|
|
||||||
|
Args:
|
||||||
|
c_sysid: 模板标识
|
||||||
|
f_type_org: 证件类型,详情见附录
|
||||||
|
f_code_org: 证件号码
|
||||||
|
f_type_lxr: 联系人证件类型(企业时填写)
|
||||||
|
f_code_lxr: 联系人证件号码(企业时填写)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
API响应结果,包含上传token
|
||||||
|
"""
|
||||||
|
body_params = {
|
||||||
|
'act': 'uploadwcftoken',
|
||||||
|
'c_sysid': c_sysid,
|
||||||
|
'f_type_org': f_type_org,
|
||||||
|
'f_code_org': f_code_org,
|
||||||
|
}
|
||||||
|
|
||||||
|
# 添加可选参数
|
||||||
|
if f_type_lxr:
|
||||||
|
body_params['f_type_lxr'] = f_type_lxr
|
||||||
|
if f_code_lxr:
|
||||||
|
body_params['f_code_lxr'] = f_code_lxr
|
||||||
|
|
||||||
|
return self._make_request('/audit/', 'POST', body_params=body_params)
|
||||||
|
|
||||||
|
def upload_real_name_files(self, token: str, file_org: str, file_lxr: Optional[str] = None) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
模板实名资料上传
|
||||||
|
|
||||||
|
Args:
|
||||||
|
token: 实名上传Token
|
||||||
|
file_org: 图片完整的base64
|
||||||
|
file_lxr: 企业联系人图片完整的base64(只有token中设置了联系人的才上传)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
API响应结果
|
||||||
|
"""
|
||||||
|
upload_url = "https://netservice.vhostgo.com/wcfservice/Service1.svc/Wcf_AuditUploadFile"
|
||||||
|
|
||||||
|
# 构建请求数据
|
||||||
|
data = {
|
||||||
|
'token': token,
|
||||||
|
'file_org': file_org,
|
||||||
|
}
|
||||||
|
|
||||||
|
# 添加可选参数
|
||||||
|
if file_lxr:
|
||||||
|
data['file_lxr'] = file_lxr
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 发送JSON格式的POST请求
|
||||||
|
jingrow.log_error("西部数码实名上传调试", f"发送POST请求,URL: {upload_url}, 数据: {data}")
|
||||||
|
response = requests.post(upload_url, json=data, headers=headers, timeout=30)
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = response.json()
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
jingrow.log_error("西部数码实名上传响应解析失败", response_text=response.text)
|
||||||
|
result = {"status": "error", "message": "无法解析API响应"}
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
jingrow.log_error("西部数码实名上传请求失败", error=str(e), url=upload_url)
|
||||||
|
return {"status": "error", "message": f"API请求失败: {str(e)}"}
|
||||||
|
|
||||||
|
|
||||||
def format_date(date):
|
def format_date(date):
|
||||||
"""格式化域名到期时间"""
|
"""格式化域名到期时间"""
|
||||||
@ -1221,6 +1298,7 @@ def get_domain_owner(name):
|
|||||||
# 返回所有者信息
|
# 返回所有者信息
|
||||||
owner_data = {
|
owner_data = {
|
||||||
"name": domain_owner.name,
|
"name": domain_owner.name,
|
||||||
|
"r_status": domain_owner.r_status,
|
||||||
"title": domain_owner.title,
|
"title": domain_owner.title,
|
||||||
"fullname": domain_owner.fullname,
|
"fullname": domain_owner.fullname,
|
||||||
"c_regtype": domain_owner.c_regtype,
|
"c_regtype": domain_owner.c_regtype,
|
||||||
@ -1708,3 +1786,89 @@ def get_west_domain_real_info(**data):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
jingrow.log_error("域名实名信息查询响应解析失败", error=str(e))
|
jingrow.log_error("域名实名信息查询响应解析失败", error=str(e))
|
||||||
return {"status": "error", "message": "域名实名信息查询响应解析失败"}
|
return {"status": "error", "message": "域名实名信息查询响应解析失败"}
|
||||||
|
|
||||||
|
|
||||||
|
@jingrow.whitelist()
|
||||||
|
def get_west_upload_token(**data):
|
||||||
|
"""获取西部数码实名上传token"""
|
||||||
|
client = get_west_client()
|
||||||
|
if not client:
|
||||||
|
return {"status": "error", "message": "API客户端初始化失败"}
|
||||||
|
|
||||||
|
c_sysid = data.get('c_sysid')
|
||||||
|
f_type_org = data.get('f_type_org')
|
||||||
|
f_code_org = data.get('f_code_org')
|
||||||
|
f_type_lxr = data.get('f_type_lxr')
|
||||||
|
f_code_lxr = data.get('f_code_lxr')
|
||||||
|
|
||||||
|
if not all([c_sysid, f_type_org, f_code_org]):
|
||||||
|
return {"status": "error", "message": "缺少必要参数:c_sysid, f_type_org, f_code_org"}
|
||||||
|
|
||||||
|
response = client.get_upload_token(c_sysid, f_type_org, f_code_org, f_type_lxr, f_code_lxr)
|
||||||
|
|
||||||
|
if response.get("status") == "error":
|
||||||
|
return response
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 检查响应格式
|
||||||
|
if response.get("result") != 200:
|
||||||
|
return {"status": "error", "message": "API查询失败"}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": "success",
|
||||||
|
"data": {
|
||||||
|
"token": response.get("data"),
|
||||||
|
"clientid": response.get("clientid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
jingrow.log_error("获取实名上传token响应解析失败", error=str(e))
|
||||||
|
return {"status": "error", "message": "获取实名上传token响应解析失败"}
|
||||||
|
|
||||||
|
|
||||||
|
@jingrow.whitelist()
|
||||||
|
def west_upload_real_name_files(**data):
|
||||||
|
"""西部数码模板实名资料上传"""
|
||||||
|
client = get_west_client()
|
||||||
|
if not client:
|
||||||
|
return {"status": "error", "message": "API客户端初始化失败"}
|
||||||
|
|
||||||
|
token = data.get('token')
|
||||||
|
file_org = data.get('file_org')
|
||||||
|
file_lxr = data.get('file_lxr')
|
||||||
|
|
||||||
|
if not all([token, file_org]):
|
||||||
|
return {"status": "error", "message": "缺少必要参数:token, file_org"}
|
||||||
|
|
||||||
|
response = client.upload_real_name_files(token, file_org, file_lxr)
|
||||||
|
|
||||||
|
if response.get("status") == "error":
|
||||||
|
return response
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 解析响应格式
|
||||||
|
d = response.get("d", {})
|
||||||
|
result = d.get("Result")
|
||||||
|
msg = d.get("Msg", "")
|
||||||
|
|
||||||
|
if result == 200:
|
||||||
|
return {
|
||||||
|
"status": "success",
|
||||||
|
"message": "实名资料上传成功",
|
||||||
|
"data": {
|
||||||
|
"result": result,
|
||||||
|
"msg": msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"实名资料上传失败: {msg}"
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
jingrow.log_error("实名资料上传响应解析失败", error=str(e))
|
||||||
|
return {"status": "error", "message": "实名资料上传响应解析失败"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user