- 新增 000070 数据库迁移:支持 chat_conversations、wallet_accounts、wallet_ledger、withdrawal_requests 按 distribution_site_id 隔离 - 消息中心:会话列表、未读数统计、站点专属客服及订单群聊与主站实现双向完全隔离 - 资金账户与提现:独立按 (user_id, distribution_site_id) 建账,分销订单自动结算至对应分站钱包,提现与流水相互独立 - 前台界面:Axios 自动透传 X-Distribution-Site-Code,钱包、提现与消息页面呈现分站专属标牌与独立说明
678 lines
22 KiB
Vue
678 lines
22 KiB
Vue
<script setup lang="ts">
|
||
import { computed, onMounted, reactive, ref } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { showDialog, showToast } from 'vant'
|
||
|
||
import {
|
||
cancelWithdrawal,
|
||
createPaymentAccount,
|
||
createWithdrawal,
|
||
deletePaymentAccount,
|
||
fetchPaymentAccounts,
|
||
fetchWithdrawals,
|
||
setDefaultPaymentAccount,
|
||
type AccountType,
|
||
type PaymentAccount,
|
||
type WithdrawalRequest,
|
||
updatePaymentAccount,
|
||
} from '@/features/wallet/api/withdrawal'
|
||
import { fetchWalletBalance, type WalletAccount } from '@/features/wallet/api/wallet'
|
||
import { uploadFile } from '@/shared/api/files'
|
||
import { readError } from '@/shared/utils/error'
|
||
import { formatCent, formatMoney, yuanToCent } from '@/shared/utils/money'
|
||
import { formatDateMinute } from '@/shared/utils/time'
|
||
import alipayReceiveQrExample from '@/assets/alipay-receive-qr-example.png'
|
||
import wechatReceiveQrExample from '@/assets/wechat-receive-qr-example.png'
|
||
import { useDistributionSiteStore } from '@/stores/distributionSite'
|
||
|
||
const router = useRouter()
|
||
const distributionStore = useDistributionSiteStore()
|
||
|
||
const loading = ref(false)
|
||
const submitting = ref(false)
|
||
const addingAccount = ref(false)
|
||
const managingAccountId = ref(0)
|
||
const uploadingCertificate = ref(false)
|
||
const showAccountPopup = ref(false)
|
||
const account = ref<WalletAccount | null>(null)
|
||
const paymentAccounts = ref<PaymentAccount[]>([])
|
||
const withdrawals = ref<WithdrawalRequest[]>([])
|
||
const editingAccount = ref<PaymentAccount | null>(null)
|
||
|
||
const MIN_AMOUNT = 10
|
||
const MAX_AMOUNT = 5000
|
||
|
||
const withdrawForm = reactive({
|
||
payment_account_id: 0,
|
||
amount: '' as number | '',
|
||
})
|
||
|
||
const accountForm = reactive({
|
||
account_type: 'alipay' as AccountType,
|
||
account_name: '',
|
||
account_no: '',
|
||
bank_name: '',
|
||
bank_branch: '',
|
||
certificate_urls: [] as string[],
|
||
})
|
||
|
||
const selectedAccount = computed(() =>
|
||
paymentAccounts.value.find(item => item.id === withdrawForm.payment_account_id)
|
||
)
|
||
const canAddMore = computed(() => paymentAccounts.value.length < 5)
|
||
const accountPopupTitle = computed(() => (editingAccount.value ? '管理收款账号' : '添加收款账号'))
|
||
const receiveQrTip = computed(() => {
|
||
if (accountForm.account_type === 'alipay') {
|
||
return {
|
||
title: '支付宝收款二维码上传提醒',
|
||
lines: [
|
||
'请在支付宝收钱码页面保存收钱码,上传保存后的二维码图片。',
|
||
'不要上传收钱码截图、聊天截图或带页面背景的整屏截图。',
|
||
],
|
||
image: alipayReceiveQrExample,
|
||
alt: '支付宝收款二维码示例',
|
||
label: '支付宝收款二维码',
|
||
}
|
||
}
|
||
if (accountForm.account_type === 'wechat') {
|
||
return {
|
||
title: '微信收款二维码上传提醒',
|
||
lines: [
|
||
'请在微信收款码页面点击保存收款码,上传保存后的二维码图片。',
|
||
'不要上传收款码截图、聊天截图或带页面背景的整屏截图。',
|
||
],
|
||
image: wechatReceiveQrExample,
|
||
alt: '微信收款二维码示例',
|
||
label: '微信收款二维码',
|
||
}
|
||
}
|
||
return null
|
||
})
|
||
|
||
const amountValue = computed(() => Number(withdrawForm.amount || 0))
|
||
const amountCent = computed(() => yuanToCent(amountValue.value))
|
||
const availableBalanceCent = computed(() => account.value?.available_balance_cent || 0)
|
||
const canWithdraw = computed(
|
||
() =>
|
||
withdrawForm.payment_account_id > 0 &&
|
||
amountValue.value >= MIN_AMOUNT &&
|
||
amountValue.value <= MAX_AMOUNT &&
|
||
amountCent.value <= availableBalanceCent.value &&
|
||
!submitting.value
|
||
)
|
||
|
||
onMounted(loadData)
|
||
|
||
async function loadData() {
|
||
loading.value = true
|
||
try {
|
||
const siteCode = distributionStore.isDistribution ? distributionStore.siteCode : undefined
|
||
const [balanceData, accountsData, withdrawalsData] = await Promise.all([
|
||
fetchWalletBalance(siteCode),
|
||
fetchPaymentAccounts(1, 100),
|
||
fetchWithdrawals(1, 20, siteCode),
|
||
])
|
||
account.value = balanceData
|
||
paymentAccounts.value = accountsData.items
|
||
withdrawals.value = withdrawalsData.items
|
||
const currentStillExists = paymentAccounts.value.some(
|
||
item => item.id === withdrawForm.payment_account_id
|
||
)
|
||
if (!currentStillExists) {
|
||
const defaultAccount = paymentAccounts.value.find(item => item.is_default)
|
||
withdrawForm.payment_account_id = defaultAccount?.id || paymentAccounts.value[0]?.id || 0
|
||
}
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '加载失败'), icon: 'cross' })
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
async function handleSubmit() {
|
||
if (!canWithdraw.value || !selectedAccount.value) return
|
||
try {
|
||
await showDialog({
|
||
title: '确认提现',
|
||
message: `提现 ¥${formatMoney(amountValue.value)} 到 ${selectedAccount.value.account_name}(${selectedAccount.value.account_no})?`,
|
||
confirmButtonText: '确认提交',
|
||
cancelButtonText: '再看看',
|
||
showCancelButton: true,
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
|
||
submitting.value = true
|
||
try {
|
||
await createWithdrawal(
|
||
{
|
||
payment_account_id: withdrawForm.payment_account_id,
|
||
amount_cent: amountCent.value,
|
||
},
|
||
distributionStore.isDistribution ? distributionStore.siteCode : undefined
|
||
)
|
||
showToast({ message: '提现申请已提交', icon: 'passed' })
|
||
withdrawForm.amount = ''
|
||
await loadData()
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '提现申请失败'), icon: 'cross' })
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
|
||
async function handleCancel(item: WithdrawalRequest) {
|
||
try {
|
||
await showDialog({
|
||
title: '取消提现',
|
||
message: '确定要取消此提现申请吗?',
|
||
confirmButtonText: '确认取消',
|
||
cancelButtonText: '返回',
|
||
showCancelButton: true,
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
|
||
try {
|
||
await cancelWithdrawal(item.id)
|
||
showToast({ message: '已取消提现', icon: 'passed' })
|
||
await loadData()
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '取消失败'), icon: 'cross' })
|
||
}
|
||
}
|
||
|
||
function openAccountPopup() {
|
||
editingAccount.value = null
|
||
Object.assign(accountForm, {
|
||
account_type: 'alipay' as AccountType,
|
||
account_name: '',
|
||
account_no: '',
|
||
bank_name: '',
|
||
bank_branch: '',
|
||
certificate_urls: [] as string[],
|
||
})
|
||
showAccountPopup.value = true
|
||
}
|
||
|
||
function openEditAccountPopup(item: PaymentAccount) {
|
||
editingAccount.value = item
|
||
Object.assign(accountForm, {
|
||
account_type: item.account_type,
|
||
account_name: item.account_name,
|
||
account_no: item.account_no,
|
||
bank_name: item.bank_name || '',
|
||
bank_branch: item.bank_branch || '',
|
||
certificate_urls: [...(item.certificate_urls || [])],
|
||
})
|
||
showAccountPopup.value = true
|
||
}
|
||
|
||
async function handleSaveAccount() {
|
||
if (!accountForm.account_name.trim()) {
|
||
showToast({ message: '请输入账户名', icon: 'warning-o' })
|
||
return
|
||
}
|
||
if (!editingAccount.value && !accountForm.account_no.trim()) {
|
||
showToast({
|
||
message: accountForm.account_type === 'bank' ? '请输入银行卡号' : '请输入账号',
|
||
icon: 'warning-o',
|
||
})
|
||
return
|
||
}
|
||
if (accountForm.account_type === 'bank' && !accountForm.bank_name.trim()) {
|
||
showToast({ message: '请输入银行名称', icon: 'warning-o' })
|
||
return
|
||
}
|
||
|
||
addingAccount.value = true
|
||
try {
|
||
if (editingAccount.value) {
|
||
await updatePaymentAccount(editingAccount.value.id, {
|
||
bank_branch: accountForm.account_type === 'bank' ? accountForm.bank_branch.trim() : '',
|
||
certificate_urls: accountForm.certificate_urls,
|
||
})
|
||
showToast({ message: '收款账号已更新', icon: 'passed' })
|
||
showAccountPopup.value = false
|
||
editingAccount.value = null
|
||
await loadData()
|
||
} else {
|
||
const created = await createPaymentAccount({
|
||
account_type: accountForm.account_type,
|
||
account_name: accountForm.account_name.trim(),
|
||
account_no: accountForm.account_no.trim(),
|
||
bank_name: accountForm.account_type === 'bank' ? accountForm.bank_name.trim() : '',
|
||
bank_branch: accountForm.account_type === 'bank' ? accountForm.bank_branch.trim() : '',
|
||
certificate_urls: accountForm.certificate_urls,
|
||
})
|
||
showToast({ message: '收款账号已添加', icon: 'passed' })
|
||
showAccountPopup.value = false
|
||
editingAccount.value = null
|
||
await loadData()
|
||
withdrawForm.payment_account_id = created.id
|
||
}
|
||
} catch (error) {
|
||
showToast({
|
||
message: readError(error, editingAccount.value ? '更新失败' : '添加失败'),
|
||
icon: 'cross',
|
||
})
|
||
} finally {
|
||
addingAccount.value = false
|
||
}
|
||
}
|
||
|
||
async function handleSetDefaultAccount(item: PaymentAccount) {
|
||
if (item.is_default || managingAccountId.value) return
|
||
managingAccountId.value = item.id
|
||
try {
|
||
await setDefaultPaymentAccount(item.id)
|
||
showToast({ message: '已设为默认账号', icon: 'passed' })
|
||
withdrawForm.payment_account_id = item.id
|
||
await loadData()
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '设置失败'), icon: 'cross' })
|
||
} finally {
|
||
managingAccountId.value = 0
|
||
}
|
||
}
|
||
|
||
async function handleDeleteAccount(item: PaymentAccount) {
|
||
if (managingAccountId.value) return
|
||
try {
|
||
await showDialog({
|
||
title: '删除收款账号',
|
||
message: `确定删除 ${accountTypeLabel(item.account_type)} · ${item.account_name} 吗?删除后不会影响已提交的提现记录。`,
|
||
confirmButtonText: '确认删除',
|
||
cancelButtonText: '取消',
|
||
showCancelButton: true,
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
|
||
managingAccountId.value = item.id
|
||
try {
|
||
await deletePaymentAccount(item.id)
|
||
showToast({ message: '收款账号已删除', icon: 'passed' })
|
||
if (editingAccount.value?.id === item.id) {
|
||
showAccountPopup.value = false
|
||
editingAccount.value = null
|
||
}
|
||
await loadData()
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '删除失败'), icon: 'cross' })
|
||
} finally {
|
||
managingAccountId.value = 0
|
||
}
|
||
}
|
||
|
||
async function handleCertificateUpload(event: Event) {
|
||
const input = event.target as HTMLInputElement
|
||
const file = input.files?.[0]
|
||
input.value = ''
|
||
if (!file) return
|
||
if (!file.type.startsWith('image/')) {
|
||
showToast({ message: '只能上传图片文件', icon: 'warning-o' })
|
||
return
|
||
}
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
showToast({ message: '图片大小不能超过5MB', icon: 'warning-o' })
|
||
return
|
||
}
|
||
if (accountForm.certificate_urls.length >= 3) {
|
||
showToast({ message: '最多上传3张图片', icon: 'warning-o' })
|
||
return
|
||
}
|
||
|
||
uploadingCertificate.value = true
|
||
try {
|
||
const uploaded = await uploadFile(file, 'payment-cert')
|
||
accountForm.certificate_urls.push(uploaded.url)
|
||
showToast({ message: '图片已上传', icon: 'passed' })
|
||
} catch (error) {
|
||
showToast({ message: readError(error, '上传失败'), icon: 'cross' })
|
||
} finally {
|
||
uploadingCertificate.value = false
|
||
}
|
||
}
|
||
|
||
function removeCertificate(index: number) {
|
||
accountForm.certificate_urls.splice(index, 1)
|
||
}
|
||
|
||
function selectAccount(id: number) {
|
||
withdrawForm.payment_account_id = id
|
||
}
|
||
|
||
function accountTypeLabel(type: string) {
|
||
const labels: Record<string, string> = {
|
||
alipay: '支付宝',
|
||
wechat: '微信',
|
||
bank: '银行卡',
|
||
}
|
||
return labels[type] || type
|
||
}
|
||
|
||
function accountTypeIcon(type: string) {
|
||
const icons: Record<string, string> = {
|
||
alipay: 'gold-coin-o',
|
||
wechat: 'chat-o',
|
||
bank: 'credit-pay',
|
||
}
|
||
return icons[type] || 'balance-o'
|
||
}
|
||
|
||
function statusLabel(status: string) {
|
||
const labels: Record<string, string> = {
|
||
pending: '待审核',
|
||
processing: '处理中',
|
||
completed: '已完成',
|
||
rejected: '已拒绝',
|
||
cancelled: '已取消',
|
||
}
|
||
return labels[status] || status
|
||
}
|
||
|
||
function statusType(status: string): 'primary' | 'success' | 'danger' | 'warning' | undefined {
|
||
const types: Record<string, 'primary' | 'success' | 'danger' | 'warning'> = {
|
||
pending: 'warning',
|
||
processing: 'primary',
|
||
completed: 'success',
|
||
rejected: 'danger',
|
||
}
|
||
return types[status]
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<main class="mobile-withdrawal">
|
||
<header class="page-header">
|
||
<button class="back-btn" type="button" @click="router.back()">
|
||
<van-icon name="arrow-left" :size="20" />
|
||
</button>
|
||
<h1>
|
||
{{ distributionStore.isDistribution ? `${distributionStore.siteName} · 提现` : '提现' }}
|
||
</h1>
|
||
<button class="refresh-btn" type="button" @click="loadData">
|
||
<van-icon name="replay" :size="18" />
|
||
</button>
|
||
</header>
|
||
|
||
<section class="balance-panel">
|
||
<div v-if="distributionStore.isDistribution" class="site-account-tip">
|
||
{{ distributionStore.siteName }}独立账户
|
||
</div>
|
||
<span>可用余额</span>
|
||
<strong>¥{{ formatCent(availableBalanceCent) }}</strong>
|
||
<small>冻结余额 ¥{{ formatCent(account?.frozen_balance_cent) }}</small>
|
||
</section>
|
||
|
||
<section class="withdraw-card">
|
||
<div class="section-title">
|
||
<h2>申请提现</h2>
|
||
<button type="button" :disabled="!canAddMore" @click="openAccountPopup">
|
||
<van-icon name="plus" :size="14" />
|
||
{{ canAddMore ? '添加账号' : '已达上限' }}
|
||
</button>
|
||
</div>
|
||
|
||
<van-loading v-if="loading && !paymentAccounts.length" class="center-loading" />
|
||
|
||
<div v-else-if="!paymentAccounts.length" class="empty-state">
|
||
<van-icon name="card" :size="32" />
|
||
<p>还没有收款账号</p>
|
||
<van-button type="primary" round size="small" @click="openAccountPopup">
|
||
添加收款账号
|
||
</van-button>
|
||
</div>
|
||
|
||
<template v-else>
|
||
<div class="account-list">
|
||
<article
|
||
v-for="item in paymentAccounts"
|
||
:key="item.id"
|
||
class="account-option"
|
||
:class="{ active: item.id === withdrawForm.payment_account_id }"
|
||
>
|
||
<button type="button" class="account-select" @click="selectAccount(item.id)">
|
||
<span class="account-icon">
|
||
<van-icon :name="accountTypeIcon(item.account_type)" :size="18" />
|
||
</span>
|
||
<span class="account-main">
|
||
<strong>{{ accountTypeLabel(item.account_type) }} · {{ item.account_name }}</strong>
|
||
<small>{{ item.account_no }}</small>
|
||
</span>
|
||
<van-tag v-if="item.is_default" type="warning" plain>默认</van-tag>
|
||
<van-icon
|
||
:name="item.id === withdrawForm.payment_account_id ? 'checked' : 'circle'"
|
||
:size="18"
|
||
/>
|
||
</button>
|
||
<div class="account-actions">
|
||
<button
|
||
v-if="!item.is_default"
|
||
type="button"
|
||
:disabled="managingAccountId === item.id"
|
||
@click="handleSetDefaultAccount(item)"
|
||
>
|
||
设默认
|
||
</button>
|
||
<button type="button" @click="openEditAccountPopup(item)">管理</button>
|
||
<button
|
||
type="button"
|
||
class="danger"
|
||
:disabled="managingAccountId === item.id"
|
||
@click="handleDeleteAccount(item)"
|
||
>
|
||
删除
|
||
</button>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<van-field
|
||
v-model.number="withdrawForm.amount"
|
||
type="number"
|
||
label="提现金额"
|
||
placeholder="请输入提现金额"
|
||
input-align="right"
|
||
>
|
||
<template #left-icon>¥</template>
|
||
</van-field>
|
||
|
||
<div class="amount-meta">
|
||
<span>单笔限额 ¥{{ MIN_AMOUNT }} - ¥{{ MAX_AMOUNT }}</span>
|
||
<button type="button" @click="withdrawForm.amount = availableBalanceCent / 100">
|
||
全部提现
|
||
</button>
|
||
</div>
|
||
|
||
<div v-if="amountValue > 0" class="amount-preview">
|
||
<span>预计到账</span>
|
||
<strong>¥{{ formatMoney(amountValue) }}</strong>
|
||
</div>
|
||
|
||
<van-notice-bar
|
||
v-if="amountValue > 0 && amountCent > availableBalanceCent"
|
||
color="#b91c1c"
|
||
background="#fef2f2"
|
||
text="余额不足,请调整提现金额"
|
||
/>
|
||
|
||
<van-button
|
||
block
|
||
round
|
||
type="primary"
|
||
class="submit-btn"
|
||
:loading="submitting"
|
||
:disabled="!canWithdraw"
|
||
loading-text="提交中..."
|
||
@click="handleSubmit"
|
||
>
|
||
提交申请
|
||
</van-button>
|
||
</template>
|
||
</section>
|
||
|
||
<section class="records-card">
|
||
<div class="section-title">
|
||
<h2>提现记录</h2>
|
||
<span>{{ withdrawals.length }} 条</span>
|
||
</div>
|
||
|
||
<van-empty v-if="!withdrawals.length && !loading" description="暂无提现记录" />
|
||
<div v-else class="record-list">
|
||
<article v-for="item in withdrawals" :key="item.id" class="record-item">
|
||
<div class="record-top">
|
||
<div>
|
||
<strong>¥{{ formatCent(item.amount_cent) }}</strong>
|
||
<small>{{ item.withdraw_no }}</small>
|
||
</div>
|
||
<van-tag :type="statusType(item.status)">{{ statusLabel(item.status) }}</van-tag>
|
||
</div>
|
||
<div class="record-meta">
|
||
<span>{{ accountTypeLabel(item.account_type) }} · {{ item.account_no }}</span>
|
||
<span>{{ formatDateMinute(item.created_at) }}</span>
|
||
</div>
|
||
<p v-if="item.review_remark" class="record-remark">{{ item.review_remark }}</p>
|
||
<button
|
||
v-if="item.status === 'pending'"
|
||
type="button"
|
||
class="cancel-btn"
|
||
@click="handleCancel(item)"
|
||
>
|
||
取消申请
|
||
</button>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<van-popup
|
||
v-model:show="showAccountPopup"
|
||
round
|
||
position="bottom"
|
||
closeable
|
||
class="account-popup"
|
||
>
|
||
<div class="popup-body">
|
||
<h2>{{ accountPopupTitle }}</h2>
|
||
<van-radio-group
|
||
v-model="accountForm.account_type"
|
||
direction="horizontal"
|
||
class="type-tabs"
|
||
>
|
||
<van-radio name="alipay" :disabled="!!editingAccount">
|
||
<span class="type-label">
|
||
<span>支付宝</span>
|
||
<span v-if="!editingAccount" class="recommend-badge">推荐</span>
|
||
</span>
|
||
</van-radio>
|
||
<van-radio name="wechat" :disabled="!!editingAccount">微信</van-radio>
|
||
<van-radio name="bank" :disabled="!!editingAccount">银行卡</van-radio>
|
||
</van-radio-group>
|
||
<p v-if="!editingAccount" class="type-tip">推荐优先添加支付宝,微信和银行卡可按需选择。</p>
|
||
|
||
<van-field
|
||
v-model.trim="accountForm.account_name"
|
||
label="账户名"
|
||
placeholder="必须与实名认证姓名一致"
|
||
:disabled="!!editingAccount"
|
||
required
|
||
/>
|
||
<van-field
|
||
v-model.trim="accountForm.account_no"
|
||
:label="accountForm.account_type === 'bank' ? '银行卡号' : '账号'"
|
||
:placeholder="
|
||
accountForm.account_type === 'alipay'
|
||
? '支付宝账号'
|
||
: accountForm.account_type === 'wechat'
|
||
? '微信号'
|
||
: '银行卡号'
|
||
"
|
||
:disabled="!!editingAccount"
|
||
required
|
||
/>
|
||
<template v-if="accountForm.account_type === 'bank'">
|
||
<van-field
|
||
v-model.trim="accountForm.bank_name"
|
||
label="银行名称"
|
||
placeholder="如:中国工商银行"
|
||
:disabled="!!editingAccount"
|
||
required
|
||
/>
|
||
<van-field v-model.trim="accountForm.bank_branch" label="开户支行" placeholder="可选" />
|
||
</template>
|
||
|
||
<div class="account-tip">
|
||
账户名必须与实名认证姓名一致;提现将转账到该收款账号,请确认账号信息准确。
|
||
</div>
|
||
|
||
<div v-if="receiveQrTip" class="receive-qr-tip">
|
||
<div>
|
||
<strong>{{ receiveQrTip.title }}</strong>
|
||
<p v-for="line in receiveQrTip.lines" :key="line">{{ line }}</p>
|
||
</div>
|
||
<img :src="receiveQrTip.image" :alt="receiveQrTip.alt" />
|
||
</div>
|
||
|
||
<section class="certificate-section">
|
||
<div class="certificate-title">
|
||
<span>{{ receiveQrTip?.label || '收款码/凭证截图' }}</span>
|
||
<small>最多3张</small>
|
||
</div>
|
||
<div class="certificate-grid">
|
||
<div
|
||
v-for="(url, index) in accountForm.certificate_urls"
|
||
:key="url"
|
||
class="certificate-item"
|
||
>
|
||
<img :src="url" alt="收款凭证" />
|
||
<button type="button" class="certificate-remove" @click="removeCertificate(index)">
|
||
<van-icon name="cross" :size="13" />
|
||
</button>
|
||
</div>
|
||
<label v-if="accountForm.certificate_urls.length < 3" class="certificate-upload">
|
||
<input
|
||
type="file"
|
||
accept="image/*"
|
||
:disabled="uploadingCertificate"
|
||
@change="handleCertificateUpload"
|
||
/>
|
||
<van-loading v-if="uploadingCertificate" size="18" color="#ff6a00" />
|
||
<van-icon v-else name="photograph" :size="22" />
|
||
<span>{{ uploadingCertificate ? '上传中' : '上传图片' }}</span>
|
||
</label>
|
||
</div>
|
||
</section>
|
||
|
||
<van-button
|
||
block
|
||
round
|
||
type="primary"
|
||
:loading="addingAccount"
|
||
:loading-text="editingAccount ? '保存中...' : '添加中...'"
|
||
@click="handleSaveAccount"
|
||
>
|
||
{{ editingAccount ? '保存变更' : '保存账号' }}
|
||
</van-button>
|
||
<van-button
|
||
v-if="editingAccount"
|
||
block
|
||
round
|
||
plain
|
||
type="danger"
|
||
class="delete-account-btn"
|
||
:loading="managingAccountId === editingAccount.id"
|
||
@click="handleDeleteAccount(editingAccount)"
|
||
>
|
||
删除此账号
|
||
</van-button>
|
||
</div>
|
||
</van-popup>
|
||
</main>
|
||
</template>
|
||
|
||
<style scoped src="./MobileWithdrawalView.css"></style>
|