增加域名所有者实名资料上传api端点及测试通过但是没有返回已提交成功
This commit is contained in:
parent
d80c0ff85d
commit
991b34232b
@ -1,270 +1,196 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-bind="$attrs" :options="{ title: '上传实名资料', size: '2xl' }" v-model="show">
|
<Dialog v-bind="$attrs" :options="{ title: '实名材料', size: 'lg' }" v-model="show">
|
||||||
<template #body>
|
<template #body-content>
|
||||||
<div class="space-y-6">
|
<div class="p-4 sm:p-6">
|
||||||
<!-- 步骤指示器 -->
|
<div class="space-y-4">
|
||||||
<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>
|
||||||
<div class="flex-shrink-0">
|
<label class="block text-sm font-medium text-gray-700 mb-2">域名:</label>
|
||||||
<InfoIcon class="h-6 w-6 text-blue-600" />
|
<div class="text-base text-black font-semibold">{{ domainDoc?.domain || domain }}</div>
|
||||||
|
</div>
|
||||||
|
<!-- 资料状态 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">资料状态</label>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<span class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||||
|
未传图片
|
||||||
|
</span>
|
||||||
|
<span class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||||
|
未实名
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4">
|
</div>
|
||||||
<h3 class="text-lg font-medium text-blue-900 mb-2">实名认证说明</h3>
|
|
||||||
<div class="text-sm text-blue-700 space-y-2">
|
<!-- 域名所有者 -->
|
||||||
<p>• 个人用户:请上传身份证正反面照片</p>
|
<div>
|
||||||
<p>• 企业用户:请上传营业执照和法人身份证</p>
|
<label class="block text-sm font-medium text-gray-700 mb-2">域名所有者</label>
|
||||||
<p>• 文件格式支持:JPG、PNG、PDF,单个文件不超过5MB</p>
|
<div class="text-sm text-gray-900">
|
||||||
<p>• 请确保证件信息清晰可见,避免反光或模糊</p>
|
(个人) 旷蓓娟
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 所有者证件号码 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">所有者证件号码</label>
|
||||||
|
<div class="flex space-x-3">
|
||||||
|
<select
|
||||||
|
v-model="formData.idType"
|
||||||
|
class="px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white text-sm"
|
||||||
|
>
|
||||||
|
<option value="idcard">身份证</option>
|
||||||
|
<option value="passport">护照</option>
|
||||||
|
<option value="other">其他证件</option>
|
||||||
|
</select>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="formData.idNumber"
|
||||||
|
class="flex-1 px-3 py-1.5 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm"
|
||||||
|
placeholder="请输入证件号码"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 所有者证件材料 -->
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-700 mb-2">所有者证件材料</label>
|
||||||
|
<div class="flex space-x-4">
|
||||||
|
<!-- 上传区域 -->
|
||||||
|
<div class="flex-1">
|
||||||
|
<div
|
||||||
|
@click="triggerFileInput"
|
||||||
|
@dragover.prevent
|
||||||
|
@drop.prevent="handleDrop"
|
||||||
|
class="border-2 border-dashed border-gray-300 rounded-md p-6 text-center cursor-pointer hover:border-blue-400 hover:bg-blue-50 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
<div class="text-green-500 mb-2">
|
||||||
|
<svg class="w-8 h-8 mx-auto" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM6.293 6.707a1 1 0 010-1.414l3-3a1 1 0 011.414 0l3 3a1 1 0 01-1.414 1.414L11 5.414V13a1 1 0 11-2 0V5.414L7.707 6.707a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-600 font-medium">点击上传</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 说明文字 -->
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="text-xs text-gray-600 leading-relaxed mb-3">
|
||||||
|
请保证图片中证件四角完整、证件上文字信息完整清晰,请使用原件拍摄或彩色扫描件,不要用复印件,否则无法通过审核。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 已上传文件列表 -->
|
||||||
|
<div v-if="uploadedFiles.length > 0" class="space-y-2">
|
||||||
|
<div
|
||||||
|
v-for="(file, index) in uploadedFiles"
|
||||||
|
:key="index"
|
||||||
|
class="flex items-center justify-between bg-gray-50 rounded-md p-2"
|
||||||
|
>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-4 h-4 text-blue-600 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<div class="text-xs 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"
|
||||||
|
>
|
||||||
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form @submit.prevent="submitUpload" class="space-y-6">
|
<!-- 隐藏的文件输入框 -->
|
||||||
<!-- 认证类型选择 -->
|
<input
|
||||||
<div>
|
ref="fileInput"
|
||||||
<label class="text-base font-medium text-gray-900 block mb-4">认证类型</label>
|
type="file"
|
||||||
<div class="grid grid-cols-2 gap-4">
|
accept="image/*,.pdf"
|
||||||
<label class="relative cursor-pointer">
|
multiple
|
||||||
<input
|
class="hidden"
|
||||||
type="radio"
|
@change="handleFileSelect"
|
||||||
v-model="formData.certType"
|
/>
|
||||||
value="personal"
|
</template>
|
||||||
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">
|
<template #actions>
|
||||||
<input
|
<div class="w-full flex justify-end space-x-3">
|
||||||
type="radio"
|
<button
|
||||||
v-model="formData.certType"
|
type="button"
|
||||||
value="enterprise"
|
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"
|
||||||
class="sr-only peer"
|
@click="$emit('close')"
|
||||||
/>
|
>
|
||||||
<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">
|
</button>
|
||||||
<BuildingIcon class="h-6 w-6 text-gray-600 mr-3" />
|
<button
|
||||||
<div>
|
type="button"
|
||||||
<div class="font-medium text-gray-900">企业认证</div>
|
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"
|
||||||
<div class="text-sm text-gray-600">使用营业执照进行认证</div>
|
@click="submitUpload"
|
||||||
</div>
|
:disabled="loading || !isValid"
|
||||||
</div>
|
>
|
||||||
</div>
|
{{ loading ? '提交中...' : '立即提交' }}
|
||||||
</label>
|
</button>
|
||||||
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Dialog, Button, createResource } from 'jingrow-ui';
|
import { Dialog, createResource } from 'jingrow-ui';
|
||||||
import { toast } from 'vue-sonner';
|
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';
|
|
||||||
|
|
||||||
// 文件上传组件
|
export default {
|
||||||
const FileUpload = {
|
name: 'JsiteDomainUploadRealNameDialog',
|
||||||
props: {
|
components: {
|
||||||
label: String,
|
Dialog
|
||||||
description: String,
|
},
|
||||||
files: Array,
|
props: {
|
||||||
accept: String,
|
domain: String,
|
||||||
maxSize: Number,
|
domainDoc: Object
|
||||||
required: Boolean
|
},
|
||||||
|
emits: ['success', 'close'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: true,
|
||||||
|
loading: false,
|
||||||
|
formData: {
|
||||||
|
idType: 'idcard',
|
||||||
|
idNumber: ''
|
||||||
|
},
|
||||||
|
uploadedFiles: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isValid() {
|
||||||
|
return this.formData.idNumber.trim() && this.uploadedFiles.length > 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resources: {
|
||||||
|
getOwnerInfo() {
|
||||||
|
return {
|
||||||
|
url: 'jcloud.api.domain_west.get_domain_owner',
|
||||||
|
params: {
|
||||||
|
name: this.domainDoc?.owner
|
||||||
|
},
|
||||||
|
onSuccess: (response) => {
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.error('获取所有者信息失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadOwnerInfo();
|
||||||
},
|
},
|
||||||
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: {
|
methods: {
|
||||||
triggerFileInput() {
|
triggerFileInput() {
|
||||||
this.$refs.fileInput.click();
|
this.$refs.fileInput.click();
|
||||||
@ -279,21 +205,18 @@ const FileUpload = {
|
|||||||
},
|
},
|
||||||
addFiles(newFiles) {
|
addFiles(newFiles) {
|
||||||
const validFiles = newFiles.filter(file => {
|
const validFiles = newFiles.filter(file => {
|
||||||
// 检查文件大小
|
// 检查文件大小 (5MB限制)
|
||||||
if (file.size > this.maxSize * 1024 * 1024) {
|
if (file.size > 5 * 1024 * 1024) {
|
||||||
toast.error(`文件 ${file.name} 超过 ${this.maxSize}MB 限制`);
|
toast.error(`文件 ${file.name} 超过 5MB 限制`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentFiles = this.files || [];
|
this.uploadedFiles = [...this.uploadedFiles, ...validFiles];
|
||||||
this.$emit('update:files', [...currentFiles, ...validFiles]);
|
|
||||||
},
|
},
|
||||||
removeFile(index) {
|
removeFile(index) {
|
||||||
const currentFiles = [...this.files];
|
this.uploadedFiles.splice(index, 1);
|
||||||
currentFiles.splice(index, 1);
|
|
||||||
this.$emit('update:files', currentFiles);
|
|
||||||
},
|
},
|
||||||
formatFileSize(bytes) {
|
formatFileSize(bytes) {
|
||||||
if (bytes === 0) return '0 Bytes';
|
if (bytes === 0) return '0 Bytes';
|
||||||
@ -301,45 +224,8 @@ const FileUpload = {
|
|||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
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 {
|
|
||||||
show: true,
|
|
||||||
loading: false,
|
|
||||||
formData: {
|
|
||||||
certType: 'personal',
|
|
||||||
idCardFront: [],
|
|
||||||
idCardBack: [],
|
|
||||||
businessLicense: [],
|
|
||||||
legalIdCard: [],
|
|
||||||
contactName: '',
|
|
||||||
contactPhone: '',
|
|
||||||
contactEmail: '',
|
|
||||||
remark: ''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async submitUpload() {
|
async submitUpload() {
|
||||||
// 验证必填字段
|
|
||||||
if (!this.validateForm()) {
|
if (!this.validateForm()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -351,67 +237,87 @@ export default {
|
|||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
// 添加基本信息
|
// 添加基本信息
|
||||||
formData.append('domain', this.domainDoc.domain);
|
console.log('domainDoc 完整对象:', JSON.stringify(this.domainDoc, null, 2));
|
||||||
formData.append('certType', this.formData.certType);
|
console.log('domainDoc.domain:', this.domainDoc?.domain);
|
||||||
formData.append('contactName', this.formData.contactName);
|
console.log('domainDoc.name:', this.domainDoc?.name);
|
||||||
formData.append('contactPhone', this.formData.contactPhone);
|
console.log('this.domain:', this.domain);
|
||||||
formData.append('contactEmail', this.formData.contactEmail);
|
|
||||||
formData.append('remark', this.formData.remark);
|
|
||||||
|
|
||||||
// 添加文件
|
// 优先使用 domainDoc.domain,如果没有则使用 this.domain
|
||||||
if (this.formData.certType === 'personal') {
|
const domain = this.domainDoc?.domain || this.domain;
|
||||||
if (this.formData.idCardFront.length > 0) {
|
console.log('提交的域名:', domain);
|
||||||
this.formData.idCardFront.forEach((file, index) => {
|
|
||||||
formData.append(`idCardFront_${index}`, file);
|
// 验证域名是否有效
|
||||||
});
|
if (!domain || domain === '36h8on65rd') {
|
||||||
}
|
console.error('域名信息无效:', domain);
|
||||||
if (this.formData.idCardBack.length > 0) {
|
toast.error('域名信息无效,请重试');
|
||||||
this.formData.idCardBack.forEach((file, index) => {
|
return;
|
||||||
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({
|
if (!domain.includes('.')) {
|
||||||
url: 'jcloud.api.domain_west.upload_domain_real_name_files',
|
console.error('域名格式无效:', domain);
|
||||||
method: 'POST',
|
toast.error('域名格式无效,请重试');
|
||||||
params: formData,
|
return;
|
||||||
onSuccess: (response) => {
|
}
|
||||||
// 修复API响应处理逻辑,支持两种响应格式
|
|
||||||
if (response && response.message && response.message.status === "success") {
|
formData.append('domain', domain);
|
||||||
toast.success('实名资料上传成功,请等待审核');
|
formData.append('idType', this.formData.idType);
|
||||||
this.$emit('success');
|
formData.append('idNumber', this.formData.idNumber);
|
||||||
this.$emit('close');
|
|
||||||
} else if (response && response.status === "success") {
|
// 添加文件
|
||||||
toast.success('实名资料上传成功,请等待审核');
|
this.uploadedFiles.forEach((file, index) => {
|
||||||
this.$emit('success');
|
formData.append(`files_${index}`, file);
|
||||||
this.$emit('close');
|
|
||||||
} else {
|
|
||||||
const errorMessage = response?.message?.message || response?.message || '上传失败,请重试';
|
|
||||||
toast.error(errorMessage);
|
|
||||||
}
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
console.error('上传实名资料失败:', error);
|
|
||||||
toast.error('上传失败,请重试');
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
uploadRequest.submit();
|
// 调用后端上传API
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.onreadystatechange = () => {
|
||||||
|
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
try {
|
||||||
|
const response = JSON.parse(xhr.responseText);
|
||||||
|
console.log('服务器响应:', response);
|
||||||
|
|
||||||
|
if (response && response.status === "success") {
|
||||||
|
// 使用 setTimeout 延迟执行,避免在 XMLHttpRequest 回调中直接调用 toast
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.success(response.message || '实名资料上传成功,请等待审核');
|
||||||
|
}, 100);
|
||||||
|
this.$emit('success');
|
||||||
|
this.$emit('close');
|
||||||
|
} else {
|
||||||
|
const errorMessage = response?.message || '上传失败,请重试';
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.error(errorMessage);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析响应失败:', error);
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.error('上传失败,请重试');
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('上传失败:', xhr.status, xhr.statusText);
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.error('上传失败,请重试');
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.open('POST', '/api/action/jcloud.api.domain_west.upload_domain_real_name_files', true);
|
||||||
|
xhr.setRequestHeader('Accept', 'application/json');
|
||||||
|
|
||||||
|
// 添加CSRF token
|
||||||
|
if (window.csrf_token && window.csrf_token !== '{{ csrf_token }}') {
|
||||||
|
xhr.setRequestHeader('X-Jingrow-CSRF-Token', window.csrf_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
xhr.send(formData);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('上传实名资料失败:', error);
|
console.error('上传实名资料失败:', error);
|
||||||
@ -421,55 +327,47 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
validateForm() {
|
validateForm() {
|
||||||
if (!this.formData.certType) {
|
if (!this.formData.idNumber.trim()) {
|
||||||
toast.error('请选择认证类型');
|
toast.error('请填写证件号码');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.formData.certType === 'personal') {
|
if (this.uploadedFiles.length === 0) {
|
||||||
if (!this.formData.idCardFront.length) {
|
toast.error('请上传证件材料');
|
||||||
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 false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
async loadOwnerInfo() {
|
||||||
|
try {
|
||||||
|
if (this.domainDoc && this.domainDoc.owner) {
|
||||||
|
// 获取域名所有者信息
|
||||||
|
const response = await this.$resources.getOwnerInfo.submit();
|
||||||
|
|
||||||
|
if (response && response.status === 'Success' && response.data) {
|
||||||
|
const owner = response.data;
|
||||||
|
// 填充身份证号码
|
||||||
|
if (owner.c_idnum_gswl) {
|
||||||
|
this.formData.idNumber = owner.c_idnum_gswl;
|
||||||
|
}
|
||||||
|
// 填充证件类型
|
||||||
|
if (owner.c_idtype_gswl) {
|
||||||
|
// 映射证件类型
|
||||||
|
if (owner.c_idtype_gswl === 'SFZ') {
|
||||||
|
this.formData.idType = 'idcard';
|
||||||
|
} else if (owner.c_idtype_gswl === 'HZ') {
|
||||||
|
this.formData.idType = 'passport';
|
||||||
|
} else {
|
||||||
|
this.formData.idType = 'other';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取所有者信息失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -12,6 +12,7 @@ from urllib.parse import urlencode
|
|||||||
from typing import Dict, Any, Optional, List
|
from typing import Dict, Any, Optional, List
|
||||||
from jcloud.utils import get_current_team
|
from jcloud.utils import get_current_team
|
||||||
from pypinyin import lazy_pinyin
|
from pypinyin import lazy_pinyin
|
||||||
|
import base64
|
||||||
|
|
||||||
class WestDomain:
|
class WestDomain:
|
||||||
"""西部数码域名API客户端"""
|
"""西部数码域名API客户端"""
|
||||||
@ -1827,7 +1828,9 @@ def get_domain_owner(name):
|
|||||||
"c_st_m": domain_owner.c_st_m,
|
"c_st_m": domain_owner.c_st_m,
|
||||||
"c_ct_m": domain_owner.c_ct_m,
|
"c_ct_m": domain_owner.c_ct_m,
|
||||||
"c_adr_m": domain_owner.c_adr_m,
|
"c_adr_m": domain_owner.c_adr_m,
|
||||||
"c_pc": domain_owner.c_pc
|
"c_pc": domain_owner.c_pc,
|
||||||
|
"c_idtype_gswl": domain_owner.c_idtype_gswl,
|
||||||
|
"c_idnum_gswl": domain_owner.c_idnum_gswl
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -2853,3 +2856,185 @@ def sync_domain_info_from_west(**data):
|
|||||||
return {"status": "error", "message": f"同步失败: {str(e)}"}
|
return {"status": "error", "message": f"同步失败: {str(e)}"}
|
||||||
|
|
||||||
|
|
||||||
|
@jingrow.whitelist()
|
||||||
|
def upload_domain_real_name_files(**data):
|
||||||
|
"""上传域名实名资料文件"""
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# 调试:打印接收到的参数
|
||||||
|
jingrow.log_error("上传实名资料参数", str(data))
|
||||||
|
|
||||||
|
# 尝试从jingrow.request中获取参数
|
||||||
|
try:
|
||||||
|
# 检查是否是FormData格式
|
||||||
|
if jingrow.request.content_type and 'multipart/form-data' in jingrow.request.content_type:
|
||||||
|
# 处理FormData格式
|
||||||
|
request_data = {}
|
||||||
|
for key in jingrow.request.form:
|
||||||
|
request_data[key] = jingrow.request.form[key]
|
||||||
|
jingrow.log_error("FormData参数", str(request_data))
|
||||||
|
else:
|
||||||
|
# 处理JSON格式
|
||||||
|
request_data = jingrow.request.get_json() if jingrow.request.is_json else {}
|
||||||
|
jingrow.log_error("request.get_json()", str(request_data))
|
||||||
|
except Exception as e:
|
||||||
|
jingrow.log_error("获取请求参数失败", str(e))
|
||||||
|
request_data = {}
|
||||||
|
|
||||||
|
client = get_west_client()
|
||||||
|
if not client:
|
||||||
|
return {"status": "error", "message": "API客户端初始化失败"}
|
||||||
|
|
||||||
|
# 从多个来源提取参数
|
||||||
|
domain = (data.get('domain') or
|
||||||
|
request_data.get('domain') or
|
||||||
|
data.get('domainDoc.domain'))
|
||||||
|
|
||||||
|
id_type = (data.get('idType') or
|
||||||
|
request_data.get('idType') or
|
||||||
|
'idcard')
|
||||||
|
|
||||||
|
id_number = (data.get('idNumber') or
|
||||||
|
request_data.get('idNumber'))
|
||||||
|
|
||||||
|
# 调试:打印提取的参数
|
||||||
|
jingrow.log_error("提取的参数", f"domain: {domain}, id_type: {id_type}, id_number: {id_number}")
|
||||||
|
|
||||||
|
if not all([domain, id_number]):
|
||||||
|
return {"status": "error", "message": f"缺少必要参数:domain={domain}, idNumber={id_number}"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 获取域名信息
|
||||||
|
jingrow.log_error("开始查询域名", f"查询域名: {domain}")
|
||||||
|
domain_list = jingrow.get_list("Jsite Domain", filters={"domain": domain})
|
||||||
|
jingrow.log_error("查询结果", f"找到 {len(domain_list)} 条记录")
|
||||||
|
|
||||||
|
if domain_list:
|
||||||
|
domain_name = domain_list[0].get('name')
|
||||||
|
jingrow.log_error("域名name", f"域名name: {domain_name}")
|
||||||
|
# 通过name获取完整的域名信息
|
||||||
|
domain_info = jingrow.get_pg("Jsite Domain", domain_name)
|
||||||
|
jingrow.log_error("完整域名信息", f"域名记录: {domain_info}")
|
||||||
|
else:
|
||||||
|
return {"status": "error", "message": f"未找到主域名{domain}"}
|
||||||
|
|
||||||
|
# 获取域名所有者信息
|
||||||
|
owner_name = domain_info.get('domain_owner') or domain_info.get('owner')
|
||||||
|
if not owner_name:
|
||||||
|
return {"status": "error", "message": "域名所有者信息不存在"}
|
||||||
|
|
||||||
|
owner_info = jingrow.get_pg("Domain Owner", owner_name)
|
||||||
|
if not owner_info:
|
||||||
|
return {"status": "error", "message": "域名所有者信息不存在"}
|
||||||
|
|
||||||
|
# 获取上传token
|
||||||
|
c_sysid = owner_info.get('c_sysid')
|
||||||
|
if not c_sysid:
|
||||||
|
return {"status": "error", "message": "域名所有者未关联西部数码ID"}
|
||||||
|
|
||||||
|
# 证件类型映射
|
||||||
|
f_type_org = "1" if id_type == "idcard" else "2" # 1=身份证, 2=护照
|
||||||
|
f_code_org = id_number
|
||||||
|
|
||||||
|
# 获取上传token
|
||||||
|
token_response = client.get_upload_token(c_sysid, f_type_org, f_code_org)
|
||||||
|
if token_response.get("status") == "error":
|
||||||
|
return token_response
|
||||||
|
|
||||||
|
if token_response.get("result") != 200:
|
||||||
|
return {"status": "error", "message": "获取上传token失败"}
|
||||||
|
|
||||||
|
token = token_response.get("data")
|
||||||
|
if not token:
|
||||||
|
return {"status": "error", "message": "获取上传token失败"}
|
||||||
|
|
||||||
|
# 处理文件上传 - 从FormData中提取文件并转换为base64
|
||||||
|
files = []
|
||||||
|
|
||||||
|
# 调试:打印所有可用的数据源
|
||||||
|
jingrow.log_error("调试文件上传", f"data keys: {list(data.keys()) if data else 'None'}")
|
||||||
|
jingrow.log_error("调试文件上传", f"request.files: {list(jingrow.request.files.keys()) if hasattr(jingrow.request, 'files') and jingrow.request.files else 'None'}")
|
||||||
|
jingrow.log_error("调试文件上传", f"form_dict keys: {list(jingrow.form_dict.keys()) if hasattr(jingrow, 'form_dict') else 'None'}")
|
||||||
|
|
||||||
|
# 从jingrow.request.files中获取文件
|
||||||
|
if hasattr(jingrow.request, 'files') and jingrow.request.files:
|
||||||
|
jingrow.log_error("request.files keys", str(list(jingrow.request.files.keys())))
|
||||||
|
for key in jingrow.request.files:
|
||||||
|
file_obj = jingrow.request.files[key]
|
||||||
|
if hasattr(file_obj, 'read'):
|
||||||
|
# 读取文件内容并转换为base64
|
||||||
|
file_content = file_obj.read()
|
||||||
|
file_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
files.append(file_base64)
|
||||||
|
jingrow.log_error(f"处理文件: {key}, 大小: {len(file_content)} bytes")
|
||||||
|
|
||||||
|
# 如果从request.files中没有找到文件,尝试从data中获取
|
||||||
|
if not files:
|
||||||
|
jingrow.log_error("从data中查找文件", str(list(data.keys())))
|
||||||
|
for key, value in data.items():
|
||||||
|
if key.startswith('files_') and hasattr(value, 'read'):
|
||||||
|
# 读取文件内容并转换为base64
|
||||||
|
file_content = value.read()
|
||||||
|
file_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
files.append(file_base64)
|
||||||
|
jingrow.log_error(f"从data处理文件: {key}, 大小: {len(file_content)} bytes")
|
||||||
|
|
||||||
|
# 如果还是没有文件,尝试从data.files中获取(前端传递的文件数组)
|
||||||
|
if not files and 'files' in data:
|
||||||
|
jingrow.log_error("从data.files中获取文件", str(len(data['files'])))
|
||||||
|
for file_obj in data['files']:
|
||||||
|
if hasattr(file_obj, 'read'):
|
||||||
|
# 读取文件内容并转换为base64
|
||||||
|
file_content = file_obj.read()
|
||||||
|
file_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
files.append(file_base64)
|
||||||
|
jingrow.log_error(f"从data.files处理文件, 大小: {len(file_content)} bytes")
|
||||||
|
|
||||||
|
# 如果还是没有文件,尝试从jingrow.form_dict中获取
|
||||||
|
if not files and hasattr(jingrow, 'form_dict'):
|
||||||
|
jingrow.log_error("从form_dict中查找文件", str(list(jingrow.form_dict.keys())))
|
||||||
|
for key, value in jingrow.form_dict.items():
|
||||||
|
if key.startswith('files_') and hasattr(value, 'read'):
|
||||||
|
# 读取文件内容并转换为base64
|
||||||
|
file_content = value.read()
|
||||||
|
file_base64 = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
files.append(file_base64)
|
||||||
|
jingrow.log_error(f"从form_dict处理文件: {key}, 大小: {len(file_content)} bytes")
|
||||||
|
|
||||||
|
if not files:
|
||||||
|
return {"status": "error", "message": "请上传证件材料"}
|
||||||
|
|
||||||
|
# 上传文件到西部数码
|
||||||
|
file_org = files[0] # 使用第一个文件作为证件文件
|
||||||
|
file_lxr = files[1] if len(files) > 1 else None # 第二个文件作为联系人文件(可选)
|
||||||
|
|
||||||
|
upload_response = client.upload_real_name_files(token, file_org, file_lxr)
|
||||||
|
|
||||||
|
if upload_response.get("status") == "error":
|
||||||
|
return upload_response
|
||||||
|
|
||||||
|
# 解析响应
|
||||||
|
d = upload_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("上传实名资料失败", str(e))
|
||||||
|
return {"status": "error", "message": "上传实名资料失败,请重试"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user