AddBankDialog.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <template>
  2. <uni-popup ref="popupRef" type="center" background-color="#fff">
  3. <view class="dialog-container">
  4. <view class="dialog-header">
  5. <text class="dialog-title" v-t="typeMap[form.type]"></text>
  6. <view class="dialog-close" @click="close">
  7. <text>×</text>
  8. </view>
  9. </view>
  10. <uni-forms ref="formRef" :rules="rules" :model="form" labelWidth="200" label-position="top"
  11. class="crm-form">
  12. <uni-row class="form-row uni-row1">
  13. <template v-if="form.type === 1">
  14. <uni-col :xs="24">
  15. <uni-forms-item>
  16. <cwg-file-picker v-model="form.bankFront" :editable="editingId === form.id" :limit="1"
  17. uploadUrl="/custom/bank/upload" :baseUrl="updateUrl" :imageWidth="150"
  18. :imageHeight="150" uploadText="点击上传" replaceText="点击替换" noImageText="暂无图片"
  19. :showPreviewDelete="editingId === form.id"
  20. @update:modelValue="(val) => handleFileUpdate(val, form, 'bankFront')" />
  21. </uni-forms-item>
  22. </uni-col>
  23. <uni-col :xs="24">
  24. <uni-forms-item :label="t('PersonalManagement.Label.BankAccountName')">
  25. <uni-easyinput :clearable="false" v-model="form.bankUname"
  26. :placeholder="locale == 'es' ? 'Introduzca el nombre de la red' : t('placeholder.input')" />
  27. </uni-forms-item>
  28. </uni-col>
  29. <uni-col :xs="24">
  30. <uni-forms-item :label="t('PersonalManagement.Label.BankName')">
  31. <cwg-combox :clearable="false" :filterable="true" v-model:value="form.bankName"
  32. :options="bankOptions" :placeholder="t('placeholder.choose')"
  33. @change="onStateChange" />
  34. </uni-forms-item>
  35. </uni-col>
  36. <uni-col :xs="24">
  37. <uni-forms-item :label="t('PersonalManagement.Label.BankAccount')">
  38. <uni-easyinput :clearable="false" v-model="form.bankCardNum"
  39. :placeholder="locale == 'es' ? 'Introduzca la dirección de la billetera' : t('placeholder.input')" />
  40. </uni-forms-item>
  41. </uni-col>
  42. <uni-col :xs="24">
  43. <uni-forms-item :label="t('PersonalManagement.Label.AccountOpeningBranch')">
  44. <uni-easyinput :clearable="false" v-model="form.bankBranchName"
  45. :placeholder="locale == 'es' ? 'Introduzca la dirección de la billetera' : t('placeholder.input')" />
  46. </uni-forms-item>
  47. </uni-col>
  48. </template>
  49. <template v-if="form.type === 4">
  50. <!-- 区块链名称 -->
  51. <uni-col :xs="24">
  52. <uni-forms-item prop="addressName" :label="t('blockchain.item3')">
  53. <uni-easyinput :clearable="false" v-model="form.addressName"
  54. :placeholder="t('placeholder.input')" />
  55. </uni-forms-item>
  56. </uni-col>
  57. <!-- 钱包地址 -->
  58. <uni-col :xs="24">
  59. <uni-forms-item prop="address" :label="t('blockchain.item4')">
  60. <uni-easyinput :clearable="false" v-model="form.address"
  61. :placeholder="t('placeholder.input')" />
  62. </uni-forms-item>
  63. </uni-col>
  64. </template>
  65. <template v-if="form.type === 2">
  66. <uni-col :xs="24">
  67. <uni-forms-item :label="t('PersonalManagement.Label.BankAccountName')">
  68. <uni-easyinput :clearable="false" v-model="form.bankUname" :disabled="true"
  69. :placeholder="locale == 'es' ? 'Introduzca el nombre de la red' : t('placeholder.input')" />
  70. </uni-forms-item>
  71. </uni-col>
  72. <uni-col :xs="24">
  73. <uni-forms-item :label="t('PersonalManagement.Label.BankAccount')">
  74. <uni-easyinput :clearable="false" v-model="form.bankCardNum"
  75. :placeholder="locale == 'es' ? 'Introduzca la dirección de la billetera' : t('placeholder.input')" />
  76. </uni-forms-item>
  77. </uni-col>
  78. <uni-col :xs="24">
  79. <uni-forms-item :label="t('PersonalManagement.Label.BankName')">
  80. <uni-easyinput :clearable="false" v-model="form.bankName"
  81. :placeholder="locale == 'es' ? 'Introduzca el nombre del banco' : t('placeholder.input')" />
  82. </uni-forms-item>
  83. </uni-col>
  84. <uni-col :xs="24">
  85. <uni-forms-item :label="t('PersonalManagement.Label.BankAddress')">
  86. <uni-easyinput :clearable="false" v-model="form.bankAddr"
  87. :placeholder="locale == 'es' ? 'Introduzca la dirección del banco' : t('placeholder.input')" />
  88. </uni-forms-item>
  89. </uni-col>
  90. <uni-col :xs="24">
  91. <uni-forms-item :label="t('PersonalManagement.Label.SwiftBIC')">
  92. <uni-easyinput :clearable="false" v-model="form.swiftCode"
  93. :placeholder="locale == 'es' ? 'Introduzca el SWIFT/BIC' : t('placeholder.input')" />
  94. </uni-forms-item>
  95. </uni-col>
  96. <uni-col :xs="24">
  97. <uni-forms-item :label="t('PersonalManagement.Label.BankCode')">
  98. <uni-easyinput :clearable="false" v-model="form.bankCode"
  99. :placeholder="locale == 'es' ? 'Introduzca el código del banco' : t('placeholder.input')" />
  100. </uni-forms-item>
  101. </uni-col>
  102. <uni-col :xs="24">
  103. <uni-forms-item
  104. :label="locale == 'es' ? 'Número de sucursal (opcional)' : 'Account Agency NO'">
  105. <uni-easyinput :clearable="false" v-model="form.agencyNo"
  106. :placeholder="locale == 'es' ? 'Introduzca el número de sucursal' : t('placeholder.input')" />
  107. </uni-forms-item>
  108. </uni-col>
  109. </template>
  110. <template v-if="form.type === 3">
  111. <uni-col :xs="24">
  112. <uni-forms-item :label="t('PersonalManagement.Label.CreditCardAccountName')">
  113. <uni-easyinput :clearable="false" v-model="form.bankUname" :disabled="true"
  114. :placeholder="t('placeholder.input')" />
  115. </uni-forms-item>
  116. </uni-col>
  117. <uni-col :xs="24">
  118. <uni-forms-item :label="t('PersonalManagement.Label.CreditCardAccount')">
  119. <uni-easyinput :clearable="false" v-model="form.bankCardNum"
  120. :placeholder="locale == 'es' ? 'Introduzca el número de tarjeta' : t('placeholder.input')" />
  121. </uni-forms-item>
  122. </uni-col>
  123. <uni-col :xs="24">
  124. <uni-forms-item :label="t('PersonalManagement.Label.ExpirationYear')">
  125. <uni-easyinput :clearable="false" v-model="form.expiryYearMonth"
  126. :placeholder="locale == 'es' ? 'Introduzca MM/AA' : t('placeholder.input')" />
  127. </uni-forms-item>
  128. </uni-col>
  129. <uni-col :xs="24">
  130. <uni-forms-item :label="t('CVV')">
  131. <uni-easyinput :clearable="false" v-model="form.cvv"
  132. :placeholder="locale == 'es' ? 'Introduzca el CVV' : t('placeholder.input')" />
  133. </uni-forms-item>
  134. </uni-col>
  135. </template>
  136. <uni-col :xs="24">
  137. <uni-forms-item class="checkbox-item" prop="defaultBank">
  138. <uni-data-checkbox v-model="form.defaultBank" multiple :localdata="hobbys" />
  139. </uni-forms-item>
  140. </uni-col>
  141. </uni-row>
  142. </uni-forms>
  143. <view class="dialog-footer">
  144. <view class="btn btn-cancel" @click="close">{{ t('Btn.Cancel') }}</view>
  145. <view class="btn btn-confirm" @click="submit">{{ t('Btn.Confirm') }}</view>
  146. </view>
  147. </view>
  148. </uni-popup>
  149. </template>
  150. <script setup lang="ts">
  151. import { ref, nextTick, computed, onMounted } from 'vue';
  152. import { useI18n } from 'vue-i18n';
  153. import { Validators } from '@/utils/validators';
  154. import { personalApi } from '@/service/personal';
  155. const { t, locale } = useI18n();
  156. const typeMap = {
  157. 4: 'blockchain.item2',
  158. 1: 'PersonalManagement.Title.ChinaUnionPayCard',
  159. 2: 'PersonalManagement.Title.BankWireTransfer',
  160. 3: 'PersonalManagement.Label.CreditCard'
  161. }
  162. interface AddBankForm {
  163. addressName: string;
  164. address: string;
  165. checkboxGroup: string[];
  166. }
  167. const hobbys = computed(() => {
  168. let value = [
  169. { value: 1, text: t('blockchain.item8') },
  170. ]
  171. switch (form.value.type){
  172. case 1:
  173. value = [
  174. { value: 1, text: t('PersonalManagement.Title.DefaultBank') },
  175. ]
  176. break;
  177. case 2:
  178. value = [
  179. { value: 1, text: t('PersonalManagement.Title.DefaultWire') },
  180. ]
  181. break;
  182. case 3:
  183. value = [
  184. { value: 1, text: t('PersonalManagement.Title.DefaultCredit') },
  185. ]
  186. break;
  187. case 4:
  188. value = [
  189. { value: 1, text: t('blockchain.item8') },
  190. ]
  191. break;
  192. }
  193. return value
  194. });
  195. const emit = defineEmits(["success"]);
  196. const popupRef = ref<any>(null);
  197. const formRef = ref<any>(null);
  198. const form = ref<AddBankForm>({});
  199. const rules = {
  200. addressName: [Validators.required(t('blockchain.item3') + t('common.cannotbeempty'))],
  201. address: [Validators.required(t('blockchain.item4') + t('common.cannotbeempty'))]
  202. };
  203. // 打开弹窗
  204. const open = async (type: number) => {
  205. form.value = {}
  206. await nextTick();
  207. form.value.type = type;
  208. getBankList()
  209. popupRef.value?.open();
  210. };
  211. // 关闭弹窗
  212. const close = () => {
  213. popupRef.value?.close();
  214. resetForm();
  215. };
  216. // 重置表单
  217. const resetForm = () => {
  218. form.value = {};
  219. formRef.value?.clearValidate();
  220. };
  221. // 提交表单
  222. const submit = async () => {
  223. try {
  224. // 校验表单
  225. const valid = await formRef.value?.validate();
  226. if (!valid) {
  227. return;
  228. }
  229. // 调用 API 添加钱包
  230. const submitData = {
  231. ...form.value,
  232. expiryYear: form.value?.expiryYearMonth ? form.value.expiryYearMonth.split("/")[0] : undefined,
  233. expiryMonth: form.value?.expiryYearMonth ? form.value.expiryYearMonth.split("/")[1] : undefined,
  234. defaultBank: form.value?.defaultBank && form.value?.defaultBank[0] ? 1 : 0,
  235. };
  236. let res = await personalApi.customBankAdd({
  237. bankUname: 'username',
  238. ...submitData,
  239. });
  240. if (res.code == 200) {
  241. uni.showToast({ title: t('Msg.Success'), icon: 'success' });
  242. emit("success", res.data);
  243. } else {
  244. uni.showToast({ title: res.msg || t('common.error'), icon: 'none' });
  245. }
  246. close();
  247. } catch (error: any) {
  248. console.log(error);
  249. uni.showToast({ title: error.message || error.msg || t('common.error'), icon: 'none' });
  250. }
  251. };
  252. const bankList = ref([])
  253. const isZh = computed(() => ['cn', 'zh', 'zhHant'].includes(locale.value));
  254. const getLangName = (item: any) => (isZh.value ? item.name : item.enName);
  255. const createOptions = (list: any[], valueKey = 'code') => {
  256. return list.map((item) => ({
  257. text: getLangName(item),
  258. value: getLangName(item)
  259. }));
  260. };
  261. const bankOptions = computed(() => createOptions(bankList.value, 'name'));
  262. // 获取银行列表
  263. const getBankList = async () => {
  264. const res = await personalApi.BankList({})
  265. if (res.code === 200) {
  266. bankList.value = res.data
  267. }
  268. }
  269. // 文件更新处理
  270. const handleFileUpdate = (newValue, item, field) => {
  271. item[field] = newValue
  272. }
  273. // 暴露方法
  274. defineExpose({
  275. open,
  276. close
  277. });
  278. </script>
  279. <style scoped lang="scss">
  280. @import "@/uni.scss";
  281. .dialog-container {
  282. width: 80vw;
  283. max-width: px2rpx(800);
  284. max-height: 85vh;
  285. padding: px2rpx(24);
  286. overflow: hidden;
  287. border-radius: px2rpx(12);
  288. .dialog-header {
  289. display: flex;
  290. justify-content: space-between;
  291. align-items: center;
  292. margin-bottom: px2rpx(24);
  293. padding-bottom: px2rpx(16);
  294. border-bottom: 1px solid #f3f4f6;
  295. .dialog-title {
  296. font-size: px2rpx(18);
  297. font-weight: 600;
  298. color: #1f2937;
  299. }
  300. .dialog-close {
  301. width: px2rpx(32);
  302. height: px2rpx(32);
  303. display: flex;
  304. align-items: center;
  305. justify-content: center;
  306. font-size: px2rpx(28);
  307. color: #9ca3af;
  308. cursor: pointer;
  309. transition: all 0.3s;
  310. &:hover {
  311. color: #1f2937;
  312. }
  313. }
  314. }
  315. .dialog-footer {
  316. display: flex;
  317. gap: px2rpx(12);
  318. justify-content: flex-end;
  319. padding-top: px2rpx(16);
  320. border-top: 1px solid #f3f4f6;
  321. .btn {
  322. min-width: px2rpx(120);
  323. padding: px2rpx(12) px2rpx(24);
  324. border-radius: px2rpx(6);
  325. font-size: px2rpx(14);
  326. font-weight: 600;
  327. border: none;
  328. cursor: pointer;
  329. text-align: center;
  330. transition: all 0.3s;
  331. display: flex;
  332. align-items: center;
  333. justify-content: center;
  334. &.btn-cancel {
  335. background: #f3f4f6;
  336. color: #6b7280;
  337. &:hover {
  338. background: #e5e7eb;
  339. }
  340. &:active {
  341. background: #d1d5db;
  342. }
  343. }
  344. &.btn-confirm {
  345. background: #ea2027;
  346. color: #fff;
  347. &:hover {
  348. background: #d11920;
  349. }
  350. &:active {
  351. background: #c01819;
  352. }
  353. }
  354. }
  355. }
  356. .crm-form {
  357. overflow-y: auto;
  358. max-height: 70vh;
  359. }
  360. }
  361. </style>