269 lines
7.0 KiB
Vue
269 lines
7.0 KiB
Vue
![]() |
<template>
|
|||
|
<view class="app-container">
|
|||
|
<HeaderBar title="我的钱包" text-align="center" enable-back/>
|
|||
|
|
|||
|
<view class="balance-container">
|
|||
|
|
|||
|
<!-- 余额卡片 -->
|
|||
|
<view class="balance-card">
|
|||
|
<view class="balance-label">
|
|||
|
<image class="balance-icon" src="https://api.ccttiot.com/78895797ae5a7b8114b52d18a0d16aa2efb0aa0155c86-t0tn1C%201-1746456527588.png" mode="aspectFit" />
|
|||
|
钱包余额
|
|||
|
</view>
|
|||
|
<view class="balance-amount">{{ balance | fix2 | dv }}</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<!-- 充值输入 -->
|
|||
|
<view class="recharge-section">
|
|||
|
<view class="recharge-label">充值金额</view>
|
|||
|
<input class="recharge-input" type="digit" v-model="rechargeAmount" placeholder="请输入要充值的金额" />
|
|||
|
<button class="recharge-btn" @click="onRecharge">立即充值</button>
|
|||
|
</view>
|
|||
|
|
|||
|
<!-- 余额变动记录 -->
|
|||
|
<view class="record-section">
|
|||
|
<view class="record-title">余额记录</view>
|
|||
|
<view class="record-item" v-for="item in recordList" :key="item.id">
|
|||
|
<view class="record-info">
|
|||
|
<view class="record-type">{{ item.reason | dv }}</view>
|
|||
|
<view class="record-time">{{ item.createTime | dv }}</view>
|
|||
|
</view>
|
|||
|
<view :class="['record-amount', item.amount > 0 ? 'plus' : 'minus']">
|
|||
|
{{ item.amount > 0 ? '+' : '' }}{{ item.amount | fix2 | dv }}
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<uni-load-more :status="loadStatus(loading, recordList.length, total)" />
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import { getMchDetail } from '@/api/app/mch'
|
|||
|
import HeaderBar from '@/components/HeaderBar.vue'
|
|||
|
import { mchListBalanceLog } from '@/api/mch/balanceLog'
|
|||
|
import { $loadList } from '@/utils/mixins'
|
|||
|
import { BalanceLogType } from '@/utils/enums'
|
|||
|
import { appCreateRechargeOrder } from '@/api/app/rechargeOrder'
|
|||
|
import { appRefreshPayResult } from '@/api/app/pay'
|
|||
|
import config from '@/config'
|
|||
|
|
|||
|
export default {
|
|||
|
mixins: [$loadList],
|
|||
|
components: {
|
|||
|
HeaderBar
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
balance: 0,
|
|||
|
BalanceLogType,
|
|||
|
rechargeAmount: '',
|
|||
|
recordList: [],
|
|||
|
loading: false,
|
|||
|
total: null,
|
|||
|
queryParams: {
|
|||
|
pageNum: 0,
|
|||
|
pageSize: 20,
|
|||
|
type: BalanceLogType.MCH_BALANCE,
|
|||
|
orderByColumn: 'createTime',
|
|||
|
isAsc: 'desc'
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
onLoad() {
|
|||
|
this.getBalance();
|
|||
|
this.getRecordList()
|
|||
|
},
|
|||
|
onReachBottom() {
|
|||
|
this.loadRecordList()
|
|||
|
},
|
|||
|
methods: {
|
|||
|
getBalance() {
|
|||
|
getMchDetail(this.$store.getters.mchId).then(res => {
|
|||
|
this.balance = res.data.balance;
|
|||
|
console.log(this.balance)
|
|||
|
})
|
|||
|
},
|
|||
|
getRecordList() {
|
|||
|
this.queryParams.pageNum = 0;
|
|||
|
this.queryParams.pageSize = 20;
|
|||
|
this.total = null;
|
|||
|
this.recordList = [];
|
|||
|
this.loadRecordList()
|
|||
|
},
|
|||
|
/**
|
|||
|
* 获取商户余额
|
|||
|
*/
|
|||
|
loadRecordList() {
|
|||
|
this.loadMore(() => {
|
|||
|
this.loading = true;
|
|||
|
this.queryParams.mchId = this.$store.getters.mchId
|
|||
|
this.queryParams.pageNum ++;
|
|||
|
// 假设商户余额字段为 balance,实际字段请根据后端返回调整
|
|||
|
mchListBalanceLog(this.queryParams).then(res => {
|
|||
|
this.recordList = this.recordList.push(...res.rows);
|
|||
|
this.total = res.total;
|
|||
|
})
|
|||
|
this.loading = false;
|
|||
|
}, this.loadStatus(this.loading, this.recordList.length, this.total))
|
|||
|
},
|
|||
|
/**
|
|||
|
* 充值操作
|
|||
|
*/
|
|||
|
onRecharge() {
|
|||
|
if (!this.rechargeAmount || Number(this.rechargeAmount) <= 0) {
|
|||
|
uni.showToast({ title: '请输入正确的充值金额', icon: 'none' })
|
|||
|
return
|
|||
|
}
|
|||
|
// 验证小数点后最多两位
|
|||
|
if (this.rechargeAmount.toString().split('.')[1]?.length > 2) {
|
|||
|
uni.showToast({ title: '充值金额最多支持两位小数', icon: 'none' })
|
|||
|
return
|
|||
|
}
|
|||
|
this.$modal.loading("充值中");
|
|||
|
appCreateRechargeOrder({
|
|||
|
mchId: this.$store.getters.mchId,
|
|||
|
amount: this.rechargeAmount,
|
|||
|
userId: this.$store.getters.userId,
|
|||
|
appId: config.appId,
|
|||
|
channelId: config.channelId
|
|||
|
}).then(res => {
|
|||
|
let payParams = res.data.payParams;
|
|||
|
wx.requestPayment({
|
|||
|
timeStamp: payParams.timeStamp,
|
|||
|
nonceStr: payParams.nonceStr,
|
|||
|
package: payParams.packageVal,
|
|||
|
signType: payParams.signType,
|
|||
|
paySign: payParams.paySign,
|
|||
|
success: () => {
|
|||
|
appRefreshPayResult(res.data.pay.no).finally(() => {
|
|||
|
this.getBalance()
|
|||
|
this.getRecordList()
|
|||
|
this.rechargeAmount = null;
|
|||
|
}).finally(() => {
|
|||
|
this.$modal.closeLoading();
|
|||
|
})
|
|||
|
},
|
|||
|
fail: () => {
|
|||
|
this.$modal.closeLoading();
|
|||
|
}
|
|||
|
});
|
|||
|
}).catch(() => {
|
|||
|
this.$modal.closeLoading();
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
.balance-container {
|
|||
|
padding: 24rpx ;
|
|||
|
}
|
|||
|
.balance-card {
|
|||
|
background: linear-gradient(180deg, #3486FF 0%, #0064F9 100%);
|
|||
|
border-radius: 20rpx;
|
|||
|
padding: 32rpx 32rpx 24rpx 32rpx;
|
|||
|
color: #fff;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: space-between;
|
|||
|
margin-bottom: 32rpx;
|
|||
|
.balance-label {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
font-size: 28rpx;
|
|||
|
.balance-icon {
|
|||
|
width: 64rpx;
|
|||
|
height: 64rpx;
|
|||
|
margin-right: 12rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
.balance-amount {
|
|||
|
font-size: 40rpx;
|
|||
|
font-weight: bold;
|
|||
|
letter-spacing: 2rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
.recharge-section {
|
|||
|
background: #fff;
|
|||
|
border-radius: 20rpx;
|
|||
|
padding: 32rpx;
|
|||
|
margin-bottom: 32rpx;
|
|||
|
.recharge-label {
|
|||
|
font-size: 28rpx;
|
|||
|
font-weight: 600;
|
|||
|
margin-bottom: 16rpx;
|
|||
|
}
|
|||
|
.recharge-input {
|
|||
|
width: 100%;
|
|||
|
height: 80rpx;
|
|||
|
border: 1rpx solid #dbe6ff;
|
|||
|
border-radius: 12rpx;
|
|||
|
padding: 0 24rpx;
|
|||
|
font-size: 30rpx;
|
|||
|
margin-bottom: 24rpx;
|
|||
|
background: #f7faff;
|
|||
|
box-sizing: border-box;
|
|||
|
}
|
|||
|
.recharge-btn {
|
|||
|
width: 100%;
|
|||
|
height: 80rpx;
|
|||
|
background: linear-gradient(180deg, #3486FF 0%, #0064F9 100%);
|
|||
|
color: #fff;
|
|||
|
font-size: 32rpx;
|
|||
|
border: none;
|
|||
|
border-radius: 40rpx;
|
|||
|
font-weight: 600;
|
|||
|
margin-top: 8rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
.record-section {
|
|||
|
background: #fff;
|
|||
|
border-radius: 20rpx;
|
|||
|
padding: 32rpx;
|
|||
|
.record-title {
|
|||
|
font-size: 28rpx;
|
|||
|
font-weight: 600;
|
|||
|
margin-bottom: 24rpx;
|
|||
|
}
|
|||
|
.record-empty {
|
|||
|
color: #bbb;
|
|||
|
text-align: center;
|
|||
|
font-size: 26rpx;
|
|||
|
padding: 32rpx 0;
|
|||
|
}
|
|||
|
.record-item {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: space-between;
|
|||
|
padding: 18rpx 0;
|
|||
|
border-bottom: 1rpx solid #f0f0f0;
|
|||
|
&:last-child {
|
|||
|
border-bottom: none;
|
|||
|
}
|
|||
|
.record-info {
|
|||
|
.record-type {
|
|||
|
font-size: 26rpx;
|
|||
|
color: #222;
|
|||
|
margin-bottom: 6rpx;
|
|||
|
}
|
|||
|
.record-time {
|
|||
|
font-size: 22rpx;
|
|||
|
color: #888;
|
|||
|
}
|
|||
|
}
|
|||
|
.record-amount {
|
|||
|
font-size: 30rpx;
|
|||
|
font-weight: 600;
|
|||
|
&.plus {
|
|||
|
color: #2ecc71;
|
|||
|
}
|
|||
|
&.minus {
|
|||
|
color: #ff4d4f;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|