增加前端格式检查配置
This commit is contained in:
@@ -32,9 +32,12 @@ export async function fetchWalletBalance() {
|
||||
}
|
||||
|
||||
export async function fetchWalletLedger(page = 1, pageSize = 20) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<WalletLedger>>>('/wallet/ledger', {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<WalletLedger>>>(
|
||||
'/wallet/ledger',
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -44,11 +47,15 @@ export async function rechargeWallet(amount: number) {
|
||||
}
|
||||
|
||||
export async function startWalletRechargePayment(amount: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<PaymentOrder>>('/wallet/recharge/pay', { amount })
|
||||
const { data } = await apiClient.post<ApiResponse<PaymentOrder>>('/wallet/recharge/pay', {
|
||||
amount,
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function queryWalletRechargePayment(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<PaymentOrder>>(`/wallet/recharge/pay/${id}/query`)
|
||||
const { data } = await apiClient.post<ApiResponse<PaymentOrder>>(
|
||||
`/wallet/recharge/pay/${id}/query`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -70,9 +70,12 @@ export interface CreateWithdrawalRequest {
|
||||
// ========== 收款账号管理 API ==========
|
||||
|
||||
export async function fetchPaymentAccounts(page = 1, pageSize = 20) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<PaymentAccount>>>('/payment-accounts', {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<PaymentAccount>>>(
|
||||
'/payment-accounts',
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -92,12 +95,16 @@ export async function updatePaymentAccount(id: number, req: UpdatePaymentAccount
|
||||
}
|
||||
|
||||
export async function deletePaymentAccount(id: number) {
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(`/payment-accounts/${id}`)
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
||||
`/payment-accounts/${id}`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function setDefaultPaymentAccount(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<{ updated: boolean }>>(`/payment-accounts/${id}/set-default`)
|
||||
const { data } = await apiClient.post<ApiResponse<{ updated: boolean }>>(
|
||||
`/payment-accounts/${id}/set-default`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -109,9 +116,12 @@ export async function createWithdrawal(req: CreateWithdrawalRequest) {
|
||||
}
|
||||
|
||||
export async function fetchWithdrawals(page = 1, pageSize = 20) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<WithdrawalRequest>>>('/withdrawals', {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<WithdrawalRequest>>>(
|
||||
'/withdrawals',
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -121,6 +131,8 @@ export async function fetchWithdrawal(id: number) {
|
||||
}
|
||||
|
||||
export async function cancelWithdrawal(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<{ cancelled: boolean }>>(`/withdrawals/${id}/cancel`)
|
||||
const { data } = await apiClient.post<ApiResponse<{ cancelled: boolean }>>(
|
||||
`/withdrawals/${id}/cancel`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ const form = ref<CreatePaymentAccountRequest>({
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
val => {
|
||||
if (val) {
|
||||
if (props.account) {
|
||||
// 编辑模式:只能修改部分字段
|
||||
@@ -157,16 +157,9 @@ function removeImage(index: number) {
|
||||
width="500px"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
>
|
||||
<el-form
|
||||
:model="form"
|
||||
label-width="100px"
|
||||
label-position="left"
|
||||
>
|
||||
<el-form :model="form" label-width="100px" label-position="left">
|
||||
<el-form-item label="账号类型" required>
|
||||
<el-radio-group
|
||||
v-model="form.account_type"
|
||||
:disabled="!!account"
|
||||
>
|
||||
<el-radio-group v-model="form.account_type" :disabled="!!account">
|
||||
<el-radio-button value="alipay">支付宝</el-radio-button>
|
||||
<el-radio-button value="wechat">微信</el-radio-button>
|
||||
<el-radio-button value="bank">银行卡</el-radio-button>
|
||||
@@ -195,26 +188,19 @@ function removeImage(index: number) {
|
||||
form.account_type === 'alipay'
|
||||
? '支付宝账号(手机号或邮箱)'
|
||||
: form.account_type === 'wechat'
|
||||
? '微信号'
|
||||
: '银行卡号'
|
||||
? '微信号'
|
||||
: '银行卡号'
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="form.account_type === 'bank'">
|
||||
<el-form-item label="银行名称" required>
|
||||
<el-input
|
||||
v-model="form.bank_name"
|
||||
placeholder="如:中国工商银行"
|
||||
:disabled="!!account"
|
||||
/>
|
||||
<el-input v-model="form.bank_name" placeholder="如:中国工商银行" :disabled="!!account" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开户支行">
|
||||
<el-input
|
||||
v-model="form.bank_branch"
|
||||
placeholder="如:北京朝阳支行(可选)"
|
||||
/>
|
||||
<el-input v-model="form.bank_branch" placeholder="如:北京朝阳支行(可选)" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
@@ -224,7 +210,7 @@ function removeImage(index: number) {
|
||||
</div>
|
||||
<div class="certificate-upload">
|
||||
<div v-for="(url, index) in form.certificate_urls" :key="url" class="certificate-item">
|
||||
<img :src="url" alt="凭证">
|
||||
<img :src="url" alt="凭证" />
|
||||
<el-button
|
||||
:icon="Delete"
|
||||
circle
|
||||
@@ -234,14 +220,18 @@ function removeImage(index: number) {
|
||||
@click="removeImage(index)"
|
||||
/>
|
||||
</div>
|
||||
<label v-if="!form.certificate_urls || form.certificate_urls.length < 3" class="upload-btn" :class="{ 'is-uploading': uploading }">
|
||||
<label
|
||||
v-if="!form.certificate_urls || form.certificate_urls.length < 3"
|
||||
class="upload-btn"
|
||||
:class="{ 'is-uploading': uploading }"
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style="display: none"
|
||||
:disabled="uploading"
|
||||
@change="handleUpload"
|
||||
>
|
||||
/>
|
||||
<el-icon v-if="uploading" class="is-loading"><Loading /></el-icon>
|
||||
<el-icon v-else><Upload /></el-icon>
|
||||
<span>{{ uploading ? '上传中...' : '上传凭证' }}</span>
|
||||
@@ -271,14 +261,8 @@ function removeImage(index: number) {
|
||||
</el-alert>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="emit('update:modelValue', false)">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="submitting"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
<el-button @click="emit('update:modelValue', false)"> 取消 </el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
||||
{{ account ? '更新' : '添加' }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
@@ -106,12 +106,7 @@ const canAddMore = computed(() => accounts.value.length < 5)
|
||||
<h2>收款账号管理</h2>
|
||||
<p class="page-desc">管理您的收款账号,用于提现时接收资金(最多5个)</p>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="canAddMore"
|
||||
type="primary"
|
||||
:icon="Plus"
|
||||
@click="openCreateDialog"
|
||||
>
|
||||
<el-button v-if="canAddMore" type="primary" :icon="Plus" @click="openCreateDialog">
|
||||
添加收款账号
|
||||
</el-button>
|
||||
<el-tag v-else type="info">已达账号数量上限</el-tag>
|
||||
@@ -136,19 +131,12 @@ const canAddMore = computed(() => accounts.value.length < 5)
|
||||
>
|
||||
<div class="account-header">
|
||||
<div class="account-type">
|
||||
<el-tag
|
||||
:color="accountTypeColor(account.account_type)"
|
||||
effect="dark"
|
||||
size="large"
|
||||
>
|
||||
<el-tag :color="accountTypeColor(account.account_type)" effect="dark" size="large">
|
||||
{{ accountTypeLabel(account.account_type) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="account-actions">
|
||||
<el-tooltip
|
||||
:content="account.is_default ? '默认账号' : '设为默认'"
|
||||
placement="top"
|
||||
>
|
||||
<el-tooltip :content="account.is_default ? '默认账号' : '设为默认'" placement="top">
|
||||
<el-button
|
||||
:icon="account.is_default ? StarFilled : Star"
|
||||
:type="account.is_default ? 'warning' : 'default'"
|
||||
@@ -157,12 +145,7 @@ const canAddMore = computed(() => accounts.value.length < 5)
|
||||
@click="handleSetDefault(account)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
:icon="Edit"
|
||||
circle
|
||||
size="small"
|
||||
@click="openEditDialog(account)"
|
||||
/>
|
||||
<el-button :icon="Edit" circle size="small" @click="openEditDialog(account)" />
|
||||
<el-button
|
||||
:icon="Delete"
|
||||
circle
|
||||
@@ -193,16 +176,14 @@ const canAddMore = computed(() => accounts.value.length < 5)
|
||||
</div>
|
||||
|
||||
<div class="account-footer">
|
||||
<span class="created-time">添加于 {{ new Date(account.created_at).toLocaleDateString() }}</span>
|
||||
<span class="created-time"
|
||||
>添加于 {{ new Date(account.created_at).toLocaleDateString() }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PaymentAccountDialog
|
||||
v-model="showDialog"
|
||||
:account="editingAccount"
|
||||
@saved="loadAccounts"
|
||||
/>
|
||||
<PaymentAccountDialog v-model="showDialog" :account="editingAccount" @saved="loadAccounts" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,7 +2,16 @@
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { CircleCheck, Coin, Loading, Lock, Money, Refresh, Tickets, Wallet as WalletIcon } from '@element-plus/icons-vue'
|
||||
import {
|
||||
CircleCheck,
|
||||
Coin,
|
||||
Loading,
|
||||
Lock,
|
||||
Money,
|
||||
Refresh,
|
||||
Tickets,
|
||||
Wallet as WalletIcon,
|
||||
} from '@element-plus/icons-vue'
|
||||
import QRCode from 'qrcode'
|
||||
|
||||
import {
|
||||
@@ -67,7 +76,7 @@ const walletMetrics = computed(() => {
|
||||
onMounted(loadWallet)
|
||||
onBeforeUnmount(stopRechargePolling)
|
||||
|
||||
watch(rechargeDialogVisible, (visible) => {
|
||||
watch(rechargeDialogVisible, visible => {
|
||||
if (!visible) {
|
||||
stopRechargePolling()
|
||||
}
|
||||
@@ -76,7 +85,10 @@ watch(rechargeDialogVisible, (visible) => {
|
||||
async function loadWallet() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [balance, result] = await Promise.all([fetchWalletBalance(), fetchWalletLedger(currentPage.value, currentPageSize.value)])
|
||||
const [balance, result] = await Promise.all([
|
||||
fetchWalletBalance(),
|
||||
fetchWalletLedger(currentPage.value, currentPageSize.value),
|
||||
])
|
||||
account.value = balance
|
||||
ledger.value = result.items
|
||||
total.value = result.total
|
||||
@@ -275,7 +287,12 @@ function amountPrefix(direction: string) {
|
||||
</div>
|
||||
|
||||
<div v-if="account" class="wallet-metric-grid">
|
||||
<div v-for="item in walletMetrics" :key="item.label" class="wallet-metric-card" :class="`is-${item.tone}`">
|
||||
<div
|
||||
v-for="item in walletMetrics"
|
||||
:key="item.label"
|
||||
class="wallet-metric-card"
|
||||
:class="`is-${item.tone}`"
|
||||
>
|
||||
<div class="metric-icon">
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
</div>
|
||||
@@ -311,7 +328,12 @@ function amountPrefix(direction: string) {
|
||||
</div>
|
||||
<div class="recharge-action-row">
|
||||
<el-input-number v-model="devRechargeAmount" :min="0.01" :precision="2" :step="1" />
|
||||
<el-button type="primary" :icon="Coin" :loading="devRecharging" @click="handleDevRecharge">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Coin"
|
||||
:loading="devRecharging"
|
||||
@click="handleDevRecharge"
|
||||
>
|
||||
创建测试支付
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -381,7 +403,11 @@ function amountPrefix(direction: string) {
|
||||
<div class="recharge-cashier">
|
||||
<div class="cashier-amount">
|
||||
<span>支付金额</span>
|
||||
<strong>{{ activeRechargePayment ? formatMoney(activeRechargePayment.amount_cent / 100) : formatMoney(devRechargeAmount) }}</strong>
|
||||
<strong>{{
|
||||
activeRechargePayment
|
||||
? formatMoney(activeRechargePayment.amount_cent / 100)
|
||||
: formatMoney(devRechargeAmount)
|
||||
}}</strong>
|
||||
</div>
|
||||
<div v-if="rechargePayURL()" class="cashier-qr">
|
||||
<div class="qr-box">
|
||||
@@ -406,7 +432,9 @@ function amountPrefix(direction: string) {
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="rechargeDialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" :loading="checkingRecharge" @click="checkDevRechargeStatus">查询支付状态</el-button>
|
||||
<el-button type="primary" :loading="checkingRecharge" @click="checkDevRechargeStatus"
|
||||
>查询支付状态</el-button
|
||||
>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</section>
|
||||
@@ -426,9 +454,7 @@ function amountPrefix(direction: string) {
|
||||
padding: 28px;
|
||||
border: 1px solid #e6eaf2;
|
||||
border-radius: 8px;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 122, 0, 0.08), rgba(15, 118, 110, 0.06)),
|
||||
#ffffff;
|
||||
background: linear-gradient(135deg, rgba(255, 122, 0, 0.08), rgba(15, 118, 110, 0.06)), #ffffff;
|
||||
box-shadow: 0 14px 36px rgba(17, 24, 39, 0.06);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,9 +175,7 @@ function accountTypeLabel(type: string) {
|
||||
<el-icon><Wallet /></el-icon>
|
||||
可用余额
|
||||
</div>
|
||||
<div class="balance-value">
|
||||
¥{{ account?.available_balance.toFixed(2) || '0.00' }}
|
||||
</div>
|
||||
<div class="balance-value">¥{{ account?.available_balance.toFixed(2) || '0.00' }}</div>
|
||||
</div>
|
||||
<div class="balance-item">
|
||||
<div class="balance-label">
|
||||
@@ -201,9 +199,7 @@ function accountTypeLabel(type: string) {
|
||||
|
||||
<div v-if="paymentAccounts.length === 0" class="no-accounts">
|
||||
<el-empty description="还没有收款账号">
|
||||
<el-button type="primary" @click="goToPaymentAccounts">
|
||||
添加收款账号
|
||||
</el-button>
|
||||
<el-button type="primary" @click="goToPaymentAccounts"> 添加收款账号 </el-button>
|
||||
</el-empty>
|
||||
</div>
|
||||
|
||||
@@ -223,7 +219,9 @@ function accountTypeLabel(type: string) {
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>
|
||||
<el-tag size="small" style="margin-right: 8px">{{ accountTypeLabel(acc.account_type) }}</el-tag>
|
||||
<el-tag size="small" style="margin-right: 8px">{{
|
||||
accountTypeLabel(acc.account_type)
|
||||
}}</el-tag>
|
||||
{{ acc.account_name }} ({{ acc.account_no }})
|
||||
</span>
|
||||
<el-tag v-if="acc.is_default" type="warning" size="small">默认</el-tag>
|
||||
@@ -231,12 +229,8 @@ function accountTypeLabel(type: string) {
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div style="margin-top: 8px; display: flex; gap: 8px">
|
||||
<el-button size="small" @click="goToPaymentAccounts">
|
||||
添加收款账号
|
||||
</el-button>
|
||||
<el-button size="small" text @click="goToPaymentAccounts">
|
||||
管理收款账号
|
||||
</el-button>
|
||||
<el-button size="small" @click="goToPaymentAccounts"> 添加收款账号 </el-button>
|
||||
<el-button size="small" text @click="goToPaymentAccounts"> 管理收款账号 </el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -262,7 +256,9 @@ function accountTypeLabel(type: string) {
|
||||
</el-form-item>
|
||||
|
||||
<el-alert
|
||||
v-if="withdrawForm.amount > 0 && account && withdrawForm.amount > account.available_balance"
|
||||
v-if="
|
||||
withdrawForm.amount > 0 && account && withdrawForm.amount > account.available_balance
|
||||
"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
@@ -271,12 +267,7 @@ function accountTypeLabel(type: string) {
|
||||
余额不足,可用余额:¥{{ account.available_balance.toFixed(2) }}
|
||||
</el-alert>
|
||||
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<el-alert type="info" :closable="false" show-icon style="margin-bottom: 16px">
|
||||
<template #title>
|
||||
<div style="font-size: 13px">
|
||||
<strong>提现说明</strong>
|
||||
@@ -313,17 +304,11 @@ function accountTypeLabel(type: string) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="withdrawals"
|
||||
stripe
|
||||
>
|
||||
<el-table v-loading="loading" :data="withdrawals" stripe>
|
||||
<el-table-column prop="withdraw_no" label="提现单号" min-width="180" />
|
||||
<el-table-column label="提现金额" width="120">
|
||||
<template #default="{ row }">
|
||||
<span style="color: #f56c6c; font-weight: 600">
|
||||
¥{{ row.amount.toFixed(2) }}
|
||||
</span>
|
||||
<span style="color: #f56c6c; font-weight: 600"> ¥{{ row.amount.toFixed(2) }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款方式" width="150">
|
||||
|
||||
Reference in New Issue
Block a user