consumer模块完成95%,在和商家端对接聊天购物闭环

This commit is contained in:
2026-02-06 17:10:31 +08:00
parent 06b7369494
commit e2f1dfb097
1454 changed files with 5425 additions and 210555 deletions

View File

@@ -0,0 +1,334 @@
<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>
id = (m.get('id') as string) || ''
bankName = (m.get('bank_name') as string) || ''
cardNum = (m.get('card_number') 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;
min-height: 100vh;
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: 10px;
}
.placeholder {
color: #999;
}
.amount-section {
margin-top: 20px;
}
.label {
font-size: 14px;
color: #666;
margin-bottom: 10px;
display: block;
}
.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: 500;
}
</style>