|
@@ -1,928 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <cwg-page-wrapper>
|
|
|
|
|
- <view class="page page-shadow">
|
|
|
|
|
- <u-form ref="formRef" :rules="rules" :model="formData" class="payment-form">
|
|
|
|
|
- <!-- 第一步:基本信息 -->
|
|
|
|
|
- <view v-show="currentStep === 1" class="form-section">
|
|
|
|
|
- <h3 class="section-title">{{ t("card.Info.s1") }}</h3>
|
|
|
|
|
- <cwg-input v-model:value="formData.lastName" fkey="lastName" :required="true" :label="t('card.Form.f4')"
|
|
|
|
|
- rulesKey="lastName" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.firstName" fkey="firstName" :required="true" :label="t('card.Form.f5')"
|
|
|
|
|
- rulesKey="firstName" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.email" fkey="email" :label="t('card.Form.f3')" :required="true"
|
|
|
|
|
- rulesKey="email" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <view class="f" v-if="phoneCodes.length > 0">
|
|
|
|
|
- <cwg-input v-model:value="formData.areaCode" class="l" fkey="areaCode" :required="true" type="select"
|
|
|
|
|
- :show-search="true" :columns="phoneCodes" :label="t('card.Form.f2')" rulesKey="areaCode"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.mobile" class="r" fkey="mobile" label=" " rulesKey="mobile"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- </view>
|
|
|
|
|
- <cwg-input v-model:value="formData.gender" fkey="gender" type="select" :required="true" rulesKey="gender"
|
|
|
|
|
- :columns="sexOptions" :label="t('card.Form.f8')" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.birthday" :required="true" type="date" fkey="birthday" rulesKey="birthday"
|
|
|
|
|
- :label="t('card.Form.f6')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- 第二步:国籍信息 -->
|
|
|
|
|
- <view v-show="currentStep === 2" class="form-section">
|
|
|
|
|
- <h3 class="section-title">{{ t("ImproveImmediately.Title.AddressInformation") }}</h3>
|
|
|
|
|
- <cwg-input v-if="countryOptions.length > 0" v-model:value="formData.nationality" fkey="nationality"
|
|
|
|
|
- type="select" :required="true" :show-search="true" rulesKey="nationality" :columns="countryOptions"
|
|
|
|
|
- :label="t('card.Form.f7')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-if="cityOptions.length > 0" v-model:value="formData.town" fkey="town" :required="true"
|
|
|
|
|
- :show-search="true" rulesKey="town" type="select" :columns="cityOptions" :label="t('card.Form.f9')"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.address" fkey="address" :label="t('card.Form.f10')" :required="true"
|
|
|
|
|
- rulesKey="address" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.postCode" :required="true" fkey="postCode" rulesKey="postCode"
|
|
|
|
|
- :label="t('card.Form.f11')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- 第三步:职业信息 -->
|
|
|
|
|
- <view v-show="currentStep === 3" class="form-section">
|
|
|
|
|
- <h3 class="section-title">{{ t("card.Info.s0") }}</h3>
|
|
|
|
|
- <cwg-input v-if="occupationList.length > 0" v-model:value="formData.occupation" fkey="occupation"
|
|
|
|
|
- type="select" :columns="occupationList" :label="t('card.Form.f12')" :readonly="isReadonly"
|
|
|
|
|
- :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.annualSalary" fkey="annualSalary" :label="t('card.Form.f13')"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.accountPurpose" fkey="accountPurpose" :label="t('card.Form.f14')"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.expectedMonthlyVolume" fkey="expectedMonthlyVolume"
|
|
|
|
|
- :label="t('card.Form.f15')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- 第四步:证件信息 -->
|
|
|
|
|
- <view v-show="currentStep === 4" class="form-section">
|
|
|
|
|
- <h3 class="section-title">{{ t("card.Info.s2") }}</h3>
|
|
|
|
|
- <cwg-input v-if="availableIdTypeOptions.length" v-model:value="formData.idType" rulesKey="idType"
|
|
|
|
|
- fkey="idType" :required="true" type="select" :columns="availableIdTypeOptions" :label="t('card.Form.f16')"
|
|
|
|
|
- :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.idNumber" :required="true" rulesKey="idNumber" fkey="idNumber"
|
|
|
|
|
- :label="t('card.Form.f17')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-if="formData.nationality == 'US'" v-model:value="formData.ssn" fkey="ssn" rulesKey="ssn"
|
|
|
|
|
- :label="t('card.Form.f18')" :readonly="isReadonly" :disabled="isReadonly" @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.issueDate" :required="true" type="date" fkey="issueDate"
|
|
|
|
|
- rulesKey="issueDate" :label="t('card.Form.f19')" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange" />
|
|
|
|
|
- <cwg-input v-model:value="formData.idNoExpiryDate" :required="true" type="date" fkey="idNoExpiryDate"
|
|
|
|
|
- rulesKey="idNoExpiryDate" :label="t('card.Form.f20')" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange" />
|
|
|
|
|
- <template v-if="formData.photoStatus == '1'">
|
|
|
|
|
- <cwg-input v-model:value="formData.idFrontUrl" :required="true" type="upload" fkey="idFrontUrl"
|
|
|
|
|
- rulesKey="idFrontUrl" :label="t('card.Form.f21')" :is-upload-d="true"
|
|
|
|
|
- accept="image/png, image/jpeg, image/jpg" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange">
|
|
|
|
|
- <view class="cwg-upload">
|
|
|
|
|
- <cwg-icon name="back-top" />
|
|
|
|
|
- <view class="name">
|
|
|
|
|
- {{ t("card.Form.f23_2") }}{{ t("card.Form.f23") }}
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="back">{{ t("card.Form.f23_3") }}</view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </cwg-input>
|
|
|
|
|
- <cwg-input v-model:value="formData.idBackUrl" type="upload" :required="true" fkey="idBackUrl"
|
|
|
|
|
- rulesKey="idBackUrl" :label="t('card.Form.f22')" :is-upload-d="true"
|
|
|
|
|
- accept="image/png, image/jpeg, image/jpg" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange">
|
|
|
|
|
- <view class="cwg-upload">
|
|
|
|
|
- <cwg-icon name="back-top" />
|
|
|
|
|
- <view class="name">
|
|
|
|
|
- {{ t("card.Form.f23_2") }}{{ t("card.Form.f23") }}
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="back">{{ t("card.Form.f23_3") }}</view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </cwg-input>
|
|
|
|
|
- <cwg-input v-model:value="formData.idHoldUrl" type="upload" fkey="idHoldUrl" :required="true"
|
|
|
|
|
- rulesKey="idHoldUrl" :label="t('card.Form.f23')" :is-upload-d="true"
|
|
|
|
|
- accept="image/png, image/jpeg, image/jpg" :readonly="isReadonly" :disabled="isReadonly"
|
|
|
|
|
- @change="handleChange">
|
|
|
|
|
- <view class="cwg-upload">
|
|
|
|
|
- <cwg-icon name="back-top" />
|
|
|
|
|
- <view class="name">
|
|
|
|
|
- {{ t("card.Form.f23_2") }}{{ t("card.Form.f23") }}
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="back">{{ t("card.Form.f23_3") }}</view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </cwg-input>
|
|
|
|
|
- </template>
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- 步骤控制按钮 -->
|
|
|
|
|
- <view class="form-actions">
|
|
|
|
|
- <template v-if="currentStep === 3">
|
|
|
|
|
- <view class="fixed-btn">
|
|
|
|
|
- <view class="cwg-button two-btn">
|
|
|
|
|
- <u-button plain block class="prev-btn" @click="goStep(2)">
|
|
|
|
|
- {{ t("card.Btn.Previous") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- <u-button type="primary" block :loading="loadingStates.validateStep3" @click="validateStep3">
|
|
|
|
|
- {{ t("card.Btn.Next") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-else-if="currentStep === 2">
|
|
|
|
|
- <view class="fixed-btn">
|
|
|
|
|
- <view class="cwg-button two-btn">
|
|
|
|
|
- <u-button plain block class="prev-btn" @click="goStep(1)">
|
|
|
|
|
- {{ t("card.Btn.Previous") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- <u-button type="warning" block :loading="loadingStates.validateStep2" @click="validateStep2">
|
|
|
|
|
- {{ t("card.Btn.Next") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-else-if="currentStep === 1">
|
|
|
|
|
- <view class="fixed-btn">
|
|
|
|
|
- <view class="cwg-button two-btn">
|
|
|
|
|
- <u-button type="warning" block :loading="loadingStates.validateStep1" @click="validateStep1">
|
|
|
|
|
- {{ t("card.Btn.Next") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-else-if="currentStep === 4">
|
|
|
|
|
- <view class="fixed-btn">
|
|
|
|
|
- <view class="cwg-button two-btn">
|
|
|
|
|
- <u-button plain block class="prev-btn" @click="goStep(3)">
|
|
|
|
|
- {{ t("card.Btn.Previous") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- <u-button v-if="!isUpdate" type="warning" block :loading="loadingStates.validateStep4"
|
|
|
|
|
- @click="validateStep4(1)">
|
|
|
|
|
- {{ t("card.Btn.Submit") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- <u-button v-if="isUpdate && !isAuthInfo" type="warning" block :loading="loadingStates.validateStep4"
|
|
|
|
|
- @click="validateStep4(2)">
|
|
|
|
|
- {{ t("card.Btn.Update") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- <u-button v-if="
|
|
|
|
|
- isUpdate &&
|
|
|
|
|
- formData.kycStatus != '2' &&
|
|
|
|
|
- formData.photoStatus != '1'
|
|
|
|
|
- " type="warning" block :loading="loadingStates.validateStep4" @click="validateStep4(3)">
|
|
|
|
|
- {{ t("card.Btn.Auth") }}
|
|
|
|
|
- </u-button>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </template>
|
|
|
|
|
- </view>
|
|
|
|
|
- </u-form>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="form-tab"></view>
|
|
|
|
|
- </cwg-page-wrapper>
|
|
|
|
|
- <card-websdk-link ref="cardWebsdkLinkRef" />
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script setup lang="ts">
|
|
|
|
|
-import { ref, onMounted, watch, computed } from "vue";
|
|
|
|
|
-import { pinyin } from "pinyin-pro";
|
|
|
|
|
-import { useI18n } from "vue-i18n";
|
|
|
|
|
-import { onLoad } from '@dcloudio/uni-app'
|
|
|
|
|
-import { userToken } from "@/composables/config";
|
|
|
|
|
-import { ucardApi } from "@/api/ucard";
|
|
|
|
|
-import { userApi } from "@/api/user";
|
|
|
|
|
-import useUserStore from "@/stores/use-user-store";
|
|
|
|
|
-import useIdTypeOptions from "@/composables/useIdTypeOptions";
|
|
|
|
|
-import { Patterns, Validators } from "@/utils/validators";
|
|
|
|
|
-import CardWebsdkLink from "@/components/card-websdkLink.vue";
|
|
|
|
|
-import useRouter from "@/hooks/useRouter";
|
|
|
|
|
-const router = useRouter();
|
|
|
|
|
-
|
|
|
|
|
-const { availableIdTypeOptions, loadIdTypesConfig } = useIdTypeOptions()
|
|
|
|
|
-console.log(availableIdTypeOptions, 1212121, 'storeIdTypeOptionsstoreIdTypeOptions');
|
|
|
|
|
-
|
|
|
|
|
-const { t } = useI18n();
|
|
|
|
|
-const currentStep = ref<number>(1);
|
|
|
|
|
-const cardWebsdkLinkRef = ref<InstanceType<typeof CardWebsdkLink> | null>(null);
|
|
|
|
|
-
|
|
|
|
|
-onLoad((options) => {
|
|
|
|
|
- currentStep.value = parseInt(options?.currentStep || '1', 10);
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const formRef = ref();
|
|
|
|
|
-
|
|
|
|
|
-function goStep(step: number) {
|
|
|
|
|
- currentStep.value = step;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const sexOptions = ref([
|
|
|
|
|
- { text: t("card.Form.v1"), value: "M" },
|
|
|
|
|
- { text: t("card.Form.v2"), value: "F" },
|
|
|
|
|
-]);
|
|
|
|
|
-
|
|
|
|
|
-function validateName(a: any, b?: any, c?: any) {
|
|
|
|
|
- const reg = /^[A-Z\s]+$/i;
|
|
|
|
|
- // Element 风格: (rule, value, callback)
|
|
|
|
|
- if (typeof c === "function") {
|
|
|
|
|
- const value = b;
|
|
|
|
|
- const callback = c;
|
|
|
|
|
- const val = String(value ?? "").trim();
|
|
|
|
|
- if (!val) return callback(new Error(t("card.vaildate.v4")));
|
|
|
|
|
- if (!reg.test(val)) return callback(new Error(t("card.vaildate.v38")));
|
|
|
|
|
- if (val.length < 2 || val.length > 23)
|
|
|
|
|
- return callback(new Error(t("card.vaildate.v39")));
|
|
|
|
|
- const firstName = String(formData.value?.firstName ?? "").trim();
|
|
|
|
|
- const lastName = String(formData.value?.lastName ?? "").trim();
|
|
|
|
|
- if (`${firstName} ${lastName}`.length > 23)
|
|
|
|
|
- return callback(new Error(t("card.vaildate.v40")));
|
|
|
|
|
- return callback();
|
|
|
|
|
- }
|
|
|
|
|
- // Vant 风格: (value) => boolean | string | Promise
|
|
|
|
|
- const val = String(a ?? "").trim();
|
|
|
|
|
- if (!val) return t("card.vaildate.v4");
|
|
|
|
|
- if (!reg.test(val)) return t("card.vaildate.v38");
|
|
|
|
|
- if (val.length < 2 || val.length > 23) return t("card.vaildate.v39");
|
|
|
|
|
- const firstName = String(formData.value?.firstName ?? "").trim();
|
|
|
|
|
- const lastName = String(formData.value?.lastName ?? "").trim();
|
|
|
|
|
- if (`${firstName} ${lastName}`.length > 23) return t("card.vaildate.v40");
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 生日校验:18 岁以上
|
|
|
|
|
-function validateBirthday(a: any, b?: any, c?: any) {
|
|
|
|
|
- // Element 风格: (rule, value, callback)
|
|
|
|
|
- if (typeof c === "function") {
|
|
|
|
|
- const value = b;
|
|
|
|
|
- const callback = c;
|
|
|
|
|
- const val = value;
|
|
|
|
|
- if (!val) return callback(new Error(t("card.vaildate.v5")));
|
|
|
|
|
-
|
|
|
|
|
- const today = new Date();
|
|
|
|
|
- const birthDate = new Date(val);
|
|
|
|
|
- let age = today.getFullYear() - birthDate.getFullYear();
|
|
|
|
|
- const month = today.getMonth() - birthDate.getMonth();
|
|
|
|
|
- if (month < 0 || (month === 0 && today.getDate() < birthDate.getDate()))
|
|
|
|
|
- age--;
|
|
|
|
|
-
|
|
|
|
|
- if (age < 18) return callback(new Error(t("card.New.n3")));
|
|
|
|
|
- return callback();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // uview-plus / Vant 风格: (value) => boolean | string
|
|
|
|
|
- const val = a;
|
|
|
|
|
- if (!val) return t("card.vaildate.v5");
|
|
|
|
|
-
|
|
|
|
|
- const today = new Date();
|
|
|
|
|
- const birthDate = new Date(val);
|
|
|
|
|
- let age = today.getFullYear() - birthDate.getFullYear();
|
|
|
|
|
- const month = today.getMonth() - birthDate.getMonth();
|
|
|
|
|
- if (month < 0 || (month === 0 && today.getDate() < birthDate.getDate()))
|
|
|
|
|
- age--;
|
|
|
|
|
-
|
|
|
|
|
- return age < 18 ? t("card.New.n3") : true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function validateAddress(a: any, b?: any, c?: any) {
|
|
|
|
|
- // 地址只需要校验长度和基础字符合法性,允许数字、字母、空格等
|
|
|
|
|
- // Element 风格: (rule, value, callback)
|
|
|
|
|
- if (typeof c === "function") {
|
|
|
|
|
- const value = b;
|
|
|
|
|
- const callback = c;
|
|
|
|
|
- const val = String(value ?? "").trim();
|
|
|
|
|
-
|
|
|
|
|
- if (!val) return callback(new Error(t("card.vaildate.v27")));
|
|
|
|
|
- if (val.length < 2 || val.length > 40)
|
|
|
|
|
- return callback(new Error(t("card.New.n1")));
|
|
|
|
|
- if (!Patterns.address.test(val))
|
|
|
|
|
- return callback(new Error(t("card.New.n1")));
|
|
|
|
|
-
|
|
|
|
|
- return callback();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Vant 风格: (value) => boolean | string | Promise
|
|
|
|
|
- const val = String(a ?? "").trim();
|
|
|
|
|
- if (!val) return t("card.vaildate.v27");
|
|
|
|
|
- if (val.length < 2 || val.length > 40) return t("card.New.n1");
|
|
|
|
|
- return Patterns.address.test(val) ? true : t("card.New.n1");
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 表单验证规则
|
|
|
|
|
-const rules = {
|
|
|
|
|
- areaCode: [Validators.required(t("card.vaildate.v1"))],
|
|
|
|
|
- mobile: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v2")),
|
|
|
|
|
- Validators.pattern(Patterns.mobile, t("card.vaildate.v44")),
|
|
|
|
|
- ],
|
|
|
|
|
- email: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v28")),
|
|
|
|
|
- Validators.pattern(Patterns.email, t("card.vaildate.v28")),
|
|
|
|
|
- ],
|
|
|
|
|
- firstName: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v3")),
|
|
|
|
|
- Validators.custom(validateName),
|
|
|
|
|
- ],
|
|
|
|
|
- lastName: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v4")),
|
|
|
|
|
- Validators.custom(validateName),
|
|
|
|
|
- ],
|
|
|
|
|
- birthday: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v5"), "change"),
|
|
|
|
|
- Validators.custom(validateBirthday, "change"),
|
|
|
|
|
- ],
|
|
|
|
|
- nationality: [Validators.required(t("card.vaildate.v6"), "change")],
|
|
|
|
|
- town: [Validators.required(t("card.vaildate.v7"), "change")],
|
|
|
|
|
- address: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v27")),
|
|
|
|
|
- Validators.custom(validateAddress),
|
|
|
|
|
- ],
|
|
|
|
|
- gender: [Validators.required(t("card.vaildate.v9"), "change")],
|
|
|
|
|
- occupation: [Validators.required(t("card.vaildate.v10"), "change")],
|
|
|
|
|
- annualSalary: [Validators.required(t("card.vaildate.v11"))],
|
|
|
|
|
- accountPurpose: [Validators.required(t("card.vaildate.v12"))],
|
|
|
|
|
- expectedMonthlyVolume: [Validators.required(t("card.vaildate.v13"))],
|
|
|
|
|
- idType: [Validators.required(t("card.vaildate.v14"), "change")],
|
|
|
|
|
- idNumber: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v15")),
|
|
|
|
|
- Validators.pattern(Patterns.idNumber, t("card.vaildate.v45")),
|
|
|
|
|
- ],
|
|
|
|
|
- ssn: [Validators.required(t("card.vaildate.v16"))],
|
|
|
|
|
- issueDate: [Validators.required(t("card.vaildate.v17"), "change")],
|
|
|
|
|
- idNoExpiryDate: [Validators.required(t("card.vaildate.v18"), "change")],
|
|
|
|
|
- idFrontUrl: [Validators.required(t("card.vaildate.v19"), "change")],
|
|
|
|
|
- idBackUrl: [Validators.required(t("card.vaildate.v20"), "change")],
|
|
|
|
|
- idHoldUrl: [Validators.required(t("card.vaildate.v21"), "change")],
|
|
|
|
|
- postCode: [
|
|
|
|
|
- Validators.required(t("card.vaildate.v8")),
|
|
|
|
|
- Validators.pattern(Patterns.postcode, t("card.New.n2")),
|
|
|
|
|
- ],
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const formData = ref({
|
|
|
|
|
- merchantOrderNo: undefined,
|
|
|
|
|
- cardTypeId: undefined,
|
|
|
|
|
- areaCode: undefined,
|
|
|
|
|
- mobile: undefined,
|
|
|
|
|
- email: undefined,
|
|
|
|
|
- firstName: undefined,
|
|
|
|
|
- lastName: undefined,
|
|
|
|
|
- birthday: undefined,
|
|
|
|
|
- nationality: undefined,
|
|
|
|
|
- country: undefined,
|
|
|
|
|
- town: undefined,
|
|
|
|
|
- address: undefined,
|
|
|
|
|
- postCode: undefined,
|
|
|
|
|
- gender: undefined,
|
|
|
|
|
- occupation: undefined,
|
|
|
|
|
- annualSalary: undefined,
|
|
|
|
|
- accountPurpose: undefined,
|
|
|
|
|
- expectedMonthlyVolume: undefined,
|
|
|
|
|
- idType: undefined,
|
|
|
|
|
- idNumber: undefined,
|
|
|
|
|
- ssn: undefined,
|
|
|
|
|
- issueDate: undefined,
|
|
|
|
|
- idNoExpiryDate: undefined,
|
|
|
|
|
- idFrontUrl: undefined,
|
|
|
|
|
- idBackUrl: undefined,
|
|
|
|
|
- idHoldUrl: undefined,
|
|
|
|
|
- ipAddress: undefined,
|
|
|
|
|
- cId: undefined,
|
|
|
|
|
- customId: undefined,
|
|
|
|
|
- photoStatus: '1',
|
|
|
|
|
- kycStatus: '1'
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const isUpdate = ref(false);
|
|
|
|
|
-const isAuthInfo = ref(false);
|
|
|
|
|
-
|
|
|
|
|
-// 国家选项
|
|
|
|
|
-const countryOptions = ref<Array<{ text: string; value: string }>>([]);
|
|
|
|
|
-const cityOptions = ref<Array<{ text: string; value: string }>>([]);
|
|
|
|
|
-const phoneCodes = ref<Array<{ text: string; value: string }>>([]);
|
|
|
|
|
-const occupationList = ref<Array<{ text: string; value: string }>>([]);
|
|
|
|
|
-
|
|
|
|
|
-// 获取国家列表
|
|
|
|
|
-async function getCountryListForSelect() {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await ucardApi.ucardCountryCity({});
|
|
|
|
|
- if (res.code === 200 || res.code === 0) {
|
|
|
|
|
- countryOptions.value = res.data.map((item: any) => ({
|
|
|
|
|
- text: item.enName,
|
|
|
|
|
- value: item.code,
|
|
|
|
|
- }));
|
|
|
|
|
- phoneCodes.value = res.data.map((item: any) => ({
|
|
|
|
|
- text: `${item.areaCode} ${item.enName}`,
|
|
|
|
|
- value: item.areaCode,
|
|
|
|
|
- }));
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('Error loading country list:', error);
|
|
|
|
|
- countryOptions.value = [];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// 获取城市列表
|
|
|
|
|
-async function getCityListForSelect(countryCode: string) {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await ucardApi.ucardCountryCity({ code: countryCode });
|
|
|
|
|
- if (res.code === 200 || res.code === 0) {
|
|
|
|
|
- const cityList = res.data.map((item: any) => ({
|
|
|
|
|
- text: item.enName,
|
|
|
|
|
- value: item.code,
|
|
|
|
|
- }));
|
|
|
|
|
- cityOptions.value = cityList;
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('Error loading city list:', error);
|
|
|
|
|
- cityOptions.value = [];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 获取职业
|
|
|
|
|
-async function getOccupationList() {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await ucardApi.getOccupationList();
|
|
|
|
|
- if (res.code === 200 || res.code === 0) {
|
|
|
|
|
- const list = res.data.map((item: any) => ({
|
|
|
|
|
- text: item.description,
|
|
|
|
|
- value: item.occupationCode,
|
|
|
|
|
- }));
|
|
|
|
|
- occupationList.value = list;
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('Error loading occupation list:', error);
|
|
|
|
|
- occupationList.value = [];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function handleChange(value: any) {
|
|
|
|
|
- formData.value = { ...formData.value, [value.key]: value.value };
|
|
|
|
|
-
|
|
|
|
|
- if (value.key === "nationality") {
|
|
|
|
|
- formData.value = { ...formData.value, country: value.value };
|
|
|
|
|
- getCityListForSelect(value.value);
|
|
|
|
|
- loadIdTypesConfig(value.value);
|
|
|
|
|
- formData.value.town = "";
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const containsChinese = (str: string) => /[\u4E00-\u9FA5]/.test(str);
|
|
|
|
|
-
|
|
|
|
|
-const convertToPinyin = (value: string) =>
|
|
|
|
|
- containsChinese(value)
|
|
|
|
|
- ? pinyin(value, { toneType: "none", type: "capitalize" })
|
|
|
|
|
- : value;
|
|
|
|
|
-
|
|
|
|
|
-// 初始化表单数据 - 使用现有用户信息进行回显
|
|
|
|
|
-function initFormDataWithUserInfo() {
|
|
|
|
|
- if (!userInfo.value) return;
|
|
|
|
|
-
|
|
|
|
|
- const customInfo = userInfo.value.customInfo || userInfo.value;
|
|
|
|
|
-
|
|
|
|
|
- // 基本信息
|
|
|
|
|
- formData.value.email = customInfo.email || formData.value.email;
|
|
|
|
|
- formData.value.areaCode = customInfo.areaCode || formData.value.areaCode;
|
|
|
|
|
- formData.value.mobile = customInfo.mobile || formData.value.mobile;
|
|
|
|
|
- formData.value.birthday = customInfo.birthday || formData.value.birthday;
|
|
|
|
|
- formData.value.gender = customInfo.gender || formData.value.gender;
|
|
|
|
|
-
|
|
|
|
|
- // 姓名处理
|
|
|
|
|
- if (customInfo.lastName) {
|
|
|
|
|
- formData.value.lastName = convertToPinyin(customInfo.lastName);
|
|
|
|
|
- }
|
|
|
|
|
- if (customInfo.firstName) {
|
|
|
|
|
- formData.value.firstName = convertToPinyin(customInfo.firstName);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 地址信息
|
|
|
|
|
- formData.value.nationality = customInfo.nationality || formData.value.nationality;
|
|
|
|
|
- formData.value.town = customInfo.town || formData.value.town;
|
|
|
|
|
- formData.value.address = customInfo.address || formData.value.address;
|
|
|
|
|
- formData.value.postCode = customInfo.postCode || formData.value.postCode;
|
|
|
|
|
-
|
|
|
|
|
- // 职业信息
|
|
|
|
|
- formData.value.occupation = customInfo.occupation || formData.value.occupation;
|
|
|
|
|
- formData.value.annualSalary = customInfo.annualSalary || formData.value.annualSalary;
|
|
|
|
|
- formData.value.accountPurpose = customInfo.accountPurpose || formData.value.accountPurpose;
|
|
|
|
|
- formData.value.expectedMonthlyVolume = customInfo.expectedMonthlyVolume || formData.value.expectedMonthlyVolume;
|
|
|
|
|
-
|
|
|
|
|
- // 证件信息
|
|
|
|
|
- formData.value.idType = customInfo.idType || formData.value.idType;
|
|
|
|
|
- formData.value.idNumber = customInfo.idNumber || formData.value.idNumber;
|
|
|
|
|
- formData.value.ssn = customInfo.ssn || formData.value.ssn;
|
|
|
|
|
- formData.value.issueDate = customInfo.issueDate || formData.value.issueDate;
|
|
|
|
|
- formData.value.idNoExpiryDate = customInfo.idNoExpiryDate || formData.value.idNoExpiryDate;
|
|
|
|
|
- formData.value.idFrontUrl = customInfo.idFrontUrl || formData.value.idFrontUrl;
|
|
|
|
|
- formData.value.idBackUrl = customInfo.idBackUrl || formData.value.idBackUrl;
|
|
|
|
|
- formData.value.idHoldUrl = customInfo.idHoldUrl || formData.value.idHoldUrl;
|
|
|
|
|
-
|
|
|
|
|
- // 状态信息
|
|
|
|
|
- formData.value.photoStatus = customInfo.photoStatus || '1';
|
|
|
|
|
- formData.value.kycStatus = customInfo.kycStatus || '1';
|
|
|
|
|
-
|
|
|
|
|
- // 对于下拉选择字段,需要确保它们在选项列表中存在
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- // 确保 areaCode 在选项中
|
|
|
|
|
- if (formData.value.areaCode && phoneCodes.value.length > 0) {
|
|
|
|
|
- const areaCodeExists = phoneCodes.value.some(item => item.value === formData.value.areaCode);
|
|
|
|
|
- if (!areaCodeExists) {
|
|
|
|
|
- // 如果不存在,添加该项到选项中
|
|
|
|
|
- phoneCodes.value.push({
|
|
|
|
|
- text: formData.value.areaCode,
|
|
|
|
|
- value: formData.value.areaCode
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 确保 nationality 在选项中
|
|
|
|
|
- if (formData.value.nationality && countryOptions.value.length > 0) {
|
|
|
|
|
- const nationalityExists = countryOptions.value.some(item => item.value === formData.value.nationality);
|
|
|
|
|
- if (!nationalityExists) {
|
|
|
|
|
- countryOptions.value.push({
|
|
|
|
|
- text: formData.value.nationality,
|
|
|
|
|
- value: formData.value.nationality
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 确保 occupation 在选项中
|
|
|
|
|
- if (formData.value.occupation && occupationList.value.length > 0) {
|
|
|
|
|
- const occupationExists = occupationList.value.some(item => item.value === formData.value.occupation);
|
|
|
|
|
- if (!occupationExists) {
|
|
|
|
|
- occupationList.value.push({
|
|
|
|
|
- text: formData.value.occupation,
|
|
|
|
|
- value: formData.value.occupation
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 确保 gender 在选项中
|
|
|
|
|
- if (formData.value.gender) {
|
|
|
|
|
- const genderExists = sexOptions.value.some(item => item.value === formData.value.gender);
|
|
|
|
|
- if (!genderExists) {
|
|
|
|
|
- sexOptions.value.push({
|
|
|
|
|
- text: formData.value.gender === 'M' ? t("card.Form.v1") : t("card.Form.v2"),
|
|
|
|
|
- value: formData.value.gender
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }, 100);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function getUserSingle() {
|
|
|
|
|
- if (!userToken.value) {
|
|
|
|
|
- uni.showToast({ title: t("common.loginFirst"), icon: 'none' });
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await userApi.getUserSingle();
|
|
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
|
|
- // 更新表单数据
|
|
|
|
|
- formData.value = { ...formData.value, ...res.data };
|
|
|
|
|
- userStore.saveUserInfo(res.data);
|
|
|
|
|
-
|
|
|
|
|
- // 设置状态
|
|
|
|
|
- if (res.data) {
|
|
|
|
|
- isUpdate.value = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (res.data.approveStatus == 2 || res.data.kycStatus == 2) {
|
|
|
|
|
- isAuthInfo.value = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (res.data.approveStatus == 3) {
|
|
|
|
|
- isAuthInfo.value = false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 如果有国籍信息,加载对应的城市列表
|
|
|
|
|
- if (res.data.nationality) {
|
|
|
|
|
- await getCityListForSelect(res.data.nationality);
|
|
|
|
|
- await loadIdTypesConfig(res.data.nationality);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- console.error('Error in getUserSingle:', error);
|
|
|
|
|
- uni.showToast({ title: error.message || t("common.error"), icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 加载状态
|
|
|
|
|
-const loadingStates = ref({
|
|
|
|
|
- validateStep1: false,
|
|
|
|
|
- validateStep2: false,
|
|
|
|
|
- validateStep3: false,
|
|
|
|
|
- validateStep4: false,
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-// 第一步校验 - 基本信息完整性
|
|
|
|
|
-async function validateStep1() {
|
|
|
|
|
- loadingStates.value.validateStep1 = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const requiredFields = [
|
|
|
|
|
- "email",
|
|
|
|
|
- "lastName",
|
|
|
|
|
- "firstName",
|
|
|
|
|
- "mobile",
|
|
|
|
|
- "areaCode",
|
|
|
|
|
- "birthday",
|
|
|
|
|
- "gender",
|
|
|
|
|
- ] as const;
|
|
|
|
|
- await formRef.value?.validateField(requiredFields, (errorsRes: any) => {
|
|
|
|
|
- const hasError = Array.isArray(errorsRes) && errorsRes.length > 0;
|
|
|
|
|
- if (hasError) {
|
|
|
|
|
- uni.showToast({ title: errorsRes[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- goStep(2);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- } finally {
|
|
|
|
|
- loadingStates.value.validateStep1 = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 第二步校验 - 国籍信息
|
|
|
|
|
-async function validateStep2() {
|
|
|
|
|
- loadingStates.value.validateStep2 = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const requiredFields = [
|
|
|
|
|
- "nationality",
|
|
|
|
|
- "town",
|
|
|
|
|
- "postCode",
|
|
|
|
|
- "address",
|
|
|
|
|
- ] as const;
|
|
|
|
|
- await formRef.value?.validateField(requiredFields, (errorsRes: any) => {
|
|
|
|
|
- const hasError = Array.isArray(errorsRes) && errorsRes.length > 0;
|
|
|
|
|
- if (hasError) {
|
|
|
|
|
- uni.showToast({ title: errorsRes[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- goStep(3);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- } finally {
|
|
|
|
|
- loadingStates.value.validateStep2 = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 第三步校验 - 职业信息
|
|
|
|
|
-async function validateStep3() {
|
|
|
|
|
- loadingStates.value.validateStep3 = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const requiredFields = [
|
|
|
|
|
- "occupation",
|
|
|
|
|
- "annualSalary",
|
|
|
|
|
- "accountPurpose",
|
|
|
|
|
- "expectedMonthlyVolume",
|
|
|
|
|
- ] as const;
|
|
|
|
|
- await formRef.value?.validateField(requiredFields, (errorsRes: any) => {
|
|
|
|
|
- const hasError = Array.isArray(errorsRes) && errorsRes.length > 0;
|
|
|
|
|
- if (hasError) {
|
|
|
|
|
- uni.showToast({ title: errorsRes[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- goStep(4);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- } finally {
|
|
|
|
|
- loadingStates.value.validateStep3 = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 第四步校验 校验所有信息
|
|
|
|
|
-async function validateStep4(type: number) {
|
|
|
|
|
- loadingStates.value.validateStep4 = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const requiredFields: Array<keyof typeof formData.value> = [
|
|
|
|
|
- "email",
|
|
|
|
|
- "lastName",
|
|
|
|
|
- "firstName",
|
|
|
|
|
- "mobile",
|
|
|
|
|
- "areaCode",
|
|
|
|
|
- "nationality",
|
|
|
|
|
- "town",
|
|
|
|
|
- "postCode",
|
|
|
|
|
- "address",
|
|
|
|
|
- "birthday",
|
|
|
|
|
- "gender",
|
|
|
|
|
- "idType",
|
|
|
|
|
- "idNumber",
|
|
|
|
|
- "issueDate",
|
|
|
|
|
- "idNoExpiryDate",
|
|
|
|
|
- "occupation",
|
|
|
|
|
- "annualSalary",
|
|
|
|
|
- "accountPurpose",
|
|
|
|
|
- "expectedMonthlyVolume",
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- // 只有在需要上传照片时才验证照片字段
|
|
|
|
|
- if (formData.value.photoStatus === '1') {
|
|
|
|
|
- requiredFields.push("idFrontUrl", "idBackUrl", "idHoldUrl");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- await formRef.value?.validateField(requiredFields, (errorsRes: any) => {
|
|
|
|
|
- const hasError = Array.isArray(errorsRes) && errorsRes.length > 0;
|
|
|
|
|
- console.log(hasError, 121212);
|
|
|
|
|
-
|
|
|
|
|
- if (hasError) {
|
|
|
|
|
- uni.showToast({ title: errorsRes[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- // 最终校验所有信息
|
|
|
|
|
- switch (type) {
|
|
|
|
|
- case 1:
|
|
|
|
|
- infoSubmit();
|
|
|
|
|
- break;
|
|
|
|
|
- case 2:
|
|
|
|
|
- infoUpdate();
|
|
|
|
|
- break;
|
|
|
|
|
- case 3:
|
|
|
|
|
- infoAuth();
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- } finally {
|
|
|
|
|
- loadingStates.value.validateStep4 = false;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function infoSubmit() {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await ucardApi.merchantRegister(formData.value);
|
|
|
|
|
- if (res.code === 200) {
|
|
|
|
|
- uni.showToast({ title: t("common.success"), icon: 'success' });
|
|
|
|
|
- // 提交成功后打开 WebSDK 弹窗
|
|
|
|
|
- router.push({
|
|
|
|
|
- path: "/pages/mine/kyc",
|
|
|
|
|
- query: { cardId: (formData.value as any).id },
|
|
|
|
|
- });
|
|
|
|
|
- // cardWebsdkLinkRef.value?.getWebsdkLink(
|
|
|
|
|
- // (formData.value as any).id
|
|
|
|
|
- // );
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: res.msg, icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- uni.showToast({ title: error.message || t("common.error"), icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function infoUpdate() {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await ucardApi.merchantUpdate(formData.value);
|
|
|
|
|
- if (res.code === 200) {
|
|
|
|
|
- uni.showToast({ title: t("common.success"), icon: 'success' });
|
|
|
|
|
- // 更新成功后打开 WebSDK 弹窗
|
|
|
|
|
- // router.push({
|
|
|
|
|
- // path: "/pages/mine/kyc",
|
|
|
|
|
- // query: { cardId: (formData.value as any).id },
|
|
|
|
|
- // });
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: res.msg, icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: t("card.New.errer"), icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-async function infoAuth() {
|
|
|
|
|
- try {
|
|
|
|
|
- // 认证操作后也打开 WebSDK 弹窗(无需等待额外接口)
|
|
|
|
|
- router.push({
|
|
|
|
|
- path: "/pages/mine/kyc",
|
|
|
|
|
- query: { cardId: (formData.value as any).id },
|
|
|
|
|
- });
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- if (Array.isArray(error) && error.length > 0) {
|
|
|
|
|
- uni.showToast({ title: error[0].message, icon: 'none' });
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: t("card.New.errer"), icon: 'none' });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const isReadonly = computed(() => isAuthInfo.value);
|
|
|
|
|
-
|
|
|
|
|
-onMounted(async () => {
|
|
|
|
|
- // 用现有用户信息回显
|
|
|
|
|
- initFormDataWithUserInfo();
|
|
|
|
|
- // 先加载选项数据
|
|
|
|
|
- await Promise.all([
|
|
|
|
|
- getOccupationList(),
|
|
|
|
|
- getCountryListForSelect()
|
|
|
|
|
- ]);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // 延迟加载用户详细信息
|
|
|
|
|
- setTimeout(async () => {
|
|
|
|
|
- await getUserSingle();
|
|
|
|
|
- }, 100);
|
|
|
|
|
-});
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
|
|
-@import "@/uni.scss";
|
|
|
|
|
-
|
|
|
|
|
-.form-tab {
|
|
|
|
|
- height: px2rpx(100);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.form-section {
|
|
|
|
|
- margin: px2rpx(8) 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.section-title {
|
|
|
|
|
- color: #1a1a1a;
|
|
|
|
|
- font-family: Roboto;
|
|
|
|
|
- font-size: px2rpx(22);
|
|
|
|
|
- font-style: normal;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
- line-height: px2rpx(22);
|
|
|
|
|
- margin-bottom: px2rpx(16);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.two-btn {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- gap: px2rpx(31);
|
|
|
|
|
-
|
|
|
|
|
- .prev-btn {
|
|
|
|
|
- border: 1px solid var(--main-yellow) !important;
|
|
|
|
|
- color: #fff !important;
|
|
|
|
|
- background: transparent;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.f {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: flex-end;
|
|
|
|
|
- gap: px2rpx(12);
|
|
|
|
|
-
|
|
|
|
|
- .l {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .r {
|
|
|
|
|
- width: px2rpx(203);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-:deep(.u-uploader) {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
-
|
|
|
|
|
- .u-uploader__wrapper {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- display: block;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .u-uploader__preview {
|
|
|
|
|
- width: 100% !important;
|
|
|
|
|
- height: px2rpx(160) !important;
|
|
|
|
|
- border-radius: px2rpx(24);
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
-
|
|
|
|
|
- .u-uploader__preview-image {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
-
|
|
|
|
|
- .u-image__img {
|
|
|
|
|
- object-fit: contain;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .u-uploader__preview-delete {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- width: px2rpx(30);
|
|
|
|
|
- height: px2rpx(30);
|
|
|
|
|
- border-radius: 0 px2rpx(24) 0 0;
|
|
|
|
|
-
|
|
|
|
|
- i {
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- line-height: px2rpx(30);
|
|
|
|
|
- font-size: px2rpx(30);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|