This commit is contained in:
2026-05-13 15:05:19 +08:00
parent f8f1159666
commit 0449c4fe8f
4 changed files with 298 additions and 299 deletions

View File

@ -44,4 +44,20 @@ export const withdraw = (params: {
beneficiary_bank_account: string beneficiary_bank_account: string
}) => { }) => {
return request.post('/withdraw/withdraw', params) return request.post('/withdraw/withdraw', params)
}
// 提现审核列表
export const getWithdrawReviewList = (params: {
page: number
page_size: number
start_time?: string
end_time?: string
user_name?: string
}) => {
return request.get('/withdraw/withdrawReviewList', params as any)
}
// 提现审核操作(通过/驳回)
export const withdrawReviewOrder = (params: { id: number; status: number }) => {
return request.post('/withdraw/withdrawReviewOrder', params)
} }

View File

@ -1,11 +1,7 @@
<template> <template>
<Dialog <Dialog :visible="dialogVisible"
:visible="dialogVisible" :title="currentStep === 1 ? t('withdraw.dialog.title1') : t('withdraw.dialog.title2')" width="600px"
:title="currentStep === 1 ? t('withdraw.dialog.title1') : t('withdraw.dialog.title2')" :show-footer="false" @close="handleUpdateVisible">
width="600px"
:show-footer="false"
@close="handleUpdateVisible"
>
<!-- 第一步输入金额并展示计算明细 --> <!-- 第一步输入金额并展示计算明细 -->
<div v-if="currentStep === 1" class="step1-container"> <div v-if="currentStep === 1" class="step1-container">
<!-- 钱包余额展示 --> <!-- 钱包余额展示 -->
@ -14,27 +10,27 @@
<div class="wallet-grid"> <div class="wallet-grid">
<div class="wallet-item"> <div class="wallet-item">
<span class="wallet-label">{{ t('withdraw.wallet.feeHandling') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.feeHandling') }}</span>
<span class="wallet-value">{{ walletInfo.commission_fee_handling || 0 }}</span> <span class="wallet-value">{{ walletInfo.commission_fee_handling || '0.00'}}</span>
</div> </div>
<div class="wallet-item"> <div class="wallet-item">
<span class="wallet-label">{{ t('withdraw.wallet.pointDiff') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.pointDiff') }}</span>
<span class="wallet-value">{{ walletInfo.commission_point_diff || 0 }}</span> <span class="wallet-value">{{ walletInfo.commission_point_diff || '0.00'}}</span>
</div> </div>
<div class="wallet-item"> <div class="wallet-item">
<span class="wallet-label">{{ t('withdraw.wallet.service') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.service') }}</span>
<span class="wallet-value">{{ walletInfo.service || 0 }}</span> <span class="wallet-value">{{ walletInfo.service || '0.00'}}</span>
</div> </div>
<div class="wallet-item" v-if="showRiskFee"> <div class="wallet-item" v-if="showRiskFee">
<span class="wallet-label">{{ t('withdraw.wallet.risk') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.risk') }}</span>
<span class="wallet-value">{{ walletInfo.risk || 0 }}</span> <span class="wallet-value">{{ walletInfo.risk || '0.00'}}</span>
</div> </div>
<div class="wallet-item"> <div class="wallet-item">
<span class="wallet-label">{{ t('withdraw.wallet.profit') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.profit') }}</span>
<span class="wallet-value">{{ walletInfo.closing_profit || 0 }}</span> <span class="wallet-value">{{ walletInfo.closing_profit || '0.00'}}</span>
</div> </div>
<div class="wallet-item" v-if="roleId >= 5"> <div class="wallet-item" v-if="roleId >= 5">
<span class="wallet-label">{{ t('withdraw.wallet.available') }}</span> <span class="wallet-label">{{ t('withdraw.wallet.available') }}</span>
<span class="wallet-value available">{{ availableBalance.toFixed(2) }}</span> <span class="wallet-value available">{{ availableBalance || '0.00' }}</span>
</div> </div>
</div> </div>
</div> </div>
@ -45,12 +41,8 @@
{{ t('withdraw.dialog.amount') }} {{ t('withdraw.dialog.amount') }}
<span class="max-balance">最大可取{{ totalWalletBalance }} {{ currentCurrency }}</span> <span class="max-balance">最大可取{{ totalWalletBalance }} {{ currentCurrency }}</span>
</div> </div>
<el-input <el-input v-model="withdrawAmount" type="number" :placeholder="t('withdraw.dialog.amountPlaceholder')"
v-model="withdrawAmount" @input="handleAmountInput">
type="number"
:placeholder="t('withdraw.dialog.amountPlaceholder')"
@input="handleAmountInput"
>
<template #prepend>{{ currentCurrency }}</template> <template #prepend>{{ currentCurrency }}</template>
</el-input> </el-input>
<div v-if="amountError" class="amount-error">{{ amountError }}</div> <div v-if="amountError" class="amount-error">{{ amountError }}</div>
@ -92,12 +84,7 @@
<!-- 快捷金额 --> <!-- 快捷金额 -->
<div class="quick-amounts"> <div class="quick-amounts">
<el-button <el-button v-for="amount in quickAmounts" :key="amount" size="small" @click="handleQuickAmount(amount)">
v-for="amount in quickAmounts"
:key="amount"
size="small"
@click="handleQuickAmount(amount)"
>
{{ amount }} {{ amount }}
</el-button> </el-button>
</div> </div>
@ -111,12 +98,7 @@
<!-- 第二步确认表单 --> <!-- 第二步确认表单 -->
<div v-else class="step2-container"> <div v-else class="step2-container">
<el-form <el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<!-- 金额信息只读 --> <!-- 金额信息只读 -->
<div class="amount-info"> <div class="amount-info">
@ -138,19 +120,23 @@
<!-- 用户取款额外字段 (role_id >= 5) --> <!-- 用户取款额外字段 (role_id >= 5) -->
<template v-if="!isAgent"> <template v-if="!isAgent">
<el-form-item :label="t('withdraw.dialog.beneficiaryName')" prop="beneficiary_name"> <el-form-item :label="t('withdraw.dialog.beneficiaryName')" prop="beneficiary_name">
<el-input v-model="formData.beneficiary_name" :placeholder="t('withdraw.dialog.beneficiaryNamePlaceholder')" /> <el-input v-model="formData.beneficiary_name"
:placeholder="t('withdraw.dialog.beneficiaryNamePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('withdraw.dialog.bankName')" prop="beneficiary_bank_name"> <el-form-item :label="t('withdraw.dialog.bankName')" prop="beneficiary_bank_name">
<el-input v-model="formData.beneficiary_bank_name" :placeholder="t('withdraw.dialog.bankNamePlaceholder')" /> <el-input v-model="formData.beneficiary_bank_name"
:placeholder="t('withdraw.dialog.bankNamePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('withdraw.dialog.swiftCode')" prop="swift_bic_code"> <el-form-item :label="t('withdraw.dialog.swiftCode')" prop="swift_bic_code">
<el-input v-model="formData.swift_bic_code" :placeholder="t('withdraw.dialog.swiftCodePlaceholder')" /> <el-input v-model="formData.swift_bic_code" :placeholder="t('withdraw.dialog.swiftCodePlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('withdraw.dialog.bankAddress')" prop="beneficiary_bank_address"> <el-form-item :label="t('withdraw.dialog.bankAddress')" prop="beneficiary_bank_address">
<el-input v-model="formData.beneficiary_bank_address" :placeholder="t('withdraw.dialog.bankAddressPlaceholder')" /> <el-input v-model="formData.beneficiary_bank_address"
:placeholder="t('withdraw.dialog.bankAddressPlaceholder')" />
</el-form-item> </el-form-item>
<el-form-item :label="t('withdraw.dialog.bankAccount')" prop="beneficiary_bank_account"> <el-form-item :label="t('withdraw.dialog.bankAccount')" prop="beneficiary_bank_account">
<el-input v-model="formData.beneficiary_bank_account" :placeholder="t('withdraw.dialog.bankAccountPlaceholder')" /> <el-input v-model="formData.beneficiary_bank_account"
:placeholder="t('withdraw.dialog.bankAccountPlaceholder')" />
</el-form-item> </el-form-item>
</template> </template>
</el-form> </el-form>
@ -158,7 +144,8 @@
<!-- 底部按钮 --> <!-- 底部按钮 -->
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="handleBack">{{ t('common.cancel') }}</el-button> <el-button @click="handleBack">{{ t('common.cancel') }}</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('withdraw.dialog.confirmWithdraw') }}</el-button> <el-button type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('withdraw.dialog.confirmWithdraw')
}}</el-button>
</div> </div>
</div> </div>
</Dialog> </Dialog>
@ -240,13 +227,13 @@ const handleAmountInput = (value: string) => {
calculatedData.value = [] calculatedData.value = []
return return
} }
if (numValue > totalWalletBalance.value) { if (numValue > totalWalletBalance.value) {
amountError.value = `输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}` amountError.value = `输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}`
calculatedData.value = [] calculatedData.value = []
return return
} }
amountError.value = '' amountError.value = ''
calculateWithdraw() calculateWithdraw()
} }
@ -261,18 +248,17 @@ const isAgent = computed(() => roleId >= 5)
// //
const currentCurrency = computed(() => props.channelInfo?.currency?.symbol || '-') const currentCurrency = computed(() => props.channelInfo?.currency?.symbol || '-')
// = amount - - freeze // = amount - freeze - ( + + + + )
// availableBalance = amount - freeze - ( + + + + )
const availableBalance = computed(() => { const availableBalance = computed(() => {
const amount = parseFloat(walletInfo.value.amount || '0') const amount = parseFloat(walletInfo.value.amount || '0')
const freeze = parseFloat(walletInfo.value.freeze || '0') const freeze = parseFloat(walletInfo.value.freeze || '0')
// //
const walletSum = const walletSum =
parseFloat(walletInfo.value.commission_fee_handling || '0') + Math.max(0, parseFloat(walletInfo.value.commission_fee_handling || '0')) +
parseFloat(walletInfo.value.commission_point_diff || '0') + Math.max(0, parseFloat(walletInfo.value.commission_point_diff || '0')) +
parseFloat(walletInfo.value.service || '0') + Math.max(0, parseFloat(walletInfo.value.service || '0')) +
parseFloat(walletInfo.value.risk || '0') + Math.max(0, parseFloat(walletInfo.value.risk || '0')) +
parseFloat(walletInfo.value.closing_profit || '0') Math.max(0, parseFloat(walletInfo.value.closing_profit || '0'))
return Math.max(0, amount - freeze - walletSum) return Math.max(0, amount - freeze - walletSum)
}) })
@ -281,7 +267,7 @@ const availableBalance = computed(() => {
const totalWalletBalance = computed(() => { const totalWalletBalance = computed(() => {
const amount = parseFloat(walletInfo.value.amount || '0') const amount = parseFloat(walletInfo.value.amount || '0')
const freeze = parseFloat(walletInfo.value.freeze || '0') const freeze = parseFloat(walletInfo.value.freeze || '0')
// + + + + // + + + +
const walletSum = const walletSum =
parseFloat(walletInfo.value.commission_fee_handling || '0') + parseFloat(walletInfo.value.commission_fee_handling || '0') +
@ -289,12 +275,11 @@ const totalWalletBalance = computed(() => {
parseFloat(walletInfo.value.service || '0') + parseFloat(walletInfo.value.service || '0') +
parseFloat(walletInfo.value.risk || '0') + parseFloat(walletInfo.value.risk || '0') +
parseFloat(walletInfo.value.closing_profit || '0') parseFloat(walletInfo.value.closing_profit || '0')
// availableBalance = amount - freeze - walletSum
const availableBal = Math.max(0, amount - freeze - walletSum)
if (roleId >= 5) { if (roleId >= 5) {
// roleId >= 5 // roleId >= 5
// availableBalance = amount - freeze - walletSum
const availableBal = Math.max(0, amount - freeze - walletSum)
return walletSum + availableBal return walletSum + availableBal
} }
return walletSum return walletSum
@ -318,13 +303,13 @@ const feeOrder = computed(() => {
}) })
// //
const feeFieldMap: Record<string, keyof WalletInfo> = { const feeFieldMap: Record<string, keyof WalletInfo | 'available'> = {
'手续费': 'commission_fee_handling', '手续费': 'commission_fee_handling',
'点差': 'commission_point_diff', '点差': 'commission_point_diff',
'服务费': 'service', '服务费': 'service',
'风险金': 'risk', '风险金': 'risk',
'头寸': 'closing_profit', '头寸': 'closing_profit',
'可用余额': 'amount', '可用余额': 'available', // computed
} }
// //
@ -381,6 +366,7 @@ const formData = ref({
withdraw_service_fee: '', withdraw_service_fee: '',
withdraw_head_fee: '', withdraw_head_fee: '',
withdraw_risk_fee: '', withdraw_risk_fee: '',
withdraw_blance: '', // 使
// //
beneficiary_name: '', beneficiary_name: '',
beneficiary_bank_name: '', beneficiary_bank_name: '',
@ -412,7 +398,7 @@ const initData = async () => {
currentStep.value = 1 currentStep.value = 1
withdrawAmount.value = '' withdrawAmount.value = ''
calculatedData.value = [] calculatedData.value = []
// //
try { try {
const res: any = await getWalletCapital() const res: any = await getWalletCapital()
@ -474,7 +460,14 @@ const calculateWithdraw = () => {
const field = feeFieldMap[feeType] const field = feeFieldMap[feeType]
if (!field) continue if (!field) continue
const original = parseFloat(walletInfo.value[field] || '0') // available
let original: number
if (field === 'available') {
original = availableBalance.value
} else {
original = parseFloat(walletInfo.value[field] || '0')
}
if (original <= 0) continue if (original <= 0) continue
const deducted = Math.min(remaining, original).toFixed(2) const deducted = Math.min(remaining, original).toFixed(2)
@ -524,7 +517,7 @@ const handleNextStep = () => {
ElMessage.warning('请输入取款金额') ElMessage.warning('请输入取款金额')
return return
} }
if (amount > totalWalletBalance.value) { if (amount > totalWalletBalance.value) {
ElMessage.warning(`输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}`) ElMessage.warning(`输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}`)
return return
@ -536,6 +529,7 @@ const handleNextStep = () => {
formData.value.withdraw_service_fee = calculatedData.value.find(item => item.type === '服务费')?.deducted || '0' formData.value.withdraw_service_fee = calculatedData.value.find(item => item.type === '服务费')?.deducted || '0'
formData.value.withdraw_risk_fee = calculatedData.value.find(item => item.type === '风险金')?.deducted || '0' formData.value.withdraw_risk_fee = calculatedData.value.find(item => item.type === '风险金')?.deducted || '0'
formData.value.withdraw_head_fee = calculatedData.value.find(item => item.type === '头寸')?.deducted || '0' formData.value.withdraw_head_fee = calculatedData.value.find(item => item.type === '头寸')?.deducted || '0'
formData.value.withdraw_blance = calculatedData.value.find(item => item.type === '可用余额')?.deducted || '0'
currentStep.value = 2 currentStep.value = 2
} }
@ -561,7 +555,7 @@ const handleSubmit = async () => {
if (isAgent.value) { if (isAgent.value) {
// //
params.withdraw_blance = walletInfo.value.amount params.withdraw_blance = formData.value.withdraw_blance
params.beneficiary_name = formData.value.beneficiary_name params.beneficiary_name = formData.value.beneficiary_name
params.beneficiary_bank_name = formData.value.beneficiary_bank_name params.beneficiary_bank_name = formData.value.beneficiary_bank_name
params.swift_bic_code = formData.value.swift_bic_code params.swift_bic_code = formData.value.swift_bic_code

View File

@ -3,10 +3,8 @@
<!-- 搜索区域复用项目内搜索组件 --> <!-- 搜索区域复用项目内搜索组件 -->
<WithdrawSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch" @reset="handleReset"> <WithdrawSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch" @reset="handleReset">
<template #button> <template #button>
<!-- 当前阶段仅完成页面按钮先保留交互占位 --> <el-button type="success" :loading="approveLoading" @click="handleApprove">通过</el-button>
<el-button type="success" @click="handleApprove">通过</el-button> <el-button type="danger" plain :loading="rejectLoading" @click="handleReject">驳回</el-button>
<el-button type="danger" plain @click="handleReject">驳回</el-button>
<el-button type="primary" plain @click="handleExport">导出</el-button>
</template> </template>
</WithdrawSearch> </WithdrawSearch>
@ -41,231 +39,161 @@
defineOptions({ defineOptions({
name: 'WithdrawCheck' name: 'WithdrawCheck'
}) })
import { ElMessage } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import dayjs from 'dayjs'
import WithdrawSearch from '@/components/common/Search.vue' import WithdrawSearch from '@/components/common/Search.vue'
import WithdrawPagination from '@/components/common/Pagination.vue' import WithdrawPagination from '@/components/common/Pagination.vue'
import { withdrawCheckSearch, withdrawCheckTableColumns } from './options' import { withdrawCheckSearch, withdrawCheckTableColumns } from './options'
import { getWithdrawReviewList, withdrawReviewOrder } from '@/api/modules/capital/withdraw'
// //
interface TableRow { interface TableRow {
id: number id: number
account: string trade_id: string
agentName: string return_trade_id: string | null
walletAddress: string user_id: number
walletType: string withdraw_currency: {
holderName: string id: number
bankName: string symbol: string
bankCode: string }
bankAddress: string withdraw_amount: string
withdrawAmount: string real_currency: {
deductAmount: string id: number
withdrawCurrency: string symbol: string
arrivalAmount: string }
arrivalCurrency: string real_amount: string
feeAmount: string rate: string
positionAmount: string status: number
userType: number channel_id: number
withdraw_fee_handle: string
withdraw_point_diff: string
withdraw_service_fee: string
withdraw_head_fee: string
withdraw_risk_fee: string
withdraw_address: string
beneficiary_name: string | null
beneficiary_bank_name: string | null
swift_bic_code: string | null
beneficiary_bank_address: string | null
beneficiary_bank_account: string | null
created_at: string
updated_at: string
deleted_at: string | null
user: {
id: number
username: string
}
channel: {
id: number
name: string
}
} }
// mock //
const mockTableData: TableRow[] = [ interface TransformedTableRow {
{ id: number
id: 1, trade_id: string
account: 'U100101', user_name: string
agentName: '一级代理A', withdraw_currency_symbol: string
walletAddress: 'TRX8x2f...7Kp9', withdraw_amount: string
walletType: 'TRC20', real_currency_symbol: string
holderName: '张三', real_amount: string
bankName: '中国银行', rate: string
bankCode: 'BKCHCNBJ', channel_name: string
bankAddress: '上海市浦东新区世纪大道100号', withdraw_service_fee: string
withdrawAmount: '1000.00', withdraw_head_fee: string
deductAmount: '20.00', withdraw_fee_handle: string
withdrawCurrency: 'USDT', withdraw_point_diff: string
arrivalAmount: '980.00', withdraw_risk_fee: string
arrivalCurrency: 'USDT', withdraw_address: string
feeAmount: '20.00', created_at: string
positionAmount: '1.20', }
userType: 1,
},
{
id: 2,
account: 'U100102',
agentName: '一级代理B',
walletAddress: '0x5fa1...ac20',
walletType: 'ERC20',
holderName: '李四',
bankName: '工商银行',
bankCode: 'ICBKCNBJ',
bankAddress: '北京市朝阳区建国路88号',
withdrawAmount: '5000.00',
deductAmount: '50.00',
withdrawCurrency: 'USD',
arrivalAmount: '4950.00',
arrivalCurrency: 'USD',
feeAmount: '50.00',
positionAmount: '2.50',
userType: 1,
},
{
id: 3,
account: 'A200101',
agentName: '总代运营中心',
walletAddress: 'bc1q7m...91fa',
walletType: 'BTC',
holderName: '王五',
bankName: '建设银行',
bankCode: 'PCBCCNBJ',
bankAddress: '深圳市南山区科技园中一路1号',
withdrawAmount: '20000.00',
deductAmount: '120.00',
withdrawCurrency: 'CNY',
arrivalAmount: '19880.00',
arrivalCurrency: 'CNY',
feeAmount: '120.00',
positionAmount: '3.00',
userType: 2,
},
{
id: 4,
account: 'U100103',
agentName: '一级代理C',
walletAddress: 'TRX9m4k...6Ts1',
walletType: 'TRC20',
holderName: '赵六',
bankName: '农业银行',
bankCode: 'ABOCCNBJ',
bankAddress: '广州市天河区珠江新城华夏路18号',
withdrawAmount: '3000.00',
deductAmount: '15.00',
withdrawCurrency: 'USDT',
arrivalAmount: '2985.00',
arrivalCurrency: 'USDT',
feeAmount: '15.00',
positionAmount: '1.10',
userType: 1,
},
{
id: 5,
account: 'A200102',
agentName: '华东代理中心',
walletAddress: '0x9bd7...b3f2',
walletType: 'ERC20',
holderName: '孙七',
bankName: '招商银行',
bankCode: 'CMBCCNBS',
bankAddress: '杭州市西湖区文三路90号',
withdrawAmount: '8000.00',
deductAmount: '80.00',
withdrawCurrency: 'USD',
arrivalAmount: '7920.00',
arrivalCurrency: 'USD',
feeAmount: '80.00',
positionAmount: '2.20',
userType: 2,
},
{
id: 6,
account: 'U100104',
agentName: '一级代理D',
walletAddress: 'TRX6a1d...3Lm8',
walletType: 'TRC20',
holderName: '周八',
bankName: '交通银行',
bankCode: 'COMMCNSH',
bankAddress: '成都市高新区天府大道北段966号',
withdrawAmount: '1200.00',
deductAmount: '12.00',
withdrawCurrency: 'USDT',
arrivalAmount: '1188.00',
arrivalCurrency: 'USDT',
feeAmount: '12.00',
positionAmount: '0.80',
userType: 1,
},
{
id: 7,
account: 'U100105',
agentName: '一级代理E',
walletAddress: 'bc1qx8...0de4',
walletType: 'BTC',
holderName: '吴九',
bankName: '浦发银行',
bankCode: 'SPDBCNBS',
bankAddress: '苏州市工业园区星湖街328号',
withdrawAmount: '15000.00',
deductAmount: '105.00',
withdrawCurrency: 'CNY',
arrivalAmount: '14895.00',
arrivalCurrency: 'CNY',
feeAmount: '105.00',
positionAmount: '2.80',
userType: 1,
},
{
id: 8,
account: 'A200103',
agentName: '华南代理中心',
walletAddress: '0x8e2f...d1a0',
walletType: 'ERC20',
holderName: '郑十',
bankName: '民生银行',
bankCode: 'MSBCCNBJ',
bankAddress: '厦门市思明区湖滨南路258号',
withdrawAmount: '6000.00',
deductAmount: '36.00',
withdrawCurrency: 'USD',
arrivalAmount: '5964.00',
arrivalCurrency: 'USD',
feeAmount: '36.00',
positionAmount: '1.90',
userType: 2,
},
]
// //
const searchOptions = ref(withdrawCheckSearch) const searchOptions = ref(withdrawCheckSearch)
const searchForm = ref({ const searchForm = ref({
account: '', user_name: '',
userType: 1, timeRange: [] as string[]
}) })
// loading // loading
const tableColumns = computed(() => withdrawCheckTableColumns) const tableColumns = computed(() => withdrawCheckTableColumns)
const tableData = ref<TableRow[]>([]) const tableData = ref<TransformedTableRow[]>([])
const selectedRows = ref<TableRow[]>([]) const selectedRows = ref<TableRow[]>([])
const loading = ref(false) const loading = ref(false)
// loading
const approveLoading = ref(false)
const rejectLoading = ref(false)
// //
const total = ref(0) const total = ref(0)
const currentPage = ref(1) const currentPage = ref(1)
const pageSize = ref(10) const pageSize = ref(30)
// mock //
const applyFilters = () => { const getDefaultTimeRange = () => {
const keyword = searchForm.value.account.trim().toLowerCase() const end = dayjs()
const filtered = mockTableData.filter((item) => { const start = end.subtract(7, 'day')
const matchAccount = !keyword || item.account.toLowerCase().includes(keyword) return [start.format('YYYY-MM-DD HH:mm:ss'), end.format('YYYY-MM-DD HH:mm:ss')]
const matchUserType = !searchForm.value.userType || item.userType === searchForm.value.userType }
return matchAccount && matchUserType
})
total.value = filtered.length //
const start = (currentPage.value - 1) * pageSize.value searchForm.value.timeRange = getDefaultTimeRange()
const end = start + pageSize.value
tableData.value = filtered.slice(start, end) //
const transformTableData = (data: TableRow[]): TransformedTableRow[] => {
return data.map(item => ({
id: item.id,
trade_id: item.trade_id,
user_name: item.user?.username || '-',
withdraw_currency_symbol: item.withdraw_currency?.symbol || '-',
withdraw_amount: item.withdraw_amount,
real_currency_symbol: item.real_currency?.symbol || '-',
real_amount: item.real_amount,
rate: item.rate,
channel_name: item.channel?.name || '-',
withdraw_service_fee: item.withdraw_service_fee,
withdraw_head_fee: item.withdraw_head_fee,
withdraw_fee_handle: item.withdraw_fee_handle,
withdraw_point_diff: item.withdraw_point_diff,
withdraw_risk_fee: item.withdraw_risk_fee,
withdraw_address: item.withdraw_address,
created_at: item.created_at
}))
}
//
interface ListResponse {
data: TableRow[]
total: number
} }
// //
// mock const getList = async () => {
const getList = () => {
loading.value = true loading.value = true
selectedRows.value = [] selectedRows.value = []
window.setTimeout(() => {
applyFilters() const [start_time, end_time] = searchForm.value.timeRange || []
try {
const res = await getWithdrawReviewList({
page: currentPage.value,
page_size: pageSize.value,
start_time: start_time || undefined,
end_time: end_time || undefined,
user_name: searchForm.value.user_name || undefined
}) as unknown as ListResponse
tableData.value = transformTableData(res.data || [])
total.value = res.total || 0
} catch (error) {
console.error('获取提现审核列表失败:', error)
ElMessage.error('获取列表失败')
} finally {
loading.value = false loading.value = false
}, 120) }
} }
// //
@ -282,46 +210,107 @@ const handleSearch = () => {
// //
const handleReset = () => { const handleReset = () => {
searchForm.value = { searchForm.value = {
account: '', user_name: '',
userType: 1, timeRange: getDefaultTimeRange()
} }
currentPage.value = 1 currentPage.value = 1
getList() getList()
} }
// //
const handleSelectionChange = (rows: TableRow[]) => { const handleSelectionChange = (rows: TransformedTableRow[]) => {
selectedRows.value = rows // id
selectedRows.value = rows.map(row => {
return tableData.value.find(item => item.id === row.id) as unknown as TableRow
})
} }
// //
const handleApprove = () => { const handleApprove = async () => {
if (!selectedRows.value.length) { if (!selectedRows.value.length) {
ElMessage.warning('请先选择要通过的记录') ElMessage.warning('请先选择要通过的记录')
return return
} }
ElMessage.success('页面已完成,接口后续接入')
try {
await ElMessageBox.confirm(
`确定要通过 ${selectedRows.value.length} 条提现记录吗?`,
'审核确认',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
approveLoading.value = true
for (const row of selectedRows.value) {
await withdrawReviewOrder({
id: row.id,
status: 2
})
}
ElMessage.success('审核通过成功')
getList()
} catch (error: any) {
if (error !== 'cancel') {
ElMessage.error(error.message || '审核通过失败')
}
} finally {
approveLoading.value = false
}
} }
// //
const handleReject = () => { const handleReject = async () => {
if (!selectedRows.value.length) { if (!selectedRows.value.length) {
ElMessage.warning('请先选择要驳回的记录') ElMessage.warning('请先选择要驳回的记录')
return return
} }
ElMessage.success('页面已完成,接口后续接入')
try {
await ElMessageBox.confirm(
`确定要驳回 ${selectedRows.value.length} 条提现记录吗?`,
'审核确认',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
rejectLoading.value = true
for (const row of selectedRows.value) {
await withdrawReviewOrder({
id: row.id,
status: 4
})
}
ElMessage.success('审核驳回成功')
getList()
} catch (error: any) {
if (error !== 'cancel') {
ElMessage.error(error.message || '审核驳回失败')
}
} finally {
rejectLoading.value = false
}
} }
// //
const handleExport = () => { const handleExport = () => {
ElMessage.success('页面已完成,接口后续接入') ElMessage.info('导出功能开发中')
} }
// //
const handlePaginationChange = (page: { currentPage: number; pageSize: number }) => { const handlePaginationChange = (page: { currentPage: number; pageSize: number }) => {
currentPage.value = page.currentPage currentPage.value = page.currentPage
pageSize.value = page.pageSize pageSize.value = page.pageSize
applyFilters() getList()
} }
</script> </script>

View File

@ -1,42 +1,42 @@
// 搜索区域配置 // 搜索区域配置
export const withdrawCheckSearch = [ export const withdrawCheckSearch = [
{ {
// 取款账户关键词 // 账户持有人姓名
prop: 'account', prop: 'user_name',
label: '取款账户', label: '账户持有人',
type: 'input' as const, type: 'input' as const,
placeholder: '请输入取款账户', placeholder: '请输入账户持有人',
width: '220px' width: '280px'
}, },
{ // {
// 客户类型1=客户2=代理 // // 时间范围选择
prop: 'userType', // prop: 'timeRange',
label: '客户类型', // label: '申请时间',
type: 'select' as const, // type: 'date' as const,
placeholder: '请选择客户类型', // dateType: 'datetimerange' as const,
width: '180px', // rangeSeparator: '至',
options: [ // startPlaceholder: '开始时间',
{ label: '客户', value: 1 }, // endPlaceholder: '结束时间',
{ label: '代理', value: 2 } // valueFormat: 'YYYY-MM-DD HH:mm:ss',
] // width: '380px'
} // }
] ]
// 表格列配置 // 表格列配置
export const withdrawCheckTableColumns = [ export const withdrawCheckTableColumns = [
{ prop: 'account', label: '账户', align: 'center' as const, width: 140 }, { prop: 'trade_id', label: '订单号', align: 'center' as const, width: 200 },
{ prop: 'agentName', label: '所属代理', align: 'center' as const, width: 140 }, { prop: 'user_name', label: '账户持有人', align: 'center' as const, width: 120 },
{ prop: 'walletAddress', label: '钱包地址', align: 'center' as const, width: 220 }, { prop: 'withdraw_currency_symbol', label: '取款币种', align: 'center' as const, width: 100 },
{ prop: 'walletType', label: '钱包类型', align: 'center' as const, width: 120 }, { prop: 'withdraw_amount', label: '取款金额', align: 'center' as const, width: 120 },
{ prop: 'holderName', label: '账户持有人姓名', align: 'center' as const, width: 160 }, { prop: 'real_currency_symbol', label: '到账币种', align: 'center' as const, width: 100 },
{ prop: 'bankName', label: '银行名称', align: 'center' as const, width: 160 }, { prop: 'real_amount', label: '到账金额', align: 'center' as const, width: 120 },
{ prop: 'bankCode', label: '银行识别代码', align: 'center' as const, width: 160 }, { prop: 'rate', label: '汇率', align: 'center' as const, width: 100 },
{ prop: 'bankAddress', label: '银行地址', align: 'center' as const, width: 200 }, { prop: 'channel_name', label: '渠道', align: 'center' as const, width: 140 },
{ prop: 'withdrawAmount', label: '取款金额', align: 'center' as const, width: 120 }, { prop: 'withdraw_service_fee', label: '服务费', align: 'center' as const, width: 100 },
{ prop: 'deductAmount', label: '取款扣除金额', align: 'center' as const, width: 140 }, { prop: 'withdraw_head_fee', label: '总部手续费', align: 'center' as const, width: 120 },
{ prop: 'withdrawCurrency', label: '取款币种', align: 'center' as const, width: 120 }, { prop: 'withdraw_fee_handle', label: '代理手续费', align: 'center' as const, width: 120 },
{ prop: 'arrivalAmount', label: '到账金额', align: 'center' as const, width: 120 }, { prop: 'withdraw_point_diff', label: '点差', align: 'center' as const, width: 100 },
{ prop: 'arrivalCurrency', label: '到账币种', align: 'center' as const, width: 120 }, { prop: 'withdraw_risk_fee', label: '风控费', align: 'center' as const, width: 100 },
{ prop: 'feeAmount', label: '手续费', align: 'center' as const, width: 100 }, { prop: 'withdraw_address', label: '提现地址', align: 'center' as const, minWidth: 180 },
{ prop: 'positionAmount', label: '头寸', align: 'center' as const, width: 100 } { prop: 'created_at', label: '申请时间', align: 'center' as const, width: 180 }
] ]