HomeLease/pages/requestWithdrawal/requestWithdrawal.vue
2025-08-25 11:40:20 +08:00

903 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- 提现容器 -->
<!-- 账户余额卡片 -->
<view class="balance-card">
<view class="balance-item">
<view class="balance-label">账户余额 ()</view>
<view class="balance-value">{{ withdrawInfo.balance }}</view>
</view>
<view class="balance-item">
<view class="balance-label">未结算金额 ()</view>
<view class="balance-value">{{ withdrawInfo.unsettled }}</view>
</view>
</view>
<view class="withdrawal-container">
<!-- 提现金额输入 -->
<view class="withdrawal-section">
<view class="section-title">提现金额</view>
<view class="amount-input">
<text class="currency-symbol">¥</text>
<input
v-model="withdrawalData.amount"
class="amount-field"
placeholder="请输入金额"
type="text"
@input="onAmountInput"
/>
<view class="withdraw-all-btn" @click="withdrawAll">全部提现</view>
</view>
</view>
<!-- 提现至银行 -->
<view class="bank-section">
<view class="section-title">提现至</view>
<view class="bank-selector" @click="selectBank">
<view class="bank-info">
<!-- <image :src="selectedBank.icon" class="bank-icon" mode="aspectFit"></image>-->
<view class="bank-details">
<text class="bank-name">{{ selectedBank.displayName || '请选择账号' }}</text>
<text class="bank-card">{{ selectedBank.cardNumber || '暂无账号' }}</text>
<text v-if="selectedBank.name" class="bank-owner"
>收款人: {{ selectedBank.name }}
</text>
</view>
</view>
<text class="arrow-icon"></text>
</view>
<!-- 账号管理按钮 -->
</view>
<view class="bank-management">
<view class="bank-btn add-btn" @click="showAddModal = true">添加账号</view>
<view class="bank-btn delete-btn" @click="showDeleteModal = true">删除账号</view>
</view>
<!-- 账号状态提示 -->
<view v-if="userBankList.length === 0" class="bank-status-tip">
<text class="tip-text">您还没有添加账号,请先添加账号</text>
</view>
<!-- 提现按钮 -->
<view class="withdraw-btn" @click="submitWithdrawal">立即提现</view>
</view>
<!-- 提现说明 -->
<view class="withdrawal-explanation">
<view class="explanation-title">提现说明:</view>
<view class="explanation-item">
<text>提现金额: {{ withdrawalData.amount ? withdrawalData.amount + '元' : '0.00元' }}</text>
</view>
<view class="explanation-item">
<text>实际到账: {{ withdrawInfo.actualAmount }}元</text>
</view>
<view class="explanation-item">
<text>提现手续费: {{ withdrawInfo.fee }}元</text>
</view>
<view class="explanation-item">
<text>最小提现金额: {{ withdrawInfo.minAmount }}元</text>
</view>
<view class="explanation-item">
<text>最大提现金额: {{ withdrawInfo.maxAmount }}</text>
</view>
</view>
<!-- 添加账号组件 -->
<add-card :visible="showAddModal" @close="showAddModal = false" @success="onBankSuccess" />
<!-- 删除账号组件 -->
<delete-card
:bank-list="userBankList"
:visible="showDeleteModal"
@close="showDeleteModal = false"
@success="onBankSuccess"
/>
</view>
</template>
<script>
import { commonEnum } from '@/enum/commonEnum.js'
import { getWithdrawInfo, submitWithdraw, computedServiceAmount } from '@/api/user/user.js'
import { getUserBankList } from '@/api/account.js'
import AddCard from './addCard.vue'
import DeleteCardd from './deleteCard.vue'
import debounce from '../../utils/debounce'
export default {
components: {
AddCard,
DeleteCard: DeleteCardd,
},
data() {
return {
loading: false,
withdrawInfo: {
balance: '0',
unsettled: '0.00',
fee: 0,
minAmount: 0,
maxAmount: 0,
actualAmount: 0,
},
withdrawalData: {
amount: '',
accountId: '',
serviceType: '',
serviceCharge: '',
arrivalAmount: '',
},
selectedBank: {
id: '',
name: '',
icon: commonEnum.CHINA_CONSTRUCTION_BANK,
cardNumber: '',
type: 'BANK',
},
// 用户账号列表
userBankList: [],
// 账号管理相关
showAddModal: false,
showDeleteModal: false,
}
},
computed: {},
onLoad() {
this.fetchWithdrawInfo()
this.fetchUserBankList()
},
methods: {
// 获取提现信息
async fetchWithdrawInfo() {
this.loading = true
try {
const response = await getWithdrawInfo()
if (response.code === 200 && response.data) {
this.withdrawInfo = {
...this.withdrawInfo,
...response.data,
}
console.log('提现信息获取成功:', this.withdrawInfo)
}
} catch (error) {
console.error('获取提现信息失败:', error)
uni.showToast({
title: '获取提现信息失败',
icon: 'none',
})
} finally {
this.loading = false
}
},
// 获取用户账号列表
async fetchUserBankList() {
try {
console.log('开始获取用户账号列表...123')
const response = await getUserBankList()
if (response.code === 200 && response.rows) {
this.userBankList = response.rows || []
console.log('用户账号列表获取成功:')
// 处理账号数据
this.userBankList = this.userBankList.map(item => ({
...item,
cardNumber: this.maskCardNumber(item.no),
icon: this.getBankIcon(item.type),
displayName: this.getDisplayName(item),
}))
console.log('用户账号列表获取成功:', this.userBankList)
// 如果有账号,设置默认选中的账号
if (this.userBankList.length > 0) {
this.selectedBank = this.userBankList[0]
this.withdrawalData.accountId = this.selectedBank.id
console.log('设置默认账号:', this.selectedBank)
} else {
console.log('没有找到账号,显示空状态')
}
} else {
console.log('API返回错误:', response)
uni.showToast({
title: response.msg || '获取账号列表失败',
icon: 'none',
})
}
} catch (error) {
console.error('获取用户账号列表失败:', error)
uni.showToast({
title: '获取账号列表失败',
icon: 'none',
})
}
},
serviceAmount: debounce(async function (amount) {
try {
console.log('发送参数', amount)
if (!amount) {
this.withdrawInfo.fee = 0
this.withdrawInfo.actualAmount = 0
this.withdrawalData.amount = 0
return
}
const res = await computedServiceAmount(amount)
if (res.code === 200 && res.data) {
const info = res.data
this.withdrawInfo.fee = info.serviceCharge
this.withdrawInfo.actualAmount = info.amount
this.withdrawalData.amount = info.withdrawAmount
}
} catch (error) {
console.error('服务费获取失败:', error)
}
}, 600), // 600ms内重复触发无效
// 掩码账号号
maskCardNumber(cardNumber) {
if (!cardNumber) return ''
if (cardNumber.length <= 8) return cardNumber
return '**** **** **** ' + cardNumber.slice(-4)
},
// 获取银行图标
getBankIcon(type) {
// 根据type字段判断类型B和BAN都表示银行卡
if (type === 'B' || type === 'BAN') {
return commonEnum.CHINA_CONSTRUCTION_BANK
} else if (type === 'QR') {
return '/static/icons/qr-code.png' // 收款二维码图标
}
return commonEnum.CHINA_CONSTRUCTION_BANK
},
// 获取显示名称
getDisplayName(item) {
// 根据type字段判断类型
if (item.type === 'B' || item.type === 'BAN') {
return '银行卡'
} else if (item.type === 'QR') {
return '收款二维码'
}
return '银行卡'
},
// 账号操作成功回调
onBankSuccess() {
// 延迟刷新账号列表,避免与子组件的关闭逻辑冲突
setTimeout(() => {
this.fetchUserBankList()
}, 2000)
},
goBack() {
uni.navigateBack()
},
onAmountInput(e) {
const value = e.detail.value
console.log(value)
this.serviceAmount(value)
},
withdrawAll() {
this.withdrawalData.amount = this.withdrawInfo.balance
console.log('全部提现,设置金额:', this.withdrawalData.amount)
},
selectBank() {
if (this.userBankList.length === 0) {
uni.showToast({
title: '请先添加账号',
icon: 'none',
})
return
}
uni.showActionSheet({
itemList: this.userBankList.map(
bank => `${bank.displayName} ${bank.cardNumber} (${bank.name})`
),
success: res => {
const selectedBank = this.userBankList[res.tapIndex]
this.selectedBank = selectedBank
this.withdrawalData.accountId = selectedBank.id
console.log('选择账号:', selectedBank)
},
})
},
async submitWithdrawal() {
if (!this.withdrawalData.amount || parseFloat(this.withdrawalData.amount) <= 0) {
uni.showToast({
title: '请输入提现金额',
icon: 'none',
})
return
}
if (!this.withdrawalData.accountId) {
uni.showToast({
title: '请选择提现账号',
icon: 'none',
})
return
}
const amount = parseFloat(this.withdrawalData.amount)
const available = parseFloat(this.withdrawInfo.available)
const minAmount = parseFloat(this.withdrawInfo.minAmount)
const maxAmount = parseFloat(this.withdrawInfo.maxAmount)
if (amount > available) {
uni.showToast({
title: '提现金额超过可提现余额',
icon: 'none',
})
return
}
if (amount < minAmount) {
uni.showToast({
title: `提现金额不能少于${minAmount}`,
icon: 'none',
})
return
}
if (amount > maxAmount) {
uni.showToast({
title: `提现金额不能超过${maxAmount}`,
icon: 'none',
})
return
}
uni.showModal({
title: '确认提现',
content: `确认提现${this.withdrawalData.amount}元到${this.selectedBank.displayName}吗?`,
success: async res => {
if (res.confirm) {
this.loading = true
try {
const response = await submitWithdraw({
amount: this.withdrawalData.amount,
accountId: this.selectedBank.id,
serviceType: '1',
serviceCharge: this.withdrawInfo.fee,
arrivalAmount: this.withdrawInfo.actualAmount,
})
if (response.code === 200) {
uni.showToast({
title: '提现申请已提交',
icon: 'success',
})
// 刷新提现信息
await this.fetchWithdrawInfo()
// 返回上一页
setTimeout(() => {
uni.navigateBack()
}, 1500)
} else {
uni.showToast({
title: response.msg || '提现申请失败',
icon: 'none',
})
}
} catch (error) {
console.error('提现申请失败:', error)
uni.showToast({
title: '提现申请失败,请重试',
icon: 'none',
})
} finally {
this.loading = false
}
}
},
})
},
},
}
</script>
<style lang="scss" scoped>
.page {
min-height: 90vh;
background: #f7f7f7;
padding-top: 20rpx;
padding-bottom: 40rpx;
}
.withdrawal-container {
background: #fff;
border-radius: 20rpx;
margin: 20rpx;
padding-bottom: 54rpx;
overflow: hidden;
}
.balance-card {
display: flex;
justify-content: space-between;
margin: 20rpx;
padding: 40rpx;
background: linear-gradient(135deg, #ff803a, #ff6b35);
border-radius: 20rpx;
color: white;
.balance-item {
text-align: center;
.balance-label {
font-size: 24rpx;
margin-bottom: 10rpx;
opacity: 0.9;
}
.balance-value {
font-size: 36rpx;
font-weight: bold;
}
}
}
.withdrawal-section {
padding: 30rpx;
//border-bottom: 1rpx solid #f0f0f0;
.section-title {
font-size: 28rpx;
color: #3d3d3d;
margin-bottom: 20rpx;
font-weight: 500;
}
.amount-input {
display: flex;
align-items: center;
border-bottom: 1rpx solid #f0f0f0;
padding-bottom: 20rpx;
.currency-symbol {
font-size: 80rpx;
color: #333;
margin-right: 20rpx;
font-weight: bold;
}
.amount-field {
height: 90rpx;
//border: #4cd964 1px solid;
flex: 1;
font-size: 80rpx;
color: #333;
}
.withdraw-all-btn {
padding: 10rpx 20rpx;
color: #ff803a;
font-size: 30rpx;
}
}
}
.bank-section {
display: flex;
padding: 30rpx;
align-items: center;
justify-content: space-between;
//border-bottom: 1rpx solid #f0f0f0;
.section-title {
font-size: 28rpx;
color: #7c7c7c;
font-weight: 500;
}
.bank-selector {
display: flex;
align-items: center;
justify-content: space-between;
.bank-info {
display: flex;
align-items: center;
gap: 20rpx;
.bank-icon {
width: 40rpx;
height: 40rpx;
}
.bank-details {
display: flex;
flex-direction: column;
.bank-name {
font-size: 28rpx;
color: #333;
margin-bottom: 5rpx;
}
.bank-card {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.bank-owner {
font-size: 22rpx;
color: #666;
margin-top: 4rpx;
}
}
}
.arrow-icon {
font-size: 32rpx;
color: #999;
}
}
}
.withdraw-btn {
margin: 17rpx;
padding: 30rpx;
background: #ffeee4;
color: #ff803a;
text-align: center;
font-size: 36rpx;
font-weight: 500;
border-radius: 46rpx;
box-shadow: rgba(0, 0, 0, 0.1) 0 5px 10px 0;
}
.available-amount {
padding-left: 66rpx;
text-align: left;
font-size: 24rpx;
color: #666;
margin-bottom: 30rpx;
}
.withdrawal-explanation {
margin: 30rpx;
padding: 30rpx;
background: #fff;
border-radius: 20rpx;
.explanation-title {
font-size: 34rpx;
color: #3d3d3d;
margin-bottom: 20rpx;
font-weight: 500;
}
.explanation-item {
padding: 10rpx 0;
font-size: 26rpx;
color: #3d3d3d;
}
}
view {
//border: red solid 1px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 账号管理样式 */
.bank-management {
margin-top: 20rpx;
display: flex;
gap: 20rpx;
.bank-btn {
flex: 1;
padding: 20rpx;
text-align: center;
border-radius: 10rpx;
font-size: 28rpx;
font-weight: 500;
&.add-btn {
background: #ff803a;
color: #fff;
}
&.delete-btn {
background: #ff4757;
color: #fff;
}
}
}
/* 账号状态提示 */
.bank-status-tip {
margin: 20rpx 30rpx;
padding: 20rpx;
background: #fff5f0;
border-radius: 10rpx;
border-left: 4rpx solid #ff803a;
.tip-text {
font-size: 26rpx;
color: #ff803a;
text-align: center;
}
}
/* 模态框样式 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
.modal-content {
width: 90%;
max-width: 600rpx;
background: #fff;
border-radius: 20rpx;
overflow: hidden;
.modal-header {
padding: 30rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
.modal-title {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
}
.modal-body {
padding: 30rpx;
.form-group {
margin-bottom: 30rpx;
.form-label {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 15rpx;
font-weight: 500;
}
.form-input {
width: 100%;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 10rpx;
padding: 0 20rpx;
font-size: 28rpx;
color: #333;
background: #fafafa;
&:focus {
border-color: #ff803a;
background: #fff;
}
}
.form-select {
width: 100%;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 10rpx;
padding: 0 20rpx;
font-size: 28rpx;
color: #333;
background: #fafafa;
}
.upload-area {
border: 2rpx dashed #e0e0e0;
border-radius: 10rpx;
padding: 40rpx;
text-align: center;
background: #fafafa;
&.has-image {
border-color: #ff803a;
background: #fff;
}
.upload-icon {
font-size: 60rpx;
color: #999;
margin-bottom: 20rpx;
}
.upload-text {
font-size: 26rpx;
color: #666;
margin-bottom: 20rpx;
}
.upload-btn {
display: inline-block;
padding: 15rpx 30rpx;
background: #ff803a;
color: #fff;
border-radius: 8rpx;
font-size: 24rpx;
}
.preview-image {
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
margin: 20rpx auto;
}
}
}
}
.modal-footer {
display: flex;
border-top: 1rpx solid #f0f0f0;
.modal-btn {
flex: 1;
padding: 30rpx;
text-align: center;
font-size: 30rpx;
font-weight: 500;
&.cancel-btn {
color: #666;
border-right: 1rpx solid #f0f0f0;
}
&.confirm-btn {
color: #ff803a;
}
}
}
}
}
/* 账号列表样式 */
.bank-list-modal {
.modal-content {
.bank-list {
max-height: 600rpx;
overflow-y: auto;
.bank-item {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.bank-icon {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
border-radius: 8rpx;
}
.bank-info {
flex: 1;
.bank-name {
font-size: 30rpx;
color: #333;
margin-bottom: 8rpx;
font-weight: 500;
}
.bank-number {
font-size: 26rpx;
color: #666;
}
.bank-type {
font-size: 24rpx;
color: #999;
margin-top: 5rpx;
}
}
.delete-icon {
width: 40rpx;
height: 40rpx;
color: #ff4757;
}
}
}
}
}
/* 响应式设计 */
@media (max-width: 750rpx) {
.modal-content {
width: 95%;
margin: 20rpx;
}
.bank-management {
flex-direction: column;
.bank-btn {
margin-bottom: 15rpx;
}
}
}
/* 动画效果 */
.modal-overlay {
animation: fadeIn 0.3s ease-out;
}
.modal-content {
animation: slideUp 0.3s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
transform: translateY(100rpx);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* 加载状态样式 */
.loading-btn {
position: relative;
color: transparent !important;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 30rpx;
height: 30rpx;
margin: -15rpx 0 0 -15rpx;
border: 3rpx solid transparent;
border-top: 3rpx solid currentColor;
border-radius: 50%;
animation: spin 1s linear infinite;
}
}
</style>