withdrawal.vue 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. <template>
  2. <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
  3. <view class="custom-withdraw">
  4. <!-- 标题 -->
  5. <!-- <view class="crm-title-box">
  6. <text class="tit">{{ t('Custom.Withdraw.Title') }}</text>
  7. </view> -->
  8. <!-- 步骤1:选择账户 -->
  9. <view class="box box-step1">
  10. <view class="b-card">
  11. <view class="card-top">
  12. <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title11') }}</text>
  13. <view class="base-info-form">
  14. <view class="uni-row2">
  15. <cwg-combox :clearable="false" v-model:value="loginValue" :options="loginComboxOptions"
  16. :placeholder="t('placeholder.choose')" @change="onAccountChange" />
  17. </view>
  18. </view>
  19. </view>
  20. </view>
  21. </view>
  22. <!-- 步骤2:支付通道列表 -->
  23. <view class="box box-step2" v-if="step2">
  24. <view class="b-card">
  25. <view class="card-top">
  26. <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title22') }}</text>
  27. <view v-for="(group, groupKey) in tableData" :key="groupKey">
  28. <!-- 通道分组标题 -->
  29. <view class="channelType" v-if="group.length" v-t="groupTitleMap[groupKey]" />
  30. <PaymentMethodsList :list="group" @select="isShowStep3" />
  31. </view>
  32. <view v-if="step3" class="reselect-btn">
  33. <button class="s-btn reselect" type="primary" @click="showTable">{{ t('Custom.Deposit.Reselect')
  34. }}</button>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. <!-- 步骤3:填写出金信息 -->
  40. <view class="box box-step3" v-if="step3">
  41. <view class="b-card">
  42. <view class="card-top">
  43. <!-- 注意事项 -->
  44. <view v-if="!isStep3" class="step3-attention">
  45. <rich-text class="attention" :nodes="isZh ? introduce.introduce : introduce.enIntroduce"></rich-text>
  46. <view class="btn-bottom">
  47. <text class="btn crm-cursor" @click="isStep3 = true">{{ t('Btn.Confirm') }}</text>
  48. </view>
  49. </view>
  50. <!-- 表单 -->
  51. <uni-forms ref="baseForm" :model="form" labelWidth="200" label-position="top" v-if="isStep3"
  52. class="base-info-form">
  53. <uni-row class="demo-uni-row uni-row1">
  54. <!-- 银行选择(针对有银行列表的通道) -->
  55. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="bankDate.length">
  56. <uni-forms-item :label="t('Custom.Withdraw.Title5')">
  57. <cwg-combox :clearable="false" v-model:value="selectedBankIndex" :options="bankOptions"
  58. :placeholder="t('placeholder.choose')" @change="onBankChange" />
  59. </uni-forms-item>
  60. </uni-col>
  61. <!-- 电子钱包地址输入 -->
  62. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
  63. v-if="['CHANNEL_TYPE_WALLET', 'UCARD_WALLET', 'CHANNEL_TYPE_ALI_WALLET'].includes(channelData.type)">
  64. <uni-forms-item :label="getWalletLabel">
  65. <uni-easyinput :clearable="false" v-model="form.address" :placeholder="t('placeholder.input')" />
  66. </uni-forms-item>
  67. </uni-col>
  68. <!-- 数字货币选择(从已保存地址中选择) -->
  69. <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="channelData.type === 'DIGITAL_CURRENCY'">
  70. <view class="add-back">
  71. <text>{{ t('blockchain.item10') }}</text>
  72. <text class="add-btn crm-cursor" @click="openAddBankCard('add_bankBlockchain')">{{
  73. t('Custom.Withdraw.addBank1') }}</text>
  74. </view>
  75. <uni-forms-item :label="t('blockchain.item10')">
  76. <cwg-combox :clearable="false" v-model:value="selectedDigitalIndex" :options="digitalOptions"
  77. :placeholder="t('placeholder.choose')" @change="onDigitalCurrencyChange"
  78. :disabled="!ruleForm.bankBlockchain.length" />
  79. </uni-forms-item>
  80. <uni-row>
  81. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
  82. <uni-forms-item :label="t('blockchain.item3')">
  83. <uni-easyinput disabled v-model="form.addressName" />
  84. </uni-forms-item>
  85. </uni-col>
  86. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
  87. <uni-forms-item :label="t('blockchain.item4')">
  88. <uni-easyinput disabled v-model="form.address" />
  89. </uni-forms-item>
  90. </uni-col>
  91. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.addressProve">
  92. <uni-forms-item :label="t('blockchain.item5')">
  93. <view class="proof">
  94. <template v-if="form.addressProve && (form.addressProve.slice(-3).toLowerCase() === 'pdf')">
  95. <a :href="imgUrl + form.addressProve" target="_blank" class="state crm_state_blue">PDF</a>
  96. </template>
  97. <image v-else :src="imgUrl + form.addressProve" mode="aspectFit"
  98. style="width: 100rpx; height: 100rpx;" @click="previewImage(imgUrl + form.addressProve)" />
  99. </view>
  100. </uni-forms-item>
  101. </uni-col>
  102. </uni-row>
  103. <text class="tit"><text class="iconfont iconi"></text>{{ t('Custom.Deposit.Des') }}</text>
  104. </uni-col>
  105. <!-- 银行卡/信用卡选择 -->
  106. <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"
  107. v-if="['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.type)">
  108. <view class="add-back" v-if="channelData.type === 'BANK_TELEGRAPHIC'">
  109. <text>{{ t('Custom.Withdraw.addWire') }}</text>
  110. <text class="add-btn crm-cursor" @click="openAddBankCard('add_wireTransfer')">{{
  111. t('Custom.Withdraw.addBank1') }}</text>
  112. </view>
  113. <view class="add-back" v-else-if="channelData.type === 'BANK'">
  114. <text>{{ t('Custom.Withdraw.addBank') }}</text>
  115. <text class="add-btn crm-cursor" @click="openAddBankCard('add_bankCard')">{{
  116. t('Custom.Withdraw.addBank1')
  117. }}</text>
  118. </view>
  119. <view class="add-back" v-else-if="channelData.type === 'CHANNEL_TYPE_CARD'">
  120. <text>{{ t('PersonalManagement.Label.addCreditCard') }}</text>
  121. <text class="add-btn crm-cursor" @click="openAddBankCard('add_CreditCard')">{{
  122. t('Custom.Withdraw.addBank1') }}</text>
  123. </view>
  124. <uni-forms-item :label="t('placeholder.choose')">
  125. <cwg-combox :clearable="false" v-model:value="selectedBankCardIndex" :options="bankCardOptions"
  126. :placeholder="t('placeholder.choose')" @change="onBankCardChange" />
  127. </uni-forms-item>
  128. <!-- 通用银行信息展示 -->
  129. <uni-row>
  130. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankUname">
  131. <uni-forms-item :label="t('Custom.Withdraw.UserName')">
  132. <uni-easyinput disabled v-model="form.bankUname" />
  133. </uni-forms-item>
  134. </uni-col>
  135. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankCardNum">
  136. <uni-forms-item :label="t('Custom.Withdraw.BankCardNum')">
  137. <uni-easyinput disabled v-model="form.bankCardNum" />
  138. </uni-forms-item>
  139. </uni-col>
  140. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankName">
  141. <uni-forms-item :label="t('Custom.Withdraw.BankName')">
  142. <uni-easyinput disabled v-model="form.bankName" />
  143. </uni-forms-item>
  144. </uni-col>
  145. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankBranchName">
  146. <uni-forms-item :label="t('Custom.Withdraw.bankBranchName')">
  147. <uni-easyinput disabled v-model="form.bankBranchName" />
  148. </uni-forms-item>
  149. </uni-col>
  150. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.swiftCode">
  151. <uni-forms-item :label="t('Custom.Withdraw.swiftCode')">
  152. <uni-easyinput disabled v-model="form.swiftCode" />
  153. </uni-forms-item>
  154. </uni-col>
  155. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.customBankCode">
  156. <uni-forms-item :label="t('Custom.Withdraw.bankCode')">
  157. <uni-easyinput disabled v-model="form.customBankCode" />
  158. </uni-forms-item>
  159. </uni-col>
  160. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankAddr">
  161. <uni-forms-item :label="t('Custom.Withdraw.bankAddr')">
  162. <uni-easyinput disabled v-model="form.bankAddr" />
  163. </uni-forms-item>
  164. </uni-col>
  165. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
  166. v-if="channelData.type === 'BANK_TELEGRAPHIC' && form.agencyNo">
  167. <uni-forms-item label="Account Agency NO">
  168. <uni-easyinput v-model="form.agencyNo" />
  169. </uni-forms-item>
  170. </uni-col>
  171. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
  172. v-if="channelData.type === 'BANK_TELEGRAPHIC' && form.cpf">
  173. <uni-forms-item label="CPF">
  174. <uni-easyinput v-model="form.cpf" />
  175. </uni-forms-item>
  176. </uni-col>
  177. </uni-row>
  178. </uni-col>
  179. <!-- 出金金额 -->
  180. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="channelData.type !== 'BANK_TELEGRAPHIC'">
  181. <uni-forms-item :label="t('Custom.Withdraw.Title3') + '(' + channelData.currency + ')'">
  182. <uni-easyinput v-model="form.amount" type="number" @input="onAmountInput" />
  183. </uni-forms-item>
  184. </uni-col>
  185. <template v-else>
  186. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
  187. <uni-forms-item :label="t('Custom.Withdraw.CurrencyType')">
  188. <cwg-combox :clearable="false" v-model:value="form.currency"
  189. :options="[{ text: 'USD', value: 'USD' }]" @change="(val) => form.currency = val" />
  190. </uni-forms-item>
  191. </uni-col>
  192. <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
  193. <uni-forms-item :label="t('Custom.Withdraw.amount')">
  194. <uni-easyinput v-model="form.amount" type="number" @input="onAmountInput" />
  195. </uni-forms-item>
  196. </uni-col>
  197. </template>
  198. </uni-row>
  199. <!-- 协议同意 -->
  200. <view class="agree">
  201. <label class="checkbox">
  202. <checkbox :checked="form.agree2" @click="form.agree2 = !form.agree2" />
  203. <text class="crm-cursor" style="text-decoration: underline;" @click="dialogCheckTip = true">{{
  204. t('Custom.Withdraw.Des') }}</text>
  205. </label>
  206. </view>
  207. <view class="agree" v-if="dialogTipsIsShow">
  208. <label class="checkbox">
  209. <checkbox :checked="form.agree3" @click="form.agree3 = !form.agree3" />
  210. <text>* {{ t('Custom.Withdraw.item1') }}<br>{{ t('Custom.Withdraw.item1_1') }}<br>{{
  211. t('Custom.Withdraw.item1_2') }}</text>
  212. </label>
  213. </view>
  214. <button class="s-btn" type="primary" @click="openTips">{{ t('Btn.Submit') }}</button>
  215. </uni-forms>
  216. </view>
  217. </view>
  218. </view>
  219. <!-- 弹窗:确认信息 -->
  220. <uni-popup ref="confirmPopup" type="center" :mask-click="false">
  221. <view class="popup-content">
  222. <text class="popup-title">{{ t('Home.page_customer.item3') }}</text>
  223. <view class="popup-form">
  224. <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title11') }}:</text><text>{{ loginValue
  225. }}</text></view>
  226. <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title22') }}:</text><text>{{ (t('lang') ===
  227. 'cn' || t('lang') === 'zhHant') ? channelData.name : channelData.enName }}</text></view>
  228. <view class="popup-row"><text class="label">{{ t('Custom.Withdraw.Title3') }}:</text><text>{{ form.amount
  229. }}({{
  230. channelData.currency }})</text></view>
  231. <view class="popup-row"><text class="label">{{ t('Custom.Withdraw.item7') }}:</text><text
  232. v-if="FreeNumber > 0 && dialogConfirmFee > 0"><text style="text-decoration:line-through">${{
  233. dialogConfirmFee
  234. }}</text> $0.00</text><text v-else>${{ dialogConfirmFee }}</text></view>
  235. </view>
  236. <view class="popup-buttons">
  237. <button @click="closeConfirmPopup">{{ t('Btn.Cancel') }}</button>
  238. <button type="primary" @click="submitConfirm">{{ t('Btn.Confirm') }}</button>
  239. </view>
  240. </view>
  241. </uni-popup>
  242. <!-- 弹窗:提交前警告 -->
  243. <uni-popup ref="warningPopup" type="center">
  244. <view class="popup-content">
  245. <text class="popup-text">{{ t('Custom.Withdraw.item2') }}</text>
  246. <view class="popup-buttons">
  247. <button @click="closeWarningPopup">{{ t('Custom.Withdraw.item4') }}</button>
  248. <button type="primary" @click="submitAfterWarning">{{ t('Custom.Withdraw.item3') }}</button>
  249. </view>
  250. </view>
  251. </uni-popup>
  252. <!-- 弹窗:结果 -->
  253. <uni-popup ref="resultPopup" type="center" :mask-click="false">
  254. <view class="popup-content">
  255. <view class="result-icon" v-if="dialogSuccess"><text class="iconfont iconchenggong"></text></view>
  256. <view class="result-icon" v-else><text class="iconfont iconjingshi"></text></view>
  257. <text class="popup-text">{{ dialogMessage }}</text>
  258. <view class="popup-buttons">
  259. <button type="primary" @click="closeResultPopup">{{ t('Btn.Confirm') }}</button>
  260. <button v-if="!dialogSuccess" @click="closeResultPopup">{{ t('Btn.Cancel') }}</button>
  261. </view>
  262. </view>
  263. </uni-popup>
  264. <!-- 弹窗:条款 -->
  265. <uni-popup ref="tipPopup" type="center">
  266. <view class="popup-content">
  267. <rich-text class="popup-text"
  268. :nodes="(t('lang') === 'cn' || t('lang') === 'zhHant') ? introduce.introduce : introduce.enIntroduce"></rich-text>
  269. <view class="popup-buttons">
  270. <button @click="closeTipPopup">{{ t('Btn.Cancel') }}</button>
  271. <button type="primary" @click="closeTipPopup">{{ t('Btn.Confirm') }}</button>
  272. </view>
  273. </view>
  274. </uni-popup>
  275. <!-- 弹窗:等待 -->
  276. <uni-popup ref="waitPopup" type="center" :mask-click="false">
  277. <view class="popup-content">
  278. <text class="iconfont icondengdai"></text>
  279. <text class="popup-text">{{ t('ApplicationDialog.Des38') }}</text>
  280. </view>
  281. </uni-popup>
  282. <!-- 弹窗:验证码 -->
  283. <uni-popup ref="codePopup" type="center">
  284. <view class="popup-content">
  285. <text class="popup-title">{{ t('signup.form.code') }}</text>
  286. <input class="code-input" v-model="emailCode" :placeholder="t('signup.form.code')" />
  287. <view class="code-timer" @click="getCode">{{ getCodeString }}</view>
  288. <view class="popup-buttons">
  289. <button @click="closeCodePopup">{{ t('Btn.Cancel') }}</button>
  290. <button type="primary" @click="submitCode">{{ t('Btn.Confirm') }}</button>
  291. </view>
  292. </view>
  293. </uni-popup>
  294. <!-- 抽屉:新增/修改银行信息 -->
  295. <!-- <drawer :dialogInfoTradingAdd="dialogInfoTradingAdd" :addType="openType" @closeAdd="closeAdd"
  296. @confirmToReload="confirmToReload" /> -->
  297. </view>
  298. </cwg-page-wrapper>
  299. </template>
  300. <script setup>
  301. import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
  302. import { onLoad } from '@dcloudio/uni-app'
  303. import { useI18n } from 'vue-i18n' // uni-app 中已集成,但需配置
  304. import { customApi } from '@/service/custom'
  305. import { financialApi } from '@/service/financial'
  306. // import {ServiceA} from '@/service/activity'
  307. import Config from '@/config/index'
  308. import Decimal from 'decimal.js'
  309. // import Drawer from '@/components/Drawer.vue' // 假设抽屉组件已存在
  310. import PaymentMethodsList from './components/PaymentMethodsList.vue'
  311. const { t, locale } = useI18n()
  312. const isZh = computed(() => ['cn', 'zhHant'].includes(locale.value))
  313. const loginComboxOptions = computed(() => {
  314. return loginOptions.value.map((item, index) => ({
  315. text: item.label,
  316. value: item.login
  317. }))
  318. })
  319. const bankOptions = computed(() => {
  320. return bankDate.value.map((item, index) => ({
  321. text: isZh.value ? item.name : item.enName,
  322. value: index
  323. }))
  324. })
  325. const digitalOptions = computed(() => {
  326. return ruleForm.bankBlockchain.map((item, index) => ({
  327. text: `${item.addressName}-${item.address}`,
  328. value: index
  329. }))
  330. })
  331. const bankCardOptions = computed(() => {
  332. return bankList.value.map((item, index) => ({
  333. text: getBankLabel(item),
  334. value: index
  335. }))
  336. })
  337. const getWalletLabel = computed(() => {
  338. if (channelData.value.type === 'CHANNEL_TYPE_WALLET') return t('Custom.Withdraw.Title7')
  339. if (channelData.value.type === 'UCARD_WALLET') return t('card.title')
  340. if (channelData.value.type === 'CHANNEL_TYPE_ALI_WALLET') return t('Label.AliAccout')
  341. return ''
  342. })
  343. const { Code, Host80 } = Config
  344. const imgUrl = Host80
  345. // 工具函数
  346. const Session = {
  347. get: (key, parse = false) => {
  348. const val = uni.getStorageSync(key)
  349. return parse ? JSON.parse(val) : val
  350. },
  351. set: (key, val) => uni.setStorageSync(key, val)
  352. }
  353. // 分组标题映射
  354. const groupTitleMap = {
  355. 'Ucard_Wallet': 'card.title',
  356. 'Digital_Currency': 'Custom.Deposit.Channel3',
  357. 'China_UnionPay': 'Custom.Deposit.Channel2',
  358. 'Electronic_Wallet': 'Custom.Deposit.Channel4',
  359. 'International_Transfer': 'Custom.Deposit.Channel1',
  360. 'CHANNEL_TYPE_CARD': 'PersonalManagement.Label.CreditCard',
  361. 'CHANNEL_TYPE_ALI_WALLET': 'Label.Ali'
  362. }
  363. // 数据
  364. const loginOptions = ref([])
  365. const selectedAccountIndex = ref(-1)
  366. const selectedAccountLabel = ref('')
  367. const loginValue = ref(null)
  368. const step2 = ref(false)
  369. const step3 = ref(false)
  370. const isStep3 = ref(false)
  371. const tableData = ref({
  372. Ucard_Wallet: [],
  373. Digital_Currency: [],
  374. China_UnionPay: [],
  375. Electronic_Wallet: [],
  376. International_Transfer: [],
  377. CHANNEL_TYPE_CARD: [],
  378. CHANNEL_TYPE_ALI_WALLET: []
  379. })
  380. const channelData = ref({})
  381. const introduce = ref({ introduce: '', enIntroduce: '' })
  382. const bankDate = ref([])
  383. const selectedBankIndex = ref(-1)
  384. const selectedBankLabel = ref('')
  385. const ruleForm = reactive({
  386. bankInfo: [],
  387. bankWrit: [],
  388. xykInfo: [],
  389. bankBlockchain: []
  390. })
  391. const form = reactive({
  392. currency: 'USD',
  393. amount: '',
  394. amount1: '',
  395. agree2: false,
  396. agree3: false,
  397. address: '',
  398. addressName: '',
  399. addressProve: '',
  400. bankUname: '',
  401. bankCardNum: '',
  402. bankName: '',
  403. bankBranchName: '',
  404. swiftCode: '',
  405. customBankCode: '',
  406. bankAddr: '',
  407. agencyNo: '',
  408. cpf: ''
  409. })
  410. const myId = ref(null)
  411. const bankList = computed(() => {
  412. if (channelData.value.type === 'BANK') return ruleForm.bankInfo
  413. if (channelData.value.type === 'BANK_TELEGRAPHIC') return ruleForm.bankWrit
  414. if (channelData.value.type === 'CHANNEL_TYPE_CARD') return ruleForm.xykInfo
  415. return []
  416. })
  417. const selectedBankCardIndex = ref(-1)
  418. const selectedBankCardLabel = ref('')
  419. const selectedDigitalIndex = ref(-1)
  420. const selectedDigitalLabel = ref('')
  421. const mAmount = reactive({ minAmount: '', maxAmount: '' })
  422. const FreeNumber = ref(0)
  423. const isFree = ref(false)
  424. const dialogTipsIsShow = ref(true)
  425. const dialogConfirmFee = ref(0)
  426. // 弹窗引用
  427. const confirmPopup = ref(null)
  428. const warningPopup = ref(null)
  429. const resultPopup = ref(null)
  430. const tipPopup = ref(null)
  431. const waitPopup = ref(null)
  432. const codePopup = ref(null)
  433. // 结果状态
  434. const dialogSuccess = ref(false)
  435. const dialogMessage = ref('')
  436. // 验证码
  437. const emailCode = ref('')
  438. const getCodeString = ref('')
  439. let timer = null
  440. let countdown = 59
  441. // 抽屉
  442. const dialogInfoTradingAdd = ref(false)
  443. const openType = ref('')
  444. // 其他
  445. const pictLoading = ref(false)
  446. const isChannel = ref(true)
  447. const bankPayType = ref('')
  448. const requestUrl = ref('')
  449. const RES = ref('')
  450. const flag = ref(false)
  451. // 方法
  452. const getDateList = async () => {
  453. const res = await customApi.CustomDropdown({ platform: '' })
  454. if (res.code === Code.StatusOK) {
  455. loginOptions.value = res.data.map(item => ({
  456. ...item,
  457. label: `${item.login} - ${groupTypeName(item.type)} - ${t('Custom.Deposit.AvailableBalance')}${groupCurrency(item.currency)}${item.balance}`
  458. }))
  459. const route = getCurrentPages().pop().$page.options
  460. if (route.login) {
  461. const found = loginOptions.value.find(opt => opt.login === Number(route.login))
  462. if (found) {
  463. selectedAccountIndex.value = loginOptions.value.indexOf(found)
  464. selectedAccountLabel.value = found.label
  465. loginValue.value = found.login
  466. step2.value = true
  467. }
  468. }
  469. } else {
  470. uni.showToast({ title: res.msg, icon: 'none' })
  471. }
  472. }
  473. const groupTypeName = (type) => {
  474. const map = {
  475. '1': 'AccountType.ClassicAccount',
  476. '2': 'AccountType.SeniorAccount',
  477. '5': 'AccountType.SpeedAccount',
  478. '6': 'AccountType.SpeedAccount',
  479. '7': 'AccountType.StandardAccount',
  480. '8': 'AccountType.CentAccount'
  481. }
  482. return t(map[type] || '')
  483. }
  484. const groupCurrency = (type) => {
  485. const symbol = { GBP: '£', USD: '$', EUR: '€', USC: '¢' }[type] || '$'
  486. return `: ${symbol}`
  487. }
  488. const getDepositList = async () => {
  489. pictLoading.value = true
  490. const res = await financialApi.RemitChannelList({})
  491. if (res.code === Code.StatusOK) {
  492. const groups = {
  493. Ucard_Wallet: [],
  494. Digital_Currency: [],
  495. China_UnionPay: [],
  496. Electronic_Wallet: [],
  497. International_Transfer: [],
  498. CHANNEL_TYPE_CARD: [],
  499. CHANNEL_TYPE_ALI_WALLET: []
  500. }
  501. res.data.forEach(item => {
  502. if (item.type === 'UCARD_WALLET') groups.Ucard_Wallet.push(item)
  503. if (item.type === 'DIGITAL_CURRENCY') groups.Digital_Currency.push(item)
  504. if (item.type === 'BANK') groups.China_UnionPay.push(item)
  505. if (item.type === 'CHANNEL_TYPE_WALLET') groups.Electronic_Wallet.push(item)
  506. if (item.type === 'BANK_TELEGRAPHIC') groups.International_Transfer.push(item)
  507. if (item.type === 'CHANNEL_TYPE_CARD') groups.CHANNEL_TYPE_CARD.push(item)
  508. if (item.type === 'CHANNEL_TYPE_ALI_WALLET') groups.CHANNEL_TYPE_ALI_WALLET.push(item)
  509. })
  510. tableData.value = groups
  511. pictLoading.value = false
  512. } else {
  513. uni.showToast({ title: res.msg, icon: 'none' })
  514. pictLoading.value = false
  515. }
  516. }
  517. const getBankList = async (row) => {
  518. const res = await financialApi.BankList({ channelCode: row.code })
  519. if (res.code === Code.StatusOK) {
  520. const data = res.data.map(j => ({
  521. ...j,
  522. minAmount: j.minAmount ?? row.minAmount,
  523. maxAmount: j.maxAmount ?? row.maxAmount,
  524. payType: row.code
  525. }))
  526. bankDate.value = data
  527. } else {
  528. uni.showToast({ title: res.msg, icon: 'none' })
  529. }
  530. }
  531. const getBankInfo = async () => {
  532. const res = await financialApi.customBankList({})
  533. if (res.code === Code.StatusOK) {
  534. ruleForm.bankInfo = []
  535. ruleForm.bankWrit = []
  536. ruleForm.xykInfo = []
  537. ruleForm.bankBlockchain = []
  538. res.data.forEach(item => {
  539. item.customBankCode = item.bankCode
  540. item.bankCode = null
  541. if (item.type === 1) ruleForm.bankInfo.push(item)
  542. else if (item.type === 2) ruleForm.bankWrit.push(item)
  543. else if (item.type === 3) {
  544. item.expiryYearMonth = `${item.expiryYear}/${item.expiryMonth}`
  545. ruleForm.xykInfo.push(item)
  546. } else if (item.type === 4) ruleForm.bankBlockchain.push(item)
  547. })
  548. // 如果有默认选中
  549. const findDefault = (list, type) => list.find(b => b.defaultBank && b.type === type)
  550. const defaultBank = findDefault(ruleForm.bankInfo, 1)
  551. const defaultWire = findDefault(ruleForm.bankWrit, 2)
  552. const defaultCard = findDefault(ruleForm.xykInfo, 3)
  553. const defaultDigital = findDefault(ruleForm.bankBlockchain, 4)
  554. if (channelData.value.type === 'BANK' && defaultBank) selectBankCard(defaultBank)
  555. if (channelData.value.type === 'BANK_TELEGRAPHIC' && defaultWire) selectBankCard(defaultWire)
  556. if (channelData.value.type === 'CHANNEL_TYPE_CARD' && defaultCard) selectBankCard(defaultCard)
  557. if (channelData.value.type === 'DIGITAL_CURRENCY' && defaultDigital && defaultDigital.authStatus === 1) selectDigital(defaultDigital)
  558. } else {
  559. uni.showToast({ title: res.msg, icon: 'none' })
  560. }
  561. }
  562. const selectBankCard = (item) => {
  563. const index = bankList.value.findIndex(b => b.id === item.id)
  564. if (index !== -1) {
  565. selectedBankCardIndex.value = index
  566. selectedBankCardLabel.value = getBankLabel(item)
  567. Object.assign(form, item)
  568. }
  569. }
  570. const selectDigital = (item) => {
  571. const index = ruleForm.bankBlockchain.findIndex(b => b.id === item.id)
  572. if (index !== -1) {
  573. selectedDigitalIndex.value = index
  574. selectedDigitalLabel.value = `${item.addressName}-${item.address}`
  575. form.addressName = item.addressName
  576. form.address = item.address
  577. form.addressProve = item.addressProve
  578. }
  579. }
  580. const getBankLabel = (item) => {
  581. if (channelData.value.type === 'BANK' || channelData.value.type === 'BANK_TELEGRAPHIC') {
  582. return `${item.bankName}-${item.bankCardNum}`
  583. } else if (channelData.value.type === 'CHANNEL_TYPE_CARD') {
  584. return item.bankCardNum
  585. }
  586. return ''
  587. }
  588. const getFreeNumber = async () => {
  589. if (!isFree.value) return
  590. const res = await financialApi.remainingReductionNumber({})
  591. if (res.code === Code.StatusOK) {
  592. FreeNumber.value = res.data || 0
  593. } else {
  594. uni.showToast({ title: res.msg, icon: 'none' })
  595. }
  596. }
  597. const isNewYear24Open = () => {
  598. // 简化,原逻辑是判断活动时间
  599. // 根据需求决定是否保留
  600. }
  601. // 事件处理
  602. const onAccountChange = (val) => {
  603. const item = loginOptions.value.find(opt => opt.login === val)
  604. if (item) {
  605. selectedAccountIndex.value = loginOptions.value.indexOf(item)
  606. selectedAccountLabel.value = item.label
  607. loginValue.value = item.login
  608. step2.value = true
  609. showTable()
  610. }
  611. }
  612. const showTable = () => {
  613. myId.value = null
  614. step3.value = false
  615. isStep3.value = false
  616. isChannel.value = true
  617. getDepositList()
  618. Object.assign(form, { currency: 'USD', amount: '', amount1: '', agree2: false, agree3: false, address: '', addressName: '', addressProve: '', bankUname: '', bankCardNum: '', bankName: '', bankBranchName: '', swiftCode: '', customBankCode: '', bankAddr: '', agencyNo: '', cpf: '' })
  619. if (bankDate.value.length) bankDate.value = []
  620. selectedBankIndex.value = -1
  621. selectedBankLabel.value = ''
  622. selectedBankCardIndex.value = -1
  623. selectedBankCardLabel.value = ''
  624. selectedDigitalIndex.value = -1
  625. selectedDigitalLabel.value = ''
  626. }
  627. const isShowStep3 = (row) => {
  628. if (row.bankValid && isChannel.value) {
  629. getBankList(row)
  630. isChannel.value = false
  631. step3.value = true
  632. channelData.value = row
  633. mAmount.minAmount = row.minAmount
  634. mAmount.maxAmount = row.maxAmount
  635. } else {
  636. step3.value = true
  637. bankDate.value = []
  638. channelData.value = row
  639. mAmount.minAmount = row.minAmount
  640. mAmount.maxAmount = row.maxAmount
  641. }
  642. if (row.code === 'UNION_PAY_TELEGRAPHIC') {
  643. // WireTransferAccount = JSON.parse(row.property) 暂略
  644. }
  645. if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD', 'DIGITAL_CURRENCY'].includes(row.type)) {
  646. getBankInfo()
  647. form.login = loginValue.value
  648. form.payType = row.code
  649. bankPayType.value = row.code
  650. }
  651. // 重新组织 tableData 只显示当前选中项
  652. const newGroups = {
  653. Ucard_Wallet: [],
  654. Digital_Currency: [],
  655. China_UnionPay: [],
  656. Electronic_Wallet: [],
  657. International_Transfer: [],
  658. CHANNEL_TYPE_CARD: [],
  659. CHANNEL_TYPE_ALI_WALLET: []
  660. }
  661. if (row.type === 'UCARD_WALLET') newGroups.Ucard_Wallet = [row]
  662. if (row.type === 'DIGITAL_CURRENCY') newGroups.Digital_Currency = [row]
  663. if (row.type === 'BANK') newGroups.China_UnionPay = [row]
  664. if (row.type === 'CHANNEL_TYPE_WALLET') newGroups.Electronic_Wallet = [row]
  665. if (row.type === 'BANK_TELEGRAPHIC') newGroups.International_Transfer = [row]
  666. if (row.type === 'CHANNEL_TYPE_CARD') newGroups.CHANNEL_TYPE_CARD = [row]
  667. if (row.type === 'CHANNEL_TYPE_ALI_WALLET') newGroups.CHANNEL_TYPE_ALI_WALLET = [row]
  668. tableData.value = newGroups
  669. introduce.value = { introduce: row.introduce, enIntroduce: row.enIntroduce }
  670. }
  671. const onBankChange = (val) => {
  672. const index = val
  673. const item = bankDate.value[index]
  674. if (item) {
  675. selectedBankIndex.value = index
  676. selectedBankLabel.value = (t('lang') === 'cn' || t('lang') === 'zhHant') ? item.name : item.enName
  677. channelData.value.rate = item.rate
  678. channelData.value.transformCurrency = item.currency
  679. channelData.value.feeTypeBank = item.feeType
  680. channelData.value.freeBank = item.free
  681. channelData.value.feeAmountBank = item.feeAmount
  682. }
  683. }
  684. const onBankCardChange = (val) => {
  685. const index = val
  686. const item = bankList.value[index]
  687. if (item) {
  688. selectedBankCardIndex.value = index
  689. selectedBankCardLabel.value = getBankLabel(item)
  690. Object.assign(form, item)
  691. }
  692. }
  693. const onDigitalCurrencyChange = (val) => {
  694. const index = val
  695. const item = ruleForm.bankBlockchain[index]
  696. if (item && item.authStatus === 1) {
  697. selectedDigitalIndex.value = index
  698. selectedDigitalLabel.value = `${item.addressName}-${item.address}`
  699. form.addressName = item.addressName
  700. form.address = item.address
  701. form.addressProve = item.addressProve
  702. } else if (item && item.authStatus === 0) {
  703. uni.showToast({ title: t('Msg.item11'), icon: 'none' })
  704. selectedDigitalIndex.value = -1
  705. selectedDigitalLabel.value = ''
  706. }
  707. }
  708. const onAmountInput = (val) => {
  709. // val is the value from uni-easyinput
  710. if (val && channelData.value.rate) {
  711. if (isFree.value) {
  712. let feeAmount = 0
  713. if (channelData.value.feeTypeBank) {
  714. if (channelData.value.feeTypeBank === 1) feeAmount = Number(val) * (Number(channelData.value.freeBank || 0) / 100)
  715. else if (channelData.value.feeTypeBank === 2) feeAmount = Number(channelData.value.feeAmountBank || 0)
  716. } else {
  717. if (channelData.value.feeType === 1) feeAmount = Number(val) * (Number(channelData.value.free || 0) / 100)
  718. else if (channelData.value.feeType === 2) feeAmount = Number(channelData.value.feeAmount || 0)
  719. }
  720. if (FreeNumber.value > 0) {
  721. form.amount1 = new Decimal(Number(val)).mul(Number(channelData.value.rate || 0)).toNumber()
  722. } else {
  723. form.amount1 = new Decimal(Number(val)).sub(Number(feeAmount || 0)).mul(Number(channelData.value.rate || 0)).toNumber()
  724. }
  725. } else {
  726. form.amount1 = (val * channelData.value.rate).toFixed(2)
  727. }
  728. if (['CNY', 'THB', 'VND'].includes(channelData.value.transformCurrency)) {
  729. form.amount1 = parseInt(form.amount1)
  730. }
  731. }
  732. }
  733. const openTips = () => {
  734. // 校验
  735. if (channelData.value.type === 'DIGITAL_CURRENCY' && !myId.value) {
  736. uni.showToast({ title: t('blockchain.item11'), icon: 'none' })
  737. return
  738. }
  739. if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.value.type) && !selectedBankCardIndex.value !== -1) {
  740. uni.showToast({ title: t('vaildate.withdrawBank.empty'), icon: 'none' })
  741. return
  742. }
  743. // 金额校验
  744. if (!form.amount) {
  745. uni.showToast({ title: t('vaildate.input.empty'), icon: 'none' })
  746. return
  747. }
  748. if (Number(form.amount) < Number(mAmount.minAmount) || Number(form.amount) > Number(mAmount.maxAmount)) {
  749. uni.showToast({ title: `${t('vaildate.amount.amount')}${mAmount.minAmount} - ${mAmount.maxAmount}`, icon: 'none' })
  750. return
  751. }
  752. if (!/^[0-9]+([.]{1}[0-9]{1,2})?$/.test(form.amount)) {
  753. uni.showToast({ title: t('vaildate.amount.format'), icon: 'none' })
  754. return
  755. }
  756. if (!form.agree2) {
  757. uni.showToast({ title: t('vaildate.agree.empty'), icon: 'none' })
  758. return
  759. }
  760. if (dialogTipsIsShow.value && !form.agree3) {
  761. uni.showToast({ title: t('vaildate.agree.empty'), icon: 'none' })
  762. return
  763. }
  764. if (dialogTipsIsShow.value) {
  765. warningPopup.value.open()
  766. } else {
  767. // 直接提交,先弹出确认框
  768. prepareConfirm()
  769. }
  770. }
  771. const prepareConfirm = () => {
  772. // 计算手续费
  773. let feeAmount = 0
  774. if (channelData.value.feeTypeBank) {
  775. if (channelData.value.feeTypeBank === 1) feeAmount = Number(form.amount) * (Number(channelData.value.freeBank || 0) / 100)
  776. else if (channelData.value.feeTypeBank === 2) feeAmount = Number(channelData.value.feeAmountBank || 0)
  777. } else {
  778. if (channelData.value.feeType === 1) feeAmount = Number(form.amount) * (Number(channelData.value.free || 0) / 100)
  779. else if (channelData.value.feeType === 2) feeAmount = Number(channelData.value.feeAmount || 0)
  780. }
  781. dialogConfirmFee.value = feeAmount
  782. confirmPopup.value.open()
  783. }
  784. const submitConfirm = () => {
  785. confirmPopup.value.close()
  786. submit()
  787. }
  788. const submitAfterWarning = () => {
  789. warningPopup.value.close()
  790. prepareConfirm()
  791. }
  792. const submit = async () => {
  793. if (flag.value) return
  794. flag.value = true
  795. waitPopup.value.open()
  796. const params = {
  797. login: loginValue.value,
  798. payType: channelData.value.code,
  799. ...form
  800. }
  801. // 根据不同通道类型调用不同接口
  802. let res = null
  803. if (channelData.value.type === 'DIGITAL_CURRENCY') {
  804. if (!emailCode.value) {
  805. waitPopup.value.close()
  806. codePopup.value.open()
  807. flag.value = false
  808. return
  809. }
  810. params.emailCode = emailCode.value
  811. res = await financialApi.WithdrawAapplyDigitalCurrency(channelData.value.requestUrl, params)
  812. } else if (['CHANNEL_TYPE_WALLET', 'UCARD_WALLET', 'CHANNEL_TYPE_ALI_WALLET'].includes(channelData.value.type)) {
  813. res = await financialApi.WithdrawAapplyDigitalCurrency(channelData.value.requestUrl, params)
  814. } else if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.value.type)) {
  815. res = await financialApi.WithdrawApplyBank(channelData.value.requestUrl, params)
  816. }
  817. waitPopup.value.close()
  818. if (res && res.code === Code.StatusOK) {
  819. dialogSuccess.value = true
  820. dialogMessage.value = t('ApplicationDialog.Des1')
  821. resultPopup.value.open()
  822. } else {
  823. dialogSuccess.value = false
  824. dialogMessage.value = res?.msg || t('ApplicationDialog.Des2')
  825. resultPopup.value.open()
  826. }
  827. flag.value = false
  828. }
  829. const getCode = async () => {
  830. if (getCodeString.value !== t('signup.form.getCode')) return
  831. const res = await financialApi.withdrawCode({})
  832. if (res.code === Code.StatusOK) {
  833. uni.showToast({ title: t('Msg.CodeSuccess'), icon: 'none' })
  834. startCountdown()
  835. } else {
  836. uni.showToast({ title: res.msg, icon: 'none' })
  837. }
  838. }
  839. const startCountdown = () => {
  840. getCodeString.value = `${t('signup.form.waitCode1')}${countdown}${t('signup.form.waitCode2')}`
  841. timer = setInterval(() => {
  842. countdown--
  843. if (countdown <= 0) {
  844. clearInterval(timer)
  845. timer = null
  846. countdown = 59
  847. getCodeString.value = t('signup.form.getCode')
  848. } else {
  849. getCodeString.value = `${t('signup.form.waitCode1')}${countdown}${t('signup.form.waitCode2')}`
  850. }
  851. }, 1000)
  852. }
  853. const submitCode = () => {
  854. if (!emailCode.value) {
  855. uni.showToast({ title: t('vaildate.code.empty'), icon: 'none' })
  856. return
  857. }
  858. codePopup.value.close()
  859. submit()
  860. }
  861. const openAddBankCard = (type) => {
  862. openType.value = type
  863. dialogInfoTradingAdd.value = true
  864. }
  865. const closeAdd = (val) => {
  866. dialogInfoTradingAdd.value = val
  867. }
  868. const confirmToReload = () => {
  869. dialogInfoTradingAdd.value = false
  870. getBankInfo()
  871. }
  872. const closeConfirmPopup = () => confirmPopup.value.close()
  873. const closeWarningPopup = () => warningPopup.value.close()
  874. const closeResultPopup = () => {
  875. resultPopup.value.close()
  876. if (dialogSuccess.value) {
  877. // 重置状态
  878. showTable()
  879. step2.value = false
  880. step3.value = false
  881. isStep3.value = false
  882. selectedAccountIndex.value = -1
  883. selectedAccountLabel.value = ''
  884. loginValue.value = null
  885. }
  886. }
  887. const closeTipPopup = () => tipPopup.value.close()
  888. const closeCodePopup = () => codePopup.value.close()
  889. // 预览图片
  890. const previewImage = (url) => {
  891. uni.previewImage({ urls: [url] })
  892. }
  893. // 生命周期
  894. onLoad(() => {
  895. getDateList()
  896. getFreeNumber()
  897. isNewYear24Open()
  898. // 计算 isFree 时间判断,原逻辑略
  899. isFree.value = true // 根据实际需求
  900. getDepositList()
  901. })
  902. onUnmounted(() => {
  903. if (timer) clearInterval(timer)
  904. })
  905. </script>
  906. <style lang="scss" scoped>
  907. @import "@/uni.scss";
  908. .custom-withdraw {
  909. background: var(--color-zinc-50);
  910. min-height: 100vh;
  911. .box {
  912. margin-bottom: px2rpx(20);
  913. .b-card {
  914. background: #fff;
  915. border-radius: px2rpx(12);
  916. padding: px2rpx(20);
  917. box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.03);
  918. .card-top {
  919. .tit {
  920. font-size: px2rpx(16);
  921. font-weight: 600;
  922. margin-bottom: px2rpx(16);
  923. display: flex;
  924. align-items: center;
  925. color: var(--color-navy-900);
  926. position: relative;
  927. padding-left: 20px;
  928. &:after {
  929. content: '';
  930. position: absolute;
  931. left: 0;
  932. top: 50%;
  933. transform: translateY(-50%);
  934. width: 0;
  935. height: 0;
  936. border-top: 6px solid transparent;
  937. border-bottom: 6px solid transparent;
  938. border-left: 8px solid currentColor;
  939. }
  940. .iconfont {
  941. margin-right: px2rpx(8);
  942. color: var(--color-primary);
  943. font-size: px2rpx(18);
  944. }
  945. }
  946. }
  947. .channelType {
  948. font-size: px2rpx(15);
  949. font-weight: 600;
  950. margin: px2rpx(24) 0 px2rpx(12);
  951. color: var(--color-navy-700);
  952. padding-left: px2rpx(8);
  953. border-left: px2rpx(4) solid var(--color-primary);
  954. }
  955. }
  956. }
  957. .reselect-btn {
  958. margin-top: px2rpx(20);
  959. display: flex;
  960. justify-content: flex-end;
  961. }
  962. .s-btn {
  963. &.reselect {
  964. background-color: var(--color-zinc-100);
  965. color: var(--color-navy-700);
  966. border: none;
  967. font-size: px2rpx(14);
  968. padding: px2rpx(8) px2rpx(20);
  969. border-radius: px2rpx(8);
  970. &:active {
  971. background-color: var(--color-zinc-200);
  972. }
  973. }
  974. &[type="primary"] {
  975. width: 100%;
  976. height: px2rpx(48);
  977. background: var(--color-navy-900);
  978. color: #fff;
  979. border-radius: px2rpx(12);
  980. font-size: px2rpx(16);
  981. font-weight: 600;
  982. display: flex;
  983. align-items: center;
  984. justify-content: center;
  985. border: none;
  986. margin-top: px2rpx(30);
  987. transition: all 0.2s;
  988. &:active {
  989. transform: scale(0.98);
  990. background: var(--color-navy-800);
  991. }
  992. }
  993. }
  994. .add-back {
  995. display: flex;
  996. justify-content: space-between;
  997. align-items: center;
  998. margin-bottom: px2rpx(12);
  999. padding: px2rpx(12) px2rpx(16);
  1000. background: var(--color-zinc-100);
  1001. border-radius: px2rpx(8);
  1002. text {
  1003. font-size: px2rpx(14);
  1004. color: var(--color-navy-700);
  1005. font-weight: 500;
  1006. }
  1007. .add-btn {
  1008. color: var(--color-primary);
  1009. font-weight: 600;
  1010. text-decoration: underline;
  1011. &:active {
  1012. opacity: 0.7;
  1013. }
  1014. }
  1015. }
  1016. .proof {
  1017. margin-top: px2rpx(8);
  1018. border: px2rpx(1) dashed var(--color-zinc-300);
  1019. border-radius: px2rpx(8);
  1020. padding: px2rpx(8);
  1021. display: flex;
  1022. justify-content: center;
  1023. align-items: center;
  1024. background: var(--color-zinc-50);
  1025. .state {
  1026. padding: px2rpx(4) px2rpx(12);
  1027. border-radius: px2rpx(4);
  1028. font-size: px2rpx(12);
  1029. font-weight: bold;
  1030. }
  1031. }
  1032. .agree {
  1033. margin: px2rpx(24) 0;
  1034. display: flex;
  1035. align-items: flex-start;
  1036. .checkbox {
  1037. display: flex;
  1038. align-items: flex-start;
  1039. gap: px2rpx(8);
  1040. :deep(uni-checkbox .uni-checkbox-input) {
  1041. border-radius: px2rpx(4);
  1042. width: px2rpx(18);
  1043. height: px2rpx(18);
  1044. }
  1045. text {
  1046. font-size: px2rpx(13);
  1047. color: var(--color-zinc-500);
  1048. line-height: 1.5;
  1049. }
  1050. }
  1051. }
  1052. .step3-attention {
  1053. background: var(--color-error-50, #fff1f0);
  1054. border-radius: px2rpx(12);
  1055. padding: px2rpx(16);
  1056. margin-bottom: px2rpx(20);
  1057. .attention {
  1058. font-size: px2rpx(14);
  1059. color: var(--color-error-600, #cf1322);
  1060. line-height: 1.6;
  1061. }
  1062. .btn-bottom {
  1063. margin-top: px2rpx(20);
  1064. display: flex;
  1065. justify-content: center;
  1066. .btn {
  1067. background: var(--color-error-600, #cf1322);
  1068. color: #fff;
  1069. padding: px2rpx(10) px2rpx(48);
  1070. border-radius: px2rpx(24);
  1071. font-size: px2rpx(15);
  1072. font-weight: 700;
  1073. box-shadow: 0 px2rpx(4) px2rpx(10) rgba(207, 19, 34, 0.2);
  1074. transition: all 0.2s;
  1075. &:active {
  1076. transform: scale(0.96);
  1077. opacity: 0.8;
  1078. }
  1079. }
  1080. }
  1081. }
  1082. :deep(.base-info-form) {
  1083. .uni-row1 {
  1084. .uni-col {
  1085. padding: 0 px2rpx(10) !important;
  1086. }
  1087. .uni-forms-item {
  1088. min-height: px2rpx(79);
  1089. margin-bottom: px2rpx(10);
  1090. }
  1091. .uni-select,
  1092. .uni-combox,
  1093. .uni-easyinput__content,
  1094. .uni-date-editor--x {
  1095. border: none !important;
  1096. background-color: var(--color-zinc-100) !important;
  1097. border-radius: px2rpx(8) !important;
  1098. }
  1099. .uni-date-x {
  1100. border: none !important;
  1101. background-color: rgba(195, 195, 195, 0) !important;
  1102. }
  1103. .uni-easyinput__content-input {
  1104. height: px2rpx(44) !important;
  1105. }
  1106. }
  1107. }
  1108. /* 弹窗样式美化 */
  1109. :deep(.uni-popup__wrapper) {
  1110. .popup-content {
  1111. background-color: #fff;
  1112. border-radius: px2rpx(20);
  1113. padding: px2rpx(24);
  1114. width: px2rpx(320);
  1115. .popup-title {
  1116. font-size: px2rpx(18);
  1117. font-weight: 700;
  1118. text-align: center;
  1119. margin-bottom: px2rpx(20);
  1120. color: var(--color-navy-900);
  1121. display: block;
  1122. }
  1123. .popup-text {
  1124. font-size: px2rpx(14);
  1125. line-height: 1.6;
  1126. color: var(--color-zinc-600);
  1127. margin-bottom: px2rpx(20);
  1128. display: block;
  1129. }
  1130. .popup-form {
  1131. background: var(--color-zinc-50);
  1132. border-radius: px2rpx(12);
  1133. padding: px2rpx(16);
  1134. margin-bottom: px2rpx(24);
  1135. .popup-row {
  1136. display: flex;
  1137. justify-content: space-between;
  1138. margin-bottom: px2rpx(12);
  1139. font-size: px2rpx(14);
  1140. &:last-child {
  1141. margin-bottom: 0;
  1142. }
  1143. .label {
  1144. color: var(--color-zinc-500);
  1145. }
  1146. text:not(.label) {
  1147. color: var(--color-navy-900);
  1148. font-weight: 500;
  1149. }
  1150. }
  1151. }
  1152. .popup-buttons {
  1153. display: flex;
  1154. gap: px2rpx(12);
  1155. button {
  1156. flex: 1;
  1157. height: px2rpx(44);
  1158. border-radius: px2rpx(10);
  1159. font-size: px2rpx(15);
  1160. font-weight: 600;
  1161. display: flex;
  1162. align-items: center;
  1163. justify-content: center;
  1164. border: none;
  1165. &[type="primary"] {
  1166. background: var(--color-navy-900);
  1167. color: #fff;
  1168. }
  1169. &:not([type="primary"]) {
  1170. background: var(--color-zinc-100);
  1171. color: var(--color-zinc-600);
  1172. }
  1173. }
  1174. }
  1175. .result-icon {
  1176. display: flex;
  1177. justify-content: center;
  1178. margin-bottom: px2rpx(16);
  1179. .iconfont {
  1180. font-size: px2rpx(48);
  1181. &.iconchenggong {
  1182. color: #52c41a;
  1183. }
  1184. &.iconjingshi {
  1185. color: #faad14;
  1186. }
  1187. &.icondengdai {
  1188. color: var(--color-primary);
  1189. animation: rotate 2s linear infinite;
  1190. }
  1191. }
  1192. }
  1193. .code-input {
  1194. background: var(--color-zinc-100);
  1195. border: none;
  1196. border-radius: px2rpx(8);
  1197. padding: px2rpx(12);
  1198. margin-bottom: px2rpx(12);
  1199. font-size: px2rpx(15);
  1200. }
  1201. .code-timer {
  1202. color: var(--color-primary);
  1203. font-size: px2rpx(13);
  1204. text-align: right;
  1205. margin-bottom: px2rpx(20);
  1206. font-weight: 500;
  1207. }
  1208. }
  1209. }
  1210. @keyframes rotate {
  1211. from {
  1212. transform: rotate(0deg);
  1213. }
  1214. to {
  1215. transform: rotate(360deg);
  1216. }
  1217. }
  1218. }
  1219. </style>