index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <div class="layout-padding">
  3. <div class="layout-padding-auto layout-padding-view">
  4. <el-row :gutter="20">
  5. <el-col :xs="24" :sm="20" :md="16" :lg="12" :xl="10">
  6. <el-card shadow="hover" class="apply-card">
  7. <template #header>
  8. <div class="card-header">
  9. <span class="card-title">{{ $t('settlement.applySettlement') }}</span>
  10. <span class="available-balance"
  11. >{{ $t('settlement.availableBalance') }}:<span class="balance-amount">¥{{ formatAmount(availableBalance) }}</span></span
  12. >
  13. </div>
  14. </template>
  15. <el-form :model="formData" :rules="rules" ref="formRef" label-width="120px">
  16. <el-form-item :label="$t('settlement.withdrawAmount')" prop="amount">
  17. <el-input-number
  18. v-model="formData.amount"
  19. :min="0"
  20. :controls="false"
  21. :placeholder="$t('settlement.withdrawAmountPlaceholder')"
  22. style="width: 100%"
  23. />
  24. </el-form-item>
  25. <el-form-item :label="$t('settlement.withdrawType')" prop="type">
  26. <el-radio-group v-model="formData.type">
  27. <el-radio :label="1">{{ $t('settlement.bankCard') }}</el-radio>
  28. <el-radio :label="2">{{ $t('settlement.usdt') }}</el-radio>
  29. </el-radio-group>
  30. </el-form-item>
  31. <el-form-item :label="$t('settlement.bankName')" prop="bankName" v-if="formData.type === 1">
  32. <el-input v-model="formData.bankName" :placeholder="$t('settlement.bankNamePlaceholder')" clearable />
  33. </el-form-item>
  34. <el-form-item :label="$t('settlement.bankAccount')" prop="bankAccount">
  35. <el-input v-model="formData.bankAccount" :placeholder="$t('settlement.bankAccountPlaceholder')" clearable />
  36. </el-form-item>
  37. <el-form-item :label="$t('settlement.realName')" prop="realName">
  38. <el-input v-model="formData.realName" :placeholder="$t('settlement.realNamePlaceholder')" clearable />
  39. </el-form-item>
  40. <el-form-item>
  41. <el-button type="primary" @click="handleSubmit" :loading="loading" size="large" style="width: 120px">
  42. {{ $t('settlement.submitApply') }}
  43. </el-button>
  44. <el-button @click="handleReset" size="large" style="width: 120px">{{ $t('common.resetBtn') }}</el-button>
  45. </el-form-item>
  46. </el-form>
  47. </el-card>
  48. </el-col>
  49. </el-row>
  50. </div>
  51. </div>
  52. </template>
  53. <script lang="ts" name="settlementApply" setup>
  54. import { applyWithdraw, getMerchantBalance } from '/@/api/settlement';
  55. import { useMessage } from '/@/hooks/message';
  56. import { useI18n } from 'vue-i18n';
  57. const { t } = useI18n();
  58. // 定义变量
  59. const formRef = ref();
  60. const loading = ref(false);
  61. const availableBalance = ref(0);
  62. const formData = ref({
  63. amount: null,
  64. type: 1,
  65. bankName: '',
  66. bankAccount: '',
  67. realName: '',
  68. });
  69. // 表单验证规则
  70. const rules = computed(() => ({
  71. amount: [{ required: true, message: t('settlement.withdrawAmountPlaceholder'), trigger: 'blur' }],
  72. type: [{ required: true, message: t('settlement.withdrawType'), trigger: 'change' }],
  73. bankName: [{ required: true, message: t('settlement.bankNamePlaceholder'), trigger: 'blur' }],
  74. bankAccount: [{ required: true, message: t('settlement.bankAccountPlaceholder'), trigger: 'blur' }],
  75. realName: [{ required: true, message: t('settlement.realNamePlaceholder'), trigger: 'blur' }],
  76. }));
  77. // 提交申请
  78. const handleSubmit = async () => {
  79. try {
  80. await formRef.value?.validate();
  81. // 验证提现金额不能超过可提现金额
  82. if (formData.value.amount && formData.value.amount > availableBalance.value) {
  83. useMessage().error(`${t('settlement.exceedBalance')} ¥${formatAmount(availableBalance.value)}`);
  84. return;
  85. }
  86. loading.value = true;
  87. const submitData: any = {
  88. amount: formData.value.amount,
  89. type: formData.value.type,
  90. bankAccount: formData.value.bankAccount,
  91. realName: formData.value.realName,
  92. };
  93. // 银行卡类型才需要银行名称
  94. if (formData.value.type === 1) {
  95. submitData.bankName = formData.value.bankName;
  96. }
  97. await applyWithdraw(submitData);
  98. useMessage().success(t('settlement.applySuccess'));
  99. handleReset();
  100. } catch (err: any) {
  101. if (err.msg) {
  102. useMessage().error(err.msg);
  103. }
  104. } finally {
  105. loading.value = false;
  106. }
  107. };
  108. // 重置表单
  109. const handleReset = () => {
  110. formRef.value?.resetFields();
  111. formData.value = {
  112. amount: null,
  113. type: 1,
  114. bankName: '',
  115. bankAccount: '',
  116. realName: '',
  117. };
  118. };
  119. // 加载商户余额
  120. const loadBalance = async () => {
  121. try {
  122. const res = await getMerchantBalance();
  123. if (res.code === 0 && res.data) {
  124. availableBalance.value = res.data.totalUseAmount || 0;
  125. }
  126. } catch (err) {
  127. // 加载余额失败
  128. }
  129. };
  130. // 格式化金额
  131. const formatAmount = (amount: number) => {
  132. return amount ? amount.toFixed(2) : '0.00';
  133. };
  134. // 页面加载时获取余额
  135. onMounted(() => {
  136. loadBalance();
  137. });
  138. </script>
  139. <style scoped lang="scss">
  140. .apply-card {
  141. margin-top: 20px;
  142. }
  143. .card-header {
  144. display: flex;
  145. justify-content: space-between;
  146. align-items: center;
  147. .card-title {
  148. font-size: 18px;
  149. font-weight: bold;
  150. color: #303133;
  151. }
  152. .available-balance {
  153. font-size: 14px;
  154. color: #606266;
  155. .balance-amount {
  156. font-size: 18px;
  157. font-weight: bold;
  158. color: #f56c6c;
  159. margin-left: 5px;
  160. }
  161. }
  162. }
  163. :deep(.el-form) {
  164. padding: 20px 0;
  165. }
  166. :deep(.el-form-item) {
  167. margin-bottom: 28px;
  168. }
  169. :deep(.el-input-number) {
  170. width: 100%;
  171. .el-input__inner {
  172. text-align: left;
  173. }
  174. }
  175. :deep(.el-input__inner) {
  176. height: 40px;
  177. line-height: 40px;
  178. }
  179. :deep(.el-radio) {
  180. margin-right: 30px;
  181. }
  182. </style>