AddBankDialog.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. { value: 1, text: t('blockchain.item8') }
  169. ]);
  170. const emit = defineEmits(["success"]);
  171. const popupRef = ref<any>(null);
  172. const formRef = ref<any>(null);
  173. const form = ref<AddBankForm>({});
  174. const rules = {
  175. addressName: [Validators.required(t('blockchain.item3') + t('common.cannotbeempty'))],
  176. address: [Validators.required(t('blockchain.item4') + t('common.cannotbeempty'))]
  177. };
  178. // 打开弹窗
  179. const open = async (type: number) => {
  180. form.value = {}
  181. await nextTick();
  182. form.value.type = type;
  183. getBankList()
  184. popupRef.value?.open();
  185. };
  186. // 关闭弹窗
  187. const close = () => {
  188. popupRef.value?.close();
  189. resetForm();
  190. };
  191. // 重置表单
  192. const resetForm = () => {
  193. form.value = {};
  194. formRef.value?.clearValidate();
  195. };
  196. // 提交表单
  197. const submit = async () => {
  198. try {
  199. // 校验表单
  200. const valid = await formRef.value?.validate();
  201. if (!valid) {
  202. return;
  203. }
  204. // 调用 API 添加钱包
  205. const submitData = {
  206. ...form.value,
  207. expiryYear: form.value?.expiryYearMonth ? form.value.expiryYearMonth.split("/")[0] : undefined,
  208. expiryMonth: form.value?.expiryYearMonth ? form.value.expiryYearMonth.split("/")[1] : undefined,
  209. defaultBank: form.value?.defaultBank && form.value?.defaultBank[0] ? 1 : 0,
  210. };
  211. let res = await personalApi.customBankAdd({
  212. bankUname: 'username',
  213. ...submitData,
  214. });
  215. if (res.code == 200) {
  216. uni.showToast({ title: t('Msg.Success'), icon: 'success' });
  217. emit("success", res.data);
  218. } else {
  219. uni.showToast({ title: res.msg || t('common.error'), icon: 'none' });
  220. }
  221. close();
  222. } catch (error: any) {
  223. console.log(error);
  224. uni.showToast({ title: error.message || error.msg || t('common.error'), icon: 'none' });
  225. }
  226. };
  227. const bankList = ref([])
  228. const isZh = computed(() => ['cn', 'zh', 'zhHant'].includes(locale.value));
  229. const getLangName = (item: any) => (isZh.value ? item.name : item.enName);
  230. const createOptions = (list: any[], valueKey = 'code') => {
  231. return list.map((item) => ({
  232. text: getLangName(item),
  233. value: getLangName(item)
  234. }));
  235. };
  236. const bankOptions = computed(() => createOptions(bankList.value, 'name'));
  237. // 获取银行列表
  238. const getBankList = async () => {
  239. const res = await personalApi.BankList({})
  240. if (res.code === 200) {
  241. bankList.value = res.data
  242. }
  243. }
  244. // 文件更新处理
  245. const handleFileUpdate = (newValue, item, field) => {
  246. item[field] = newValue
  247. }
  248. // 暴露方法
  249. defineExpose({
  250. open,
  251. close
  252. });
  253. </script>
  254. <style scoped lang="scss">
  255. @import "@/uni.scss";
  256. .dialog-container {
  257. width: 80vw;
  258. max-width: px2rpx(800);
  259. max-height: 85vh;
  260. padding: px2rpx(24);
  261. overflow: hidden;
  262. border-radius: px2rpx(12);
  263. .dialog-header {
  264. display: flex;
  265. justify-content: space-between;
  266. align-items: center;
  267. margin-bottom: px2rpx(24);
  268. padding-bottom: px2rpx(16);
  269. border-bottom: 1px solid #f3f4f6;
  270. .dialog-title {
  271. font-size: px2rpx(18);
  272. font-weight: 600;
  273. color: #1f2937;
  274. }
  275. .dialog-close {
  276. width: px2rpx(32);
  277. height: px2rpx(32);
  278. display: flex;
  279. align-items: center;
  280. justify-content: center;
  281. font-size: px2rpx(28);
  282. color: #9ca3af;
  283. cursor: pointer;
  284. transition: all 0.3s;
  285. &:hover {
  286. color: #1f2937;
  287. }
  288. }
  289. }
  290. .dialog-footer {
  291. display: flex;
  292. gap: px2rpx(12);
  293. justify-content: flex-end;
  294. padding-top: px2rpx(16);
  295. border-top: 1px solid #f3f4f6;
  296. .btn {
  297. min-width: px2rpx(120);
  298. padding: px2rpx(12) px2rpx(24);
  299. border-radius: px2rpx(6);
  300. font-size: px2rpx(14);
  301. font-weight: 600;
  302. border: none;
  303. cursor: pointer;
  304. text-align: center;
  305. transition: all 0.3s;
  306. display: flex;
  307. align-items: center;
  308. justify-content: center;
  309. &.btn-cancel {
  310. background: #f3f4f6;
  311. color: #6b7280;
  312. &:hover {
  313. background: #e5e7eb;
  314. }
  315. &:active {
  316. background: #d1d5db;
  317. }
  318. }
  319. &.btn-confirm {
  320. background: #ea2027;
  321. color: #fff;
  322. &:hover {
  323. background: #d11920;
  324. }
  325. &:active {
  326. background: #c01819;
  327. }
  328. }
  329. }
  330. }
  331. .crm-form {
  332. overflow-y: auto;
  333. max-height: 70vh;
  334. }
  335. }
  336. </style>