| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- <template>
- <cwg-page-wrapper>
- <view class="info-card">
- <view class="content-title" v-if="current != 3 && current != 4">
- <view>{{ tabs[current - 1].name }}</view>
- <!-- <view class="content-title-btns">-->
- <!-- <view v-if="current == 3 && !isSHowIdentity" class="btn-primary" @click="infoSubmit()">-->
- <!-- <cwg-icon icon="crm-plus" :size="16" color="#fff" />-->
- <!-- <text v-t="'PersonalManagement.Title.ProofOfIdentity'"></text>-->
- <!-- </view>-->
- <!-- <view v-if="current == 3 && !isSHowAddress" class="btn-primary" @click="cancle()">-->
- <!-- <cwg-icon icon="crm-plus" :size="16" color="#fff" />-->
- <!-- <text v-t="'PersonalManagement.Title.ProofOfAddress'"></text>-->
- <!-- </view>-->
- <!-- <view v-if="current == 3" class="btn-primary" @click="cancle()">-->
- <!-- <cwg-icon icon="crm-plus" :size="16" color="#fff" />-->
- <!-- <text v-t="'PersonalManagement.Title.AttachedFile'"></text>-->
- <!-- </view>-->
- <!-- </view>-->
- </view>
- <view v-if="current == 1">
- <personal-info-tab v-model="PersonalInformation" :is-readonly="isReadonly" @cancel="cancle"
- @next="next(2)" />
- </view>
- <view v-if="current == 2">
- <bank-info-tab />
- </view>
- <view v-if="current == 3">
- <file-management-tab />
- </view>
- <view v-if="current == 4">
- <security-center-tab />
- </view>
- </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 { personalApi } from "@/service/personal";
- import { userApi } from "@/api/user";
- import useUserStore from "@/stores/use-user-store";
- import useIdTypeOptions from "@/composables/useIdTypeOptions";
- import CardWebsdkLink from "@/components/card-websdkLink.vue";
- import PersonalInfoTab from "./components/PersonalInfoTab.vue";
- import FileManagementTab from "./components/FileManagementTab.vue";
- import BankInfoTab from "./components/BankInfoTab.vue";
- import SecurityCenterTab from "./components/SecurityCenterTab.vue";
- import useRouter from "@/hooks/useRouter";
- const notCountry = [
- "AF",
- "AI",
- "AG",
- "BS",
- "BY",
- "BZ",
- "BA",
- "BI",
- "CF",
- "CD",
- "CU",
- "ET",
- "FJ",
- "PS",
- "GN",
- "GW",
- "HT",
- "IR",
- "IQ",
- "LB",
- "LY",
- "ML",
- "MM",
- "NI",
- "KP",
- "PW",
- "RU",
- "SO",
- "SS",
- "SD",
- "SY",
- "UA",
- "US",
- "VE",
- "YE",
- "ZW",
- ]
- const router = useRouter();
- const userStore = useUserStore();
- const userInfo = computed(() => userStore.userInfo);
- const current = ref(0);
- onLoad((options) => {
- current.value = options?.type;
- });
- const tabs = computed(() => [
- { id: 1, name: t('PersonalManagement.Title.PersonalInformation'), icon: 'crm-circle-user' },
- { id: 2, name: t('PersonalManagement.Title.BankInformation'), icon: 'crm-building-columns' },
- { id: 3, name: t('PersonalManagement.Title.FileManagement'), icon: 'crm-file' },
- { id: 4, name: t('PersonalManagement.Title.SecurityCenter'), icon: 'crm-lock' }
- ]);
- const changeTab = (index) => {
- router.push(`/pages/mine/info?type=${index + 1}`);
- }
- const { t, locale } = useI18n();
- const cardWebsdkLinkRef = ref<InstanceType<typeof CardWebsdkLink> | null>(null);
- const PersonalInformation = 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(true);
- const dialogCheck = ref(false);
- const dialogCheck1 = ref(false);
- const isApprove = computed(() => [2, 4].includes(userInfo.value.approveStatus))
- const countryList = ref<any[]>([]);
- const getCountry = async () => {
- const res = await personalApi.Country({});
- if (res.code === 200) {
- countryList.value = res.data || [];
- }
- };
- const cancle = async () => {
- if (!isApprove.value) {
- dialogCheck.value = true;
- dialogCheck1.value = true;
- } else {
- router.push({ path: "/customer/index" });
- }
- }
- const currentUploadCard = computed(() => {
- if (!PersonalInformation.value.nationality || !countryList.value.length) {
- return 0;
- }
- const selectedCountry = countryList.value.find(
- (item) => item.code === PersonalInformation.value.nationality
- );
- return selectedCountry ? (selectedCountry.uploadCard || 0) : 0;
- })
- const next = async (index) => {
- // 从 step 2 跳转到 step 3 时,应该直接跳转,不做验证
- // 只有在 step 3 点击下一步时,才检查是否需要跳过到 step 4
- if (current.value == 3 && index == 4 && PersonalInformation.value.uploadImage == 0) {
- // 如果不需要上传图片,跳过 step 3 直接到 step 4
- index = 4;
- }
- // 从 step 3 跳转到 step 4 时,需要验证身份证明相关字段
- if (index == 4) {
- // 根据当前选中国籍的 uploadCard 值判断是否需要验证证件照
- if (currentUploadCard.value === 1) {
- if (!PersonalInformation.value.cardType) {
- uni.showToast({ title: t('vaildate.CardType.empty'), icon: 'none' });
- return;
- }
- if (!PersonalInformation.value.fileListID1.path || !PersonalInformation.value.fileListID2.path) {
- uni.showToast({ title: t('vaildate.IDPhoto.empty'), icon: 'none' });
- return;
- }
- }
- }
- router.push({ path: `/pages/mine/info?type=${index}` });
- }
- function handleChange(value: any) {
- PersonalInformation.value = { ...PersonalInformation.value, [value.key]: value.value };
- }
- const containsChinese = (str: string) => /[\u4E00-\u9FA5]/.test(str);
- const convertToPinyin = (value: string) =>
- containsChinese(value)
- ? pinyin(value, { toneType: "none", type: "capitalize" })
- : value;
- async function getUserSingle() {
- if (!userToken.value) {
- uni.showToast({ title: t("common.loginFirst"), icon: 'none' });
- return;
- }
- if (current.value != 1) {
- return;
- }
- try {
- const res = await personalApi.CustomLoginInfo();
- if (res.code === 200 && res.data) {
- // 更新表单数据
- PersonalInformation.value = {
- ...res.data.customInfo,
- customType: res.data.customInfo?.customType || 1,
- addressLines1: res.data.customInfo?.addressLines[0] || '',
- addressLines2: res.data.customInfo?.addressLines[1] || '',
- };
- 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;
- // }
- }
- getCountry()
- } catch (error: any) {
- console.error('Error in getUserSingle:', error);
- uni.showToast({ title: error.message || t("common.error"), icon: 'none' });
- }
- }
- async function infoSubmit() {
- try {
- const res = await ucardApi.merchantRegister(PersonalInformation.value);
- if (res.code === 200) {
- uni.showToast({ title: t("common.success"), icon: 'success' });
- // 提交成功后打开 WebSDK 弹窗
- router.push({
- path: "/pages/mine/kyc",
- query: { cardId: (PersonalInformation.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' });
- }
- }
- const isReadonly = computed(() => isAuthInfo.value);
- onMounted(async () => {
- // 先加载选项数据
- await Promise.all([
- getUserSingle(),
- ]);
- });
- </script>
- <style scoped lang="scss">
- @import "@/uni.scss";
- .tab-title {
- display: flex;
- align-items: center;
- gap: px2rpx(4);
- border: 1px solid #f3f4f6;
- font-size: px2rpx(18);
- padding: px2rpx(8) px2rpx(16);
- border-radius: px2rpx(2);
- background-color: white;
- }
- .active {
- background-color: var(--color-error);
- color: var(--bs-emphasis-color);
- border: none;
- }
- .info-card {
- padding: px2rpx(5);
- //border: 1px solid rgba(108, 133, 149, 0.12);
- border-radius: px2rpx(8);
- .btns {
- display: flex;
- justify-content: flex-end;
- gap: px2rpx(30);
- margin-top: px2rpx(30);
- .btn-primary {
- min-width: px2rpx(120);
- background-color: var(--bs-heading-color);
- color: white;
- padding: 0 px2rpx(12);
- border-radius: px2rpx(8);
- border: none;
- font-size: px2rpx(14);
- text-align: center;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: px2rpx(8);
- }
- .btn-primary:active {
- background-color: #cf1322;
- ;
- }
- }
- }
- .form-tab {
- height: px2rpx(100);
- }
- .form-section {
- margin: px2rpx(8) 0;
- }
- :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>
|