Pārlūkot izejas kodu

Merge branch 'admin_dev' of http://112.213.107.185:3000/cwg-crm/gypsy-crm-frontend-vu into admin_dev

zhb 2 mēneši atpakaļ
vecāks
revīzija
6190635d25

+ 82 - 48
components/cwg-file-picker.vue

@@ -2,9 +2,22 @@
     <view class="common-file-uploader" :class="customClass">
         <!-- 编辑状态:显示可上传的文件选择器 -->
         <view v-if="editable" class="upload-wrapper">
-            <uni-file-picker :limit="multiple ? limit : 1" :title="title" :file-mediatype="fileMediatype" :mode="mode"
-                :auto-upload="false" :value="fileList" :disabled="disabled" :readonly="readonly"
-                :image-styles="imageStyles" :list-styles="listStyles" @select="handleSelect" @delete="handleDelete">
+            <uni-file-picker
+              :limit="multiple ? limit : 1"
+              :title="title"
+              :file-mediatype="fileMediatype"
+              :mode="mode"
+              :auto-upload="false"
+              :value="fileList"
+              :disabled="disabled"
+              :readonly="readonly"
+              :image-styles="imageStyles"
+              :list-styles="listStyles"
+              :del-icon="showPreviewDelete"
+              :disablePreview="disablePreview"
+              :canChoose="canChoose"
+              @select="handleSelect"
+              @delete="handleDelete">
                 <!-- 自定义上传按钮(单张图片且已有图片时显示替换) -->
                 <template v-if="$slots.default || showCustomButton">
                     <slot name="default">
@@ -16,7 +29,7 @@
                             </template>
                             <template v-else>
                                 <text class="plus">+</text>
-                                <text class="tip">{{ uploadText || t('Common.Upload') }}</text>
+<!--                                <text class="tip">{{ uploadText || t('common.upload') }}</text>-->
                             </template>
                         </view>
                     </slot>
@@ -31,7 +44,7 @@
             </view>
 
             <!-- 上传错误提示 -->
-            <view v-if="uploadError" class="upload-error">
+            <view v-if="uploadError && showError" class="upload-error">
                 <text class="error-text">{{ uploadError }}</text>
             </view>
         </view>
@@ -117,6 +130,14 @@ const props = defineProps({
         type: Boolean,
         default: false
     },
+    disablePreview: {
+        type: Boolean,
+        default: false
+    },
+    canChoose: {
+        type: Boolean,
+        default: false
+    },
     readonly: {
         type: Boolean,
         default: false
@@ -266,6 +287,12 @@ const props = defineProps({
     customStyles: {
         type: Object,
         default: () => ({})
+    },
+
+    // 展示错误信息
+    showError: {
+        type: Object,
+        default: true
     }
 })
 
@@ -600,12 +627,62 @@ defineExpose({
 
     .upload-wrapper {
         width: 100%;
+        height: 100%;
 
         :deep(.uni-file-picker) {
             .file-picker__box {
                 border: none;
                 background: transparent;
             }
+          .uni-file-picker__files{
+            height: 100%;
+          }
+          .files-button{
+            height: 100%;
+          }
+          .custom-upload-btn {
+            width: 100%!important;
+            height: 100%!important;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+
+            &.replace-btn {
+              background: rgba(0, 0, 0, 0.03);
+
+              .replace-icon {
+                font-size: 40px;
+                color: #666;
+                margin-bottom: 4px;
+                transform: rotate(90deg);
+              }
+
+              .tip {
+                color: #666;
+              }
+
+              &:hover {
+                background: rgba(234, 32, 39, 0.05);
+
+                .replace-icon,
+                .tip {
+                  color: #ea2027;
+                }
+              }
+            }
+
+            .plus {
+              font-size: 48px;
+              color: #9ca3af;
+              //line-height: 1;
+            }
+
+            .tip {
+              font-size: 24px;
+              color: #6b7280;
+            }
+          }
 
             .file-picker__box-list {
                 display: flex;
@@ -661,50 +738,7 @@ defineExpose({
                     background: #fef2f2;
                 }
 
-                .custom-upload-btn {
-                    width: 100%;
-                    height: 100%;
-                    display: flex;
-                    flex-direction: column;
-                    align-items: center;
-                    justify-content: center;
-
-                    &.replace-btn {
-                        background: rgba(0, 0, 0, 0.03);
-
-                        .replace-icon {
-                            font-size: 40px;
-                            color: #666;
-                            margin-bottom: 4px;
-                            transform: rotate(90deg);
-                        }
-
-                        .tip {
-                            color: #666;
-                        }
-
-                        &:hover {
-                            background: rgba(234, 32, 39, 0.05);
-
-                            .replace-icon,
-                            .tip {
-                                color: #ea2027;
-                            }
-                        }
-                    }
 
-                    .plus {
-                        font-size: 48px;
-                        color: #9ca3af;
-                        line-height: 1;
-                        margin-bottom: 8px;
-                    }
-
-                    .tip {
-                        font-size: 24px;
-                        color: #6b7280;
-                    }
-                }
 
                 .add-icon {
                     display: none;

+ 6 - 6
config/index.ts

@@ -12,13 +12,13 @@ const config = {
 
   HostWs: "wss://ws." + ho + ".com",
   Host80: ht + "//secure." + ho + ".com",
-  Host00: ht + "//ucard." + ho + ".com",
-  Host85: ht + "//ucard." + ho + ".com",
-  Host04: ht + "//pay." + ho + ".com",
+  // Host00: ht + "//ucard." + ho + ".com",
+  // Host85: ht + "//ucard." + ho + ".com",
+  // Host04: ht + "//pay." + ho + ".com",
   // Host80: 'http://192.168.0.21:8000',
-  // Host00: 'http://192.168.0.21:8000',
-  // Host85: 'http://192.168.0.21:8000',
-  // Host04: 'http://192.168.0.21:8004',
+  Host00: 'http://192.168.0.21:8000',
+  Host85: 'http://192.168.0.21:8000',
+  Host04: 'http://192.168.0.21:8004',
   Host90: ht + "//data." + ho + ".com",
   HostShop: ht + "//shopcustom." + ho + ".com",
   HostShopImg: ht + "//shopmanager." + ho + ".com",

+ 2 - 1
locale/cn.json

@@ -15,7 +15,8 @@
     "copy3": "复制失败",
     "year": "年",
     "month": "月",
-    "day": "日"
+    "day": "日",
+    "upload": "上传"
   },
   "pages": {
     "login": {

+ 6 - 0
pages.json

@@ -91,6 +91,12 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/mine/improveImmediately",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
     {
       "path": "pages/login/index",
       "style": {

+ 1923 - 0
pages/mine/improveImmediately.vue

@@ -0,0 +1,1923 @@
+<template>
+  <cwg-page-wrapper>
+    <view class="page page-shadow">
+      <uni-forms ref="formRef" :model="formData" :rules="rules" labelWidth="200" label-position="top"
+                 class="payment-form">
+        <!-- 第一步:个人信息 -->
+        <view v-show="currentStep === 1" class="form-section">
+          <h3 class="section-title">{{ t('ImproveImmediately.Title.BasicInformation') }}</h3>
+          <uni-row class="demo-uni-row uni-row1">
+            <!-- 客户类型 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item :label="t('ImproveImmediately.Label.CustomerType')">
+                <cwg-combox :clearable="false" v-model:value="formData.customType"
+                            :options="customerTypeOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 公司名称 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="formData.customType == 2">
+              <uni-forms-item :label="t('ImproveImmediately.Label.CompanyName')">
+                <uni-easyinput :clearable="false" v-model="formData.companyName"
+                               :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 姓 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item :label="formData.customType == 2
+                ? t('ImproveImmediately.Label.CorporationLastName')
+                : t('ImproveImmediately.Label.LastName')">
+                <uni-easyinput :clearable="false" v-model="formData.lastName" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 名 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item :label="formData.customType == 2
+                ? t('ImproveImmediately.Label.CorporationName')
+                : t('ImproveImmediately.Label.Name')">
+                <uni-easyinput :clearable="false" v-model="formData.firstName" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 法人中间名 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="lang == 'en'">
+              <uni-forms-item name="middle" :label="t('placeholder.middle')">
+                <uni-easyinput :clearable="false" v-model="formData.middle" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 国家 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="countryOptions.length > 0">
+              <uni-forms-item name="nationality" :label="t('ImproveImmediately.Label.Nationality')">
+                <cwg-combox :clearable="false" :filterable="true"
+                            v-model:value="formData.nationality" :options="countryOptions"
+                            :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 证件类型 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="IdentityType" :label="identityLabel">
+                <cwg-combox :clearable="false" v-model:value="formData.IdentityType"
+                            :options="identityTypes" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 证件号 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="identity" :label="t('ImproveImmediately.Label.IdentityID')">
+                <uni-easyinput :clearable="false" v-model="formData.identity" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 拼音 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="['cn', 'zhHant'].includes(lang)">
+              <uni-forms-item name="nameEn" :label="t('ImproveImmediately.Label.NamePinYin')">
+                <uni-easyinput :clearable="false" v-model="formData.nameEn" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 性别 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="gender" :label="t('ImproveImmediately.Label.Gender')">
+                <cwg-combox :clearable="false" v-model:value="formData.gender" :options="genderOptions"
+                            :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 生日 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="birth" :label="t('ImproveImmediately.Label.Birthday')">
+                <uni-datetime-picker :clear-icon="false" type="date" return-type="timestamp"
+                                     v-model="formData.birth" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :span="24">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('ImproveImmediately.Title.AddressInformation') }}</text>
+                <uni-tooltip placement="top">
+                  <text class="icon-tip">ⓘ</text>
+                  <template v-slot:content>
+                    <view class="address-tip">
+                      {{ t('ImproveImmediately.Title.AddressTip') }}
+                    </view>
+                  </template>
+                </uni-tooltip>
+
+              </view>
+            </uni-col>
+
+            <!-- 国家/地区 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="countryOptions.length > 0">
+              <uni-forms-item name="country" :label="t('ImproveImmediately.Label.CountryRegionOfResidence')">
+                <cwg-combox :clearable="false" :filterable="true" v-model:value="formData.country"
+                            :options="countryOptions" :placeholder="t('placeholder.choose')" @change="changeCountry" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 省份/州 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                     v-if="formData.country == 'CN' || formData.country == 'CNX' || formData.country == 'CNA' || formData.country == 'CNT'">
+              <uni-forms-item name="state" :label="t('ImproveImmediately.Label.ProvinceRegion')">
+                <cwg-combox :clearable="false" :filterable="true" v-model:value="formData.state"
+                            :options="stateOptions" :placeholder="t('placeholder.choose')" @change="changeState" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 国外省份/州 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-else>
+              <uni-forms-item name="state" :label="t('ImproveImmediately.Label.ProvinceRegion')">
+                <uni-easyinput :clearable="false" v-model="formData.state" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 城市 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                     v-if="formData.country == 'CN' || formData.country == 'CNX' || formData.country == 'CNA' || formData.country == 'CNT'">
+              <uni-forms-item name="city" :label="t('ImproveImmediately.Label.City')">
+                <cwg-combox :clearable="false" :filterable="true" v-model:value="formData.city"
+                            :options="cityOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <!-- 国外城市 -->
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-else>
+              <uni-forms-item name="city" :label="t('ImproveImmediately.Label.City')">
+                <uni-easyinput :clearable="false" v-model="formData.city" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="addressLines1" :label="t('ImproveImmediately.Label.DetailedAddress')">
+                <uni-easyinput :clearable="false" v-model="formData.addressLines1"
+                               :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="zipCode" :label="t('ImproveImmediately.Label.ZipCode')">
+                <uni-easyinput :clearable="false" v-model="formData.zipCode" :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="addressLines2" :label="t('ImproveImmediately.Label.DetailedAddressStandby')">
+                <uni-easyinput :clearable="false" v-model="formData.addressLines2"
+                               :placeholder="t('placeholder.input')" />
+              </uni-forms-item>
+            </uni-col>
+          </uni-row>
+        </view>
+        <!-- 第二步:财务背景 -->
+        <view v-show="currentStep === 2" class="form-section">
+          <h3 class="section-title">{{ t('ImproveImmediately.Title.FinancialBackground') }}</h3>
+          <uni-row class="demo-uni-row uni-row1">
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="level" :label="t('ImproveImmediately.Label.Education')">
+                <cwg-combox :clearable="false" v-model:value="formData.level"
+                            :options="educationOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="employmentStatus" :label="t('ImproveImmediately.Label.OnJob')">
+                <cwg-combox :clearable="false" v-model:value="formData.employmentStatus"
+                            :options="employmentOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="tradingObjectives" :label="t('ImproveImmediately.Label.purposeTransaction')">
+                <cwg-combox :clearable="false" v-model:value="formData.tradingObjectives"
+                            :options="transactionPurposeOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="sourceFunding" :label="t('ImproveImmediately.Label.SourceFunds')">
+                <cwg-combox :clearable="false" v-model:value="formData.sourceFunding"
+                            :options="fundSourceOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="grossAnnualIncome" :label="t('ImproveImmediately.Label.TotalAnnualRevenue')">
+                <cwg-combox :clearable="false" v-model:value="formData.grossAnnualIncome"
+                            :options="annualIncomeOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+              <uni-forms-item name="totalNewWorth" :label="t('ImproveImmediately.Label.TotalNetAssets')">
+                <cwg-combox :clearable="false" v-model:value="formData.totalNewWorth"
+                            :options="netWorthOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+            </uni-col>
+          </uni-row>
+          <h3 class="section-title">{{ t('ImproveImmediately.Title.TradingExperience') }}</h3>
+          <view class="experience">
+            <text class="Trad-experience">{{ t('ImproveImmediately.Content.TradingExperience1') }}</text>
+            <view class="Trad-choose">
+              <uni-data-checkbox v-model="formData.experienceTradingDerivative"
+                                 :localdata="radioList"></uni-data-checkbox>
+            </view>
+          </view>
+          <view class="experience">
+            <text class="Trad-experience">{{ t('ImproveImmediately.Content.TradingExperience2') }}</text>
+            <view class="Trad-choose">
+              <uni-data-checkbox v-model="formData.experienceTradingForex" :localdata="radioList"></uni-data-checkbox>
+            </view>
+          </view>
+          <view class="experience">
+            <text class="Trad-experience">{{ t('ImproveImmediately.Content.TradingExperience3') }}</text>
+            <view class="Trad-choose">
+              <uni-data-checkbox v-model="formData.derivativeProducts" :localdata="radioList"></uni-data-checkbox>
+            </view>
+          </view>
+          <view class="experience">
+            <text class="Trad-experience">{{ t('ImproveImmediately.Content.TradingExperience4') }}</text>
+            <view class="Trad-choose">
+              <uni-data-checkbox v-model="formData.experienceQualification" :localdata="radioList"></uni-data-checkbox>
+            </view>
+          </view>
+        </view>
+        <!-- 第三步:身份证明 -->
+        <view v-show="currentStep === 3" class="form-section">
+
+          <uni-row class="demo-uni-row uni-row1">
+            <uni-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('ImproveImmediately.Title.ProofIdentityUpdate') }}</text>
+                <uni-tooltip placement="bottom">
+                  <text class="icon-tip">ⓘ</text>
+                  <template v-slot:content>
+                    <view class="address-tip">
+                      {{ t('ImproveImmediately.Content.popover1') }}
+                    </view>
+                  </template>
+                </uni-tooltip>
+
+              </view>
+              <uni-forms-item name="cardType" :label="t('ImproveImmediately.Label.CardType')">
+                <cwg-combox :clearable="false" v-model:value="formData.cardType"
+                            :options="cardTypeOptions" :placeholder="t('placeholder.choose')" />
+              </uni-forms-item>
+              <uni-row class="demo-uni-row uni-row1">
+                <uni-col :xs="24" :sm="24" :md="10" :lg="10" :xl="10">
+                  <cwg-file-picker
+                    v-if="!fileListID1.path"
+                    v-model="fileListID1.path"
+                    :editable="fileListID1.status != 2"
+                    :limit="1"
+                    :fileMediatype="'all'"
+                    uploadUrl="/custom/file/upload/1"
+                    :baseUrl="updateUrl"
+                    :imageWidth="150"
+                    :imageHeight="150"
+                    :showPreviewDelete="false"
+                    :canDelete="false"
+                    :uploadError="false"
+                    :showProgress="false"
+                    :image-styles="imageStyle"
+                    @update:modelValue="(val) => handleFileUpdate(val, '1')"
+                    customClass="avatar-uploader"
+                  />
+                  <view v-else>
+                    <view class="file-item">
+                      <image
+                        v-if="!isPdf(fileListID1.path)"
+                        class="avatar"
+                        :src="updateUrl + fileListID1.path"
+                      ></image>
+                      <view v-else>
+                        <image class="icon" :src="icon_doc" />
+                      </view>
+
+                    </view>
+                  </view>
+                </uni-col>
+                <uni-col :xs="24" :sm="24" :md="10" :lg="10" :xl="10">
+                  <cwg-file-picker
+                    v-if="!fileListID2.path"
+                    v-model="fileListID2.path"
+                    :editable="fileListID2.status != 2"
+                    :limit="1"
+                    :fileMediatype="'all'"
+                    uploadUrl="/custom/file/upload/2"
+                    :baseUrl="updateUrl"
+                    :imageWidth="150"
+                    :imageHeight="150"
+                    :showPreviewDelete="false"
+                    :canDelete="false"
+                    :uploadError="false"
+                    :showProgress="false"
+                    :image-styles="imageStyle"
+                    @update:modelValue="(val) => handleFileUpdate(val, '2')"
+                    customClass="avatar-uploader"
+                  >
+                  </cwg-file-picker>
+                  <view v-else>
+                    <view class="file-item">
+                      <image
+                        v-if="!isPdf(fileListID2.path)"
+                        class="avatar"
+                        :src="updateUrl + fileListID2.path"
+                      ></image>
+                      <view v-else>
+                        <image class="icon" :src="icon_doc" />
+                      </view>
+                    </view>
+                  </view>
+                </uni-col>
+                <uni-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4">
+                  <view class="refresh">
+                    <image :src="icon_refresh" @click="getCustomFileList" />
+                  </view>
+                </uni-col>
+              </uni-row>
+            </uni-col>
+            <uni-col v-if="isPC" :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('ImproveImmediately.Title.MobileDeviceUpload') }}</text>
+                <uni-tooltip placement="bottom">
+                  <text class="icon-tip">ⓘ</text>
+                  <template v-slot:content>
+                    <view class="address-tip">
+                      {{ t('ImproveImmediately.Content.popover2') }}
+                    </view>
+                  </template>
+                </uni-tooltip>
+              </view>
+              <view class="con-box">
+                <view class="box">
+                  <image class="mobile" :src="icon_mobile" />
+                  <image class="arrow" :src="icon_arrowR" />
+                  <image
+                    class="img_mobile"
+                    style="
+                      display: inline-block;
+                      width: 120px;
+                      height: 120px;
+                      border: 8px solid var(--color-gray);
+                    "
+                    :src="mobile"
+                  >
+                    <div slot="error" class="image-slot">
+                      <i class="el-icon-picture-outline"></i>
+                    </div>
+                  </image>
+                  <image class="icon_refresh" :src="icon_refresh" @click="getMobileInfo" />
+                </view>
+              </view>
+
+            </uni-col>
+          </uni-row>
+          <view class="descending">
+            <p class="title">
+              <span class="dian1">·</span>
+              <span>{{ t('ImproveImmediately.Title.IdentificationStatement') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity4') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity5') }}</span>
+            </p>
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity6') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity1') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity2') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity3') }}</span>
+            </p>
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity7') }}</span>
+            </p>
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofIdentity8') }}</span>
+            </p>
+          </view>
+        </view>
+        <!-- 第四步:地址证明 -->
+        <view v-show="currentStep === 4" class="form-section">
+          <uni-row class="demo-uni-row uni-row1">
+            <uni-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('ImproveImmediately.Title.ProofAddress') }}</text>
+                <uni-tooltip placement="bottom">
+                  <text class="icon-tip">ⓘ</text>
+                  <template v-slot:content>
+                    <view class="address-tip">
+                      {{ t('ImproveImmediately.Content.ProofAddress5') }}
+                    </view>
+                  </template>
+                </uni-tooltip>
+
+              </view>
+              <uni-row class="demo-uni-row uni-row1">
+                <uni-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
+                  <cwg-file-picker
+                    v-if="!fileListAdd1.path"
+                    v-model="fileListAdd1.path"
+                    :editable="fileListAdd1.status != 2"
+                    :limit="1"
+                    :fileMediatype="'all'"
+                    uploadUrl="/custom/file/upload/3"
+                    :baseUrl="updateUrl"
+                    :imageWidth="150"
+                    :imageHeight="150"
+                    :showPreviewDelete="false"
+                    :canDelete="false"
+                    :uploadError="false"
+                    :showProgress="false"
+                    :image-styles="imageStyle"
+                    @update:modelValue="(val) => handleFileUpdate(val, '1')"
+                    customClass="avatar-uploader"
+                  />
+                  <view v-else>
+                    <view class="file-item">
+                      <image
+                        v-if="!isPdf(fileListAdd1.path)"
+                        class="avatar"
+                        :src="updateUrl + fileListAdd1.path"
+                      ></image>
+                      <view v-else>
+                        <image class="icon" :src="icon_doc" />
+                      </view>
+                    </view>
+                  </view>
+                </uni-col>
+                <uni-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4">
+                  <view class="refresh">
+                    <image :src="icon_refresh" @click="getCustomFileList" />
+                  </view>
+                </uni-col>
+              </uni-row>
+            </uni-col>
+            <uni-col v-if="isPC" :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('ImproveImmediately.Title.MobileDeviceUpload') }}</text>
+                <uni-tooltip placement="bottom">
+                  <text class="icon-tip">ⓘ</text>
+                  <template v-slot:content>
+                    <view class="address-tip">
+                      {{ t('ImproveImmediately.Content.popover2') }}
+                    </view>
+                  </template>
+                </uni-tooltip>
+              </view>
+              <view class="con-box">
+                <view class="box">
+                  <image class="mobile" :src="icon_mobile" />
+                  <image class="arrow" :src="icon_arrowR" />
+                  <image
+                    class="img_mobile"
+                    style="
+                      display: inline-block;
+                      width: 120px;
+                      height: 120px;
+                      border: 8px solid var(--color-gray);
+                    "
+                    :src="mobile"
+                  >
+                    <div slot="error" class="image-slot">
+                      <i class="el-icon-picture-outline"></i>
+                    </div>
+                  </image>
+                  <image class="icon_refresh" :src="icon_refresh" @click="getMobileInfo" />
+                </view>
+              </view>
+
+            </uni-col>
+          </uni-row>
+          <uni-row class="demo-uni-row uni-row1">
+            <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+              <view class="crm-title-box">
+                <text class="tit">{{ t('PersonalManagement.Title.AttachedFile') }}</text>
+              </view>
+              <uni-row class="demo-uni-row uni-row1">
+                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+                  <cwg-file-picker
+                    :limit="9"
+                    :multiple="true"
+                    :editable="true"
+                    :fileMediatype="'all'"
+                    uploadUrl="/custom/file/upload/10"
+                    :baseUrl="updateUrl"
+                    :imageWidth="100"
+                    :imageHeight="60"
+                    :showPreviewDelete="false"
+                    :canDelete="false"
+                    :uploadError="false"
+                    :showProgress="false"
+                    :image-styles="imageStyle"
+                    @update:modelValue="(val) => handleFileUpdate(val, '1')"
+                    custom-class="fileOther"
+                    :showError="false"
+                  >
+                    <button type="primary">{{ t('Btn.Upload') }}</button>
+                  </cwg-file-picker>
+                  <view class="fileList">
+                    <view id="files" v-for="(item,index) in fileListOthers" :key="index">
+
+                      <cwg-file-picker
+                        customClass="list_upload"
+                        v-model="item.path"
+                        :editable="item.status != 2"
+                        :limit="1"
+                        :fileMediatype="'all'"
+                        :uploadUrl="'/custom/file/upload/10/'+item.id"
+                        :baseUrl="updateUrl"
+                        :uploadError="false"
+                        :showProgress="false"
+                        :imageWidth="100"
+                        :imageHeight="60"
+                        :showPreviewDelete="true"
+                        :disablePreview="true"
+                        :image-styles="imageStyle"
+                        :canChoose="true"
+                        @update:modelValue="(val) => handleFileUpdate(val, '1')"
+                      >
+                        <view class="file-item">
+                          <image
+                            v-if="!isPdf(item.path) || !isPdf(item.againPath)"
+                            class="avatar"
+                            :src="updateUrl + (item.againPath || item.path)"
+                          ></image>
+                          <view v-else>
+                            <image class="icon" :src="icon_doc" />
+                          </view>
+                        </view>
+                      </cwg-file-picker>
+                      <view class="options">
+                        <u-button
+                          style="margin-right: 20px;"
+                          :disabled="item.status == 2"
+                        >
+                          <a
+                            :href="updateUrl + (item.againPath || item.path)"
+                            target="_blank"
+                          >
+                            {{ t('Btn.item12') }}
+                          </a>
+                        </u-button>
+                        <u-button
+                          :disabled="item.status == 2"
+                          @click="fileOtherDelete(item.id)"
+                        >
+                          {{ t('Btn.Delete') }}
+                        </u-button>
+                      </view>
+                    </view>
+                  </view>
+                </uni-col>
+                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+                  <view class="refresh">
+                    <image :src="icon_refresh" @click="getCustomFileList" />
+                  </view>
+                </uni-col>
+              </uni-row>
+            </uni-col>
+          </uni-row>
+          <view class="descending">
+            <p class="title">
+              <span>{{ t('ImproveImmediately.Title.AddressDescription') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress1') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress2') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress3') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian" v-if="['cn', 'zhHant'].indexOf(lang) != -1">·</span>
+              <span class="dian" v-if="lang == 'en'">-</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress4') }}</span>
+            </p>
+            <p class="des">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress6') }}</span>
+            </p>
+            <p class="des" v-if="lang == 'en'">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress7') }}</span>
+            </p>
+            <p class="des" v-if="lang == 'en'">
+              <span class="dian">·</span>
+              <span>{{ t('ImproveImmediately.Content.ProofAddress8') }}</span>
+            </p>
+          </view>
+        </view>
+        <!-- 步骤控制按钮 -->
+        <view>
+          <template v-if="currentStep === 4">
+            <view class="btns">
+              <view class="cwg-button two-btn">
+                <u-button class="btn-primary" type="primary" block @click="cancle">
+                  {{ t('Btn.Cancel') }}
+                </u-button>
+                <u-button plain block class="prev-btn btn-primary" @click="goStep(3)">
+                  {{ t('Btn.Last') }}
+                </u-button>
+                <u-button type="primary" class="btn-primary" block :loading="loadingStates.submit" @click="Submit">
+                  {{ t('Btn.Submit') }}
+                </u-button>
+              </view>
+            </view>
+          </template>
+          <template v-else-if="currentStep === 3">
+            <view class="btns">
+              <view class="cwg-button two-btn">
+                <u-button class="btn-primary" type="primary" block @click="cancle">
+                  {{ t('Btn.Cancel') }}
+                </u-button>
+                <u-button plain block class="prev-btn btn-primary" @click="goStep(2)">
+                  {{ t('Btn.Last') }}
+                </u-button>
+                <u-button class="btn-primary" type="primary" block :loading="loadingStates.next" @click="goStep(4)">
+                  {{ t('Btn.Next') }}
+                </u-button>
+              </view>
+            </view>
+          </template>
+          <template v-else-if="currentStep === 2">
+            <view class="btns">
+              <view class="cwg-button two-btn">
+                <u-button class="btn-primary" type="primary" block @click="cancle">
+                  {{ t('Btn.Cancel') }}
+                </u-button>
+                <u-button plain block class="prev-btn btn-primary" @click="goStep(1)">
+                  {{ t('Btn.Last') }}
+                </u-button>
+                <u-button class="btn-primary" type="primary" block :loading="loadingStates.next" @click="goStep(3)">
+                  {{ t('Btn.Next') }}
+                </u-button>
+              </view>
+            </view>
+          </template>
+          <template v-else-if="currentStep === 1">
+            <view class="btns">
+              <view class="cwg-button two-btn">
+                <u-button class="btn-primary" type="primary" block @click="cancle">
+                  {{ t('Btn.Cancel') }}
+                </u-button>
+                <u-button class="btn-primary" type="primary" block :loading="loadingStates.next" @click="goStep(2)">
+                  {{ t('Btn.Next') }}
+                </u-button>
+              </view>
+            </view>
+          </template>
+        </view>
+      </uni-forms>
+    </view>
+    <view class="form-tab"></view>
+  </cwg-page-wrapper>
+  <!--离开弹出框-->
+  <uni-popup ref="dialogCheck" type="center" background-color="#fff">
+    <view class="dia-content" v-if="dialogCheck1">
+      <view class="icon">
+        <i class="iconfont iconjingshi"></i>
+      </view>
+      <view class="des1">{{ t('ImproveImmediately.Content.Leave1') }}</view>
+      <view class="des2">{{ t('ImproveImmediately.Content.Leave2') }}</view>
+      <view class="dialog-footer">
+        <u-button @click="closeDia">{{ t('Btn.TemporarilyNot') }}</u-button>
+        <u-button type="primary" @click="save">{{ t('Btn.Save') }}</u-button>
+      </view>
+    </view>
+    <view class="dia-content" v-if="!dialogCheck1">
+      <view class="icon">
+        <i class="iconfont iconchenggong"></i>
+      </view>
+      <view class="des1">{{ t('ApplicationDialog.Des1') }}</view>
+      <QrCode :text="text1"></QrCode>
+      <view class="dialog-footer">
+        <u-button @click="closeDia">{{ t('Btn.Cancel') }}</u-button>
+        <u-button type="primary" @click="toHome">{{ t('Btn.Home') }}</u-button>
+      </view>
+    </view>
+  </uni-popup>
+</template>
+
+<script setup lang="ts">
+  import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
+  import { useI18n } from 'vue-i18n'
+  import { onLoad } from '@dcloudio/uni-app'
+  import { personalApi } from '@/service/personal'
+  import Config from '@/config/index'
+  import QrCode from '@/components/QRCode.vue'
+  import { userToken } from '@/composables/config'
+  import useRouter from '@/hooks/useRouter'
+  import { Patterns, Validators } from '@/utils/validators'
+  import { pinyin } from 'pinyin-pro'
+  import config from '@/config/index'
+  import icon_doc from '@/static/icons/crm-document.svg'
+  import icon_refresh from '@/static/icons/crm-refresh.svg'
+  import icon_mobile from '@/static/icons/icon_mobile.svg'
+  import icon_arrowR from '@/static/icons/icon_arrowR.svg'
+
+  const router = useRouter()
+  const { t } = useI18n()
+  const currentStep = ref<number>(3)
+  const formRef = ref()
+  const lang = ref('cn')
+  const dialogCheck = ref(false)
+  const dialogCheck1 = ref(false)
+  const text1 = ref('')
+  const qrCodeStatus = ref(false)
+  const addressTipPopup = ref()
+
+  // 新增的响应式数据
+  const divActiveHelf = ref(false)
+  const divActiveAll = ref(false)
+  const websock = ref(null)
+  const isPC = ref(true)
+  const fileListID1 = ref({ againPath: '', id: null, path: '', status: null, type: null })
+  const fileListID2 = ref({ againPath: '', id: null, path: '', status: null, type: null })
+  const fileListAdd1 = ref({ againPath: '', id: null, path: '', status: null, type: null })
+  const fileListAdd2 = ref({ againPath: '', id: null, path: '', status: null, type: null })
+  const fileListOthers = ref([])
+  const actionID1 = ref('')
+  const actionID2 = ref('')
+  const actionAdd1 = ref('')
+  const actionAdd2 = ref('')
+  const actionOtherAdd = ref('')
+  const flag = ref(false)
+  const pictLoading = ref(false)
+  const pictLoadingImg = ref(false)
+  const isApprove = ref(false)
+  const metaInfo = ref({})
+  const HostWs = ref(Config.HostWs)
+  const cities = ref([])
+  const states = ref([])
+  const countries = ref([])
+  const uploadImage = ref(0)
+  const updateUrl = config.Host80
+  const mobile = ref('')
+  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 imageStyle = ref({
+    width: 200,
+    height: 150,
+    border: {
+      radius: '5px',
+    },
+  })
+
+  // 验证函数
+  function validateName(a: any, b?: any, c?: any) {
+    const reg = /^[A-Z\s]+$/i
+    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()
+    }
+    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
+  }
+
+  function validateBirthday(a: any, b?: any, c?: any) {
+    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()
+    }
+    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) {
+    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()
+    }
+    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 = {
+    customType: [Validators.required(t('card.vaildate.v1'))],
+    firstName: [Validators.required(t('card.vaildate.v3')), Validators.custom(validateName)],
+    lastName: [Validators.required(t('card.vaildate.v4')), Validators.custom(validateName)],
+    nationality: [Validators.required(t('card.vaildate.v6'), 'change')],
+    IdentityType: [Validators.required(t('card.vaildate.v1'))],
+    identity: [Validators.required(t('card.vaildate.v4'))],
+    gender: [Validators.required(t('card.vaildate.v9'), 'change')],
+    birth: [
+      Validators.required(t('card.vaildate.v5'), 'change'),
+      Validators.custom(validateBirthday, 'change'),
+    ],
+    country: [Validators.required(t('card.vaildate.v1'))],
+    state: [Validators.required(t('card.vaildate.v1'))],
+    city: [Validators.required(t('card.vaildate.v1'))],
+    addressLines1: [Validators.required(t('card.vaildate.v27')), Validators.custom(validateAddress)],
+    zipCode: [
+      Validators.required(t('card.vaildate.v8')),
+      Validators.pattern(Patterns.postcode, t('card.New.n2')),
+    ],
+    level: [Validators.required(t('card.vaildate.v1'))],
+    employmentStatus: [Validators.required(t('card.vaildate.v1'))],
+    tradingObjectives: [Validators.required(t('card.vaildate.v1'))],
+    sourceFunding: [Validators.required(t('card.vaildate.v1'))],
+    grossAnnualIncome: [Validators.required(t('card.vaildate.v1'))],
+    totalNewWorth: [Validators.required(t('card.vaildate.v1'))],
+    cardType: [Validators.required(t('card.vaildate.v1'))],
+    idFrontUrl: [Validators.required(t('card.vaildate.v1'))],
+    idBackUrl: [Validators.required(t('card.vaildate.v1'))],
+    addressProofUrl: [Validators.required(t('card.vaildate.v1'))],
+  }
+
+  onLoad((options) => {
+    currentStep.value = parseInt(options?.currentStep || '4', 10)
+  })
+
+  function goStep(step: number) {
+    currentStep.value = step
+  }
+
+  // 选项数据
+  const customerTypeOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.CustomerType1') },
+    { value: 2, text: t('ImproveImmediately.Label.CustomerType2') },
+  ]
+
+  const identityTypes = ref([
+    { text: t('ImproveImmediately.Label.IDCard'), value: 2 },
+    { text: t('ImproveImmediately.Label.Passport'), value: 3 },
+  ])
+
+  const genderOptions = [
+    { value: 1, text: t('PersonalManagement.Label.Men') },
+    { value: 2, text: t('PersonalManagement.Label.Women') },
+  ]
+  const radioList = [
+    { value: 1, text: t('ImproveImmediately.Label.Yes') },
+    { value: 0, text: t('ImproveImmediately.Label.No') },
+  ]
+
+  const educationOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.Education1') },
+    { value: 2, text: t('ImproveImmediately.Label.Education2') },
+    { value: 3, text: t('ImproveImmediately.Label.Education3') },
+    { value: 4, text: t('ImproveImmediately.Label.Education4') },
+    { value: 5, text: t('ImproveImmediately.Label.Education5') },
+  ]
+
+  const employmentOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.OnJob1') },
+    { value: 2, text: t('ImproveImmediately.Label.OnJob2') },
+    { value: 3, text: t('ImproveImmediately.Label.OnJob3') },
+    { value: 4, text: t('ImproveImmediately.Label.OnJob4') },
+    { value: 5, text: t('ImproveImmediately.Label.OnJob5') },
+  ]
+
+  const transactionPurposeOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.purposeTransaction1') },
+    { value: 2, text: t('ImproveImmediately.Label.purposeTransaction2') },
+    { value: 3, text: t('ImproveImmediately.Label.purposeTransaction3') },
+    { value: 4, text: t('ImproveImmediately.Label.purposeTransaction4') },
+  ]
+
+  const fundSourceOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.SourceFunds1') },
+    { value: 2, text: t('ImproveImmediately.Label.SourceFunds2') },
+    { value: 3, text: t('ImproveImmediately.Label.SourceFunds3') },
+    { value: 4, text: t('ImproveImmediately.Label.SourceFunds4') },
+    { value: 5, text: t('ImproveImmediately.Label.SourceFunds5') },
+    { value: 6, text: t('ImproveImmediately.Label.SourceFunds6') },
+  ]
+
+  const annualIncomeOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.TotalAnnualRevenue1') },
+    { value: 2, text: t('ImproveImmediately.Label.TotalAnnualRevenue2') },
+    { value: 3, text: t('ImproveImmediately.Label.TotalAnnualRevenue3') },
+    { value: 4, text: t('ImproveImmediately.Label.TotalAnnualRevenue4') },
+    { value: 5, text: t('ImproveImmediately.Label.TotalAnnualRevenue5') },
+  ]
+
+  const netWorthOptions = [
+    { value: 1, text: t('ImproveImmediately.Label.TotalNetAssets1') },
+    { value: 2, text: t('ImproveImmediately.Label.TotalNetAssets2') },
+    { value: 3, text: t('ImproveImmediately.Label.TotalNetAssets3') },
+    { value: 4, text: t('ImproveImmediately.Label.TotalNetAssets4') },
+    { value: 5, text: t('ImproveImmediately.Label.TotalNetAssets5') },
+  ]
+
+  const cardTypeOptions = [
+    { value: 'ID_CARD', text: 'ID Card' },
+    { value: 'PASSPORT', text: 'Passport' },
+    { value: 'DRIVERS', text: 'Driver\'s License' },
+    { value: 'RESIDENCE_PERMIT', text: 'Residence Permit' },
+  ]
+
+  // 表单数据
+  const formData = ref({
+    customType: 1,
+    companyName: undefined,
+    lastName: undefined,
+    firstName: undefined,
+    middle: undefined,
+    nationality: undefined,
+    IdentityType: 1,
+    identity: undefined,
+    nameEn: undefined,
+    gender: undefined,
+    birth: undefined,
+    country: undefined,
+    state: undefined,
+    city: undefined,
+    addressLines1: undefined,
+    addressLines2: undefined,
+    zipCode: undefined,
+    level: undefined,
+    employmentStatus: undefined,
+    tradingObjectives: undefined,
+    sourceFunding: undefined,
+    grossAnnualIncome: undefined,
+    totalNewWorth: undefined,
+    experienceTradingDerivative: 0,
+    experienceTradingForex: 0,
+    derivativeProducts: 0,
+    experienceQualification: 0,
+    cardType: undefined,
+    idFrontUrl: undefined,
+    idBackUrl: undefined,
+    addressProofUrl: undefined,
+    otherFiles: undefined,
+    addressLines: [],
+  })
+
+  // 选项数据
+  const countryOptions = ref<Array<{ text: string; value: string }>>([])
+  const stateOptions = ref<Array<{ text: string; value: string }>>([])
+  const cityOptions = ref<Array<{ text: string; value: string }>>([])
+
+  // 加载状态
+  const loadingStates = ref({
+    next: false,
+    submit: false,
+  })
+
+  // 计算属性
+  const identityLabel = computed(() => {
+    if (formData.value.IdentityType === 2) return t('ImproveImmediately.Label.IDCard')
+    if (formData.value.IdentityType === 3) return t('ImproveImmediately.Label.Passport')
+    return t('ImproveImmediately.Label.IdentityID')
+  })
+
+  // 计算属性:当前选中国籍的 uploadCard 值
+  const currentUploadCard = computed(() => {
+    if (!formData.value.nationality || !countries.value.length) {
+      return 0
+    }
+    const selectedCountry = countries.value.find(
+      (item: any) => item.code === formData.value.nationality,
+    )
+    return selectedCountry ? (selectedCountry.uploadCard || 0) : 0
+  })
+
+  // 计算属性:当前选中国籍的 uploadAddress 值
+  const currentUploadAddress = computed(() => {
+    if (!formData.value.nationality || !countries.value.length) {
+      return 0
+    }
+    const selectedCountry = countries.value.find(
+      (item: any) => item.code === formData.value.nationality,
+    )
+    return selectedCountry ? (selectedCountry.uploadAddress || 0) : 0
+  })
+
+  // 方法
+  function changeCountry(value: any) {
+    // 处理国家选择变化
+    // 清空省份/城市选择//
+    formData.value.state = ''
+    formData.value.city = ''
+    stateOptions.value = []
+    cityOptions.value = []
+    states.value = []
+    cities.value = []
+    let item = {}
+    countries.value.forEach(element => {
+      if (element.code == value) {
+        item = element
+        return
+      }
+    })
+    getStateList(item.id)
+  }
+
+
+  function handleFileUpdate(value, type) {
+    console.log(value, type, 'uplaod')
+  }
+
+  async function fileOtherDelete(id) {
+    uni.showModal({
+      title: t('Msg.SystemPrompt'),
+      content: t('Msg.Delete'),
+      cancelText: t('Btn.Cancel'),
+      confirmText: t('Btn.Confirm'),
+      success: async (res) => {
+        if (res.confirm) {
+          // 确认删除
+          let data = await personalApi.customFileDelete({ ids: [id] })
+          if (data.code == 200) {
+            uni.showToast(t('Msg.DeleteSuccess'))
+            getCustomFileList()
+          } else {
+            uni.showToast(res.msg)
+          }
+        }
+      },
+      fail: () => {
+
+      },
+    })
+  }
+
+
+  function changeState(val) {
+    formData.value.city = ''
+    cityOptions.value = []
+    let item = {}
+    states.value.forEach((element) => {
+      if (element.name == val || element.enName == val) {
+        item = element
+        return
+      }
+    })
+    getCityList(item.id)
+  }
+
+  function handleChange(value: any) {
+    formData.value = { ...formData.value, [value.key]: value.value }
+    console.log(value)
+    if (value.key === 'country') {
+      formData.value.state = ''
+      formData.value.city = ''
+      stateOptions.value = []
+      cityOptions.value = []
+      if (value.value) {
+        getStateList(value.value)
+      }
+    } else if (value.key === 'state') {
+      formData.value.city = ''
+      cityOptions.value = []
+      if (value.value) {
+        getCityList(value.value)
+      }
+    }
+  }
+
+  function openAddressTip() {
+    // 打开地址提示弹窗
+    addressTipPopup.value.open()
+  }
+
+  function isPdf(url, image) {
+    let res = !!url
+    if (image) {
+      return res && url.substr(-3, 3) == 'pdf' &&
+        url.substr(-3, 3) == 'PDF'
+    }
+    return res && (url.substr(-3, 3) == 'pdf' ||
+      url.substr(-3, 3) == 'PDF')
+  }
+
+  function cancle() {
+    if (!isApprove.value) {
+      dialogCheck.value.open()
+      dialogCheck1.value = true
+    } else {
+      router.push({ path: '/customer/index' })
+    }
+  }
+
+  function closeDia() {
+    dialogCheck.value = false
+  }
+
+  function toHome() {
+    dialogCheck.value = false
+    router.push({ path: '/customer/index' })
+  }
+
+  async function save() {
+    await updateInfo(1)
+  }
+
+  async function Submit() {
+    loadingStates.value.submit = true
+    try {
+      formData.value.addressLines = []
+      if (formData.value.addressLines1) {
+        formData.value.addressLines.push(formData.value.addressLines1)
+      }
+      if (formData.value.addressLines2) {
+        formData.value.addressLines.push(formData.value.addressLines2)
+      }
+      if (!formData.value.addressLines1 && !formData.value.addressLines2) {
+        formData.value.addressLines = []
+      }
+      if (formData.value.customType != 2) {
+        formData.value.companyName = ''
+      }
+      let res = await personalApi.CustomUpdateInfo({
+        ...formData.value,
+      })
+      if (res.code == Config.Code.StatusOK) {
+        await getCustomFileList()
+        await customApply()
+      } else {
+        uni.showToast(res.msg)
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    } finally {
+      loadingStates.value.submit = false
+    }
+  }
+
+  async function updateInfo(save: number) {
+    try {
+      formData.value.addressLines = []
+      if (formData.value.addressLines1) {
+        formData.value.addressLines.push(formData.value.addressLines1)
+      }
+      if (formData.value.addressLines2) {
+        formData.value.addressLines.push(formData.value.addressLines2)
+      }
+      if (!formData.value.addressLines1 && !formData.value.addressLines2) {
+        formData.value.addressLines = []
+      }
+      let res = await personalApi.CustomUpdateInfo({
+        ...formData.value,
+      })
+      if (res.code == Config.Code.StatusOK) {
+        if (save) {
+          dialogCheck.value = false
+          router.push({ path: '/customer/index' })
+        }
+      } else {
+        uni.showToast({ title: res.msg, icon: 'none' })
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  async function customApply() {
+    try {
+      let res = await personalApi.customApplyReal({})
+      if (res.code == Config.Code.StatusOK) {
+        isApprove.value = true
+        await getLoginInfo()
+        dialogCheck.value = true
+        dialogCheck1.value = false
+      } else {
+        uni.showToast({ title: res.msg, icon: 'none' })
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  async function getCountryList() {
+    try {
+      let res = await personalApi.Country({})
+      if (res.code == Config.Code.StatusOK) {
+        countryOptions.value = res.data.map((item: any) => ({
+          text: item.enName,
+          value: item.code,
+          disabled: notCountry.indexOf(item.code) !== -1,
+        }))
+        countries.value = res.data
+        const country = formData.value.country
+        if (country) {
+          countries.value.forEach((item) => {
+            if (item.code == country) {
+              getStateList(item.id)
+            }
+          })
+        }
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  async function getStateList(pid: string) {
+    try {
+      let res = await personalApi.Country({ pid })
+      if (res.code == Config.Code.StatusOK) {
+        stateOptions.value = res.data.map((item: any) => ({
+          text: lang.value === 'en' ? item.enName : item.name,
+          value: lang.value === 'en' ? item.enName : item.name,
+        }))
+        states.value = res.data
+        const state = formData.value.state
+        if (state) {
+          states.value.forEach((item) => {
+            if (
+              item.name == state ||
+              item.enName == state
+            ) {
+              getCityList(item.id)
+            }
+          })
+        }
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  async function getCityList(pid: string) {
+    try {
+      let res = await personalApi.Country({ pid })
+      if (res.code == Config.Code.StatusOK) {
+        cityOptions.value = res.data.map((item: any) => ({
+          text: lang.value === 'en' ? item.enName : item.name,
+          value: lang.value === 'en' ? item.enName : item.name,
+        }))
+        cities.value = res.data
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  async function getLoginInfo() {
+    try {
+      let res = await personalApi.CustomLoginInfo()
+      if (res.code == Config.Code.StatusOK) {
+        formData.value = res.data.customInfo
+        if (formData.value.addressLines != null && formData.value.addressLines.length) {
+          formData.value.addressLines1 = formData.value.addressLines[0]
+          formData.value.addressLines2 = formData.value.addressLines[1]
+        }
+        formData.value.customType = formData.value.customType ? formData.value.customType : 1
+        await getCountryList()
+      } else {
+        uni.showToast({ title: t('Msg.SystemError'), icon: 'none' })
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  // 获取二维码
+  async function getMobileInfo() {
+    try {
+      let res = await personalApi.CustomFileMobileFiles({
+        responseType: 'arraybuffer',
+      })
+      // console.log(res);
+      mobile.value = 'data:image/png;base64,' + Buffer.from(res).toString('base64')
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  // 获取上传文件信息
+  async function getCustomFileList() {
+    try {
+      let res = await personalApi.CustomFileList()
+      if (res.code == Config.Code.StatusOK) {
+        let myData = res.data
+        fileListOthers.value = []
+        myData.forEach((item: any) => {
+          if (item.type == 1) {
+            fileListID1.value = item
+          } else if (item.type == 2) {
+            fileListID2.value = item
+          } else if (item.type == 3) {
+            fileListAdd1.value = item
+          } else if (item.type == 4) {
+            fileListAdd2.value = item
+          } else if (item.type == 10) {
+            fileListOthers.value.push(item)
+          }
+        })
+        actionType()
+      } else {
+        uni.showToast({ title: res.msg, icon: 'none' })
+        flag.value = false
+      }
+    } catch (error: any) {
+      uni.showToast({ title: error.message || t('Msg.SystemError'), icon: 'none' })
+    }
+  }
+
+  // 请求头
+  function actionType() {
+    if (fileListID1.value.id) {
+      actionID1.value = Config.Host80 + '/custom/file/upload/1/' + fileListID1.value.id
+    } else {
+      actionID1.value = Config.Host80 + '/custom/file/upload/1'
+    }
+    if (fileListID2.value.id) {
+      actionID2.value = Config.Host80 + '/custom/file/upload/2/' + fileListID2.value.id
+    } else {
+      actionID2.value = Config.Host80 + '/custom/file/upload/2'
+    }
+    if (fileListAdd1.value.id) {
+      actionAdd1.value = Config.Host80 + '/custom/file/upload/3/' + fileListAdd1.value.id
+    } else {
+      actionAdd1.value = Config.Host80 + '/custom/file/upload/3'
+    }
+    if (fileListAdd2.value.id) {
+      actionAdd2.value = Config.Host80 + '/custom/file/upload/4/' + fileListAdd2.value.id
+    } else {
+      actionAdd2.value = Config.Host80 + '/custom/file/upload/4'
+    }
+    actionOtherAdd.value = Config.Host80 + '/custom/file/upload/10'
+  }
+
+  // WebSocket
+  function initWebSocket() {
+    // 初始化WebSocket
+    let token = localStorage.getItem('access_token')
+    if (typeof WebSocket == 'undefined') {
+      uni.showToast({ title: t('Msg.socket'), icon: 'none' })
+    } else {
+      const wsUrl = HostWs.value + '/webSocket?Access-Token=' + token
+      websock.value = new WebSocket(wsUrl)
+      websock.value.onmessage = websocketonmessage
+      websock.value.onopen = websocketonopen
+      websock.value.onerror = websocketonerror
+      websock.value.onclose = websocketclose
+    }
+  }
+
+  function websocketonopen() {
+  }
+
+  function websocketonerror() {
+    initWebSocket()
+  }
+
+  function websocketonmessage(e: any) {
+    let data = JSON.parse(e.data)
+    if (data.newsType == 1) {
+      let myData = JSON.parse(e.data)
+      if (myData.type == 1) {
+        fileListID1.value = myData
+      } else if (myData.type == 2) {
+        fileListID2.value = myData
+      } else if (myData.type == 3) {
+        fileListAdd1.value = myData
+      } else if (myData.type == 4) {
+        fileListAdd2.value = myData
+      } else if (myData.type == 10) {
+        if (!fileListOthers.value.length) {
+          fileListOthers.value.push(myData)
+        } else {
+          let flag = true
+          fileListOthers.value.forEach((item: any) => {
+            if (item.id == myData.id) {
+              item = myData
+              flag = false
+            }
+          })
+          if (flag) {
+            fileListOthers.value.push(myData)
+          }
+        }
+      }
+      actionType()
+    }
+  }
+
+  function websocketclose() {
+  }
+
+  // 判断是否为PC端
+  function IsPC() {
+    let userAgentInfo = navigator.userAgent
+    let Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']
+    let flag = true
+    for (let v = 0; v < Agents.length; v++) {
+      if (userAgentInfo.indexOf(Agents[v]) > 0) {
+        flag = false
+        break
+      }
+    }
+    return flag
+  }
+
+  // div大小改变重载
+  function divInit() {
+    // 由于elementResizeDetectorMaker在UniApp中可能不可用,这里简化处理
+    const width = window.innerWidth
+    if (width <= 1100 && width > 800) {
+      divActiveHelf.value = true
+      divActiveAll.value = false
+    } else if (width <= 800) {
+      divActiveAll.value = true
+      divActiveHelf.value = false
+    } else if (1100 < width) {
+      divActiveAll.value = false
+      divActiveHelf.value = false
+    }
+  }
+
+  // 监听表单字段变化
+  watch(
+    () => formData.value.firstName,
+    () => {
+      if (localStorage.getItem('lang') == 'cn' && formData.value.firstName && formData.value.lastName) {
+        formData.value.nameEn = pinyin(`${formData.value.firstName} ${formData.value.lastName}`)
+        pinyin
+      }
+    },
+  )
+
+  watch(
+    () => formData.value.lastName,
+    () => {
+      if (localStorage.getItem('lang') == 'cn' && formData.value.firstName && formData.value.lastName) {
+        formData.value.nameEn = pinyin(`${formData.value.firstName} ${formData.value.lastName}`
+        )
+      }
+    },
+  )
+
+  // 生命周期
+  onMounted(async () => {
+    divInit()
+    await getLoginInfo()
+    await getMobileInfo()
+    await getCustomFileList()
+    // WebSocket
+    initWebSocket()
+    isPC.value = IsPC()
+  })
+
+  // 组件销毁时
+  onUnmounted(() => {
+    if (websock.value) {
+      websock.value.close() // 离开路由之后断开WebSocket连接
+    }
+  })
+</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-weight: 500;
+    margin: px2rpx(10) 0;
+  }
+
+  :deep(.file-picker__box) {
+    width: px2rpx(200) !important;
+    height: px2rpx(150) !important;
+  }
+
+  :deep(.uni-file-picker) {
+    width: 100%;
+    height: 100%;
+  }
+
+  .avatar-uploader {
+    border: 1px dashed;
+    width: px2rpx(200);
+    height: px2rpx(150);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    /*float: left;*/
+    //overflow: hidden;
+  }
+
+  .file-item {
+    border: 1px dashed;
+    border-radius: px2rpx(5);
+    width: px2rpx(200);
+    height: px2rpx(150);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    .icon {
+      width: px2rpx(24);
+      height: px2rpx(24);
+    }
+  }
+
+  .avatar {
+    width: 100%;
+    height: 100%;
+  }
+
+  .custom-upload-btn {
+    width: px2rpx(200);
+    height: px2rpx(150);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+
+    .plus {
+      font-size: px2rpx(24);
+      color: #9ca3af;
+    }
+  }
+
+  .refresh {
+    width: 100%;
+    height: px2rpx(150);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    image {
+      width: px2rpx(28);
+      height: px2rpx(28);
+    }
+  }
+
+  .fileOther {
+
+    :deep(.upload-wrapper .uni-file-picker) {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    :deep(.uni-file-picker__lists) {
+      display: none !important;
+    }
+  }
+
+  .fileList {
+    width: 100%;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+  }
+
+  #files {
+    :deep(.uni-file-picker__lists) {
+      display: none !important;
+    }
+
+    :deep(.upload-wrapper .uni-file-picker) {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .list_upload {
+      width: px2rpx(150);
+      height: px2rpx(60);
+    }
+
+    .file-item {
+      //border: none;
+      box-sizing: border-box;
+      width: px2rpx(150);
+      height: px2rpx(60);
+      border-radius: 0;
+    }
+
+    margin-top: px2rpx(20);
+    max-width: px2rpx(600);
+    border: 1px dashed;
+    display: flex;
+
+    .options {
+      flex: 1;
+      padding: 8px;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: center;
+      align-content: center;
+      align-items: center;
+
+      uni-button {
+        min-width: px2rpx(100);
+        max-height: px2rpx(30);
+        padding: 0;
+        line-height: px2rpx(30);
+
+        span,
+        a {
+          display: inline-block;
+          height: 100%;
+          width: 100%;
+          color: var(--color-black);
+        }
+      }
+    }
+  }
+
+  .con-box {
+    background-color: var(--color-white);
+    border-radius: 2px;
+    padding: 20px;
+
+    .box {
+      width: 100%;
+      // height: 190px;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+
+      .mobile {
+        width: px2rpx(50);
+        height: px2rpx(50);
+        margin-right: px2rpx(10);
+      }
+
+      .arrow {
+        width: px2rpx(30);
+        height: px2rpx(30);
+        margin-right: px2rpx(10);
+      }
+
+      .img_mobile {
+        width: 120px;
+        height: 120px;
+        margin: 10px;
+        border: 5px solid;
+        background-color: var(--color-gray);
+      }
+
+      .icon_refresh {
+        width: px2rpx(30);
+        height: px2rpx(30);
+        margin-right: px2rpx(10);
+      }
+    }
+  }
+
+  .experience {
+    display: flex;
+    margin: px2rpx(10) 0;
+    align-items: center;
+  }
+
+  .Trad-experience {
+    flex: 1;
+    color: #1a1a1a;
+    font-size: px2rpx(16);
+  }
+
+  .Trad-choose {
+    display: flex;
+  }
+
+  .descending {
+    margin: px2rpx(20) 0;
+    padding: px2rpx(20);
+    background-color: #f5f5f5;
+    border-radius: px2rpx(8);
+  }
+
+  .title {
+    font-weight: 500;
+    margin-bottom: px2rpx(10);
+  }
+
+  .des {
+    margin: px2rpx(5) 0;
+    font-size: px2rpx(14);
+    color: #666;
+  }
+
+  .dian1 {
+    font-size: px2rpx(20);
+    margin-right: px2rpx(5);
+  }
+
+  .dian {
+    margin-right: px2rpx(10);
+  }
+
+  .btns {
+    margin-top: px2rpx(30);
+  }
+
+  .cwg-button {
+    display: flex;
+    flex-direction: column;
+    gap: px2rpx(15);
+
+    &.two-btn {
+      flex-direction: row;
+      justify-content: space-between;
+
+      u-button {
+        flex: 1;
+        margin: 0 px2rpx(10);
+
+        &:first-child {
+          margin-left: 0;
+        }
+
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+
+  .btn-primary {
+    height: px2rpx(80);
+    font-size: px2rpx(18);
+  }
+
+  .prev-btn {
+    border-color: #4a6cf7;
+    color: #4a6cf7;
+  }
+
+  .address-tip {
+    width: px2rpx(120);
+    font-size: px2rpx(14);
+  }
+
+  .crm-title-box {
+    display: flex;
+    align-items: center;
+    margin: px2rpx(20) 0;
+
+    .tit {
+      font-size: px2rpx(18);
+      font-weight: 500;
+      color: var(--color-white);
+    }
+
+    .icon-tip {
+      margin-left: px2rpx(10);
+      font-size: px2rpx(16);
+      color: var(--color-white);
+      cursor: pointer;
+    }
+  }
+
+  .popup-content {
+    padding: px2rpx(20);
+    text-align: center;
+  }
+
+  .dia-content {
+    padding: px2rpx(30);
+    text-align: center;
+
+    .icon {
+      margin-bottom: px2rpx(20);
+
+      i {
+        font-size: px2rpx(60);
+        color: #4a6cf7;
+      }
+    }
+
+    .des1 {
+      font-size: px2rpx(18);
+      font-weight: 500;
+      margin-bottom: px2rpx(10);
+    }
+
+    .des2 {
+      font-size: px2rpx(14);
+      color: #666;
+      margin-bottom: px2rpx(30);
+    }
+
+    .dialog-footer {
+      display: flex;
+      justify-content: space-between;
+      margin-top: px2rpx(30);
+
+      uni-button {
+        flex: 1;
+        margin: 0 px2rpx(10);
+
+        &:first-child {
+          margin-left: 0;
+        }
+
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+
+  .cwg-upload {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: px2rpx(40);
+    border: 1px dashed #ddd;
+    border-radius: px2rpx(8);
+    cursor: pointer;
+
+    cwg-icon {
+      font-size: px2rpx(40);
+      margin-bottom: px2rpx(10);
+      color: #999;
+    }
+
+    .name {
+      font-size: px2rpx(16);
+      margin-bottom: px2rpx(5);
+    }
+
+    .back {
+      font-size: px2rpx(12);
+      color: #999;
+    }
+  }
+</style>

+ 1 - 0
static/icons/crm-document.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1774422618227" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2082" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M288 320h448a32 32 0 0 0 0-64H288a32 32 0 0 0 0 64zM288 544h448a32 32 0 0 0 0-64H288a32 32 0 0 0 0 64zM544 704H288a32 32 0 0 0 0 64h256a32 32 0 0 0 0-64z" p-id="2083"></path><path d="M896 132.928C896 77.28 851.552 32 796.928 32H227.04C172.448 32 128 77.28 128 132.928v758.144C128 946.72 172.448 992 227.04 992h435.008c1.568 0 2.912-0.672 4.416-0.896 8.96 1.6 18.464-0.256 25.984-6.528l192-160a31.424 31.424 0 0 0 10.816-27.2c0.16-1.184 0.736-2.208 0.736-3.424V132.928zM192 891.072V132.928C192 112.576 207.712 96 227.04 96h569.888C816.288 96 832 112.576 832 132.928V736h-96a96 96 0 0 0-96 96v96H227.04C207.712 928 192 911.424 192 891.072zM814.016 800L704 891.68V832a32 32 0 0 1 32-32h78.016z" p-id="2084"></path></svg>

+ 1 - 0
static/icons/crm-refresh.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M129.9 292.5C143.2 199.5 223.3 128 320 128C373 128 421 149.5 455.8 184.2C456 184.4 456.2 184.6 456.4 184.8L464 192L416.1 192C398.4 192 384.1 206.3 384.1 224C384.1 241.7 398.4 256 416.1 256L544.1 256C561.8 256 576.1 241.7 576.1 224L576.1 96C576.1 78.3 561.8 64 544.1 64C526.4 64 512.1 78.3 512.1 96L512.1 149.4L500.8 138.7C454.5 92.6 390.5 64 320 64C191 64 84.3 159.4 66.6 283.5C64.1 301 76.2 317.2 93.7 319.7C111.2 322.2 127.4 310 129.9 292.6zM573.4 356.5C575.9 339 563.7 322.8 546.3 320.3C528.9 317.8 512.6 330 510.1 347.4C496.8 440.4 416.7 511.9 320 511.9C267 511.9 219 490.4 184.2 455.7C184 455.5 183.8 455.3 183.6 455.1L176 447.9L223.9 447.9C241.6 447.9 255.9 433.6 255.9 415.9C255.9 398.2 241.6 383.9 223.9 383.9L96 384C87.5 384 79.3 387.4 73.3 393.5C67.3 399.6 63.9 407.7 64 416.3L65 543.3C65.1 561 79.6 575.2 97.3 575C115 574.8 129.2 560.4 129 542.7L128.6 491.2L139.3 501.3C185.6 547.4 249.5 576 320 576C449 576 555.7 480.6 573.4 356.5z"/></svg>

+ 1 - 0
static/icons/icon_arrowR.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M566.6 342.6C579.1 330.1 579.1 309.8 566.6 297.3L406.6 137.3C394.1 124.8 373.8 124.8 361.3 137.3C348.8 149.8 348.8 170.1 361.3 182.6L466.7 288L96 288C78.3 288 64 302.3 64 320C64 337.7 78.3 352 96 352L466.7 352L361.3 457.4C348.8 469.9 348.8 490.2 361.3 502.7C373.8 515.2 394.1 515.2 406.6 502.7L566.6 342.7z"/></svg>

+ 1 - 0
static/icons/icon_mobile.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1774435430334" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4085" width="48" height="48" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M728.118989 1010.749509 294.99432 1010.749509c-47.854537 0-86.634178-38.779641-86.634178-86.637827L208.360142 101.096115c0-47.854537 38.779641-86.634178 86.634178-86.634178l433.181836 0c47.859402 0 86.634178 38.779641 86.634178 86.634178l0 823.014351C814.753167 971.969868 775.973526 1010.749509 728.118989 1010.749509L728.118989 1010.749509zM771.464662 101.096115c0-23.899293-19.389212-43.288506-43.288506-43.288506L294.99432 57.807609c-23.899293 0-43.288506 19.389212-43.288506 43.288506l0 64.963166 519.816014 0 0-64.963166L771.464662 101.096115zM771.464662 209.409818 251.648648 209.409818l0 498.140137 519.816014 0L771.464662 209.409818 771.464662 209.409818zM771.464662 750.838461 251.648648 750.838461l0 173.272005c0 23.898077 19.389212 43.288506 43.288506 43.288506l433.181836 0c23.898077 0 43.288506-19.389212 43.288506-43.288506L771.407495 750.838461 771.464662 750.838461zM511.558479 924.110466c-35.909147 0-64.963166-29.111186-64.963166-64.963166 0-35.905498 29.111186-64.963166 64.963166-64.963166 35.848332 0 64.959517 29.116051 64.959517 64.963166C576.517996 895.000497 547.463977 924.110466 511.558479 924.110466L511.558479 924.110466zM511.558479 924.110466" fill="#272636" p-id="4086"></path></svg>

+ 20 - 1
static/scss/global/global.scss

@@ -46,6 +46,8 @@
     --color-gray-200: oklch(92.8% .006 264.531);
     --color-zinc-100: oklch(96.7% .001 286.375);
     --color-black: #000;
+    --color-gray: #F2F2F2;
+    --color-gray-second: #6B7188;
     --color-white: #fff;
     --font-size-10: px2rpx(10);
     --font-size-12: px2rpx(12);
@@ -239,6 +241,7 @@
     --color-warning-focus: #e68200;
     --color-error: #e32326;
     --color-error-focus: #f03000;
+    --color-gray-second: #6B7188;
     --text-tiny: .625rem;
     --text-tiny--line-height: .8125rem;
     --text-tiny-plus: .6875rem;
@@ -559,7 +562,7 @@ uni-content {
         font-size: var(--font-size-16);
         font-weight: bold;
         color: var(--black);
-        background: var(--main-yellow) !important;
+        background-color: var(--color-navy-900) !important;
         border: none !important;
         border-radius: px2rpx(100) !important;
 
@@ -1022,6 +1025,22 @@ uni-content {
     // border: 1px solid rgba(108, 133, 149, 0.12);
     border-radius: px2rpx(8);
 }
+.crm-title-box{
+  background-color: var(--color-gray-second);
+  color: var(--color-white);
+  height: 40px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 10px;
+  border-radius: 2px;
+  padding: 0 20px;
+  .tit {
+    font-size: 14px;
+    font-weight: bold;
+    color: var(--color-white);
+  }
+}
 
 @media screen and (max-width: 991px) {
     .info-card {

+ 7 - 2
uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue

@@ -138,6 +138,10 @@
 				type: String,
 				default: ''
 			},
+      canChoose: {
+				type: Boolean,
+				default: false
+			},
 			listStyles: {
 				type: Object,
 				default () {
@@ -331,8 +335,9 @@
 			 */
 			choose() {
 				if (this.disabled) return
+        // canchoose 为 false 时,走正常逻辑,否则可以重新选择文件
 				if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
-					'array') {
+					'array' && !this.canChoose) {
 					uni.showToast({
 						title: `您最多选择 ${this.limitLength} 个文件`,
 						icon: 'none'
@@ -677,4 +682,4 @@
 		position: absolute;
 		transform: rotate(90deg);
 	}
-</style>
+</style>