|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <ion-page>
|
|
|
+ <ion-page class="wallet-page">
|
|
|
<ion-header>
|
|
|
<ion-toolbar>
|
|
|
<ion-buttons slot="start">
|
|
|
@@ -15,9 +15,9 @@
|
|
|
>{{ balance.balance }}
|
|
|
</div>
|
|
|
<div class="label">{{ $t('balance.balance') }}</div>
|
|
|
- <div class="btn-record">
|
|
|
+ <div class="btn-record" @click="$router.push({ name: 'balanceRecord' })">
|
|
|
<img src="../assets/double_arrow_left.png" class="arrow" />
|
|
|
- <div>{{ $t('balance.record') }}</div>
|
|
|
+ <div>{{ $t('title.balanceRecord') }}</div>
|
|
|
<img src="../assets/double_arrow_right.png" class="arrow" />
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -28,11 +28,11 @@
|
|
|
class="amount-item"
|
|
|
v-for="item in amountOptions"
|
|
|
:key="item"
|
|
|
- :class="{ active: amount === item }"
|
|
|
- @click="amount = item"
|
|
|
+ :class="{ active: rechargeAmount === item }"
|
|
|
+ @click="rechargeAmount = item"
|
|
|
>
|
|
|
- <span class="sym">{{ $t('balance.symbol') }}</span
|
|
|
- >{{ item }}
|
|
|
+ <span class="sym">{{ $t('balance.symbol') }}</span>
|
|
|
+ {{ item }}
|
|
|
</div>
|
|
|
<div class="input-wrapper">
|
|
|
<span class="sym">{{ $t('balance.symbol') }}</span>
|
|
|
@@ -51,11 +51,61 @@
|
|
|
<ion-footer class="ion-no-border">
|
|
|
<ion-toolbar>
|
|
|
<div class="bottom-buttons">
|
|
|
- <ion-button color="light">{{ $t('balance.withdraw') }}</ion-button>
|
|
|
- <ion-button>{{ $t('balance.recharge') }}</ion-button>
|
|
|
+ <ion-button class="btn-withdraw" @click="showWithdrawModal = true">{{
|
|
|
+ $t('balance.withdraw')
|
|
|
+ }}</ion-button>
|
|
|
+ <ion-button class="btn-recharge" @click="confirmRecharge">{{ $t('balance.recharge') }}</ion-button>
|
|
|
</div>
|
|
|
</ion-toolbar>
|
|
|
</ion-footer>
|
|
|
+ <ion-modal
|
|
|
+ id="modal-withdraw"
|
|
|
+ :is-open="showWithdrawModal"
|
|
|
+ :initial-breakpoint="breakpoint"
|
|
|
+ :breakpoints="[0, breakpoint]"
|
|
|
+ @didDismiss="showWithdrawModal = false"
|
|
|
+ >
|
|
|
+ <ion-content :style="{ height: `${breakpoint * 100}%` }">
|
|
|
+ <div>
|
|
|
+ <div class="head">
|
|
|
+ <div class="title">{{ $t('balance.withdrawModalTitle') }}</div>
|
|
|
+ <div class="close" @click="showWithdrawModal = false">
|
|
|
+ <img src="@/assets/icon_close.svg" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="label">{{ $t('balance.withdrawAmount') }}</div>
|
|
|
+ <div class="desc">
|
|
|
+ {{ $t('balance.availableWidthdrawAmount') }}{{ $t('balance.symbol') }}{{ balance.balance }}
|
|
|
+ </div>
|
|
|
+ <div class="input-wrapper">
|
|
|
+ <span class="sym">{{ $t('balance.symbol') }}</span>
|
|
|
+ <ion-input
|
|
|
+ v-model="withdrawAmount"
|
|
|
+ :placeholder="$t('balance.withdrawInputTip')"
|
|
|
+ inputmode="decimal"
|
|
|
+ :size="36"
|
|
|
+ clearInput
|
|
|
+ ></ion-input>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <div class="item-label">{{ $t('balance.withdrawFee') }}</div>
|
|
|
+ <div class="value">{{ fee.fee }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <div class="item-label">{{ $t('balance.realReceipt') }}</div>
|
|
|
+ <div class="value">{{ fee.realReceipt }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="tip">
|
|
|
+ {{ $t('balance.withdrawFeeTip0') }}<span class="orange">{{ withdrawFeeRate * 100 + '%' }}</span
|
|
|
+ >{{ $t('balance.withdrawFeeTip1')
|
|
|
+ }}<span class="orange">{{ withdrawFeeLowRate * 100 + '%' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="footer">
|
|
|
+ <ion-button expand="block" @click="withdraw">{{ $t('balance.confirmWithdraw') }}</ion-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ion-content>
|
|
|
+ </ion-modal>
|
|
|
</ion-page>
|
|
|
</template>
|
|
|
<script>
|
|
|
@@ -63,17 +113,51 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
balance: {
|
|
|
- balance: 0
|
|
|
+ balance: 0,
|
|
|
+ feeFreeAllowances: 0
|
|
|
},
|
|
|
showRecharge: false,
|
|
|
- rechargeAmount: 999,
|
|
|
+ rechargeAmount: 100,
|
|
|
amountOptions: [100, 200, 300, 600, 800, 1000],
|
|
|
- amount: 100,
|
|
|
- customAmount: null
|
|
|
+ customAmount: null,
|
|
|
+ showWithdrawModal: false,
|
|
|
+ withdrawAmount: null,
|
|
|
+ withdrawFeeRate: 0.08,
|
|
|
+ withdrawFeeLowRate: 0.01,
|
|
|
+ breakpoint: Number((450 / window.innerHeight).toFixed(2))
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
this.getBalance()
|
|
|
+ this.$http.get('/sysConfig/get/withdraw_fee_rate').then(res => {
|
|
|
+ this.withdrawFeeRate = Number(res.value)
|
|
|
+ })
|
|
|
+ this.$http.get('/sysConfig/get/withdraw_fee_low_rate').then(res => {
|
|
|
+ this.withdrawFeeLowRate = Number(res.value)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ fee() {
|
|
|
+ const amount = Number(this.withdrawAmount)
|
|
|
+ if (!amount || this.withdrawAmount <= 0 || this.withdrawAmount > this.balance.balance) {
|
|
|
+ return {
|
|
|
+ fee: '-',
|
|
|
+ realReceipt: '-'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let fee
|
|
|
+ if (amount <= this.balance.feeFreeAllowances) {
|
|
|
+ fee = this.withdrawFeeLowRate * amount
|
|
|
+ } else {
|
|
|
+ fee =
|
|
|
+ this.withdrawFeeRate * (amount - this.balance.feeFreeAllowances) +
|
|
|
+ this.withdrawFeeLowRate * this.balance.feeFreeAllowances
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ fee: fee.toFixed(2),
|
|
|
+ realReceipt: (amount - fee).toFixed(2)
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
methods: {
|
|
|
getBalance() {
|
|
|
@@ -88,11 +172,32 @@ export default {
|
|
|
this.$toast.success('充值成功')
|
|
|
this.getBalance()
|
|
|
})
|
|
|
+ },
|
|
|
+ withdraw() {
|
|
|
+ const amount = Number(this.withdrawAmount)
|
|
|
+ if (!amount || this.withdrawAmount <= 0 || this.withdrawAmount > this.balance.balance) {
|
|
|
+ this.$toast.error(this.$t('balance.withdrawAmountError'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$toast.loading(this.$t('balance.withdrawing'))
|
|
|
+ this.$http
|
|
|
+ .post('/withdrawApply/apply', { amount })
|
|
|
+ .then(res => {
|
|
|
+ this.$toast.success(this.$t('balance.withdrawSuccess'))
|
|
|
+ this.getBalance()
|
|
|
+ this.showWithdrawModal = false
|
|
|
+ })
|
|
|
+ .catch(e => {
|
|
|
+ this.$toast.error(e.error)
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
<style lang="less" scoped>
|
|
|
+:deep(.wallet-page) {
|
|
|
+ --ion-color-primary: #477bff;
|
|
|
+}
|
|
|
.wallet-page {
|
|
|
background-color: white;
|
|
|
display: flex;
|
|
|
@@ -202,13 +307,118 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-ion-footer {
|
|
|
- background: var(--ion-item-background);
|
|
|
+:deep(ion-footer ion-toolbar) {
|
|
|
+ --background: var(--ion-color-step-0);
|
|
|
}
|
|
|
.bottom-buttons {
|
|
|
+ padding: 0 16px;
|
|
|
.f();
|
|
|
ion-button {
|
|
|
flex-grow: 1;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ion-button.btn-withdraw {
|
|
|
+ height: 38px;
|
|
|
+ --background: none;
|
|
|
+ --background-hover: rgba(var(--ion-color-light-contrast-rgb), 0.04);
|
|
|
+ --background-activated: rgba(var(--ion-color-light-contrast-rgb), 0.04);
|
|
|
+ --background-focused: rgba(var(--ion-color-light-contrast-rgb), 0.04);
|
|
|
+ --border-color: var(--ion-color-step-400);
|
|
|
+ --border-style: solid;
|
|
|
+ --border-width: 1px;
|
|
|
+ --color: var(--ion-color-step-400);
|
|
|
+ --border-radius: 4px;
|
|
|
+}
|
|
|
+ion-button.btn-recharge {
|
|
|
+ height: 38px;
|
|
|
+ margin-left: 20px;
|
|
|
+ --border-radius: 4px;
|
|
|
+}
|
|
|
+ion-modal#modal-withdraw {
|
|
|
+ --ion-color-primary: #477bff;
|
|
|
+ ion-content {
|
|
|
+ --background: var(--ion-color-step-0);
|
|
|
+ }
|
|
|
+ .head {
|
|
|
+ .f();
|
|
|
+ padding-left: 16px;
|
|
|
+ border-bottom: 1px solid var(--ion-color-step-50);
|
|
|
+ font-size: 14px;
|
|
|
+ .title {
|
|
|
+ flex-grow: 1;
|
|
|
+ color: var(--ion-color-text);
|
|
|
+ padding: 16px 0 10px 0;
|
|
|
+ }
|
|
|
+ .close {
|
|
|
+ padding: 16px 16px 10px 0;
|
|
|
+ img {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .label {
|
|
|
+ margin: 20px 0 0 16px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: bold;
|
|
|
+ line-height: 24px;
|
|
|
+ }
|
|
|
+ .desc {
|
|
|
+ margin: 2px 0 0 16px;
|
|
|
+ color: var(--ion-color-step-400);
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 22px;
|
|
|
+ }
|
|
|
+ .input-wrapper {
|
|
|
+ .f();
|
|
|
+ align-items: baseline;
|
|
|
+ margin: 12px 16px 0 16px;
|
|
|
+ background: var(--ion-color-step-50);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding-left: 16px;
|
|
|
+ .sym {
|
|
|
+ font-size: 17px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ ion-input {
|
|
|
+ font-size: 26px;
|
|
|
+ font-weight: bold;
|
|
|
+ --placeholder-font-weight: 400;
|
|
|
+ --placeholder-color: var(--ion-color-step-400);
|
|
|
+ ::-webkit-input-placeholder {
|
|
|
+ font-size: 18px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .item {
|
|
|
+ .f();
|
|
|
+ height: 54px;
|
|
|
+ border-bottom: 1px solid var(--ion-color-step-50);
|
|
|
+ margin: 0 16px;
|
|
|
+ color: var(--ion-color-step-400);
|
|
|
+ font-size: 14px;
|
|
|
+ .item-label {
|
|
|
+ flex-grow: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .tip {
|
|
|
+ margin-top: 14px;
|
|
|
+ padding: 0 16px;
|
|
|
+ line-height: 18px;
|
|
|
+ color: var(--ion-color-step-400);
|
|
|
+ font-size: 13px;
|
|
|
+ .orange {
|
|
|
+ color: #ff7f1f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .footer {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 9px 27px;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|