提现管理
This commit is contained in:
parent
3655207bfa
commit
0f00347a00
@ -28,3 +28,9 @@ export const CodeAuth=(params:any)=>request.put("/v1/auth/update_password_auth",
|
||||
|
||||
//提现
|
||||
export const tixian=(params:any)=>request.put("/v1/balance/withdraw",params)
|
||||
|
||||
//充值记录
|
||||
export const getUpList=(params:any)=>request.get("/v1/balance/top_up_list",{params})
|
||||
|
||||
//提现记录
|
||||
export const getWithdrawList=(params:any)=>request.get("/v1/balance/withdraw_list",{params})
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin: 20px;">
|
||||
<a-row :gutter="[16, 16]">
|
||||
<a-col :span="24">
|
||||
<a-card title="基本设置">
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="recharge-page">
|
||||
<!-- 面包屑导航 -->
|
||||
<a-breadcrumb class="breadcrumb">
|
||||
<!-- <a-breadcrumb class="breadcrumb">
|
||||
<a-breadcrumb-item>
|
||||
<router-link to="/">首页</router-link>
|
||||
</a-breadcrumb-item>
|
||||
<a-breadcrumb-item>我的余额</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</a-breadcrumb> -->
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<div class="page-header">
|
||||
<!-- <div class="page-header">
|
||||
<h1 class="page-title">我的余额</h1>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="main-content">
|
||||
<!-- 余额和充值部分 -->
|
||||
@ -22,40 +22,28 @@
|
||||
<div class="balance-info">
|
||||
<div class="balance-amount">
|
||||
<div class="amount-label">账户余额</div>
|
||||
<div class="amount-value">¥{{ formatCurrency(balance) }}</div>
|
||||
<div class="amount-value">¥{{ formatCurrency(userInfo.balance || 0) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="recharge-content">
|
||||
<!-- 充值金额选择 -->
|
||||
<div class="recharge-section">
|
||||
<h3 class="section-title">充值金额(¥)</h3>
|
||||
<div class="amount-options">
|
||||
<div
|
||||
v-for="option in amountOptions"
|
||||
:key="option.value"
|
||||
<div v-for="option in amountOptions" :key="option.value"
|
||||
:class="['amount-option', { 'selected': selectedAmount === option.value }]"
|
||||
@click="selectAmount(option.value)"
|
||||
>
|
||||
@click="selectAmount(option.value)">
|
||||
<div class="amount-number">¥{{ option.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义金额输入 -->
|
||||
<div class="recharge-section">
|
||||
<h3 class="section-title">自定义充值金额</h3>
|
||||
<div class="custom-amount">
|
||||
<a-input
|
||||
v-model:value="customAmount"
|
||||
placeholder="请输入金额"
|
||||
size="large"
|
||||
:disabled="loading"
|
||||
@change="handleCustomAmountChange"
|
||||
>
|
||||
<a-input v-model:value="customAmount" placeholder="请输入金额" size="large" :disabled="loading"
|
||||
@change="handleCustomAmountChange">
|
||||
<template #prefix>
|
||||
<span class="input-prefix">¥</span>
|
||||
</template>
|
||||
@ -70,12 +58,9 @@
|
||||
<div class="payment-methods-container">
|
||||
<div class="payment-methods-title">充值方式</div>
|
||||
<div class="payment-methods-row">
|
||||
<div
|
||||
v-for="method in paymentMethods"
|
||||
:key="method.value"
|
||||
<div v-for="method in paymentMethods" :key="method.value"
|
||||
:class="['payment-method-item', { 'selected': selectedPaymentMethod === method.value }]"
|
||||
@click="selectPaymentMethod(method.value)"
|
||||
>
|
||||
@click="selectPaymentMethod(method.value)">
|
||||
<div class="method-icon">
|
||||
<component :is="method.icon" />
|
||||
</div>
|
||||
@ -92,14 +77,8 @@
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="action-section">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="loading"
|
||||
:disabled="!canRecharge"
|
||||
@click="handleRecharge"
|
||||
class="recharge-btn"
|
||||
>
|
||||
<a-button type="primary" size="large" :loading="loading" :disabled="!canRecharge" @click="handleRecharge"
|
||||
class="recharge-btn">
|
||||
立即充值
|
||||
</a-button>
|
||||
</div>
|
||||
@ -111,14 +90,12 @@
|
||||
<a-card class="records-card" title="充值记录">
|
||||
<!-- 筛选条件 -->
|
||||
<div class="filter-section">
|
||||
<a-range-picker
|
||||
v-model:value="dateRange"
|
||||
format="YYYY-MM-DD"
|
||||
placeholder="开始时间 - 结束时间"
|
||||
style="width: 300px; margin-right: 16px;"
|
||||
/>
|
||||
<a-range-picker v-model:value="dateRange" format="YYYY-MM-DD" placeholder="开始时间 - 结束时间"
|
||||
style="width: 300px; margin-right: 16px;" />
|
||||
<a-button type="primary" @click="handleSearch" :loading="searchLoading">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
查询
|
||||
</a-button>
|
||||
<a-button style="margin-left: 8px" @click="handleReset">
|
||||
@ -128,15 +105,8 @@
|
||||
|
||||
<!-- 记录表格 -->
|
||||
<div class="records-table">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="rechargeRecords"
|
||||
:pagination="pagination"
|
||||
:loading="tableLoading"
|
||||
@change="handleTableChange"
|
||||
size="middle"
|
||||
bordered
|
||||
>
|
||||
<a-table :columns="columns" :data-source="rechargeRecords" :pagination="pagination" :loading="tableLoading"
|
||||
@change="handleTableChange" size="middle" bordered>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'amount'">
|
||||
<span class="amount-cell">¥{{ record.amount }}</span>
|
||||
@ -173,14 +143,8 @@
|
||||
</div>
|
||||
|
||||
<!-- 充值确认模态框 -->
|
||||
<a-modal
|
||||
v-model:visible="rechargeModalVisible"
|
||||
title="确认充值"
|
||||
:confirm-loading="modalLoading"
|
||||
@ok="handleRechargeConfirm"
|
||||
@cancel="handleRechargeCancel"
|
||||
centered
|
||||
>
|
||||
<a-modal v-model:visible="rechargeModalVisible" title="确认充值" :confirm-loading="modalLoading"
|
||||
@ok="handleRechargeConfirm" @cancel="handleRechargeCancel" centered>
|
||||
<div class="recharge-confirm">
|
||||
<div class="confirm-item">
|
||||
<span class="confirm-label">充值金额:</span>
|
||||
@ -192,11 +156,11 @@
|
||||
</div>
|
||||
<div class="confirm-item">
|
||||
<span class="confirm-label">当前余额:</span>
|
||||
<span class="confirm-value">¥{{ formatCurrency(balance) }}</span>
|
||||
<span class="confirm-value">¥{{ formatCurrency(userInfo.balance) }}</span>
|
||||
</div>
|
||||
<div class="confirm-item">
|
||||
<span class="confirm-label">充值后余额:</span>
|
||||
<span class="confirm-value highlight">¥{{ formatCurrency(balance + selectedRechargeAmount) }}</span>
|
||||
<span class="confirm-value highlight">¥{{ formatCurrency(userInfo.balance + selectedRechargeAmount) }}</span>
|
||||
</div>
|
||||
<div class="confirm-tips">
|
||||
<InfoCircleOutlined />
|
||||
@ -208,7 +172,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, } from 'vue'
|
||||
import {
|
||||
SearchOutlined,
|
||||
CheckCircleFilled,
|
||||
@ -219,9 +183,10 @@ import {
|
||||
} from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { getUpList } from "@/apis/home"
|
||||
|
||||
// 用户余额
|
||||
const balance = ref(5.00)
|
||||
const balance = ref(0)
|
||||
|
||||
// 充值金额选项
|
||||
const amountOptions = ref([
|
||||
@ -248,7 +213,7 @@ const loading = ref(false)
|
||||
const tableLoading = ref(false)
|
||||
const searchLoading = ref(false)
|
||||
const modalLoading = ref(false)
|
||||
|
||||
const userInfo = ref({})
|
||||
// 模态框
|
||||
const rechargeModalVisible = ref(false)
|
||||
|
||||
@ -362,6 +327,7 @@ const handleRecharge = () => {
|
||||
// 确认充值
|
||||
const handleRechargeConfirm = () => {
|
||||
modalLoading.value = true
|
||||
|
||||
setTimeout(() => {
|
||||
balance.value += selectedRechargeAmount.value
|
||||
const now = new Date()
|
||||
@ -375,12 +341,10 @@ const handleRechargeConfirm = () => {
|
||||
}
|
||||
rechargeRecords.value.unshift(newRecord)
|
||||
pagination.total += 1
|
||||
|
||||
// 重置表单
|
||||
selectedAmount.value = 0
|
||||
customAmount.value = ''
|
||||
customAmountError.value = ''
|
||||
|
||||
modalLoading.value = false
|
||||
rechargeModalVisible.value = false
|
||||
message.success(`充值成功!¥${selectedRechargeAmount.value} 已到账`)
|
||||
@ -411,61 +375,33 @@ const viewDetail = (record) => {
|
||||
message.info(`充值¥${record.amount},时间:${formatDateTime(record.rechargeTime)}`)
|
||||
}
|
||||
|
||||
// 加载记录(含模拟数据)
|
||||
const loadRechargeRecords = () => {
|
||||
tableLoading.value = true
|
||||
setTimeout(() => {
|
||||
const mockData = generateMockData(35)
|
||||
let filtered = [...mockData]
|
||||
|
||||
if (dateRange.value?.length === 2) {
|
||||
const start = dayjs(dateRange.value[0]).startOf('day')
|
||||
const end = dayjs(dateRange.value[1]).endOf('day')
|
||||
filtered = filtered.filter(r => {
|
||||
const d = dayjs(r.rechargeTime)
|
||||
return d.isAfter(start) && d.isBefore(end)
|
||||
})
|
||||
}
|
||||
|
||||
const startIdx = (pagination.current - 1) * pagination.pageSize
|
||||
rechargeRecords.value = filtered.slice(startIdx, startIdx + pagination.pageSize)
|
||||
pagination.total = filtered.length
|
||||
|
||||
tableLoading.value = false
|
||||
searchLoading.value = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 生成模拟数据(无算力点)
|
||||
const generateMockData = (count) => {
|
||||
const methods = ['alipay', 'wechat', 'bank']
|
||||
const statuses = ['success', 'processing', 'failed', 'pending']
|
||||
let currentBalance = 5.00
|
||||
const data = []
|
||||
|
||||
for (let i = 1; i <= count; i++) {
|
||||
const amount = [100, 500, 1000, 5000][Math.floor(Math.random() * 4)]
|
||||
const method = methods[Math.floor(Math.random() * methods.length)]
|
||||
const status = statuses[Math.floor(Math.random() * statuses.length)]
|
||||
|
||||
if (status === 'success') currentBalance += amount
|
||||
|
||||
data.push({
|
||||
key: i,
|
||||
amount: amount,
|
||||
rechargeTime: dayjs().subtract(Math.floor(Math.random() * 30), 'day').toDate(),
|
||||
paymentMethod: method,
|
||||
accountBalance: currentBalance,
|
||||
status: status
|
||||
})
|
||||
const loadRechargeRecords = async () => {
|
||||
try {
|
||||
tableLoading.value = true
|
||||
const params = {
|
||||
start_at: dateRange.value[0],
|
||||
end_at: dateRange.value[1],
|
||||
page_num: pagination.current,
|
||||
page_size: pagination.pageSize
|
||||
}
|
||||
const res = await getUpList(params)
|
||||
rechargeRecords.value = res.data
|
||||
pagination.total = res.total
|
||||
tableLoading.value = false
|
||||
} catch (error) {
|
||||
tableLoading.value = false
|
||||
}
|
||||
|
||||
return data.sort((a, b) => new Date(b.rechargeTime) - new Date(a.rechargeTime))
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
rechargeRecords.value = generateMockData(15)
|
||||
pagination.total = rechargeRecords.value.length
|
||||
const userInfoStr = localStorage.getItem('userInfo');
|
||||
if (userInfoStr) {
|
||||
userInfo.value = JSON.parse(userInfoStr);
|
||||
}
|
||||
loadRechargeRecords()
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -492,7 +428,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.main-content {
|
||||
max-width: 1200px;
|
||||
/* max-width: 1200px; */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@ -609,9 +545,17 @@ onMounted(() => {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.payment-method-item:nth-child(1) .method-icon { color: #1677ff; }
|
||||
.payment-method-item:nth-child(2) .method-icon { color: #07c160; }
|
||||
.payment-method-item:nth-child(3) .method-icon { color: #722ed1; }
|
||||
.payment-method-item:nth-child(1) .method-icon {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
.payment-method-item:nth-child(2) .method-icon {
|
||||
color: #07c160;
|
||||
}
|
||||
|
||||
.payment-method-item:nth-child(3) .method-icon {
|
||||
color: #722ed1;
|
||||
}
|
||||
|
||||
.method-info {
|
||||
flex: 1;
|
||||
|
||||
@ -13,13 +13,8 @@
|
||||
<div class="balance-desc">
|
||||
当前可提现金额,提现将在1-3个工作日内到账
|
||||
</div>
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
class="w-full mt-4"
|
||||
@click="showWithdrawalModal"
|
||||
:disabled="accountInfo.availableBalance <= 0"
|
||||
>
|
||||
<a-button type="primary" class="w-full mt-4" @click="showWithdrawalModal"
|
||||
:disabled="accountInfo.availableBalance <= 0">
|
||||
去提现
|
||||
</a-button>
|
||||
</div>
|
||||
@ -30,49 +25,17 @@
|
||||
<!-- 提现记录查询 -->
|
||||
<a-card title="提现记录" class="mb-6">
|
||||
<template #extra>
|
||||
<a-range-picker
|
||||
v-model:value="searchParams.dateRange"
|
||||
:format="dateFormat"
|
||||
@change="handleDateChange"
|
||||
/>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 查询条件 -->
|
||||
<a-form layout="inline" :model="searchParams" class="mb-4">
|
||||
<a-form-item label="提现单号">
|
||||
<a-input
|
||||
v-model:value="searchParams.orderNo"
|
||||
placeholder="请输入提现单号"
|
||||
@pressEnter="handleSearch"
|
||||
/>
|
||||
<a-input v-model:value="searchParams.orderNo" placeholder="请输入提现单号" @pressEnter="handleSearch" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="账户">
|
||||
<a-select
|
||||
v-model:value="searchParams.account"
|
||||
placeholder="请选择账户"
|
||||
style="width: 150px"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option v-for="account in accountOptions" :key="account.value">
|
||||
{{ account.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-form-item label="时间">
|
||||
<a-range-picker v-model:value="searchParams.dateRange" :format="dateFormat" @change="handleDateChange" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
v-model:value="searchParams.status"
|
||||
placeholder="请选择状态"
|
||||
style="width: 150px"
|
||||
allowClear
|
||||
>
|
||||
<a-select-option value="pending">处理中</a-select-option>
|
||||
<a-select-option value="success">成功</a-select-option>
|
||||
<a-select-option value="failed">失败</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||||
<a-button @click="handleReset" class="ml-2">重置</a-button>
|
||||
@ -80,14 +43,8 @@
|
||||
</a-form>
|
||||
|
||||
<!-- 提现记录表格 -->
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="withdrawalRecords"
|
||||
:pagination="pagination"
|
||||
@change="handleTableChange"
|
||||
:loading="loading"
|
||||
rowKey="id"
|
||||
>
|
||||
<a-table :columns="columns" :data-source="withdrawalRecords" :pagination="pagination" @change="handleTableChange"
|
||||
:loading="loading" rowKey="id">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'amount'">
|
||||
<span class="amount-cell">{{ formatCurrency(record.amount) }}元</span>
|
||||
@ -115,29 +72,14 @@
|
||||
</a-card>
|
||||
|
||||
<!-- 提现弹窗 -->
|
||||
<a-modal
|
||||
v-model:visible="withdrawalModal.visible"
|
||||
title="提现申请"
|
||||
@ok="handleWithdrawalSubmit"
|
||||
@cancel="handleWithdrawalCancel"
|
||||
:confirm-loading="withdrawalModal.confirming"
|
||||
>
|
||||
<a-form
|
||||
ref="withdrawalFormRef"
|
||||
:model="withdrawalForm"
|
||||
:rules="withdrawalRules"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-modal v-model:visible="withdrawalModal.visible" title="提现申请" @ok="handleWithdrawalSubmit"
|
||||
@cancel="handleWithdrawalCancel" :confirm-loading="withdrawalModal.confirming">
|
||||
<a-form ref="withdrawalFormRef" :model="withdrawalForm" :rules="withdrawalRules" layout="vertical">
|
||||
<a-form-item label="提现金额" name="amount">
|
||||
<a-input-number
|
||||
v-model:value="withdrawalForm.amount"
|
||||
placeholder="请输入提现金额"
|
||||
:min="1"
|
||||
:max="accountInfo.availableBalance"
|
||||
style="width: 100%"
|
||||
<a-input-number v-model:value="withdrawalForm.amount" placeholder="请输入提现金额" :min="1"
|
||||
:max="accountInfo.availableBalance" style="width: 100%"
|
||||
:formatter="value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
|
||||
:parser="value => value.replace(/¥\s?|(,*)/g, '')"
|
||||
/>
|
||||
:parser="value => value.replace(/¥\s?|(,*)/g, '')" />
|
||||
<div class="amount-hint mt-2">
|
||||
<div>可提现金额: {{ formatCurrency(accountInfo.availableBalance) }}元</div>
|
||||
<div>单笔最低提现: 1元</div>
|
||||
@ -145,23 +87,16 @@
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="提现到账账户" name="accountId">
|
||||
<a-select
|
||||
v-model:value="withdrawalForm.accountId"
|
||||
placeholder="请选择提现账户"
|
||||
>
|
||||
<a-select v-model:value="withdrawalForm.accountId" placeholder="请选择提现账户">
|
||||
<a-select-option :value="accountInfo.id">
|
||||
{{ accountInfo.bank }} ({{ accountInfo.number }})
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-alert
|
||||
v-if="withdrawalForm.amount"
|
||||
:message="`预计到账金额: ${formatCurrency(calculateActualAmount(withdrawalForm.amount))}元`"
|
||||
type="info"
|
||||
show-icon
|
||||
class="mb-4"
|
||||
/>
|
||||
<a-alert v-if="withdrawalForm.amount"
|
||||
:message="`预计到账金额: ${formatCurrency(calculateActualAmount(withdrawalForm.amount))}元`" type="info" show-icon
|
||||
class="mb-4" />
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
@ -171,7 +106,7 @@
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import { getWithdrawList } from "@/apis/home"
|
||||
// 账户信息
|
||||
const accountInfo = reactive({
|
||||
id: '1',
|
||||
@ -294,51 +229,19 @@ onMounted(() => {
|
||||
// 获取提现记录
|
||||
const fetchWithdrawalRecords = async () => {
|
||||
loading.value = true
|
||||
console.log(searchParams)
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// 模拟数据
|
||||
const mockData = Array.from({ length: 35 }, (_, index) => ({
|
||||
id: index + 1,
|
||||
orderNo: `TX${Date.now()}${index}`,
|
||||
bank: ['工商银行', '建设银行', '农业银行'][index % 3],
|
||||
accountNumber: `6228 **** **** ${1000 + index}`,
|
||||
amount: Math.floor(Math.random() * 10000) + 100,
|
||||
fee: Math.floor(Math.random() * 10),
|
||||
status: ['pending', 'success', 'failed'][index % 3],
|
||||
createdAt: dayjs().subtract(index, 'day').format('YYYY-MM-DD HH:mm:ss'),
|
||||
completedAt: index % 3 !== 0 ? dayjs().subtract(index, 'day').add(1, 'hour').format('YYYY-MM-DD HH:mm:ss') : null
|
||||
}))
|
||||
|
||||
// 应用筛选
|
||||
let filteredData = mockData
|
||||
if (searchParams.orderNo) {
|
||||
filteredData = filteredData.filter(item => item.orderNo.includes(searchParams.orderNo))
|
||||
let params = {
|
||||
withdraw_number: searchParams.orderNo,
|
||||
page_num: pagination.current,
|
||||
page_size: pagination.pageSize,
|
||||
start_at: formatDate(searchParams.dateRange[0]),
|
||||
end_at: formatDate(searchParams.dateRange[1]),
|
||||
}
|
||||
if (searchParams.account) {
|
||||
filteredData = filteredData.filter(item => item.accountNumber.endsWith(searchParams.account))
|
||||
}
|
||||
if (searchParams.status) {
|
||||
filteredData = filteredData.filter(item => item.status === searchParams.status)
|
||||
}
|
||||
|
||||
// 应用日期范围筛选
|
||||
if (searchParams.dateRange && searchParams.dateRange[0] && searchParams.dateRange[1]) {
|
||||
const start = searchParams.dateRange[0]
|
||||
const end = searchParams.dateRange[1]
|
||||
filteredData = filteredData.filter(item => {
|
||||
const date = dayjs(item.createdAt)
|
||||
return date.isAfter(start) && date.isBefore(end)
|
||||
})
|
||||
}
|
||||
|
||||
// 分页
|
||||
const start = (pagination.current - 1) * pagination.pageSize
|
||||
const end = start + pagination.pageSize
|
||||
withdrawalRecords.value = filteredData.slice(start, end)
|
||||
pagination.total = filteredData.length
|
||||
const res = await getWithdrawList(params)
|
||||
console.log(res)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
message.error('获取提现记录失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
@ -428,7 +331,7 @@ const formatCurrency = (amount) => {
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateString) => {
|
||||
return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss')
|
||||
return dayjs(dateString).format('YYYY-MM-DD')
|
||||
}
|
||||
|
||||
// 获取状态颜色
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<div class="money">¥ {{ formatAmount(userInfo.balance || 0) }}</div>
|
||||
<div class="money-btn">
|
||||
<div><a-button type="primary" size="small" @click="goToRecharge">充值</a-button></div>
|
||||
<div><a-button size="small" @click="dialogWithDrawal = true">提现</a-button></div>
|
||||
<div><a-button size="small" @click="router.push('/layout/admin/deposit')">提现</a-button></div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
@ -21,7 +21,8 @@
|
||||
<a-card title="算力点" :bordered="false" class="card computing-card">
|
||||
<div class="computing-content">
|
||||
<div class="computing-amount">
|
||||
<span class="amount-value">{{ '¥' + formatAmount(userInfo.computingPowerPoint || 0) }}</span>
|
||||
<span class="amount-value">{{ '¥' + formatAmount(userInfo.computingPowerPoint || 0)
|
||||
}}</span>
|
||||
<!-- <span class="amount-unit">点</span> -->
|
||||
</div>
|
||||
<div class="computing-actions">
|
||||
@ -45,47 +46,48 @@
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- 底部账单区域 -->
|
||||
<div class="bill-section">
|
||||
<div class="bill-header">
|
||||
<h3 class="bill-title">消费明细</h3>
|
||||
</div>
|
||||
<!-- 账单表格 -->
|
||||
<a-table :columns="columns" :data-source="billData" :pagination="pagination" @change="handleTableChange"
|
||||
:loading="loading" class="bill-table" :scroll="{ x: 1200 }">
|
||||
<!-- 流水号列 -->
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span class="serial-number">{{ record.serialNumber }}</span>
|
||||
</template>
|
||||
<!-- <div class="bill-section">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="充值记录">
|
||||
|
||||
<!-- 交易类型列 -->
|
||||
<template v-else-if="column.key === 'transactionType'">
|
||||
<a-tag :color="getTransactionTypeColor(record.transactionType)">
|
||||
{{ record.transactionType }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<a-table :columns="columns" :data-source="billData" :pagination="pagination"
|
||||
@change="handleTableChange" :loading="loading" class="bill-table" :scroll="{ x: 1200 }">
|
||||
|
||||
<!-- 金额相关列 -->
|
||||
<template
|
||||
v-else-if="['transactionAmount', 'originalPrice', 'discountAmount', 'balancePayment', 'voucherDeduction'].includes(column.key)">
|
||||
<span :class="{
|
||||
'amount-positive': record[column.key] > 0,
|
||||
'amount-negative': record[column.key] < 0
|
||||
}">
|
||||
¥ {{ formatAmount(Math.abs(record[column.key])) }}
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span class="serial-number">{{ record.serialNumber }}</span>
|
||||
</template>
|
||||
|
||||
|
||||
<template v-else-if="column.key === 'transactionType'">
|
||||
<a-tag :color="getTransactionTypeColor(record.transactionType)">
|
||||
{{ record.transactionType }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template
|
||||
v-else-if="['transactionAmount', 'originalPrice', 'discountAmount', 'balancePayment', 'voucherDeduction'].includes(column.key)">
|
||||
<span :class="{
|
||||
'amount-positive': record[column.key] > 0,
|
||||
'amount-negative': record[column.key] < 0
|
||||
}">
|
||||
¥ {{ formatAmount(Math.abs(record[column.key])) }}
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="提现记录">Content of Tab Pane 2</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div> -->
|
||||
</div>
|
||||
<a-modal v-model:open="dialogWithDrawal" title="提现" @ok="handleOk">
|
||||
<a-card>
|
||||
<div style="display: flex;justify-content: flex-start;align-items: center;">
|
||||
<span style="width: 120px;">提现金额:</span>
|
||||
<a-input-number id="inputNumber" v-model:value="withDrawalCount" placeholder="请输入提现金额" style="width: 100%;"/>
|
||||
<a-button type="link" @click="withDrawalCount=userInfo.balance" :loading="btnLoading">全部提现</a-button>
|
||||
<a-input-number id="inputNumber" v-model:value="withDrawalCount" placeholder="请输入提现金额"
|
||||
style="width: 100%;" />
|
||||
<a-button type="link" @click="withDrawalCount = userInfo.balance" :loading="btnLoading">全部提现</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-modal>
|
||||
@ -94,13 +96,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import {message,TableProps} from 'ant-design-vue'
|
||||
import { message, TableProps } from 'ant-design-vue'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
import{tixian} from "@/apis/home"
|
||||
import { tixian } from "@/apis/home"
|
||||
import { fetchUserInfo } from '@/apis/modules/login';
|
||||
const router = useRouter()
|
||||
const activeKey = ref('1')
|
||||
// 资产数据
|
||||
const btnLoading=ref(false)
|
||||
const btnLoading = ref(false)
|
||||
const dialogWithDrawal = ref(false)
|
||||
const withDrawalCount = ref(0)
|
||||
// 表格数据
|
||||
@ -132,66 +135,40 @@ const pagination = ref({
|
||||
// 表格列定义
|
||||
const columns = computed(() => [
|
||||
{
|
||||
title: '流水号',
|
||||
dataIndex: 'serialNumber',
|
||||
key: 'serialNumber',
|
||||
title: '账户',
|
||||
dataIndex: 'account',
|
||||
key: 'account',
|
||||
width: 180,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '交易时间',
|
||||
dataIndex: 'transactionTime',
|
||||
key: 'transactionTime',
|
||||
title: '充值时间',
|
||||
dataIndex: 'CreatedAt',
|
||||
key: 'CreatedAt',
|
||||
width: 170,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '交易类型',
|
||||
dataIndex: 'transactionType',
|
||||
key: 'transactionType',
|
||||
title: '余额',
|
||||
dataIndex: 'balance',
|
||||
key: 'balance',
|
||||
width: 120,
|
||||
filters: [
|
||||
{ text: '充值', value: '充值' },
|
||||
{ text: '消费', value: '消费' },
|
||||
{ text: '提现', value: '提现' },
|
||||
{ text: '退款', value: '退款' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '收支类型',
|
||||
dataIndex: 'productName',
|
||||
key: 'productName',
|
||||
title: '支付方式',
|
||||
dataIndex: 'payMethod',
|
||||
key: 'payMethod',
|
||||
width: 150,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '交易渠道',
|
||||
dataIndex: 'transactionAmount',
|
||||
key: 'transactionAmount',
|
||||
title: '充值金额',
|
||||
dataIndex: 'topUpAmount',
|
||||
key: 'topUpAmount',
|
||||
width: 120,
|
||||
align: 'right'
|
||||
align: 'left'
|
||||
},
|
||||
{
|
||||
title: '交易金额',
|
||||
dataIndex: 'transactionAmount',
|
||||
key: 'transactionAmount',
|
||||
width: 120,
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: '账户余额',
|
||||
dataIndex: 'balancePayment',
|
||||
key: 'balancePayment',
|
||||
width: 120,
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'voucherDeduction',
|
||||
key: 'voucherDeduction',
|
||||
width: 120,
|
||||
align: 'right'
|
||||
}
|
||||
|
||||
])
|
||||
|
||||
// 生命周期
|
||||
@ -245,94 +222,13 @@ const handleTableChange: TableProps['onChange'] = (pag, filters, sorter) => {
|
||||
// 模拟获取账单数据
|
||||
const fetchBillData = () => {
|
||||
loading.value = true
|
||||
|
||||
// 模拟API调用延迟
|
||||
setTimeout(() => {
|
||||
// 模拟数据
|
||||
const mockData: BillRecord[] = [
|
||||
{
|
||||
key: '1',
|
||||
serialNumber: 'TX202401010001',
|
||||
transactionTime: '2024-01-01 10:30:25',
|
||||
transactionType: '充值',
|
||||
productName: '账户充值',
|
||||
transactionAmount: 100.00,
|
||||
originalPrice: 100.00,
|
||||
discountAmount: 0.00,
|
||||
balancePayment: 0.00,
|
||||
voucherDeduction: 0.00
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
serialNumber: 'TX202401010002',
|
||||
transactionTime: '2024-01-01 14:20:15',
|
||||
transactionType: '消费',
|
||||
productName: 'GPU算力服务',
|
||||
transactionAmount: -50.00,
|
||||
originalPrice: 60.00,
|
||||
discountAmount: 10.00,
|
||||
balancePayment: 40.00,
|
||||
voucherDeduction: 10.00
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
serialNumber: 'TX202401020001',
|
||||
transactionTime: '2024-01-02 09:15:30',
|
||||
transactionType: '充值',
|
||||
productName: '账户充值',
|
||||
transactionAmount: 200.00,
|
||||
originalPrice: 200.00,
|
||||
discountAmount: 0.00,
|
||||
balancePayment: 0.00,
|
||||
voucherDeduction: 0.00
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
serialNumber: 'TX202401030001',
|
||||
transactionTime: '2024-01-03 16:45:20',
|
||||
transactionType: '消费',
|
||||
productName: '存储空间',
|
||||
transactionAmount: -30.00,
|
||||
originalPrice: 30.00,
|
||||
discountAmount: 0.00,
|
||||
balancePayment: 30.00,
|
||||
voucherDeduction: 0.00
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
serialNumber: 'TX202401040001',
|
||||
transactionTime: '2024-01-04 11:10:05',
|
||||
transactionType: '提现',
|
||||
productName: '余额提现',
|
||||
transactionAmount: -100.00,
|
||||
originalPrice: 100.00,
|
||||
discountAmount: 0.00,
|
||||
balancePayment: 100.00,
|
||||
voucherDeduction: 0.00
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
serialNumber: 'TX202401050001',
|
||||
transactionTime: '2024-01-05 15:30:40',
|
||||
transactionType: '退款',
|
||||
productName: 'GPU算力服务',
|
||||
transactionAmount: 25.00,
|
||||
originalPrice: 25.00,
|
||||
discountAmount: 0.00,
|
||||
balancePayment: 0.00,
|
||||
voucherDeduction: 0.00
|
||||
}
|
||||
]
|
||||
|
||||
billData.value = mockData
|
||||
pagination.value.total = mockData.length
|
||||
loading.value = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 路由跳转方法
|
||||
const goToRecharge = () => {
|
||||
router.push('/recharge')
|
||||
router.push('/layout/admin/balance')
|
||||
}
|
||||
|
||||
const goToBills = () => {
|
||||
@ -348,19 +244,19 @@ const goToExchange = () => {
|
||||
// 这里应该实现跳转到兑换页面的逻辑
|
||||
router.push('/layout/admin/exchange')
|
||||
}
|
||||
const handleOk=async ()=>{
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
btnLoading.value=true
|
||||
const res=await tixian({amount:withDrawalCount.value})
|
||||
if(res){
|
||||
btnLoading.value = true
|
||||
const res = await tixian({ amount: withDrawalCount.value })
|
||||
if (res) {
|
||||
message.success("提现成功")
|
||||
const userRes = await fetchUserInfo();
|
||||
localStorage.setItem('userInfo', JSON.stringify(userRes));
|
||||
const userRes = await fetchUserInfo();
|
||||
localStorage.setItem('userInfo', JSON.stringify(userRes));
|
||||
}
|
||||
btnLoading.value=false
|
||||
} catch (error:any) {
|
||||
btnLoading.value = false
|
||||
} catch (error: any) {
|
||||
message.error(error)
|
||||
btnLoading.value=false
|
||||
btnLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -18,14 +18,14 @@
|
||||
<div>
|
||||
<p><span>认证类型</span> <span>{{ certificationInfo.certificationType }}</span></p>
|
||||
<p><span>证件类型</span> <span></span><span>{{ certificationInfo.documentType }}</span></p>
|
||||
<p><span>认证人</span> <span></span><span>{{ certificationInfo.name }}</span></p>
|
||||
<p><span>认证人</span> <span></span><span>{{ certificationInfo.name }}</span></p>
|
||||
<p>
|
||||
<a-button type="primary" v-if="certificationInfo.certificationType==='个人认证'" @click="transOpen=true">变更为企业认证</a-button>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><span>认证时间</span><span>{{ certificationInfo.certificationTime }}</span></p>
|
||||
<p><span>身份证号</span><span>{{ certificationInfo.idCard }}</span></p>
|
||||
<p><span>认证时间</span> <span>{{ certificationInfo.certificationTime }}</span></p>
|
||||
<p><span>身份证号</span> <span>{{ certificationInfo.idCard }}</span></p>
|
||||
<!-- <p><span>认证人</span><span>用户名</span></p> -->
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<!-- 左侧栏:实例、数据、邀请好友 -->
|
||||
<a-col :span="16">
|
||||
<!-- 实例卡片 -->
|
||||
<a-card title="GPU容器实例" :bordered="false" class="card">
|
||||
<a-card title="GPU容器实例" class="card">
|
||||
<a-row :gutter="32" align="middle">
|
||||
<!-- 第一栏:容器实例和运行中 -->
|
||||
<a-col :span="18">
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
|
||||
<!-- 邀请好友卡片 -->
|
||||
<a-card title="邀请好友得算力券" :bordered="false" class="card margin-top">
|
||||
<a-card title="邀请好友得算力券" class="card margin-top">
|
||||
<a-row :gutter="24" class="invite-container">
|
||||
<!-- 左侧:邀请信息和链接 -->
|
||||
<a-col :span="24">
|
||||
@ -95,7 +95,7 @@
|
||||
<!-- 右侧栏:用户信息 + 费用信息 -->
|
||||
<a-col :span="8">
|
||||
<!-- 费用信息卡片 -->
|
||||
<a-card :bordered="false" class="card ">
|
||||
<a-card class="card ">
|
||||
<div class="fee-header">
|
||||
<div class="fee-title">我的账号</div>
|
||||
</div>
|
||||
@ -174,10 +174,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-button type="link" class="view-coupons-btn" @click="goToCoupons">
|
||||
<!-- <a-button type="link" class="view-coupons-btn" @click="goToCoupons">
|
||||
查看全部权益
|
||||
<RightOutlined style="font-size: 10px; margin-left: 2px;" />
|
||||
</a-button>
|
||||
</a-button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -276,7 +276,7 @@ const goToRules = () => {
|
||||
|
||||
// 跳转到充值页面
|
||||
const goToRecharge = () => {
|
||||
router.push('/recharge')
|
||||
router.push('/layout/admin/balance')
|
||||
}
|
||||
|
||||
// 跳转到权益页面
|
||||
@ -302,16 +302,11 @@ const goToInvoice = () => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home-page {
|
||||
padding: 15px;
|
||||
margin: 20px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.margin-top {
|
||||
margin-top: 20px;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { h, reactive, computed } from 'vue';
|
||||
import { h, reactive, computed,watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
HomeOutlined,
|
||||
@ -57,8 +57,8 @@ const menuItems: MenuItem[] = [
|
||||
// { path: '/layout/admin/home', name: '总览', icon: HomeOutlined, visible: true },
|
||||
|
||||
{
|
||||
path: '',
|
||||
name: '费用',
|
||||
path: '/fee',
|
||||
name: '费用中心',
|
||||
icon: MoneyCollectOutlined,
|
||||
visible: true,
|
||||
children: [
|
||||
@ -78,13 +78,13 @@ const menuItems: MenuItem[] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
name: '账号',
|
||||
path: '/account',
|
||||
name: '我的账号',
|
||||
icon: TeamOutlined,
|
||||
visible: true,
|
||||
children: [
|
||||
{ path: '/layout/admin/security', name: '账号安全', visible: true },
|
||||
{ path: '/layout/admin/history', name: '访问记录', visible: true },
|
||||
// { path: '/layout/admin/security', name: '账号安全', visible: true },
|
||||
// { path: '/layout/admin/history', name: '访问记录', visible: true },
|
||||
{ path: '/layout/admin/accountSet', name: '账户设置', visible: true },
|
||||
{ path: '/layout/admin/realnameAuth', name: '实名认证', visible: true },
|
||||
{ path: '/layout/admin/myCertificate', name: '我的算力券', visible: true },
|
||||
@ -184,8 +184,28 @@ const items = computed(() => {
|
||||
})
|
||||
.filter(Boolean) as MenuItemType[];
|
||||
});
|
||||
watch(
|
||||
() => router.currentRoute.value.path,
|
||||
(currentPath) => {
|
||||
// 设置选中项
|
||||
state.selectedKeys = [currentPath];
|
||||
|
||||
// 自动展开父级菜单(如果有)
|
||||
const openKeys: string[] = [];
|
||||
menuItems.forEach((item) => {
|
||||
if (item.children && item.children.some(child => child.path === currentPath)) {
|
||||
openKeys.push(item.path || ''); // 父菜单的 key(这里用 path 作为 key)
|
||||
}
|
||||
});
|
||||
state.openKeys = openKeys;
|
||||
},
|
||||
{ immediate: true } // 立即执行一次,确保初始加载也生效
|
||||
);
|
||||
const handleMenuSelect = ({ key }: { key: string }) => {
|
||||
// 如果是虚拟父菜单(无实际页面),不跳转
|
||||
if (key === '/fee' || key === '/account') {
|
||||
return;
|
||||
}
|
||||
// 递归查找菜单项(需要包含所有项,包括隐藏的)
|
||||
const allItems = flattenMenuItems(menuItems);
|
||||
const targetItem = allItems.find(item => item.path === key);
|
||||
@ -239,8 +259,8 @@ const changeTheme = (checked: boolean) => {
|
||||
|
||||
.admin-contain {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
/* padding: 20px; */
|
||||
overflow-y: auto;
|
||||
background-color: #f0f2f5;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user