diff --git a/src/core/auth/auth.test.ts b/src/core/auth/auth.test.ts index eed3a8cc..ee88a86c 100644 --- a/src/core/auth/auth.test.ts +++ b/src/core/auth/auth.test.ts @@ -98,6 +98,10 @@ describe('admin auth session', () => { await auth.login('platform_admin', 'password') + expect(mocks.post).toHaveBeenCalledWith('/auth/login', { + loginId: 'platform_admin', + password: 'password', + }) expect(auth.isAuthenticated).toBe(true) expect(auth.refreshToken).toBe('refresh-domestic') }) diff --git a/src/core/auth/auth.ts b/src/core/auth/auth.ts index 03aa5f7b..6d995ae4 100644 --- a/src/core/auth/auth.ts +++ b/src/core/auth/auth.ts @@ -176,7 +176,7 @@ export const useAuthStore = defineStore('admin-auth', () => { try { const response = await http.post, ApiEnvelope>( '/auth/login', - { username: account, password }, + { loginId: account, password }, ) const result = unwrapApiResponse(response) await applySession(result, expectedGeneration) diff --git a/src/modules/customers/pages/CustomersView.vue b/src/modules/customers/pages/CustomersView.vue index 8e82b61d..38133af8 100644 --- a/src/modules/customers/pages/CustomersView.vue +++ b/src/modules/customers/pages/CustomersView.vue @@ -9,7 +9,6 @@ import { approveEnterpriseReview, archivePlatformTenant, changePlatformTenantStatus, - checkPlatformTenantContactPhone, createPlatformTenant, createPlatformTenantImpersonation, downloadTenantQualification, @@ -148,11 +147,14 @@ const rules: FormRules = { tenantName: [{ required: true, message: '请输入公司名称', trigger: 'blur' }], legalName: [{ required: true, message: '请输入营业执照上的企业名称', trigger: 'blur' }], legalRepresentative: [{ required: true, message: '请输入法定代表人姓名', trigger: 'blur' }], - unifiedSocialCreditCode: [{ pattern: /^[0-9A-Z]{18}$/, message: '请输入 18 位大写字母或数字', trigger: 'blur' }], + unifiedSocialCreditCode: [ + { required: true, message: '请输入统一社会信用代码', trigger: 'blur' }, + { pattern: /^[0-9A-Z]{18}$/, message: '请输入 18 位大写字母或数字', trigger: 'blur' }, + ], contactName: [{ required: true, message: '请输入联系人姓名', trigger: 'blur' }], contactPhone: [ - { required: true, message: '请输入联系电话', trigger: 'blur' }, - { pattern: /^[0-9-]{4,32}$/, message: '请输入 4-32 位数字或连字符,联系电话将作为登录用户名', trigger: 'blur' }, + { required: true, message: '请输入公司联系电话', trigger: 'blur' }, + { pattern: /^[0-9-]{4,32}$/, message: '请输入 4-32 位数字或连字符', trigger: 'blur' }, ], contactEmail: [{ type: 'email', message: '请输入有效邮箱地址', trigger: 'blur' }], servicePackage: [{ required: true, message: '请选择客户套餐', trigger: 'change' }], @@ -171,7 +173,7 @@ const decisionRules: FormRules = { function newQualificationDrafts(): QualificationDraft[] { const definitions: Array> = [ { type: 'BUSINESS_LICENSE', label: '营业执照', required: true }, - { type: 'LEGAL_PERSON_ID', label: '法人身份证', required: true }, + { type: 'LEGAL_PERSON_ID', label: '法人身份证', required: false }, { type: 'FREIGHT_FORWARDER_CERTIFICATE', label: '货代资质证书', required: false }, { type: 'BANK_ACCOUNT_LICENSE', label: '银行开户许可证', required: false }, ] @@ -221,23 +223,16 @@ const uploadingQualifications = computed(() => qualifications.value.some((item) const hasSelectedQualifications = computed(() => qualifications.value.some((item) => item.file)) const selectedBusinessLicense = computed(() => qualifications.value.find((item) => item.type === 'BUSINESS_LICENSE')?.file) const selectedLegalPersonId = computed(() => qualifications.value.find((item) => item.type === 'LEGAL_PERSON_ID')?.file) -const requiredPackageChangeSelected = computed(() => Boolean(selectedBusinessLicense.value || selectedLegalPersonId.value)) -const requiredPackageFilesSelected = computed(() => Boolean(selectedBusinessLicense.value && selectedLegalPersonId.value)) -const creditCodeReadyForSave = computed(() => requiredPackageChangeSelected.value - ? requiredPackageFilesSelected.value && (creditCodeEstablished.value - || unifiedSocialCreditCodePattern.test(form.value.unifiedSocialCreditCode || '')) - : creditCodeEstablished.value) -const requiredQualificationPackageComplete = computed(() => creditCodeReadyForSave.value - && (requiredPackageChangeSelected.value - ? requiredPackageFilesSelected.value - : qualifications.value.filter((item) => item.required).every((item) => item.uploaded))) +const businessLicenseReadyForSave = computed(() => Boolean(selectedBusinessLicense.value + || qualifications.value.find((item) => item.type === 'BUSINESS_LICENSE')?.uploaded)) +const creditCodeReadyForSave = computed(() => creditCodeEstablished.value + || unifiedSocialCreditCodePattern.test(form.value.unifiedSocialCreditCode || '')) +const requiredQualificationPackageComplete = computed(() => businessLicenseReadyForSave.value && creditCodeReadyForSave.value) const missingQualificationPackageItems = computed(() => { const businessLicense = qualifications.value.find((item) => item.type === 'BUSINESS_LICENSE') - const legalPersonId = qualifications.value.find((item) => item.type === 'LEGAL_PERSON_ID') const missing: string[] = [] - if (requiredPackageChangeSelected.value ? !businessLicense?.file : !businessLicense?.uploaded) missing.push('营业执照') - if (!creditCodeReadyForSave.value) missing.push('18位统一社会信用代码(需随必填资质包保存)') - if (requiredPackageChangeSelected.value ? !legalPersonId?.file : !legalPersonId?.uploaded) missing.push('法人身份证') + if (!businessLicense?.file && !businessLicense?.uploaded) missing.push('营业执照') + if (!creditCodeReadyForSave.value) missing.push('18位统一社会信用代码(需随营业执照保存)') return missing }) const hasUnsavedChanges = computed(() => Boolean(editingId.value) && JSON.stringify(form.value) !== savedFormSnapshot.value) @@ -512,27 +507,38 @@ async function uploadSelectedQualifications(tenantId: string) { const failures: string[] = [] const businessLicense = qualifications.value.find((item) => item.type === 'BUSINESS_LICENSE') const legalPersonId = qualifications.value.find((item) => item.type === 'LEGAL_PERSON_ID') - if (requiredPackageChangeSelected.value && businessLicense?.file && legalPersonId?.file) { - businessLicense.uploading = true; legalPersonId.uploading = true - businessLicense.error = ''; legalPersonId.error = '' + const businessLicenseFile = businessLicense?.file || null + const legalPersonIdFile = legalPersonId?.file || null + if (businessLicense && businessLicenseFile) { + businessLicense.uploading = true + if (legalPersonIdFile && legalPersonId) legalPersonId.uploading = true + businessLicense.error = '' + if (legalPersonId) legalPersonId.error = '' try { const uploaded = await uploadPlatformTenantRequiredQualificationPackage( - tenantId, businessLicense.file, legalPersonId.file, form.value.unifiedSocialCreditCode, - businessLicense.uploaded, legalPersonId.uploaded, + tenantId, businessLicenseFile, legalPersonIdFile, form.value.unifiedSocialCreditCode, + businessLicense.uploaded, Boolean(legalPersonIdFile && legalPersonId?.uploaded), ) - businessLicense.uploaded = true; legalPersonId.uploaded = true + if (legalPersonIdFile && !uploaded.legalPersonIdDocumentUrl) throw new Error('法人身份证上传结果缺少文件地址') + businessLicense.uploaded = true creditCodeEstablished.value = true - businessLicense.uploadedName = businessLicense.file.name - legalPersonId.uploadedName = legalPersonId.file.name + businessLicense.uploadedName = businessLicenseFile.name businessLicense.documentUrl = uploaded.businessLicenseDocumentUrl - legalPersonId.documentUrl = uploaded.legalPersonIdDocumentUrl - businessLicense.file = null; legalPersonId.file = null + businessLicense.file = null + if (legalPersonIdFile && legalPersonId) { + legalPersonId.uploaded = true + legalPersonId.uploadedName = legalPersonIdFile.name + legalPersonId.documentUrl = uploaded.legalPersonIdDocumentUrl || '' + legalPersonId.file = null + } } catch (error) { - const message = getApiErrorMessage(error, '必填资质包上传失败,请重试') - businessLicense.error = message; legalPersonId.error = message - failures.push('必填资质包') + const message = getApiErrorMessage(error, '营业执照及统一社会信用代码保存失败,请重试') + businessLicense.error = message + if (legalPersonIdFile && legalPersonId) legalPersonId.error = message + failures.push('营业执照资质') } finally { - businessLicense.uploading = false; legalPersonId.uploading = false + businessLicense.uploading = false + if (legalPersonId) legalPersonId.uploading = false } } for (const draft of failures.length ? [] : qualifications.value.filter((item) => !item.required && item.file)) { diff --git a/src/modules/iam/api/platformIam.ts b/src/modules/iam/api/platformIam.ts index 9689de43..2ff8f2c8 100644 --- a/src/modules/iam/api/platformIam.ts +++ b/src/modules/iam/api/platformIam.ts @@ -128,10 +128,10 @@ export interface PlatformQualificationUploadResponse { export interface PlatformRequiredQualificationPackageUploadResponse { businessLicenseQualificationId: number | string - legalPersonIdQualificationId: number | string + legalPersonIdQualificationId: number | string | null tenantStatus: PlatformTenantStatus businessLicenseDocumentUrl: string - legalPersonIdDocumentUrl: string + legalPersonIdDocumentUrl: string | null } export interface EnterpriseApprovalResponse { @@ -429,14 +429,14 @@ export async function uploadPlatformTenantQualification( export async function uploadPlatformTenantRequiredQualificationPackage( tenantId: number | string, businessLicense: File, - legalPersonId: File, + legalPersonId: File | null, unifiedSocialCreditCode: string, replaceBusinessLicense = false, replaceLegalPersonId = false, ) { const form = new FormData() form.append('businessLicense', businessLicense) - form.append('legalPersonId', legalPersonId) + if (legalPersonId) form.append('legalPersonId', legalPersonId) form.append('unifiedSocialCreditCode', unifiedSocialCreditCode) if (replaceBusinessLicense) form.append('replaceBusinessLicense', 'true') if (replaceLegalPersonId) form.append('replaceLegalPersonId', 'true') diff --git a/src/shared/api/http.test.ts b/src/shared/api/http.test.ts index 871ac892..15b361fb 100644 --- a/src/shared/api/http.test.ts +++ b/src/shared/api/http.test.ts @@ -32,7 +32,7 @@ describe('API error diagnostics', () => { } } - await http.post('/auth/login', { username: 'operator', password: 'secret' }) + await http.post('/auth/login', { loginId: 'operator', password: 'secret' }) expect(authorization).toBeUndefined() localStorage.removeItem('cc-admin-token')