fetch(add): 账户管理
This commit is contained in:
558
src/views/finance/commission/agent-commission/index.vue
Normal file
558
src/views/finance/commission/agent-commission/index.vue
Normal file
@@ -0,0 +1,558 @@
|
||||
<template>
|
||||
<ArtTableFullScreen>
|
||||
<div class="agent-commission-page" id="table-full-screen">
|
||||
<!-- 搜索栏 -->
|
||||
<ElCard shadow="never" class="search-card">
|
||||
<ElForm :inline="true" :model="searchForm" class="search-form">
|
||||
<ElFormItem label="店铺名称">
|
||||
<ElInput
|
||||
v-model="searchForm.shop_name"
|
||||
placeholder="请输入店铺名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="店铺编码">
|
||||
<ElInput
|
||||
v-model="searchForm.shop_code"
|
||||
placeholder="请输入店铺编码"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem>
|
||||
<ElButton type="primary" @click="handleSearch">查询</ElButton>
|
||||
<ElButton @click="handleReset">重置</ElButton>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
</ElCard>
|
||||
|
||||
<ElCard shadow="never" class="art-table-card">
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader
|
||||
:columnList="columnOptions"
|
||||
v-model:columns="columnChecks"
|
||||
@refresh="handleRefresh"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="tableRef"
|
||||
row-key="shop_id"
|
||||
:loading="loading"
|
||||
:data="summaryList"
|
||||
:currentPage="pagination.page"
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
|
||||
<!-- 详情抽屉 -->
|
||||
<ElDrawer
|
||||
v-model="detailDrawerVisible"
|
||||
:title="`${currentShop?.shop_name || ''} - 佣金详情`"
|
||||
size="60%"
|
||||
destroy-on-close
|
||||
>
|
||||
<ElTabs v-model="activeTab" class="detail-tabs">
|
||||
<!-- 佣金明细 Tab -->
|
||||
<ElTabPane label="佣金明细" name="commission">
|
||||
<ArtTable
|
||||
ref="commissionTableRef"
|
||||
row-key="id"
|
||||
:loading="commissionLoading"
|
||||
:data="commissionRecords"
|
||||
:currentPage="commissionPagination.page"
|
||||
:pageSize="commissionPagination.pageSize"
|
||||
:total="commissionPagination.total"
|
||||
:marginTop="10"
|
||||
:height="500"
|
||||
@size-change="handleCommissionSizeChange"
|
||||
@current-change="handleCommissionCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn label="佣金金额" prop="amount" width="120">
|
||||
<template #default="scope">
|
||||
<span style="font-weight: 500; color: var(--el-color-success)">
|
||||
{{ formatMoney(scope.row.amount) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="入账后余额" prop="balance_after" width="120">
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.balance_after) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="佣金类型" prop="commission_type" width="120">
|
||||
<template #default="scope">
|
||||
<ElTag
|
||||
:type="
|
||||
CommissionTypeMap[scope.row.commission_type as keyof typeof CommissionTypeMap]
|
||||
?.type || 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
CommissionTypeMap[scope.row.commission_type as keyof typeof CommissionTypeMap]
|
||||
?.label || scope.row.commission_type
|
||||
}}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="状态" prop="status" width="100">
|
||||
<template #default="scope">
|
||||
<ElTag
|
||||
:type="
|
||||
CommissionStatusMap[scope.row.status as keyof typeof CommissionStatusMap]
|
||||
?.type || 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
CommissionStatusMap[scope.row.status as keyof typeof CommissionStatusMap]
|
||||
?.label || scope.row.status
|
||||
}}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="订单号" prop="order_no" min-width="180" show-overflow-tooltip />
|
||||
<ElTableColumn label="ICCID" prop="iccid" min-width="150" show-overflow-tooltip />
|
||||
<ElTableColumn label="设备号" prop="device_no" min-width="150" show-overflow-tooltip />
|
||||
<ElTableColumn label="入账时间" prop="created_at" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatDateTime(scope.row.created_at) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElTabPane>
|
||||
|
||||
<!-- 提现记录 Tab -->
|
||||
<ElTabPane label="提现记录" name="withdrawal">
|
||||
<ArtTable
|
||||
ref="withdrawalTableRef"
|
||||
row-key="id"
|
||||
:loading="withdrawalLoading"
|
||||
:data="withdrawalRecords"
|
||||
:currentPage="withdrawalPagination.page"
|
||||
:pageSize="withdrawalPagination.pageSize"
|
||||
:total="withdrawalPagination.total"
|
||||
:marginTop="10"
|
||||
:height="500"
|
||||
@size-change="handleWithdrawalSizeChange"
|
||||
@current-change="handleWithdrawalCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn
|
||||
label="提现单号"
|
||||
prop="withdrawal_no"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<ElTableColumn label="提现金额" prop="amount" width="120">
|
||||
<template #default="scope">
|
||||
<span style="font-weight: 500; color: var(--el-color-danger)">
|
||||
{{ formatMoney(scope.row.amount) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="实际到账" prop="actual_amount" width="120">
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.actual_amount) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="手续费" prop="fee" width="100">
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.fee) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="提现方式" prop="withdrawal_method" width="100">
|
||||
<template #default="scope">
|
||||
{{
|
||||
WithdrawalMethodMap[
|
||||
scope.row.withdrawal_method as keyof typeof WithdrawalMethodMap
|
||||
]?.label || scope.row.withdrawal_method
|
||||
}}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="状态" prop="status" width="100">
|
||||
<template #default="scope">
|
||||
<ElTag
|
||||
:type="
|
||||
WithdrawalStatusMap[scope.row.status as keyof typeof WithdrawalStatusMap]
|
||||
?.type || 'info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
WithdrawalStatusMap[scope.row.status as keyof typeof WithdrawalStatusMap]
|
||||
?.label || scope.row.status
|
||||
}}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="申请时间" prop="created_at" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatDateTime(scope.row.created_at) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="处理时间" prop="processed_at" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatDateTime(scope.row.processed_at) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElTabPane>
|
||||
</ElTabs>
|
||||
</ElDrawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { CommissionService } from '@/api/modules'
|
||||
import { ElMessage, ElTag } from 'element-plus'
|
||||
import type {
|
||||
ShopCommissionSummaryItem,
|
||||
ShopCommissionRecordItem,
|
||||
WithdrawalRequestItem
|
||||
} from '@/types/api/commission'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
import { formatDateTime, formatMoney } from '@/utils/business/format'
|
||||
import {
|
||||
CommissionStatusMap,
|
||||
WithdrawalStatusMap,
|
||||
WithdrawalMethodMap,
|
||||
CommissionTypeMap
|
||||
} from '@/config/constants/commission'
|
||||
|
||||
defineOptions({ name: 'AgentCommission' })
|
||||
|
||||
// 主表格状态
|
||||
const loading = ref(false)
|
||||
const tableRef = ref()
|
||||
const summaryList = ref<ShopCommissionSummaryItem[]>([])
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
shop_name: '',
|
||||
shop_code: ''
|
||||
})
|
||||
|
||||
// 主表格分页
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 详情抽屉状态
|
||||
const detailDrawerVisible = ref(false)
|
||||
const activeTab = ref<'commission' | 'withdrawal'>('commission')
|
||||
const currentShop = ref<ShopCommissionSummaryItem | null>(null)
|
||||
|
||||
// 佣金明细状态
|
||||
const commissionLoading = ref(false)
|
||||
const commissionTableRef = ref()
|
||||
const commissionRecords = ref<ShopCommissionRecordItem[]>([])
|
||||
const commissionPagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 提现记录状态
|
||||
const withdrawalLoading = ref(false)
|
||||
const withdrawalTableRef = ref()
|
||||
const withdrawalRecords = ref<WithdrawalRequestItem[]>([])
|
||||
const withdrawalPagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: '店铺ID', prop: 'shop_id' },
|
||||
{ label: '店铺编码', prop: 'shop_code' },
|
||||
{ label: '店铺名称', prop: 'shop_name' },
|
||||
{ label: '用户名', prop: 'username' },
|
||||
{ label: '手机号', prop: 'phone' },
|
||||
{ label: '总佣金', prop: 'total_commission' },
|
||||
{ label: '可提现', prop: 'available_commission' },
|
||||
{ label: '冻结中', prop: 'frozen_commission' },
|
||||
{ label: '提现中', prop: 'withdrawing_commission' },
|
||||
{ label: '已提现', prop: 'withdrawn_commission' },
|
||||
{ label: '未提现', prop: 'unwithdraw_commission' },
|
||||
{ label: '操作', prop: 'operation' }
|
||||
]
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
prop: 'shop_id',
|
||||
label: '店铺ID',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
prop: 'shop_code',
|
||||
label: '店铺编码',
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
prop: 'shop_name',
|
||||
label: '店铺名称',
|
||||
minWidth: 180,
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
{
|
||||
prop: 'username',
|
||||
label: '用户名',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
prop: 'phone',
|
||||
label: '手机号',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
prop: 'total_commission',
|
||||
label: '总佣金',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => formatMoney(row.total_commission)
|
||||
},
|
||||
{
|
||||
prop: 'available_commission',
|
||||
label: '可提现',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => {
|
||||
return h(
|
||||
'span',
|
||||
{ style: 'color: var(--el-color-success); font-weight: 500' },
|
||||
formatMoney(row.available_commission)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'frozen_commission',
|
||||
label: '冻结中',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => formatMoney(row.frozen_commission)
|
||||
},
|
||||
{
|
||||
prop: 'withdrawing_commission',
|
||||
label: '提现中',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => {
|
||||
return h(
|
||||
'span',
|
||||
{ style: 'color: var(--el-color-warning)' },
|
||||
formatMoney(row.withdrawing_commission)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'withdrawn_commission',
|
||||
label: '已提现',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => formatMoney(row.withdrawn_commission)
|
||||
},
|
||||
{
|
||||
prop: 'unwithdraw_commission',
|
||||
label: '未提现',
|
||||
width: 120,
|
||||
formatter: (row: ShopCommissionSummaryItem) => formatMoney(row.unwithdraw_commission)
|
||||
},
|
||||
{
|
||||
prop: 'operation',
|
||||
label: '操作',
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
formatter: (row: ShopCommissionSummaryItem) => {
|
||||
return h(ArtButtonTable, {
|
||||
icon: '',
|
||||
onClick: () => showDetail(row)
|
||||
})
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
getTableData()
|
||||
})
|
||||
|
||||
// 获取代理商佣金汇总列表
|
||||
const getTableData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
shop_name: searchForm.shop_name || undefined,
|
||||
shop_code: searchForm.shop_code || undefined
|
||||
}
|
||||
const res = await CommissionService.getShopCommissionSummary(params)
|
||||
if (res.code === 0) {
|
||||
summaryList.value = res.data.items || []
|
||||
pagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('获取数据失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.page = 1
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
searchForm.shop_name = ''
|
||||
searchForm.shop_code = ''
|
||||
pagination.page = 1
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 刷新
|
||||
const handleRefresh = () => {
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 分页变化
|
||||
const handleSizeChange = (newPageSize: number) => {
|
||||
pagination.pageSize = newPageSize
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const handleCurrentChange = (newCurrentPage: number) => {
|
||||
pagination.page = newCurrentPage
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 显示详情抽屉
|
||||
const showDetail = (row: ShopCommissionSummaryItem) => {
|
||||
currentShop.value = row
|
||||
detailDrawerVisible.value = true
|
||||
activeTab.value = 'commission'
|
||||
|
||||
// 重置分页
|
||||
commissionPagination.page = 1
|
||||
withdrawalPagination.page = 1
|
||||
|
||||
// 加载佣金明细
|
||||
loadCommissionRecords()
|
||||
}
|
||||
|
||||
// 监听tab切换
|
||||
watch(activeTab, (newTab) => {
|
||||
if (newTab === 'commission') {
|
||||
loadCommissionRecords()
|
||||
} else if (newTab === 'withdrawal') {
|
||||
loadWithdrawalRecords()
|
||||
}
|
||||
})
|
||||
|
||||
// 加载佣金明细
|
||||
const loadCommissionRecords = async () => {
|
||||
if (!currentShop.value) return
|
||||
|
||||
commissionLoading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: commissionPagination.page,
|
||||
pageSize: commissionPagination.pageSize
|
||||
}
|
||||
const res = await CommissionService.getShopCommissionRecords(
|
||||
currentShop.value.shop_id,
|
||||
params
|
||||
)
|
||||
if (res.code === 0) {
|
||||
commissionRecords.value = res.data.items || []
|
||||
commissionPagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('获取佣金明细失败')
|
||||
} finally {
|
||||
commissionLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 佣金明细分页
|
||||
const handleCommissionSizeChange = (newPageSize: number) => {
|
||||
commissionPagination.pageSize = newPageSize
|
||||
loadCommissionRecords()
|
||||
}
|
||||
|
||||
const handleCommissionCurrentChange = (newCurrentPage: number) => {
|
||||
commissionPagination.page = newCurrentPage
|
||||
loadCommissionRecords()
|
||||
}
|
||||
|
||||
// 加载提现记录
|
||||
const loadWithdrawalRecords = async () => {
|
||||
if (!currentShop.value) return
|
||||
|
||||
withdrawalLoading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: withdrawalPagination.page,
|
||||
pageSize: withdrawalPagination.pageSize
|
||||
}
|
||||
const res = await CommissionService.getShopWithdrawalRequests(
|
||||
currentShop.value.shop_id,
|
||||
params
|
||||
)
|
||||
if (res.code === 0) {
|
||||
withdrawalRecords.value = res.data.items || []
|
||||
withdrawalPagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('获取提现记录失败')
|
||||
} finally {
|
||||
withdrawalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 提现记录分页
|
||||
const handleWithdrawalSizeChange = (newPageSize: number) => {
|
||||
withdrawalPagination.pageSize = newPageSize
|
||||
loadWithdrawalRecords()
|
||||
}
|
||||
|
||||
const handleWithdrawalCurrentChange = (newCurrentPage: number) => {
|
||||
withdrawalPagination.page = newCurrentPage
|
||||
loadWithdrawalRecords()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.agent-commission-page {
|
||||
.search-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-tabs {
|
||||
:deep(.el-tabs__content) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
874
src/views/finance/commission/my-commission/index.vue
Normal file
874
src/views/finance/commission/my-commission/index.vue
Normal file
@@ -0,0 +1,874 @@
|
||||
<template>
|
||||
<div class="my-commission-page">
|
||||
<!-- 佣金概览卡片 -->
|
||||
<ElRow :gutter="20" style="margin-bottom: 20px">
|
||||
<ElCol :xs="24" :sm="12" :md="8" :lg="4">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-label">总佣金</div>
|
||||
<div class="stat-value">{{ formatMoney(summary.total_commission) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCol>
|
||||
<ElCol :xs="24" :sm="12" :md="8" :lg="4">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-label">可提现佣金</div>
|
||||
<div class="stat-value">{{ formatMoney(summary.available_commission) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCol>
|
||||
<ElCol :xs="24" :sm="12" :md="8" :lg="4">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-label">冻结佣金</div>
|
||||
<div class="stat-value">{{ formatMoney(summary.frozen_commission) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCol>
|
||||
<ElCol :xs="24" :sm="12" :md="8" :lg="4">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-label">提现中佣金</div>
|
||||
<div class="stat-value">{{ formatMoney(summary.withdrawing_commission) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCol>
|
||||
<ElCol :xs="24" :sm="12" :md="8" :lg="4">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-label">已提现佣金</div>
|
||||
<div class="stat-value">{{ formatMoney(summary.withdrawn_commission) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
|
||||
<!-- 标签页 -->
|
||||
<ElCard shadow="never">
|
||||
<ElTabs v-model="activeTab">
|
||||
<!-- 佣金明细 -->
|
||||
<ElTabPane label="佣金明细" name="commission">
|
||||
<!-- 搜索栏 -->
|
||||
<ArtSearchBar
|
||||
v-model:filter="commissionSearchForm"
|
||||
:items="commissionSearchItems"
|
||||
:show-expand="false"
|
||||
@reset="handleCommissionReset"
|
||||
@search="handleCommissionSearch"
|
||||
/>
|
||||
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader
|
||||
:columnList="commissionColumnOptions"
|
||||
v-model:columns="commissionColumnChecks"
|
||||
@refresh="handleCommissionRefresh"
|
||||
style="margin-top: 20px"
|
||||
>
|
||||
<template #left>
|
||||
<ElButton type="primary" @click="showWithdrawalDialog">发起提现</ElButton>
|
||||
</template>
|
||||
</ArtTableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="commissionTableRef"
|
||||
row-key="id"
|
||||
:loading="commissionLoading"
|
||||
:data="commissionList"
|
||||
:currentPage="commissionPagination.page"
|
||||
:pageSize="commissionPagination.pageSize"
|
||||
:total="commissionPagination.total"
|
||||
:marginTop="10"
|
||||
:height="420"
|
||||
@size-change="handleCommissionSizeChange"
|
||||
@current-change="handleCommissionCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn
|
||||
v-for="col in commissionColumns"
|
||||
:key="col.prop || col.type"
|
||||
v-bind="col"
|
||||
/>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElTabPane>
|
||||
|
||||
<!-- 提现记录 -->
|
||||
<ElTabPane label="提现记录" name="withdrawal">
|
||||
<!-- 搜索栏 -->
|
||||
<ArtSearchBar
|
||||
v-model:filter="withdrawalSearchForm"
|
||||
:items="withdrawalSearchItems"
|
||||
:show-expand="false"
|
||||
@reset="handleWithdrawalReset"
|
||||
@search="handleWithdrawalSearch"
|
||||
/>
|
||||
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader
|
||||
:columnList="withdrawalColumnOptions"
|
||||
v-model:columns="withdrawalColumnChecks"
|
||||
@refresh="handleWithdrawalRefresh"
|
||||
style="margin-top: 20px"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="withdrawalTableRef"
|
||||
row-key="id"
|
||||
:loading="withdrawalLoading"
|
||||
:data="withdrawalList"
|
||||
:currentPage="withdrawalPagination.page"
|
||||
:pageSize="withdrawalPagination.pageSize"
|
||||
:total="withdrawalPagination.total"
|
||||
:marginTop="10"
|
||||
:height="500"
|
||||
@size-change="handleWithdrawalSizeChange"
|
||||
@current-change="handleWithdrawalCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn
|
||||
v-for="col in withdrawalColumns"
|
||||
:key="col.prop || col.type"
|
||||
v-bind="col"
|
||||
/>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElTabPane>
|
||||
</ElTabs>
|
||||
</ElCard>
|
||||
|
||||
<!-- 发起提现对话框 -->
|
||||
<ElDialog
|
||||
v-model="withdrawalDialogVisible"
|
||||
title="发起提现"
|
||||
width="600px"
|
||||
@close="handleDialogClose"
|
||||
>
|
||||
<ElForm
|
||||
ref="withdrawalFormRef"
|
||||
:model="withdrawalForm"
|
||||
:rules="withdrawalRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<ElFormItem label="可提现金额">
|
||||
<span style="font-size: 20px; font-weight: 500; color: var(--el-color-success)">
|
||||
{{ formatMoney(summary.available_commission) }}
|
||||
</span>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="提现金额" prop="amount">
|
||||
<ElInputNumber
|
||||
v-model="withdrawalForm.amount"
|
||||
:min="100"
|
||||
:max="summary.available_commission"
|
||||
:precision="0"
|
||||
:step="100"
|
||||
style="width: 100%"
|
||||
placeholder="请输入提现金额(分)"
|
||||
/>
|
||||
<div style="margin-top: 4px; font-size: 12px; color: var(--el-text-color-secondary)">
|
||||
金额单位为分,如1元=100分
|
||||
</div>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="提现方式" prop="withdrawal_method">
|
||||
<ElRadioGroup v-model="withdrawalForm.withdrawal_method">
|
||||
<ElRadio :label="WithdrawalMethod.ALIPAY">支付宝</ElRadio>
|
||||
<ElRadio :label="WithdrawalMethod.WECHAT">微信</ElRadio>
|
||||
<ElRadio :label="WithdrawalMethod.BANK">银行卡</ElRadio>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
|
||||
<!-- 支付宝/微信 -->
|
||||
<template v-if="withdrawalForm.withdrawal_method !== WithdrawalMethod.BANK">
|
||||
<ElFormItem label="账户名" prop="account_name">
|
||||
<ElInput v-model="withdrawalForm.account_name" placeholder="请输入账户名" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="账号" prop="account_number">
|
||||
<ElInput v-model="withdrawalForm.account_number" placeholder="请输入账号" />
|
||||
</ElFormItem>
|
||||
</template>
|
||||
|
||||
<!-- 银行卡 -->
|
||||
<template v-if="withdrawalForm.withdrawal_method === WithdrawalMethod.BANK">
|
||||
<ElFormItem label="银行名称" prop="bank_name">
|
||||
<ElSelect
|
||||
v-model="withdrawalForm.bank_name"
|
||||
placeholder="请选择银行"
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption label="中国工商银行" value="中国工商银行" />
|
||||
<ElOption label="中国建设银行" value="中国建设银行" />
|
||||
<ElOption label="中国农业银行" value="中国农业银行" />
|
||||
<ElOption label="中国银行" value="中国银行" />
|
||||
<ElOption label="招商银行" value="招商银行" />
|
||||
<ElOption label="交通银行" value="交通银行" />
|
||||
<ElOption label="中国邮政储蓄银行" value="中国邮政储蓄银行" />
|
||||
<ElOption label="其他银行" value="其他银行" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="账户名" prop="account_name">
|
||||
<ElInput v-model="withdrawalForm.account_name" placeholder="请输入账户名" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="卡号" prop="account_number">
|
||||
<ElInput v-model="withdrawalForm.account_number" placeholder="请输入银行卡号" />
|
||||
</ElFormItem>
|
||||
</template>
|
||||
|
||||
<ElFormItem label="备注" prop="remark">
|
||||
<ElInput v-model="withdrawalForm.remark" type="textarea" :rows="3" placeholder="选填" />
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="withdrawalDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmitWithdrawal" :loading="submitLoading">
|
||||
提交
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { CommissionService } from '@/api/modules'
|
||||
import { ElMessage, ElTag } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type {
|
||||
MyCommissionSummary,
|
||||
MyCommissionRecordItem,
|
||||
WithdrawalRequestItem,
|
||||
CommissionRecordQueryParams,
|
||||
WithdrawalRequestQueryParams,
|
||||
SubmitWithdrawalParams,
|
||||
CommissionType,
|
||||
CommissionStatus,
|
||||
WithdrawalStatus
|
||||
} from '@/types/api/commission'
|
||||
import { WithdrawalMethod } from '@/types/api/commission'
|
||||
import {
|
||||
CommissionStatusMap,
|
||||
CommissionTypeMap,
|
||||
WithdrawalStatusMap,
|
||||
WithdrawalMethodMap
|
||||
} from '@/config/constants/commission'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import { formatDateTime, formatMoney } from '@/utils/business/format'
|
||||
|
||||
defineOptions({ name: 'MyCommission' })
|
||||
|
||||
// 标签页
|
||||
const activeTab = ref('commission')
|
||||
|
||||
// 佣金概览
|
||||
const summary = ref<MyCommissionSummary>({
|
||||
total_commission: 0,
|
||||
available_commission: 0,
|
||||
frozen_commission: 0,
|
||||
withdrawing_commission: 0,
|
||||
withdrawn_commission: 0
|
||||
})
|
||||
|
||||
// ==================== 佣金明细 ====================
|
||||
|
||||
const commissionLoading = ref(false)
|
||||
const commissionTableRef = ref()
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialCommissionSearchState = {
|
||||
commission_type: undefined as CommissionType | undefined,
|
||||
status: undefined as CommissionStatus | undefined,
|
||||
start_time: '',
|
||||
end_time: ''
|
||||
}
|
||||
|
||||
// 搜索表单
|
||||
const commissionSearchForm = reactive({ ...initialCommissionSearchState })
|
||||
|
||||
// 搜索表单配置
|
||||
const commissionSearchItems = computed<SearchFormItem[]>(() => [
|
||||
{
|
||||
label: '佣金类型',
|
||||
prop: 'commission_type',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '一次性佣金', value: 'one_time' },
|
||||
{ label: '长期佣金', value: 'long_term' }
|
||||
],
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请选择佣金类型'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '已冻结', value: 1 },
|
||||
{ label: '解冻中', value: 2 },
|
||||
{ label: '已发放', value: 3 },
|
||||
{ label: '已失效', value: 4 }
|
||||
],
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请选择状态'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '时间范围',
|
||||
prop: 'dateRange',
|
||||
type: 'date',
|
||||
config: {
|
||||
type: 'daterange',
|
||||
clearable: true,
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期'
|
||||
},
|
||||
onChange: ({ val }: { prop: string; val: any }) => {
|
||||
if (val && val.length === 2) {
|
||||
commissionSearchForm.start_time = val[0]
|
||||
commissionSearchForm.end_time = val[1]
|
||||
} else {
|
||||
commissionSearchForm.start_time = ''
|
||||
commissionSearchForm.end_time = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// 分页
|
||||
const commissionPagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 列配置
|
||||
const commissionColumnOptions = [
|
||||
{ label: 'ID', prop: 'id' },
|
||||
{ label: '佣金金额', prop: 'amount' },
|
||||
{ label: '佣金类型', prop: 'commission_type' },
|
||||
{ label: '状态', prop: 'status' },
|
||||
{ label: '订单ID', prop: 'order_id' },
|
||||
{ label: '创建时间', prop: 'created_at' }
|
||||
]
|
||||
|
||||
const commissionList = ref<MyCommissionRecordItem[]>([])
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks: commissionColumnChecks, columns: commissionColumns } = useCheckedColumns(
|
||||
() => [
|
||||
{
|
||||
prop: 'id',
|
||||
label: 'ID',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'amount',
|
||||
label: '佣金金额',
|
||||
width: 140,
|
||||
formatter: (row: MyCommissionRecordItem) => formatMoney(row.amount)
|
||||
},
|
||||
{
|
||||
prop: 'commission_type',
|
||||
label: '佣金类型',
|
||||
width: 120,
|
||||
formatter: (row: MyCommissionRecordItem) => {
|
||||
const config = CommissionTypeMap[row.commission_type as keyof typeof CommissionTypeMap]
|
||||
return h(ElTag, { type: config.type }, () => config.label)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
width: 100,
|
||||
formatter: (row: MyCommissionRecordItem) => {
|
||||
const config = CommissionStatusMap[row.status as keyof typeof CommissionStatusMap]
|
||||
return h(ElTag, { type: config.type }, () => config.label)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'order_id',
|
||||
label: '订单ID',
|
||||
width: 100,
|
||||
formatter: (row: MyCommissionRecordItem) => row.order_id || '-'
|
||||
},
|
||||
{
|
||||
prop: 'shop_id',
|
||||
label: '店铺ID',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
label: '创建时间',
|
||||
width: 180,
|
||||
formatter: (row: MyCommissionRecordItem) => formatDateTime(row.created_at)
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
// 获取佣金明细
|
||||
const getCommissionList = async () => {
|
||||
commissionLoading.value = true
|
||||
try {
|
||||
const params = {
|
||||
pageSize: commissionPagination.pageSize,
|
||||
current: commissionPagination.page,
|
||||
commission_type: commissionSearchForm.commission_type,
|
||||
status: commissionSearchForm.status,
|
||||
start_time: commissionSearchForm.start_time || undefined,
|
||||
end_time: commissionSearchForm.end_time || undefined
|
||||
} as CommissionRecordQueryParams
|
||||
const res = await CommissionService.getMyCommissionRecords(params)
|
||||
if (res.code === 0) {
|
||||
commissionList.value = res.data.items || []
|
||||
commissionPagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
commissionLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const handleCommissionReset = () => {
|
||||
Object.assign(commissionSearchForm, { ...initialCommissionSearchState })
|
||||
commissionPagination.page = 1
|
||||
getCommissionList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleCommissionSearch = () => {
|
||||
commissionPagination.page = 1
|
||||
getCommissionList()
|
||||
}
|
||||
|
||||
// 刷新表格
|
||||
const handleCommissionRefresh = () => {
|
||||
getCommissionList()
|
||||
}
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleCommissionSizeChange = (newPageSize: number) => {
|
||||
commissionPagination.pageSize = newPageSize
|
||||
getCommissionList()
|
||||
}
|
||||
|
||||
const handleCommissionCurrentChange = (newCurrentPage: number) => {
|
||||
commissionPagination.page = newCurrentPage
|
||||
getCommissionList()
|
||||
}
|
||||
|
||||
// ==================== 提现记录 ====================
|
||||
|
||||
const withdrawalLoading = ref(false)
|
||||
const withdrawalTableRef = ref()
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialWithdrawalSearchState = {
|
||||
status: undefined as WithdrawalStatus | undefined,
|
||||
start_time: '',
|
||||
end_time: ''
|
||||
}
|
||||
|
||||
// 搜索表单
|
||||
const withdrawalSearchForm = reactive({ ...initialWithdrawalSearchState })
|
||||
|
||||
// 搜索表单配置
|
||||
const withdrawalSearchItems = computed<SearchFormItem[]>(() => [
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 1 },
|
||||
{ label: '已通过', value: 2 },
|
||||
{ label: '已拒绝', value: 3 },
|
||||
{ label: '已到账', value: 4 }
|
||||
],
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '请选择状态'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '时间范围',
|
||||
prop: 'dateRange',
|
||||
type: 'date',
|
||||
config: {
|
||||
type: 'daterange',
|
||||
clearable: true,
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期'
|
||||
},
|
||||
onChange: ({ val }: { prop: string; val: any }) => {
|
||||
if (val && val.length === 2) {
|
||||
withdrawalSearchForm.start_time = val[0]
|
||||
withdrawalSearchForm.end_time = val[1]
|
||||
} else {
|
||||
withdrawalSearchForm.start_time = ''
|
||||
withdrawalSearchForm.end_time = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// 分页
|
||||
const withdrawalPagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 列配置
|
||||
const withdrawalColumnOptions = [
|
||||
{ label: 'ID', prop: 'id' },
|
||||
{ label: '提现单号', prop: 'withdrawal_no' },
|
||||
{ label: '金额', prop: 'amount' },
|
||||
{ label: '手续费', prop: 'fee' },
|
||||
{ label: '实际到账', prop: 'actual_amount' },
|
||||
{ label: '提现方式', prop: 'withdrawal_method' },
|
||||
{ label: '状态', prop: 'status' },
|
||||
{ label: '申请时间', prop: 'created_at' }
|
||||
]
|
||||
|
||||
const withdrawalList = ref<WithdrawalRequestItem[]>([])
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks: withdrawalColumnChecks, columns: withdrawalColumns } = useCheckedColumns(
|
||||
() => [
|
||||
{
|
||||
prop: 'id',
|
||||
label: 'ID',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'withdrawal_no',
|
||||
label: '提现单号',
|
||||
minWidth: 160
|
||||
},
|
||||
{
|
||||
prop: 'amount',
|
||||
label: '金额',
|
||||
width: 120,
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.amount)
|
||||
},
|
||||
{
|
||||
prop: 'fee',
|
||||
label: '手续费',
|
||||
width: 100,
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.fee)
|
||||
},
|
||||
{
|
||||
prop: 'actual_amount',
|
||||
label: '实际到账',
|
||||
width: 120,
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.actual_amount)
|
||||
},
|
||||
{
|
||||
prop: 'withdrawal_method',
|
||||
label: '提现方式',
|
||||
width: 100,
|
||||
formatter: (row: WithdrawalRequestItem) => {
|
||||
const config =
|
||||
WithdrawalMethodMap[row.withdrawal_method as keyof typeof WithdrawalMethodMap]
|
||||
return config ? config.label : row.withdrawal_method
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
width: 100,
|
||||
formatter: (row: WithdrawalRequestItem) => {
|
||||
const config = WithdrawalStatusMap[row.status as keyof typeof WithdrawalStatusMap]
|
||||
return h(ElTag, { type: config.type }, () => config.label)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
label: '申请时间',
|
||||
width: 180,
|
||||
formatter: (row: WithdrawalRequestItem) => formatDateTime(row.created_at)
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
// 获取提现记录
|
||||
const getWithdrawalList = async () => {
|
||||
withdrawalLoading.value = true
|
||||
try {
|
||||
const params = {
|
||||
pageSize: withdrawalPagination.pageSize,
|
||||
current: withdrawalPagination.page,
|
||||
status: withdrawalSearchForm.status,
|
||||
start_time: withdrawalSearchForm.start_time || undefined,
|
||||
end_time: withdrawalSearchForm.end_time || undefined
|
||||
} as WithdrawalRequestQueryParams
|
||||
const res = await CommissionService.getMyWithdrawalRequests(params)
|
||||
if (res.code === 0) {
|
||||
withdrawalList.value = res.data.items || []
|
||||
withdrawalPagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
withdrawalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const handleWithdrawalReset = () => {
|
||||
Object.assign(withdrawalSearchForm, { ...initialWithdrawalSearchState })
|
||||
withdrawalPagination.page = 1
|
||||
getWithdrawalList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleWithdrawalSearch = () => {
|
||||
withdrawalPagination.page = 1
|
||||
getWithdrawalList()
|
||||
}
|
||||
|
||||
// 刷新表格
|
||||
const handleWithdrawalRefresh = () => {
|
||||
getWithdrawalList()
|
||||
}
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleWithdrawalSizeChange = (newPageSize: number) => {
|
||||
withdrawalPagination.pageSize = newPageSize
|
||||
getWithdrawalList()
|
||||
}
|
||||
|
||||
const handleWithdrawalCurrentChange = (newCurrentPage: number) => {
|
||||
withdrawalPagination.page = newCurrentPage
|
||||
getWithdrawalList()
|
||||
}
|
||||
|
||||
// ==================== 发起提现 ====================
|
||||
|
||||
const withdrawalDialogVisible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const withdrawalFormRef = ref<FormInstance>()
|
||||
|
||||
// 提现表单
|
||||
const withdrawalForm = reactive<SubmitWithdrawalParams>({
|
||||
amount: 0,
|
||||
withdrawal_method: WithdrawalMethod.ALIPAY,
|
||||
account_name: '',
|
||||
account_number: '',
|
||||
bank_name: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
// 提现表单验证规则
|
||||
const withdrawalRules = reactive<FormRules>({
|
||||
amount: [
|
||||
{ required: true, message: '请输入提现金额', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value < 100) {
|
||||
callback(new Error('提现金额不能小于100分(1元)'))
|
||||
} else if (value > summary.value.available_commission) {
|
||||
callback(new Error('提现金额不能大于可提现佣金'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
withdrawal_method: [{ required: true, message: '请选择提现方式', trigger: 'change' }],
|
||||
account_name: [
|
||||
{ required: true, message: '请输入账户名', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
account_number: [
|
||||
{ required: true, message: '请输入账号', trigger: 'blur' },
|
||||
{ min: 5, max: 50, message: '长度在 5 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
bank_name: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (withdrawalForm.withdrawal_method === WithdrawalMethod.BANK && !value) {
|
||||
callback(new Error('请选择银行名称'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 显示提现对话框
|
||||
const showWithdrawalDialog = () => {
|
||||
if (summary.value.available_commission < 100) {
|
||||
ElMessage.warning('可提现佣金不足100分(1元),无法发起提现')
|
||||
return
|
||||
}
|
||||
withdrawalDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const handleDialogClose = () => {
|
||||
withdrawalFormRef.value?.resetFields()
|
||||
withdrawalForm.amount = 0
|
||||
withdrawalForm.withdrawal_method = WithdrawalMethod.ALIPAY
|
||||
withdrawalForm.account_name = ''
|
||||
withdrawalForm.account_number = ''
|
||||
withdrawalForm.bank_name = ''
|
||||
withdrawalForm.remark = ''
|
||||
}
|
||||
|
||||
// 提交提现申请
|
||||
const handleSubmitWithdrawal = async () => {
|
||||
if (!withdrawalFormRef.value) return
|
||||
|
||||
await withdrawalFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const params: SubmitWithdrawalParams = {
|
||||
amount: withdrawalForm.amount,
|
||||
withdrawal_method: withdrawalForm.withdrawal_method,
|
||||
account_name: withdrawalForm.account_name,
|
||||
account_number: withdrawalForm.account_number,
|
||||
remark: withdrawalForm.remark
|
||||
}
|
||||
|
||||
// 如果是银行卡提现,添加银行名称
|
||||
if (withdrawalForm.withdrawal_method === WithdrawalMethod.BANK) {
|
||||
params.bank_name = withdrawalForm.bank_name
|
||||
}
|
||||
|
||||
await CommissionService.submitWithdrawalRequest(params)
|
||||
ElMessage.success('提现申请提交成功')
|
||||
withdrawalDialogVisible.value = false
|
||||
|
||||
// 刷新数据
|
||||
loadSummary()
|
||||
if (activeTab.value === 'withdrawal') {
|
||||
getWithdrawalList()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 初始化 ====================
|
||||
|
||||
// 加载佣金概览
|
||||
const loadSummary = async () => {
|
||||
try {
|
||||
const res = await CommissionService.getMyCommissionSummary()
|
||||
if (res.code === 0) {
|
||||
summary.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听标签页切换
|
||||
watch(activeTab, (newTab) => {
|
||||
if (newTab === 'commission') {
|
||||
getCommissionList()
|
||||
} else if (newTab === 'withdrawal') {
|
||||
getWithdrawalList()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadSummary()
|
||||
getCommissionList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.my-commission-page {
|
||||
.stat-card {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
.stat-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
font-size: 28px;
|
||||
color: white;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
|
||||
.stat-label {
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
425
src/views/finance/commission/withdrawal-approval/index.vue
Normal file
425
src/views/finance/commission/withdrawal-approval/index.vue
Normal file
@@ -0,0 +1,425 @@
|
||||
<template>
|
||||
<ArtTableFullScreen>
|
||||
<div class="withdrawal-approval-page" id="table-full-screen">
|
||||
<!-- 搜索栏 -->
|
||||
<ArtSearchBar
|
||||
v-model:filter="searchForm"
|
||||
:items="searchFormItems"
|
||||
:show-expand="false"
|
||||
@reset="handleReset"
|
||||
@search="handleSearch"
|
||||
></ArtSearchBar>
|
||||
|
||||
<ElCard shadow="never" class="art-table-card">
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader
|
||||
:columnList="columnOptions"
|
||||
v-model:columns="columnChecks"
|
||||
@refresh="handleRefresh"
|
||||
>
|
||||
</ArtTableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:data="withdrawalList"
|
||||
:currentPage="pagination.page"
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
|
||||
</template>
|
||||
</ArtTable>
|
||||
|
||||
<!-- 拒绝提现对话框 -->
|
||||
<ElDialog
|
||||
v-model="rejectDialogVisible"
|
||||
:title="$t('commission.dialog.reject')"
|
||||
width="500px"
|
||||
>
|
||||
<ElForm ref="rejectFormRef" :model="rejectForm" :rules="rejectRules" label-width="100px">
|
||||
<ElFormItem :label="$t('commission.form.rejectReason')" prop="reject_reason">
|
||||
<ElInput
|
||||
v-model="rejectForm.reject_reason"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:placeholder="$t('commission.form.rejectReasonPlaceholder')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('commission.form.remark')" prop="remark">
|
||||
<ElInput
|
||||
v-model="rejectForm.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
:placeholder="$t('commission.form.remarkPlaceholder')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="rejectDialogVisible = false">{{ $t('common.cancel') }}</ElButton>
|
||||
<ElButton type="primary" @click="handleRejectSubmit" :loading="rejectSubmitLoading">
|
||||
{{ $t('common.confirm') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { CommissionService } from '@/api/modules'
|
||||
import { ElMessage, ElMessageBox, ElTag } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type {
|
||||
WithdrawalRequestItem,
|
||||
WithdrawalStatus,
|
||||
WithdrawalMethod
|
||||
} from '@/types/api/commission'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
import { formatDateTime, formatMoney } from '@/utils/business/format'
|
||||
import { WithdrawalStatusMap, WithdrawalMethodMap } from '@/config/constants'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineOptions({ name: 'WithdrawalApproval' })
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rejectDialogVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
const rejectSubmitLoading = ref(false)
|
||||
const tableRef = ref()
|
||||
const currentWithdrawalId = ref<number>(0)
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState = {
|
||||
withdrawal_no: '',
|
||||
shop_name: '',
|
||||
status: undefined as WithdrawalStatus | undefined,
|
||||
start_time: '',
|
||||
end_time: ''
|
||||
}
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({ ...initialSearchState })
|
||||
|
||||
// 提现状态选项
|
||||
const withdrawalStatusOptions = [
|
||||
{ label: t('commission.status.pending'), value: 1 },
|
||||
{ label: t('commission.status.approved'), value: 2 },
|
||||
{ label: t('commission.status.rejected'), value: 3 },
|
||||
{ label: t('commission.status.completed'), value: 4 }
|
||||
]
|
||||
|
||||
// 搜索表单配置
|
||||
const searchFormItems: SearchFormItem[] = [
|
||||
{
|
||||
label: t('commission.searchForm.status'),
|
||||
prop: 'status',
|
||||
type: 'select',
|
||||
options: withdrawalStatusOptions,
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: t('commission.searchForm.statusPlaceholder')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('commission.searchForm.withdrawalNo'),
|
||||
prop: 'withdrawal_no',
|
||||
type: 'input',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: t('commission.searchForm.withdrawalNoPlaceholder')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('commission.searchForm.shopName'),
|
||||
prop: 'shop_name',
|
||||
type: 'input',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: t('commission.searchForm.shopNamePlaceholder')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('commission.searchForm.dateRange'),
|
||||
prop: 'dateRange',
|
||||
type: 'daterange',
|
||||
config: {
|
||||
clearable: true,
|
||||
startPlaceholder: t('commission.searchForm.dateRangePlaceholder.0'),
|
||||
endPlaceholder: t('commission.searchForm.dateRangePlaceholder.1'),
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
onChange: (val: [string, string] | null) => {
|
||||
if (val && val.length === 2) {
|
||||
searchForm.start_time = val[0]
|
||||
searchForm.end_time = val[1]
|
||||
} else {
|
||||
searchForm.start_time = ''
|
||||
searchForm.end_time = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: t('commission.table.withdrawalNo'), prop: 'withdrawal_no' },
|
||||
{ label: t('commission.table.shopName'), prop: 'shop_name' },
|
||||
{ label: t('commission.table.applicant'), prop: 'applicant_name' },
|
||||
{ label: t('commission.table.withdrawalAmount'), prop: 'amount' },
|
||||
{ label: t('commission.table.fee'), prop: 'fee' },
|
||||
{ label: t('commission.table.actualAmount'), prop: 'actual_amount' },
|
||||
{ label: t('commission.table.withdrawalMethod'), prop: 'withdrawal_method' },
|
||||
{ label: t('commission.table.status'), prop: 'status' },
|
||||
{ label: t('commission.table.applyTime'), prop: 'created_at' },
|
||||
{ label: t('commission.table.approveTime'), prop: 'processed_at' },
|
||||
{ label: t('commission.table.actions'), prop: 'operation' }
|
||||
]
|
||||
|
||||
const rejectFormRef = ref<FormInstance>()
|
||||
|
||||
const rejectRules = reactive<FormRules>({
|
||||
reject_reason: [
|
||||
{ required: true, message: t('commission.validation.rejectReasonRequired'), trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
const rejectForm = reactive({
|
||||
reject_reason: '',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const withdrawalList = ref<WithdrawalRequestItem[]>([])
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
prop: 'withdrawal_no',
|
||||
label: t('commission.table.withdrawalNo'),
|
||||
minWidth: 180
|
||||
},
|
||||
{
|
||||
prop: 'shop_name',
|
||||
label: t('commission.table.shopName'),
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
prop: 'applicant_name',
|
||||
label: t('commission.table.applicant'),
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: 'amount',
|
||||
label: t('commission.table.withdrawalAmount'),
|
||||
width: 120,
|
||||
align: 'right',
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.amount)
|
||||
},
|
||||
{
|
||||
prop: 'fee',
|
||||
label: t('commission.table.fee'),
|
||||
width: 100,
|
||||
align: 'right',
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.fee)
|
||||
},
|
||||
{
|
||||
prop: 'actual_amount',
|
||||
label: t('commission.table.actualAmount'),
|
||||
width: 120,
|
||||
align: 'right',
|
||||
formatter: (row: WithdrawalRequestItem) => formatMoney(row.actual_amount)
|
||||
},
|
||||
{
|
||||
prop: 'withdrawal_method',
|
||||
label: t('commission.table.withdrawalMethod'),
|
||||
width: 120,
|
||||
formatter: (row: WithdrawalRequestItem) => {
|
||||
const method = WithdrawalMethodMap[row.withdrawal_method as WithdrawalMethod]
|
||||
return method?.label || row.withdrawal_method
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: t('commission.table.status'),
|
||||
width: 100,
|
||||
formatter: (row: WithdrawalRequestItem) => {
|
||||
const statusInfo = WithdrawalStatusMap[row.status as keyof typeof WithdrawalStatusMap]
|
||||
return h(ElTag, { type: statusInfo?.type || 'info' }, () => statusInfo?.label || '未知')
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
label: t('commission.table.applyTime'),
|
||||
width: 180,
|
||||
formatter: (row: WithdrawalRequestItem) => formatDateTime(row.created_at)
|
||||
},
|
||||
{
|
||||
prop: 'processed_at',
|
||||
label: t('commission.table.approveTime'),
|
||||
width: 180,
|
||||
formatter: (row: WithdrawalRequestItem) => formatDateTime(row.processed_at)
|
||||
},
|
||||
{
|
||||
prop: 'operation',
|
||||
label: t('commission.table.actions'),
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
formatter: (row: WithdrawalRequestItem) => {
|
||||
// 只有待审核状态才显示操作按钮
|
||||
if (row.status === 1) {
|
||||
return h('div', { style: 'display: flex; gap: 8px;' }, [
|
||||
h(ArtButtonTable, {
|
||||
text: t('commission.buttons.approve'),
|
||||
iconColor: '#67C23A',
|
||||
onClick: () => handleApprove(row)
|
||||
}),
|
||||
h(ArtButtonTable, {
|
||||
text: t('commission.buttons.reject'),
|
||||
iconColor: '#F56C6C',
|
||||
onClick: () => showRejectDialog(row)
|
||||
})
|
||||
])
|
||||
}
|
||||
return '-'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
getTableData()
|
||||
})
|
||||
|
||||
// 获取提现申请列表
|
||||
const getTableData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
withdrawal_no: searchForm.withdrawal_no || undefined,
|
||||
shop_name: searchForm.shop_name || undefined,
|
||||
status: searchForm.status,
|
||||
start_time: searchForm.start_time || undefined,
|
||||
end_time: searchForm.end_time || undefined
|
||||
}
|
||||
const res = await CommissionService.getWithdrawalRequests(params)
|
||||
if (res.code === 0) {
|
||||
withdrawalList.value = res.data.items || []
|
||||
pagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置搜索
|
||||
const handleReset = () => {
|
||||
Object.assign(searchForm, { ...initialSearchState })
|
||||
pagination.page = 1
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.page = 1
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 刷新表格
|
||||
const handleRefresh = () => {
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleSizeChange = (newPageSize: number) => {
|
||||
pagination.pageSize = newPageSize
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const handleCurrentChange = (newCurrentPage: number) => {
|
||||
pagination.page = newCurrentPage
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 审批通过
|
||||
const handleApprove = (row: WithdrawalRequestItem) => {
|
||||
ElMessageBox.confirm(t('commission.messages.approveConfirm'), t('common.tips'), {
|
||||
confirmButtonText: t('common.confirm'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await CommissionService.approveWithdrawal(row.id)
|
||||
ElMessage.success(t('commission.messages.approveSuccess'))
|
||||
getTableData()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// 用户取消
|
||||
})
|
||||
}
|
||||
|
||||
// 显示拒绝对话框
|
||||
const showRejectDialog = (row: WithdrawalRequestItem) => {
|
||||
currentWithdrawalId.value = row.id
|
||||
rejectForm.reject_reason = ''
|
||||
rejectForm.remark = ''
|
||||
rejectDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交拒绝
|
||||
const handleRejectSubmit = async () => {
|
||||
if (!rejectFormRef.value) return
|
||||
|
||||
await rejectFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
rejectSubmitLoading.value = true
|
||||
try {
|
||||
await CommissionService.rejectWithdrawal(currentWithdrawalId.value, {
|
||||
reject_reason: rejectForm.reject_reason,
|
||||
remark: rejectForm.remark || undefined
|
||||
})
|
||||
ElMessage.success(t('commission.messages.rejectSuccess'))
|
||||
rejectDialogVisible.value = false
|
||||
rejectFormRef.value?.resetFields()
|
||||
getTableData()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
rejectSubmitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.withdrawal-approval-page {
|
||||
// 可以在这里添加提现审批页面特定样式
|
||||
}
|
||||
</style>
|
||||
453
src/views/finance/commission/withdrawal-settings/index.vue
Normal file
453
src/views/finance/commission/withdrawal-settings/index.vue
Normal file
@@ -0,0 +1,453 @@
|
||||
<template>
|
||||
<ArtTableFullScreen>
|
||||
<div class="withdrawal-settings-page" id="table-full-screen">
|
||||
<!-- 当前生效配置卡片 -->
|
||||
<ElCard shadow="never" class="current-setting-card" v-if="currentSetting">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<div class="header-left">
|
||||
<span class="header-title">当前生效配置</span>
|
||||
<ElTag type="success" effect="dark">生效中</ElTag>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span class="creator-info"
|
||||
>{{ currentSetting.creator_name || '-' }} 创建于
|
||||
{{ formatDateTime(currentSetting.created_at) }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="setting-info">
|
||||
<div class="info-card">
|
||||
<div
|
||||
class="info-icon"
|
||||
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
|
||||
>
|
||||
<i class="el-icon">💰</i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">最低提现金额</div>
|
||||
<div class="info-value">{{ formatMoney(currentSetting.min_withdrawal_amount) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div
|
||||
class="info-icon"
|
||||
style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)"
|
||||
>
|
||||
<i class="el-icon">📊</i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">手续费率</div>
|
||||
<div class="info-value">{{ formatFeeRate(currentSetting.fee_rate) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div
|
||||
class="info-icon"
|
||||
style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)"
|
||||
>
|
||||
<i class="el-icon">🔢</i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">每日提现次数</div>
|
||||
<div class="info-value">{{ currentSetting.daily_withdrawal_limit }} 次</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<div
|
||||
class="info-icon"
|
||||
style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)"
|
||||
>
|
||||
<i class="el-icon">⏰</i>
|
||||
</div>
|
||||
<div class="info-content">
|
||||
<div class="info-label">到账天数</div>
|
||||
<div class="info-value">{{
|
||||
currentSetting.arrival_days === 0 ? '实时到账' : `${currentSetting.arrival_days} 天`
|
||||
}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCard>
|
||||
|
||||
<!-- 配置列表 -->
|
||||
<ElCard shadow="never" class="art-table-card" style="margin-top: 20px">
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader
|
||||
:columnList="columnOptions"
|
||||
v-model:columns="columnChecks"
|
||||
@refresh="handleRefresh"
|
||||
>
|
||||
<template #left>
|
||||
<ElButton type="primary" @click="showDialog">新增配置</ElButton>
|
||||
</template>
|
||||
</ArtTableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:data="settingsList"
|
||||
:marginTop="10"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElCard>
|
||||
|
||||
<!-- 新增配置对话框 -->
|
||||
<ElDialog v-model="dialogVisible" title="新增提现配置" width="500px">
|
||||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<ElFormItem label="最低提现金额" prop="min_withdrawal_amount">
|
||||
<ElInputNumber
|
||||
v-model="form.min_withdrawal_amount"
|
||||
:min="1"
|
||||
:precision="2"
|
||||
:step="10"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<div class="form-tip">单位:元</div>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="手续费率" prop="fee_rate">
|
||||
<ElInputNumber
|
||||
v-model="form.fee_rate"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<div class="form-tip">单位:%(百分比)</div>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="每日提现次数" prop="daily_withdrawal_limit">
|
||||
<ElInputNumber
|
||||
v-model="form.daily_withdrawal_limit"
|
||||
:min="1"
|
||||
:max="100"
|
||||
:step="1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<div class="form-tip">单位:次</div>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="到账天数" prop="arrival_days">
|
||||
<ElInputNumber
|
||||
v-model="form.arrival_days"
|
||||
:min="0"
|
||||
:max="30"
|
||||
:step="1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<div class="form-tip">单位:天(0表示实时到账)</div>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="dialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit(formRef)" :loading="submitLoading">
|
||||
提交
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { CommissionService } from '@/api/modules'
|
||||
import { ElMessage, ElTag } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { WithdrawalSettingItem } from '@/types/api/commission'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import { formatDateTime, formatMoney, formatFeeRate } from '@/utils/business/format'
|
||||
|
||||
defineOptions({ name: 'CommissionWithdrawalSettings' })
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const tableRef = ref()
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 当前生效的配置
|
||||
const currentSetting = ref<WithdrawalSettingItem | null>(null)
|
||||
|
||||
// 配置列表
|
||||
const settingsList = ref<WithdrawalSettingItem[]>([])
|
||||
|
||||
// 表单数据(使用元和百分比)
|
||||
const form = reactive({
|
||||
min_withdrawal_amount: 100,
|
||||
fee_rate: 0.2,
|
||||
daily_withdrawal_limit: 3,
|
||||
arrival_days: 1
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive<FormRules>({
|
||||
min_withdrawal_amount: [
|
||||
{ required: true, message: '请输入最低提现金额', trigger: 'blur' },
|
||||
{ type: 'number', min: 1, message: '最低提现金额必须大于0', trigger: 'blur' }
|
||||
],
|
||||
fee_rate: [
|
||||
{ required: true, message: '请输入手续费率', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, max: 100, message: '手续费率必须在0-100之间', trigger: 'blur' }
|
||||
],
|
||||
daily_withdrawal_limit: [
|
||||
{ required: true, message: '请输入每日提现次数', trigger: 'blur' },
|
||||
{ type: 'number', min: 1, message: '每日提现次数必须大于0', trigger: 'blur' }
|
||||
],
|
||||
arrival_days: [
|
||||
{ required: true, message: '请输入到账天数', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '到账天数不能为负数', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: '最低提现金额', prop: 'min_withdrawal_amount' },
|
||||
{ label: '手续费率', prop: 'fee_rate' },
|
||||
{ label: '每日提现次数', prop: 'daily_withdrawal_limit' },
|
||||
{ label: '到账天数', prop: 'arrival_days' },
|
||||
{ label: '是否生效', prop: 'is_active' },
|
||||
{ label: '创建人', prop: 'creator_name' },
|
||||
{ label: '创建时间', prop: 'created_at' }
|
||||
]
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
prop: 'min_withdrawal_amount',
|
||||
label: '最低提现金额',
|
||||
formatter: (row: WithdrawalSettingItem) => formatMoney(row.min_withdrawal_amount)
|
||||
},
|
||||
{
|
||||
prop: 'fee_rate',
|
||||
label: '手续费率',
|
||||
formatter: (row: WithdrawalSettingItem) => formatFeeRate(row.fee_rate)
|
||||
},
|
||||
{
|
||||
prop: 'daily_withdrawal_limit',
|
||||
label: '每日提现次数',
|
||||
formatter: (row: WithdrawalSettingItem) => `${row.daily_withdrawal_limit} 次`
|
||||
},
|
||||
{
|
||||
prop: 'arrival_days',
|
||||
label: '到账天数',
|
||||
formatter: (row: WithdrawalSettingItem) => {
|
||||
return row.arrival_days === 0 ? '实时到账' : `${row.arrival_days} 天`
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'is_active',
|
||||
label: '是否生效',
|
||||
formatter: (row: WithdrawalSettingItem) => {
|
||||
return h(ElTag, { type: row.is_active ? 'success' : 'info' }, () =>
|
||||
row.is_active ? '生效中' : '已失效'
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'creator_name',
|
||||
label: '创建人',
|
||||
formatter: (row: WithdrawalSettingItem) => row.creator_name || '-'
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
label: '创建时间',
|
||||
formatter: (row: WithdrawalSettingItem) => formatDateTime(row.created_at)
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
await Promise.all([loadCurrentSetting(), loadSettingsList()])
|
||||
}
|
||||
|
||||
// 加载当前生效配置
|
||||
const loadCurrentSetting = async () => {
|
||||
try {
|
||||
const res = await CommissionService.getCurrentWithdrawalSetting()
|
||||
if (res.code === 0 && res.data) {
|
||||
currentSetting.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取当前配置失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载配置列表
|
||||
const loadSettingsList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await CommissionService.getWithdrawalSettings()
|
||||
if (res.code === 0) {
|
||||
settingsList.value = res.data.items || []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取配置列表失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
const handleRefresh = () => {
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 显示新增对话框
|
||||
const showDialog = () => {
|
||||
dialogVisible.value = true
|
||||
// 重置表单
|
||||
form.min_withdrawal_amount = 100
|
||||
form.fee_rate = 0.2
|
||||
form.daily_withdrawal_limit = 3
|
||||
form.arrival_days = 1
|
||||
formRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
// 转换单位:元 -> 分,百分比 -> 基点
|
||||
const params = {
|
||||
min_withdrawal_amount: Math.round(form.min_withdrawal_amount * 100), // 元转分
|
||||
fee_rate: Math.round(form.fee_rate * 100), // 百分比转基点
|
||||
daily_withdrawal_limit: form.daily_withdrawal_limit,
|
||||
arrival_days: form.arrival_days
|
||||
}
|
||||
|
||||
await CommissionService.createWithdrawalSetting(params)
|
||||
ElMessage.success('新增配置成功')
|
||||
dialogVisible.value = false
|
||||
formEl.resetFields()
|
||||
loadData()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.withdrawal-settings-page {
|
||||
.current-setting-card {
|
||||
:deep(.el-card__header) {
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
|
||||
.header-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
.creator-info {
|
||||
font-size: 13px;
|
||||
color: rgb(255 255 255 / 90%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setting-info {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 20px;
|
||||
padding: 4px 0;
|
||||
|
||||
@media (width <= 1400px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgb(0 0 0 / 10%);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 24px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
.info-label {
|
||||
margin-bottom: 4px;
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
.info-value {
|
||||
overflow: hidden;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,13 +4,28 @@
|
||||
<!-- 搜索栏 -->
|
||||
<ElForm :inline="true" :model="searchForm" class="search-form">
|
||||
<ElFormItem label="客户账号">
|
||||
<ElInput v-model="searchForm.accountNo" placeholder="请输入客户账号" clearable style="width: 200px" />
|
||||
<ElInput
|
||||
v-model="searchForm.accountNo"
|
||||
placeholder="请输入客户账号"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="客户名称">
|
||||
<ElInput v-model="searchForm.customerName" placeholder="请输入客户名称" clearable style="width: 200px" />
|
||||
<ElInput
|
||||
v-model="searchForm.customerName"
|
||||
placeholder="请输入客户名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="客户类型">
|
||||
<ElSelect v-model="searchForm.customerType" placeholder="请选择" clearable style="width: 150px">
|
||||
<ElSelect
|
||||
v-model="searchForm.customerType"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
>
|
||||
<ElOption label="代理商" value="agent" />
|
||||
<ElOption label="企业客户" value="enterprise" />
|
||||
</ElSelect>
|
||||
@@ -38,12 +53,16 @@
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="可提现金额" prop="availableAmount" width="150">
|
||||
<template #default="scope">
|
||||
<span style="color: var(--el-color-success)"> ¥{{ scope.row.availableAmount.toFixed(2) }} </span>
|
||||
<span style="color: var(--el-color-success)">
|
||||
¥{{ scope.row.availableAmount.toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="待入账金额" prop="pendingAmount" width="150">
|
||||
<template #default="scope">
|
||||
<span style="color: var(--el-color-warning)"> ¥{{ scope.row.pendingAmount.toFixed(2) }} </span>
|
||||
<span style="color: var(--el-color-warning)">
|
||||
¥{{ scope.row.pendingAmount.toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="已提现金额" prop="withdrawnAmount" width="150">
|
||||
@@ -67,7 +86,7 @@
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
style="margin-top: 20px; justify-content: flex-end"
|
||||
style="justify-content: flex-end; margin-top: 20px"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
@@ -84,18 +103,30 @@
|
||||
</ElTag>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="联系电话">{{ currentRow?.phone }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="佣金总额">¥{{ currentRow?.totalCommission.toFixed(2) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="佣金总额"
|
||||
>¥{{ currentRow?.totalCommission.toFixed(2) }}</ElDescriptionsItem
|
||||
>
|
||||
<ElDescriptionsItem label="可提现金额">
|
||||
<span style="color: var(--el-color-success)"> ¥{{ currentRow?.availableAmount.toFixed(2) }} </span>
|
||||
<span style="color: var(--el-color-success)">
|
||||
¥{{ currentRow?.availableAmount.toFixed(2) }}
|
||||
</span>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="待入账金额">
|
||||
<span style="color: var(--el-color-warning)"> ¥{{ currentRow?.pendingAmount.toFixed(2) }} </span>
|
||||
<span style="color: var(--el-color-warning)">
|
||||
¥{{ currentRow?.pendingAmount.toFixed(2) }}
|
||||
</span>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="已提现金额">¥{{ currentRow?.withdrawnAmount.toFixed(2) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="已提现金额"
|
||||
>¥{{ currentRow?.withdrawnAmount.toFixed(2) }}</ElDescriptionsItem
|
||||
>
|
||||
<ElDescriptionsItem label="提现次数">{{ currentRow?.withdrawCount }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="最后提现时间">{{ currentRow?.lastWithdrawTime }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="最后提现时间">{{
|
||||
currentRow?.lastWithdrawTime
|
||||
}}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="注册时间">{{ currentRow?.createTime }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="备注" :span="2">{{ currentRow?.remark || '无' }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="备注" :span="2">{{
|
||||
currentRow?.remark || '无'
|
||||
}}</ElDescriptionsItem>
|
||||
</ElDescriptions>
|
||||
</ElDialog>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
@@ -18,7 +21,10 @@
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
@@ -31,7 +37,10 @@
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
@@ -44,7 +53,10 @@
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElCard shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%)">
|
||||
<div
|
||||
class="stat-icon"
|
||||
style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%)"
|
||||
>
|
||||
<i class="iconfont-sys"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
@@ -65,7 +77,7 @@
|
||||
<!-- 收支流水 -->
|
||||
<ElCard shadow="never">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||
<span style="font-weight: 500">收支流水</span>
|
||||
<ElRadioGroup v-model="flowType" size="small">
|
||||
<ElRadioButton value="all">全部</ElRadioButton>
|
||||
@@ -87,7 +99,14 @@
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="金额" prop="amount">
|
||||
<template #default="scope">
|
||||
<span :style="{ color: scope.row.type === 'income' ? 'var(--el-color-success)' : 'var(--el-color-danger)' }">
|
||||
<span
|
||||
:style="{
|
||||
color:
|
||||
scope.row.type === 'income'
|
||||
? 'var(--el-color-success)'
|
||||
: 'var(--el-color-danger)'
|
||||
}"
|
||||
>
|
||||
{{ scope.row.type === 'income' ? '+' : '-' }}¥{{ scope.row.amount.toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
@@ -103,9 +122,14 @@
|
||||
|
||||
<!-- 提现申请对话框 -->
|
||||
<ElDialog v-model="withdrawDialogVisible" title="申请提现" width="600px" align-center>
|
||||
<ElForm ref="withdrawFormRef" :model="withdrawForm" :rules="withdrawRules" label-width="120px">
|
||||
<ElForm
|
||||
ref="withdrawFormRef"
|
||||
:model="withdrawForm"
|
||||
:rules="withdrawRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<ElFormItem label="可提现金额">
|
||||
<span style="color: var(--el-color-success); font-size: 20px; font-weight: 500">
|
||||
<span style="font-size: 20px; font-weight: 500; color: var(--el-color-success)">
|
||||
¥{{ accountInfo.availableAmount.toFixed(2) }}
|
||||
</span>
|
||||
</ElFormItem>
|
||||
@@ -125,12 +149,16 @@
|
||||
</span>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="实际到账">
|
||||
<span style="color: var(--el-color-success); font-size: 18px; font-weight: 500">
|
||||
<span style="font-size: 18px; font-weight: 500; color: var(--el-color-success)">
|
||||
¥{{ actualAmount.toFixed(2) }}
|
||||
</span>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="收款银行" prop="bankName">
|
||||
<ElSelect v-model="withdrawForm.bankName" placeholder="请选择收款银行" style="width: 100%">
|
||||
<ElSelect
|
||||
v-model="withdrawForm.bankName"
|
||||
placeholder="请选择收款银行"
|
||||
style="width: 100%"
|
||||
>
|
||||
<ElOption label="中国工商银行" value="工商银行" />
|
||||
<ElOption label="中国建设银行" value="建设银行" />
|
||||
<ElOption label="中国农业银行" value="农业银行" />
|
||||
@@ -271,27 +299,27 @@
|
||||
.page-content {
|
||||
.stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
.stat-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
font-size: 28px;
|
||||
color: white;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
|
||||
.stat-label {
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
<template>
|
||||
<div class="page-content">
|
||||
<ElCard shadow="never">
|
||||
<template #header>
|
||||
<span style="font-weight: 500">提现参数配置</span>
|
||||
</template>
|
||||
|
||||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="150px" style="max-width: 800px">
|
||||
<ElFormItem label="最低提现金额" prop="minAmount">
|
||||
<ElInputNumber v-model="form.minAmount" :min="1" :precision="2" />
|
||||
<span style="margin-left: 8px">元</span>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="手续费模式" prop="feeMode">
|
||||
<ElRadioGroup v-model="form.feeMode">
|
||||
<ElRadio value="fixed">固定手续费</ElRadio>
|
||||
<ElRadio value="percent">比例手续费</ElRadio>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem v-if="form.feeMode === 'fixed'" label="固定手续费" prop="fixedFee">
|
||||
<ElInputNumber v-model="form.fixedFee" :min="0" :precision="2" />
|
||||
<span style="margin-left: 8px">元/笔</span>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem v-if="form.feeMode === 'percent'" label="手续费比例" prop="feePercent">
|
||||
<ElInputNumber v-model="form.feePercent" :min="0" :max="100" :precision="2" />
|
||||
<span style="margin-left: 8px">%</span>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="单日提现次数" prop="dailyLimit">
|
||||
<ElInputNumber v-model="form.dailyLimit" :min="1" :max="10" />
|
||||
<span style="margin-left: 8px">次</span>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="提现到账时间" prop="arrivalTime">
|
||||
<ElSelect v-model="form.arrivalTime" style="width: 200px">
|
||||
<ElOption label="实时到账" value="realtime" />
|
||||
<ElOption label="2小时内到账" value="2hours" />
|
||||
<ElOption label="24小时内到账" value="24hours" />
|
||||
<ElOption label="T+1到账" value="t1" />
|
||||
<ElOption label="T+3到账" value="t3" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="工作日提现" prop="workdayOnly">
|
||||
<ElSwitch v-model="form.workdayOnly" />
|
||||
<span style="margin-left: 8px; color: var(--el-text-color-secondary)">
|
||||
{{ form.workdayOnly ? '仅工作日可提现' : '每天都可提现' }}
|
||||
</span>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="提现时间段" prop="timeRange">
|
||||
<ElTimePicker
|
||||
v-model="form.timeRange"
|
||||
is-range
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
format="HH:mm"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="配置说明" prop="description">
|
||||
<ElInput
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入配置说明,如配置生效时间等"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem>
|
||||
<ElButton type="primary" @click="handleSave">保存配置</ElButton>
|
||||
<ElButton @click="resetForm">重置</ElButton>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
</ElCard>
|
||||
|
||||
<ElCard shadow="never" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<span style="font-weight: 500">配置历史记录</span>
|
||||
</template>
|
||||
|
||||
<ArtTable :data="historyData" index>
|
||||
<template #default>
|
||||
<ElTableColumn label="配置时间" prop="configTime" width="180" />
|
||||
<ElTableColumn label="最低金额" prop="minAmount">
|
||||
<template #default="scope"> ¥{{ scope.row.minAmount.toFixed(2) }} </template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="手续费" prop="fee">
|
||||
<template #default="scope">
|
||||
{{
|
||||
scope.row.feeMode === 'fixed'
|
||||
? `¥${scope.row.fixedFee.toFixed(2)}/笔`
|
||||
: `${scope.row.feePercent}%`
|
||||
}}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="单日限制" prop="dailyLimit">
|
||||
<template #default="scope"> {{ scope.row.dailyLimit }}次/天 </template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="到账时间" prop="arrivalTime">
|
||||
<template #default="scope">
|
||||
{{ getArrivalTimeText(scope.row.arrivalTime) }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="配置人" prop="operator" />
|
||||
<ElTableColumn label="状态" prop="status">
|
||||
<template #default="scope">
|
||||
<ElTag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
||||
{{ scope.row.status === 'active' ? '当前生效' : '已过期' }}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'WithdrawalSettings' })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const form = reactive({
|
||||
minAmount: 100,
|
||||
feeMode: 'percent',
|
||||
fixedFee: 2,
|
||||
feePercent: 0.2,
|
||||
dailyLimit: 3,
|
||||
arrivalTime: '24hours',
|
||||
workdayOnly: false,
|
||||
timeRange: [new Date(2024, 0, 1, 0, 0), new Date(2024, 0, 1, 23, 59)],
|
||||
description: ''
|
||||
})
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
minAmount: [{ required: true, message: '请输入最低提现金额', trigger: 'blur' }],
|
||||
feeMode: [{ required: true, message: '请选择手续费模式', trigger: 'change' }],
|
||||
dailyLimit: [{ required: true, message: '请输入单日提现次数', trigger: 'blur' }],
|
||||
arrivalTime: [{ required: true, message: '请选择到账时间', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const historyData = ref([
|
||||
{
|
||||
id: '1',
|
||||
configTime: '2026-01-09 10:00:00',
|
||||
minAmount: 100,
|
||||
feeMode: 'percent',
|
||||
fixedFee: 0,
|
||||
feePercent: 0.2,
|
||||
dailyLimit: 3,
|
||||
arrivalTime: '24hours',
|
||||
operator: 'admin',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
configTime: '2026-01-01 10:00:00',
|
||||
minAmount: 50,
|
||||
feeMode: 'fixed',
|
||||
fixedFee: 2.0,
|
||||
feePercent: 0,
|
||||
dailyLimit: 5,
|
||||
arrivalTime: 't1',
|
||||
operator: 'admin',
|
||||
status: 'expired'
|
||||
}
|
||||
])
|
||||
|
||||
const getArrivalTimeText = (value: string) => {
|
||||
const map: Record<string, string> = {
|
||||
realtime: '实时到账',
|
||||
'2hours': '2小时内',
|
||||
'24hours': '24小时内',
|
||||
t1: 'T+1',
|
||||
t3: 'T+3'
|
||||
}
|
||||
return map[value] || '未知'
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!formRef.value) return
|
||||
await formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
// 添加到历史记录
|
||||
historyData.value.unshift({
|
||||
id: Date.now().toString(),
|
||||
configTime: new Date().toLocaleString('zh-CN'),
|
||||
...form,
|
||||
operator: 'admin',
|
||||
status: 'active'
|
||||
})
|
||||
// 将之前的配置标记为过期
|
||||
historyData.value.slice(1).forEach((item) => {
|
||||
item.status = 'expired'
|
||||
})
|
||||
ElMessage.success('配置保存成功')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
:deep(.el-card__header) {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid var(--el-border-color-light);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,351 +0,0 @@
|
||||
<template>
|
||||
<div class="page-content">
|
||||
<ElRow>
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElInput v-model="searchQuery" placeholder="申请人/手机号" clearable></ElInput>
|
||||
</ElCol>
|
||||
<div style="width: 12px"></div>
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElSelect v-model="statusFilter" placeholder="审核状态" clearable style="width: 100%">
|
||||
<ElOption label="待审核" value="pending" />
|
||||
<ElOption label="已通过" value="approved" />
|
||||
<ElOption label="已拒绝" value="rejected" />
|
||||
</ElSelect>
|
||||
</ElCol>
|
||||
<div style="width: 12px"></div>
|
||||
<ElCol :xs="24" :sm="12" :lg="6">
|
||||
<ElDatePicker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</ElCol>
|
||||
<div style="width: 12px"></div>
|
||||
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
|
||||
<ElButton v-ripple @click="handleSearch">搜索</ElButton>
|
||||
<ElButton v-ripple @click="handleBatchApprove" :disabled="selectedIds.length === 0"
|
||||
>批量审核</ElButton
|
||||
>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
|
||||
<ArtTable :data="filteredData" index @selection-change="handleSelectionChange">
|
||||
<template #default>
|
||||
<ElTableColumn type="selection" width="55" />
|
||||
<ElTableColumn label="申请单号" prop="orderNo" min-width="180" />
|
||||
<ElTableColumn label="申请人" prop="applicantName" />
|
||||
<ElTableColumn label="客户类型" prop="customerType">
|
||||
<template #default="scope">
|
||||
<ElTag :type="scope.row.customerType === 'agent' ? '' : 'success'">
|
||||
{{ scope.row.customerType === 'agent' ? '代理商' : '企业客户' }}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="提现金额" prop="amount">
|
||||
<template #default="scope">
|
||||
<span style="color: var(--el-color-danger); font-weight: 500">
|
||||
¥{{ scope.row.amount.toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="手续费" prop="fee">
|
||||
<template #default="scope"> ¥{{ scope.row.fee.toFixed(2) }} </template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="实际到账" prop="actualAmount">
|
||||
<template #default="scope">
|
||||
<span style="color: var(--el-color-success); font-weight: 500">
|
||||
¥{{ scope.row.actualAmount.toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="收款账户" prop="bankAccount" show-overflow-tooltip />
|
||||
<ElTableColumn label="状态" prop="status">
|
||||
<template #default="scope">
|
||||
<ElTag :type="getStatusTagType(scope.row.status)">
|
||||
{{ getStatusText(scope.row.status) }}
|
||||
</ElTag>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="申请时间" prop="createTime" width="180" />
|
||||
<ElTableColumn fixed="right" label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button link @click="viewDetail(scope.row)">详情</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 'pending'"
|
||||
link
|
||||
type="success"
|
||||
@click="handleApprove(scope.row)"
|
||||
>通过</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="scope.row.status === 'pending'"
|
||||
link
|
||||
type="danger"
|
||||
@click="handleReject(scope.row)"
|
||||
>拒绝</el-button
|
||||
>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</template>
|
||||
</ArtTable>
|
||||
|
||||
<!-- 详情对话框 -->
|
||||
<ElDialog v-model="detailDialogVisible" title="提现申请详情" width="700px" align-center>
|
||||
<ElDescriptions :column="2" border>
|
||||
<ElDescriptionsItem label="申请单号">{{ currentItem?.orderNo }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="申请人">{{ currentItem?.applicantName }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="手机号">{{ currentItem?.phone }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="客户类型">
|
||||
{{ currentItem?.customerType === 'agent' ? '代理商' : '企业客户' }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="提现金额">
|
||||
<span style="color: var(--el-color-danger); font-weight: 500">
|
||||
¥{{ currentItem?.amount.toFixed(2) }}
|
||||
</span>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="手续费">¥{{ currentItem?.fee.toFixed(2) }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="实际到账">
|
||||
<span style="color: var(--el-color-success); font-weight: 500">
|
||||
¥{{ currentItem?.actualAmount.toFixed(2) }}
|
||||
</span>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="收款银行">{{ currentItem?.bankName }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="收款账户" :span="2">{{
|
||||
currentItem?.bankAccount
|
||||
}}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="开户姓名">{{ currentItem?.accountName }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="申请时间">{{ currentItem?.createTime }}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="审核状态">
|
||||
<ElTag :type="getStatusTagType(currentItem?.status || 'pending')">
|
||||
{{ getStatusText(currentItem?.status || 'pending') }}
|
||||
</ElTag>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem v-if="currentItem?.status !== 'pending'" label="审核时间">{{
|
||||
currentItem?.auditTime
|
||||
}}</ElDescriptionsItem>
|
||||
<ElDescriptionsItem v-if="currentItem?.rejectReason" label="拒绝原因" :span="2">{{
|
||||
currentItem?.rejectReason
|
||||
}}</ElDescriptionsItem>
|
||||
</ElDescriptions>
|
||||
</ElDialog>
|
||||
|
||||
<!-- 拒绝对话框 -->
|
||||
<ElDialog v-model="rejectDialogVisible" title="拒绝提现" width="500px" align-center>
|
||||
<ElForm ref="rejectFormRef" :model="rejectForm" :rules="rejectRules" label-width="100px">
|
||||
<ElFormItem label="拒绝原因" prop="reason">
|
||||
<ElInput
|
||||
v-model="rejectForm.reason"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入拒绝原因"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="rejectDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="confirmReject">确认拒绝</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'WithdrawalManagement' })
|
||||
|
||||
interface WithdrawalItem {
|
||||
id: string
|
||||
orderNo: string
|
||||
applicantName: string
|
||||
phone: string
|
||||
customerType: 'agent' | 'enterprise'
|
||||
amount: number
|
||||
fee: number
|
||||
actualAmount: number
|
||||
bankName: string
|
||||
bankAccount: string
|
||||
accountName: string
|
||||
status: 'pending' | 'approved' | 'rejected'
|
||||
createTime: string
|
||||
auditTime?: string
|
||||
rejectReason?: string
|
||||
}
|
||||
|
||||
const mockData = ref<WithdrawalItem[]>([
|
||||
{
|
||||
id: '1',
|
||||
orderNo: 'WD202601090001',
|
||||
applicantName: '张三',
|
||||
phone: '13800138001',
|
||||
customerType: 'agent',
|
||||
amount: 5000.0,
|
||||
fee: 10.0,
|
||||
actualAmount: 4990.0,
|
||||
bankName: '中国工商银行',
|
||||
bankAccount: '6222 **** **** 1234',
|
||||
accountName: '张三',
|
||||
status: 'pending',
|
||||
createTime: '2026-01-09 10:00:00'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
orderNo: 'WD202601090002',
|
||||
applicantName: '李四',
|
||||
phone: '13800138002',
|
||||
customerType: 'enterprise',
|
||||
amount: 3000.0,
|
||||
fee: 6.0,
|
||||
actualAmount: 2994.0,
|
||||
bankName: '中国建设银行',
|
||||
bankAccount: '6227 **** **** 5678',
|
||||
accountName: '李四',
|
||||
status: 'approved',
|
||||
createTime: '2026-01-08 14:30:00',
|
||||
auditTime: '2026-01-08 15:00:00'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
orderNo: 'WD202601090003',
|
||||
applicantName: '王五',
|
||||
phone: '13800138003',
|
||||
customerType: 'agent',
|
||||
amount: 2000.0,
|
||||
fee: 4.0,
|
||||
actualAmount: 1996.0,
|
||||
bankName: '中国农业银行',
|
||||
bankAccount: '6228 **** **** 9012',
|
||||
accountName: '王五',
|
||||
status: 'rejected',
|
||||
createTime: '2026-01-07 16:20:00',
|
||||
auditTime: '2026-01-07 17:00:00',
|
||||
rejectReason: '账户信息与实名不符'
|
||||
}
|
||||
])
|
||||
|
||||
const searchQuery = ref('')
|
||||
const statusFilter = ref('')
|
||||
const dateRange = ref<[Date, Date] | null>(null)
|
||||
const selectedIds = ref<string[]>([])
|
||||
const detailDialogVisible = ref(false)
|
||||
const rejectDialogVisible = ref(false)
|
||||
const currentItem = ref<WithdrawalItem | null>(null)
|
||||
const rejectFormRef = ref<FormInstance>()
|
||||
|
||||
const rejectForm = reactive({
|
||||
reason: ''
|
||||
})
|
||||
|
||||
const rejectRules = reactive<FormRules>({
|
||||
reason: [{ required: true, message: '请输入拒绝原因', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const filteredData = computed(() => {
|
||||
let data = mockData.value
|
||||
if (searchQuery.value) {
|
||||
data = data.filter(
|
||||
(item) => item.applicantName.includes(searchQuery.value) || item.phone.includes(searchQuery.value)
|
||||
)
|
||||
}
|
||||
if (statusFilter.value) {
|
||||
data = data.filter((item) => item.status === statusFilter.value)
|
||||
}
|
||||
return data
|
||||
})
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
const map: Record<string, string> = {
|
||||
pending: '待审核',
|
||||
approved: '已通过',
|
||||
rejected: '已拒绝'
|
||||
}
|
||||
return map[status] || '未知'
|
||||
}
|
||||
|
||||
const getStatusTagType = (status: string) => {
|
||||
const map: Record<string, string> = {
|
||||
pending: 'warning',
|
||||
approved: 'success',
|
||||
rejected: 'danger'
|
||||
}
|
||||
return map[status] || 'info'
|
||||
}
|
||||
|
||||
const handleSearch = () => {}
|
||||
|
||||
const handleSelectionChange = (selection: WithdrawalItem[]) => {
|
||||
selectedIds.value = selection.map((item) => item.id)
|
||||
}
|
||||
|
||||
const viewDetail = (row: WithdrawalItem) => {
|
||||
currentItem.value = row
|
||||
detailDialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleApprove = (row: WithdrawalItem) => {
|
||||
ElMessageBox.confirm(
|
||||
`确认通过提现申请?金额:¥${row.amount.toFixed(2)},实际到账:¥${row.actualAmount.toFixed(2)}`,
|
||||
'审核确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'success'
|
||||
}
|
||||
).then(() => {
|
||||
row.status = 'approved'
|
||||
row.auditTime = new Date().toLocaleString('zh-CN')
|
||||
ElMessage.success('审核通过')
|
||||
})
|
||||
}
|
||||
|
||||
const handleReject = (row: WithdrawalItem) => {
|
||||
currentItem.value = row
|
||||
rejectForm.reason = ''
|
||||
rejectDialogVisible.value = true
|
||||
}
|
||||
|
||||
const confirmReject = async () => {
|
||||
if (!rejectFormRef.value) return
|
||||
await rejectFormRef.value.validate((valid) => {
|
||||
if (valid && currentItem.value) {
|
||||
currentItem.value.status = 'rejected'
|
||||
currentItem.value.auditTime = new Date().toLocaleString('zh-CN')
|
||||
currentItem.value.rejectReason = rejectForm.reason
|
||||
rejectDialogVisible.value = false
|
||||
ElMessage.success('已拒绝提现申请')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleBatchApprove = () => {
|
||||
ElMessageBox.confirm(`确认批量审核 ${selectedIds.value.length} 条提现申请吗?`, '批量审核', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
selectedIds.value.forEach((id) => {
|
||||
const item = mockData.value.find((i) => i.id === id)
|
||||
if (item && item.status === 'pending') {
|
||||
item.status = 'approved'
|
||||
item.auditTime = new Date().toLocaleString('zh-CN')
|
||||
}
|
||||
})
|
||||
ElMessage.success('批量审核成功')
|
||||
selectedIds.value = []
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-content {
|
||||
:deep(.el-descriptions__label) {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user