Files
medical-mall/pages/mall/consumer/withdraw.uvue

346 lines
8.4 KiB
Plaintext
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-container">
<view class="card">
<view class="section-title">提现至</view>
<view class="bank-selector" @click="openBankSelector">
<view class="bank-info" v-if="selectedBank">
<text class="bank-name">{{ selectedBank?.bank_name }}</text>
<text class="card-type">储蓄卡</text>
<text class="card-no">尾号 {{ getTailNumber(selectedBank?.card_number) }}</text>
</view>
<view class="bank-info placeholder" v-else>
<text>请选择到账银行卡</text>
</view>
<text class="arrow">></text>
</view>
<view class="amount-section">
<text class="label">提现金额</text>
<view class="input-wrapper">
<text class="currency">¥</text>
<input
class="amount-input"
type="digit"
v-model="amount"
placeholder="请输入提现金额"
/>
</view>
<view class="balance-line">
<text class="balance-text">当前可提现余额 ¥{{ balance }}</text>
<text class="all-btn" @click="setAll">全部提现</text>
</view>
</view>
<button
class="submit-btn"
:disabled="!isValid"
:loading="loading"
@click="submitWithdraw"
>
{{ loading ? '处理中...' : '确认提现' }}
</button>
</view>
<!-- 简单弹窗选择银行卡 -->
<view v-if="showBankPopup" class="popup-mask" @click="showBankPopup = false">
<view class="popup-content" @click.stop>
<view class="popup-header">
<text class="popup-title">选择到账银行卡</text>
<text class="close-btn" @click="showBankPopup = false">×</text>
</view>
<scroll-view scroll-y="true" class="bank-list">
<view
v-for="(item, index) in bankCards"
:key="index"
class="bank-item"
@click="selectBank(item)"
>
<view class="bank-row">
<text class="bank-name-popup">{{ item.bank_name }}</text>
<text class="card-no-popup">({{ getTailNumber(item.card_number) }})</text>
</view>
<text v-if="selectedBank?.id == item.id" class="check">✓</text>
</view>
<view class="add-card-btn" @click="navigateToAddCard">
<text>+ 添加银行卡</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, computed, onMounted } from 'vue'
import { supabaseService } from '@/utils/supabaseService.uts'
type BankCard = {
id: string
bank_name: string
card_number: string
}
const amount = ref('')
const balance = ref(0.00)
const loading = ref(false)
const bankCards = ref<BankCard[]>([])
const selectedBank = ref<BankCard | null>(null)
const showBankPopup = ref(false)
const isValid = computed((): boolean => {
const val = parseFloat(amount.value)
if (isNaN(val) || val <= 0) return false
if (val > balance.value) return false
if (selectedBank.value == null) return false
return true
})
onMounted(() => {
loadData()
})
const loadData = async () => {
try {
const bal = await supabaseService.getUserBalance()
balance.value = bal
// 获取银行卡
const res = await supabaseService.getUserBankCards()
// 转换类型
const list: BankCard[] = []
for(let i=0; i<res.length; i++) {
const item = res[i]
let id = ''
let bankName = ''
let cardNum = ''
if (item instanceof UTSJSONObject) {
id = item.getString('id') ?? ''
bankName = item.getString('bank_name') ?? ''
cardNum = item.getString('card_number') ?? ''
} else {
const m = item as Map<string, any>
const idVal = m.get('id')
id = idVal != null ? (idVal as string) : ''
const nameVal = m.get('bank_name')
bankName = nameVal != null ? (nameVal as string) : ''
const numVal = m.get('card_number')
cardNum = numVal != null ? (numVal as string) : ''
}
if (id != '') {
list.push({
id: id,
bank_name: bankName,
card_number: cardNum
})
}
}
bankCards.value = list
if (bankCards.value.length > 0) {
selectedBank.value = bankCards.value[0]
}
} catch (e) {
console.error(e)
}
}
const getTailNumber = (cardNo: string | null): string => {
if (cardNo == null) return ''
if (cardNo.length <= 4) return cardNo
return cardNo.substring(cardNo.length - 4)
}
const setAll = () => {
amount.value = balance.value.toString()
}
const openBankSelector = () => {
showBankPopup.value = true
}
const selectBank = (bank: BankCard) => {
selectedBank.value = bank
showBankPopup.value = false
}
const navigateToAddCard = () => {
uni.navigateTo({
url: '/pages/mall/consumer/bank-cards/add'
})
showBankPopup.value = false
}
const submitWithdraw = async () => {
if (!isValid.value) return
loading.value = true
try {
const val = parseFloat(amount.value)
const success = await supabaseService.withdrawBalance(val)
if (success) {
uni.showToast({
title: '提现申请已提交',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
} else {
uni.showToast({
title: '提现失败, ' + (val > balance.value ? '余额不足' : '请重试'),
icon: 'none'
})
}
} catch (e) {
uni.showToast({
title: '系统异常',
icon: 'none'
})
} finally {
loading.value = false
}
}
</script>
<style scoped>
.page-container {
background-color: #f5f5f5;
flex: 1; /* Fixed 100vh issue */
padding: 20px;
}
.card {
background-color: #fff;
border-radius: 12px;
padding: 20px;
}
.section-title {
font-size: 16px;
color: #333;
margin-bottom: 15px;
}
.bank-selector {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #eee;
}
.bank-info {
display: flex;
align-items: center;
/* gap removed */
}
.bank-name {
margin-right: 10px;
font-weight: bold;
}
.card-type {
margin-right: 10px;
}
.placeholder {
color: #999;
}
.amount-section {
margin-top: 20px;
}
.label {
font-size: 14px;
color: #666;
margin-bottom: 10px;
/* display: block removed */
}
.input-wrapper {
display: flex;
align-items: center;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-bottom: 10px;
}
.currency {
font-size: 30px;
font-weight: bold;
margin-right: 10px;
}
.amount-input {
flex: 1;
font-size: 30px;
font-weight: bold;
height: 40px;
}
.balance-line {
display: flex;
justify-content: space-between;
font-size: 12px;
}
.balance-text {
color: #999;
}
.all-btn {
color: #5785e5;
}
.submit-btn {
margin-top: 40px;
background-color: #5785e5;
color: #fff;
border-radius: 25px;
}
.submit-btn:disabled {
background-color: #ccc;
}
.popup-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 999;
display: flex;
justify-content: center;
align-items: flex-end;
}
.popup-content {
background-color: #fff;
width: 100%;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
padding: 20px;
min-height: 300px;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.popup-title {
font-size: 16px;
font-weight: bold;
}
.close-btn {
font-size: 20px;
color: #999;
padding: 5px;
}
.bank-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #f5f5f5;
}
.add-card-btn {
padding: 15px 0;
text-align: center;
color: #5785e5;
font-weight: bold;
}
</style>