withdrawal.vue 46 KB

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