新增资金出款查询与财务统计

This commit is contained in:
yml2213
2026-07-26 16:18:31 +08:00
parent 321f0781cf
commit dbe0cda2c6
17 changed files with 1604 additions and 31 deletions
@@ -50,6 +50,12 @@ export interface FinanceDailyItem {
pending_refund_count: number
settled_order_count: number
offline_settlement_pending_count: number
offline_settlement_paid_amount_cent: number
offline_settlement_paid_count: number
withdrawal_paid_amount_cent: number
withdrawal_paid_count: number
disbursement_paid_amount_cent: number
disbursement_paid_count: number
}
export interface FinancePickupSummary {
@@ -59,10 +65,87 @@ export interface FinancePickupSummary {
in_progress_count: number
}
export interface FinanceDisbursementSummary {
paid_amount_cent: number
paid_count: number
pending_payment_amount_cent: number
pending_payment_count: number
offline_settlement_paid_amount_cent: number
offline_settlement_paid_count: number
offline_settlement_pending_amount_cent: number
offline_settlement_pending_count: number
withdrawal_amount_cent: number
withdrawal_fee_amount_cent: number
withdrawal_paid_amount_cent: number
withdrawal_paid_count: number
withdrawal_pending_amount_cent: number
withdrawal_pending_count: number
withdrawal_review_amount_cent: number
withdrawal_review_count: number
}
export interface FinanceDisbursementListSummary {
record_count: number
paid_amount_cent: number
paid_count: number
payment_pending_amount_cent: number
payment_pending_count: number
review_pending_amount_cent: number
review_pending_count: number
withdrawal_fee_amount_cent: number
}
export interface FinanceDisbursementItem {
source_type: 'platform_managed' | 'withdrawal'
source_id: number
business_no: string
order_id?: number
withdrawal_id?: number
user_id: number
payee_name: string
payee_phone: string
uploader_name: string
source_channel: string
account_type: string
account_name: string
account_no: string
bank_name: string
amount_cent: number
fee_cent: number
actual_amount_cent: number
status: 'review_pending' | 'payment_pending' | 'paid' | 'rejected' | 'cancelled'
raw_status: string
business_created_at?: string
paid_at?: string
operator_id?: number
operator_name: string
remark: string
}
export interface FinanceDisbursementQuery extends FinanceDateQuery {
source_type?: string
status?: string
date_type?: string
business_no?: string
keyword?: string
user_id?: string
page?: number
page_size?: number
}
export interface FinanceDisbursementList {
items: FinanceDisbursementItem[]
total: number
page: number
page_size: number
summary: FinanceDisbursementListSummary
}
export interface FinanceDashboard {
summary: FinanceSummary
daily_items: FinanceDailyItem[]
pickup_summary: FinancePickupSummary
disbursement_summary: FinanceDisbursementSummary
generated_at: string
}
@@ -113,6 +196,8 @@ export interface FinanceDetailQuery extends FinanceDateQuery {
user_id?: string
order_status?: string
settlement_status?: string
settlement_mode?: string
offline_settlement_status?: string
date_type?: string
page?: number
page_size?: number
@@ -137,6 +222,24 @@ export async function fetchFinanceDashboard(query: FinanceDateQuery = {}) {
completed_count: 0,
in_progress_count: 0,
},
disbursement_summary: data.data?.disbursement_summary ?? {
paid_amount_cent: 0,
paid_count: 0,
pending_payment_amount_cent: 0,
pending_payment_count: 0,
offline_settlement_paid_amount_cent: 0,
offline_settlement_paid_count: 0,
offline_settlement_pending_amount_cent: 0,
offline_settlement_pending_count: 0,
withdrawal_amount_cent: 0,
withdrawal_fee_amount_cent: 0,
withdrawal_paid_amount_cent: 0,
withdrawal_paid_count: 0,
withdrawal_pending_amount_cent: 0,
withdrawal_pending_count: 0,
withdrawal_review_amount_cent: 0,
withdrawal_review_count: 0,
},
}
}
@@ -153,3 +256,27 @@ export async function fetchFinanceDetails(query: FinanceDetailQuery = {}) {
page_size: Number(result?.page_size ?? query.page_size ?? 20),
}
}
export async function fetchFinanceDisbursements(query: FinanceDisbursementQuery = {}) {
const { data } = await apiClient.get<ApiResponse<FinanceDisbursementList>>(
'/admin/finance/disbursements',
{ params: cleanParams(query) }
)
const result = data.data
return {
items: Array.isArray(result?.items) ? result.items : [],
total: Number(result?.total ?? 0),
page: Number(result?.page ?? query.page ?? 1),
page_size: Number(result?.page_size ?? query.page_size ?? 20),
summary: result?.summary ?? {
record_count: 0,
paid_amount_cent: 0,
paid_count: 0,
payment_pending_amount_cent: 0,
payment_pending_count: 0,
review_pending_amount_cent: 0,
review_pending_count: 0,
withdrawal_fee_amount_cent: 0,
},
}
}
@@ -66,7 +66,7 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
<div class="page-header">
<p class="eyebrow">Finance Dashboard</p>
<h1>财务仪表盘</h1>
<p>按天查看第三方收款退平台收入号主钱包入账/线下结算和结算差异</p>
<p>按天查看收付平台收入号主结算平台代管打款和用户提现</p>
</div>
<div class="toolbar-actions">
<el-date-picker
@@ -118,12 +118,12 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
<small>结账单口径</small>
</div>
<div class="metric-card">
<span>号主结算金额</span>
<span>号主结算金额</span>
<strong>{{ moneyCent(dashboard.summary.owner_effective_settlement_amount_cent) }}</strong>
<small>钱包入账 + 平台代管线下结算</small>
<small>钱包入账 + 平台代管应付</small>
</div>
<div class="metric-card">
<span>待线下结算</span>
<span>区间待线下结算</span>
<strong>{{ moneyCent(dashboard.summary.offline_settlement_pending_amount_cent) }}</strong>
<small>{{ dashboard.summary.offline_settlement_pending_count }} 笔平台代管待处理</small>
</div>
@@ -148,6 +148,65 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
</div>
</div>
<div v-if="dashboard?.disbursement_summary" class="section-heading">
<div>
<h2>资金出款</h2>
<p>已打款按所选日期统计待处理金额为当前全部待办</p>
</div>
</div>
<div v-if="dashboard?.disbursement_summary" class="metric-grid disbursement-grid">
<div class="metric-card disbursement-card">
<span>代管及提现出款</span>
<strong>{{ moneyCent(dashboard.disbursement_summary.paid_amount_cent) }}</strong>
<small>{{ dashboard.disbursement_summary.paid_count }} 笔实际出款合计</small>
</div>
<div class="metric-card disbursement-card">
<span>平台代管打款</span>
<strong>{{
moneyCent(dashboard.disbursement_summary.offline_settlement_paid_amount_cent)
}}</strong>
<small>{{ dashboard.disbursement_summary.offline_settlement_paid_count }} 笔线下结算</small>
</div>
<div class="metric-card disbursement-card">
<span>用户提现打款</span>
<strong>{{ moneyCent(dashboard.disbursement_summary.withdrawal_paid_amount_cent) }}</strong>
<small>
{{ dashboard.disbursement_summary.withdrawal_paid_count }} 钱包核销
{{ moneyCent(dashboard.disbursement_summary.withdrawal_amount_cent) }}手续费
{{ moneyCent(dashboard.disbursement_summary.withdrawal_fee_amount_cent) }}
</small>
</div>
<div class="metric-card pending-card">
<span>当前待出款</span>
<strong>{{ moneyCent(dashboard.disbursement_summary.pending_payment_amount_cent) }}</strong>
<small>{{ dashboard.disbursement_summary.pending_payment_count }} 笔已进入打款阶段</small>
</div>
<div class="metric-card pending-card">
<span>代管待打款</span>
<strong>{{
moneyCent(dashboard.disbursement_summary.offline_settlement_pending_amount_cent)
}}</strong>
<small
>{{ dashboard.disbursement_summary.offline_settlement_pending_count }} 笔待处理</small
>
</div>
<div class="metric-card pending-card">
<span>提现待打款</span>
<strong>{{
moneyCent(dashboard.disbursement_summary.withdrawal_pending_amount_cent)
}}</strong>
<small>{{ dashboard.disbursement_summary.withdrawal_pending_count }} 笔已审核</small>
</div>
<div class="metric-card review-card">
<span>提现待审核</span>
<strong>{{
moneyCent(dashboard.disbursement_summary.withdrawal_review_amount_cent)
}}</strong>
<small>{{ dashboard.disbursement_summary.withdrawal_review_count }} 笔待审核</small>
</div>
</div>
<div v-if="dashboard?.pickup_summary" class="metric-grid pickup-grid">
<div class="metric-card pickup-card">
<span>线下提号结算</span>
@@ -188,6 +247,21 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
moneyCent(row.owner_effective_settlement_amount_cent)
}}</template>
</el-table-column>
<el-table-column label="实际出款" width="130">
<template #default="{ row }">
{{ moneyCent(row.disbursement_paid_amount_cent) }}
</template>
</el-table-column>
<el-table-column label="代管打款" width="130">
<template #default="{ row }">
{{ moneyCent(row.offline_settlement_paid_amount_cent) }}
</template>
</el-table-column>
<el-table-column label="提现打款" width="130">
<template #default="{ row }">
{{ moneyCent(row.withdrawal_paid_amount_cent) }}
</template>
</el-table-column>
<el-table-column label="待线下" width="130">
<template #default="{ row }">
<span :class="rowOfflinePendingClass(row)">
@@ -238,6 +312,42 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
margin-top: 12px;
}
.section-heading {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin: 4px 0 12px;
}
.section-heading h2 {
margin: 0;
color: #1f2937;
font-size: 18px;
letter-spacing: 0;
}
.section-heading p {
margin: 5px 0 0;
color: #7f8aa3;
font-size: 13px;
}
.disbursement-grid {
margin-bottom: 20px;
}
.disbursement-card {
border-left: 3px solid #0f766e;
}
.pending-card {
border-left: 3px solid #d97706;
}
.review-card {
border-left: 3px solid #64748b;
}
.pickup-card {
border-left: 3px solid #6366f1;
}
@@ -26,6 +26,8 @@ const filters = reactive({
user_id: '',
order_status: '',
settlement_status: '',
settlement_mode: '',
offline_settlement_status: '',
})
onMounted(loadDetails)
@@ -53,6 +55,8 @@ function resetFilters() {
filters.user_id = ''
filters.order_status = ''
filters.settlement_status = ''
filters.settlement_mode = ''
filters.offline_settlement_status = ''
currentPage.value = 1
void loadDetails()
}
@@ -146,6 +150,7 @@ function defaultEndDate() {
<el-form-item label="日期类型">
<el-select v-model="filters.date_type" class="full-control">
<el-option label="结算日期" value="settled" />
<el-option label="线下打款日期" value="offline_settled" />
<el-option label="下单日期" value="created" />
</el-select>
</el-form-item>
@@ -196,6 +201,29 @@ function defaultEndDate() {
<el-option label="已结算" value="settled" />
</el-select>
</el-form-item>
<el-form-item label="结算模式">
<el-select
v-model="filters.settlement_mode"
clearable
placeholder="全部模式"
class="full-control"
>
<el-option label="号主钱包" value="owner_wallet" />
<el-option label="平台代管" value="platform_managed" />
</el-select>
</el-form-item>
<el-form-item label="线下状态">
<el-select
v-model="filters.offline_settlement_status"
clearable
placeholder="全部状态"
class="full-control"
>
<el-option label="待线下结算" value="pending" />
<el-option label="已线下结算" value="settled" />
<el-option label="无需线下结算" value="none" />
</el-select>
</el-form-item>
</el-form>
<div v-loading="loading" class="table-panel finance-details-table">
@@ -298,7 +326,7 @@ function defaultEndDate() {
}
.finance-filter-panel {
grid-template-columns: 7% 10% 10% 29% 23% 10% 11%;
grid-template-columns: repeat(9, minmax(100px, 1fr));
gap: 10px;
margin-bottom: 16px;
padding: 14px 16px;
@@ -0,0 +1,451 @@
<script setup lang="ts">
import { Search, View } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { onMounted, reactive, ref } from 'vue'
import {
fetchFinanceDisbursements,
type FinanceDisbursementItem,
type FinanceDisbursementListSummary,
} from '@/features/admin/api/adminFinance'
import { fetchAdminWithdrawal, type WithdrawalDetail } from '@/features/admin/api/adminWithdrawal'
import { useAdminSessionStore } from '@/stores/adminSession'
import { adminPath } from '@/shared/utils/adminPath'
import { readError } from '@/shared/utils/error'
import { formatCentWithSymbol } from '@/shared/utils/money'
import { formatDateTime, formatInputDate } from '@/shared/utils/time'
import AdminTablePagination from '../components/AdminTablePagination.vue'
import WithdrawalDetailDialog from '../components/WithdrawalDetailDialog.vue'
const adminSession = useAdminSessionStore()
const loading = ref(false)
const detailLoading = ref(false)
const items = ref<FinanceDisbursementItem[]>([])
const total = ref(0)
const currentPage = ref(1)
const currentPageSize = ref(20)
const showWithdrawalDetail = ref(false)
const selectedWithdrawal = ref<WithdrawalDetail | null>(null)
const summary = ref<FinanceDisbursementListSummary>(emptySummary())
const filters = reactive({
date_type: 'created',
start_date: defaultStartDate(),
end_date: formatInputDate(new Date()),
source_type: '',
status: '',
business_no: '',
keyword: '',
user_id: '',
})
onMounted(loadItems)
async function loadItems() {
loading.value = true
try {
const result = await fetchFinanceDisbursements({
...filters,
page: currentPage.value,
page_size: currentPageSize.value,
})
items.value = result.items
total.value = result.total
summary.value = result.summary
} catch (error) {
items.value = []
total.value = 0
summary.value = emptySummary()
ElMessage.error(readError(error, '资金出款明细加载失败'))
} finally {
loading.value = false
}
}
function search() {
currentPage.value = 1
void loadItems()
}
function resetFilters() {
filters.date_type = 'created'
filters.start_date = defaultStartDate()
filters.end_date = formatInputDate(new Date())
filters.source_type = ''
filters.status = ''
filters.business_no = ''
filters.keyword = ''
filters.user_id = ''
currentPage.value = 1
void loadItems()
}
async function openWithdrawalDetail(row: FinanceDisbursementItem) {
if (!row.withdrawal_id || detailLoading.value) return
detailLoading.value = true
try {
selectedWithdrawal.value = await fetchAdminWithdrawal(row.withdrawal_id)
showWithdrawalDetail.value = true
} catch (error) {
ElMessage.error(readError(error, '提现详情加载失败'))
} finally {
detailLoading.value = false
}
}
function onWithdrawalSaved() {
showWithdrawalDetail.value = false
selectedWithdrawal.value = null
void loadItems()
}
function emptySummary(): FinanceDisbursementListSummary {
return {
record_count: 0,
paid_amount_cent: 0,
paid_count: 0,
payment_pending_amount_cent: 0,
payment_pending_count: 0,
review_pending_amount_cent: 0,
review_pending_count: 0,
withdrawal_fee_amount_cent: 0,
}
}
function defaultStartDate() {
const date = new Date()
date.setDate(date.getDate() - 29)
return formatInputDate(date)
}
function money(value: number) {
return formatCentWithSymbol(Number(value || 0))
}
function sourceLabel(source: string) {
return source === 'platform_managed' ? '平台代管' : '用户提现'
}
function sourceType(source: string) {
return source === 'platform_managed' ? 'primary' : 'info'
}
function statusLabel(status: string) {
const labels: Record<string, string> = {
review_pending: '待审核',
payment_pending: '待打款',
paid: '已打款',
rejected: '已拒绝',
cancelled: '已取消',
}
return labels[status] || status
}
function statusType(status: string) {
if (status === 'paid') return 'success'
if (status === 'review_pending' || status === 'payment_pending') return 'warning'
if (status === 'rejected') return 'danger'
return 'info'
}
function accountTypeLabel(type: string) {
const labels: Record<string, string> = {
alipay: '支付宝',
wechat: '微信',
bank: '银行卡',
}
return labels[type] || type || '线下约定'
}
</script>
<template>
<section class="page disbursement-page">
<div class="page-header-row">
<div class="page-header">
<p class="eyebrow">Disbursements</p>
<h1>资金出款</h1>
<p>查询平台代管线下结算与用户提现的应付待办和实际打款记录</p>
</div>
<div class="toolbar-actions">
<el-button @click="resetFilters">重置</el-button>
<el-button type="primary" :icon="Search" :loading="loading" @click="search">
查询
</el-button>
</div>
</div>
<div class="metric-grid disbursement-metrics">
<div class="metric-card">
<span>筛选记录</span>
<strong>{{ summary.record_count }} </strong>
<small>当前筛选条件</small>
</div>
<div class="metric-card paid-metric">
<span>已打款</span>
<strong>{{ money(summary.paid_amount_cent) }}</strong>
<small>{{ summary.paid_count }} 笔实际出款</small>
</div>
<div class="metric-card pending-metric">
<span>待打款</span>
<strong>{{ money(summary.payment_pending_amount_cent) }}</strong>
<small>{{ summary.payment_pending_count }} 笔已进入打款阶段</small>
</div>
<div class="metric-card review-metric">
<span>提现待审核</span>
<strong>{{ money(summary.review_pending_amount_cent) }}</strong>
<small>{{ summary.review_pending_count }} 笔待审核</small>
</div>
<div class="metric-card fee-metric">
<span>已完成提现手续费</span>
<strong>{{ money(summary.withdrawal_fee_amount_cent) }}</strong>
<small>随筛选结果统计</small>
</div>
</div>
<el-form class="filter-panel disbursement-filters" label-position="top" @keyup.enter="search">
<el-form-item label="日期类型">
<el-select v-model="filters.date_type" class="full-control">
<el-option label="业务形成日期" value="created" />
<el-option label="实际打款日期" value="paid" />
</el-select>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker
v-model="filters.start_date"
class="full-control"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker
v-model="filters.end_date"
class="full-control"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="出款类型">
<el-select
v-model="filters.source_type"
clearable
placeholder="全部类型"
class="full-control"
>
<el-option label="平台代管" value="platform_managed" />
<el-option label="用户提现" value="withdrawal" />
</el-select>
</el-form-item>
<el-form-item label="出款状态">
<el-select v-model="filters.status" clearable placeholder="全部状态" class="full-control">
<el-option label="待审核" value="review_pending" />
<el-option label="待打款" value="payment_pending" />
<el-option label="已打款" value="paid" />
<el-option label="已拒绝" value="rejected" />
<el-option label="已取消" value="cancelled" />
</el-select>
</el-form-item>
<el-form-item label="业务单号">
<el-input v-model="filters.business_no" clearable placeholder="订单号或提现单号" />
</el-form-item>
<el-form-item label="收款人">
<el-input v-model="filters.keyword" clearable placeholder="姓名、手机号或账号" />
</el-form-item>
<el-form-item label="用户 ID">
<el-input v-model="filters.user_id" clearable placeholder="按用户 ID" />
</el-form-item>
</el-form>
<el-table v-loading="loading" class="table-panel" :data="items" empty-text="暂无出款记录">
<el-table-column label="业务" min-width="205" fixed="left">
<template #default="{ row }">
<div class="business-cell">
<el-tag size="small" :type="sourceType(row.source_type)">
{{ sourceLabel(row.source_type) }}
</el-tag>
<RouterLink
v-if="row.order_id"
class="business-no"
:to="adminPath(`orders/${row.order_id}`)"
>
{{ row.business_no }}
</RouterLink>
<strong v-else class="business-no">{{ row.business_no }}</strong>
</div>
</template>
</el-table-column>
<el-table-column label="收款人" min-width="170">
<template #default="{ row }">
<div class="stack-cell">
<strong>{{ row.payee_name || '-' }}</strong>
<small v-if="row.payee_phone">{{ row.payee_phone }}</small>
<small v-else-if="row.source_type === 'withdrawal'">用户 ID {{ row.user_id }}</small>
<small v-else>联系方式未登记</small>
<small v-if="row.uploader_name">上传{{ row.uploader_name }}</small>
<small v-if="row.source_channel">渠道{{ row.source_channel }}</small>
</div>
</template>
</el-table-column>
<el-table-column label="收款账户" min-width="205">
<template #default="{ row }">
<div v-if="row.source_type === 'withdrawal'" class="stack-cell">
<span>{{ accountTypeLabel(row.account_type) }} · {{ row.account_name || '-' }}</span>
<small>{{ row.account_no || '-' }}</small>
<small v-if="row.bank_name">{{ row.bank_name }}</small>
</div>
<span v-else class="muted-text">线下约定</span>
</template>
</el-table-column>
<el-table-column label="金额" min-width="155" align="right">
<template #default="{ row }">
<div class="amount-stack">
<strong>{{ money(row.actual_amount_cent) }}</strong>
<small v-if="row.source_type === 'withdrawal'">
申请 {{ money(row.amount_cent) }} / 手续费 {{ money(row.fee_cent) }}
</small>
</div>
</template>
</el-table-column>
<el-table-column label="状态" width="105" align="center">
<template #default="{ row }">
<el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="形成时间" min-width="175">
<template #default="{ row }">{{ formatDateTime(row.business_created_at) }}</template>
</el-table-column>
<el-table-column label="打款时间" min-width="175">
<template #default="{ row }">{{ formatDateTime(row.paid_at) }}</template>
</el-table-column>
<el-table-column label="处理人" min-width="120">
<template #default="{ row }">{{ row.operator_name || '-' }}</template>
</el-table-column>
<el-table-column label="备注" min-width="180" show-overflow-tooltip>
<template #default="{ row }">{{ row.remark || '-' }}</template>
</el-table-column>
<el-table-column label="操作" width="90" fixed="right">
<template #default="{ row }">
<el-button
v-if="row.withdrawal_id && adminSession.hasPermission('withdrawal:detail')"
link
type="primary"
:icon="View"
:loading="detailLoading"
@click="openWithdrawalDetail(row)"
>
详情
</el-button>
<RouterLink v-else-if="row.order_id" :to="adminPath(`orders/${row.order_id}`)">
<el-button link type="primary" :icon="View">详情</el-button>
</RouterLink>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
<AdminTablePagination
v-if="total > 0"
v-model:current-page="currentPage"
v-model:page-size="currentPageSize"
:total="total"
:loading="loading"
@page-change="loadItems"
/>
<WithdrawalDetailDialog
v-model="showWithdrawalDetail"
:withdrawal="selectedWithdrawal"
@saved="onWithdrawalSaved"
/>
</section>
</template>
<style scoped>
.disbursement-metrics {
grid-template-columns: repeat(5, minmax(170px, 1fr));
gap: 12px;
margin-bottom: 16px;
}
.paid-metric {
border-left: 3px solid #0f766e;
}
.pending-metric {
border-left: 3px solid #d97706;
}
.review-metric {
border-left: 3px solid #64748b;
}
.fee-metric {
border-left: 3px solid #2563eb;
}
.disbursement-filters {
grid-template-columns: repeat(8, minmax(110px, 1fr));
gap: 10px;
margin-bottom: 16px;
padding: 14px 16px;
}
.business-cell,
.stack-cell,
.amount-stack {
display: flex;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.business-cell {
align-items: flex-start;
}
.business-no {
overflow: hidden;
max-width: 100%;
color: #344054;
font-size: 13px;
text-overflow: ellipsis;
white-space: nowrap;
}
.stack-cell strong,
.stack-cell span,
.amount-stack strong {
color: #344054;
}
.stack-cell small,
.amount-stack small,
.muted-text {
color: #7f8aa3;
font-size: 12px;
}
.amount-stack {
align-items: flex-end;
}
.amount-stack strong {
font-size: 14px;
}
@media (max-width: 1440px) {
.disbursement-metrics {
grid-template-columns: repeat(3, minmax(170px, 1fr));
}
.disbursement-filters {
grid-template-columns: repeat(4, minmax(130px, 1fr));
}
}
@media (max-width: 760px) {
.disbursement-metrics,
.disbursement-filters {
grid-template-columns: 1fr;
}
}
</style>
+6
View File
@@ -163,6 +163,12 @@ const allNavGroups: NavGroup[] = [
icon: Document,
permission: 'wallet:view',
},
{
label: '资金出款',
to: adminPath('finance/disbursements'),
icon: Money,
permission: 'wallet:view',
},
{
label: '资金流水',
to: adminPath('wallet-ledger'),
+6
View File
@@ -132,6 +132,12 @@ export const adminRoutes: RouteRecordRaw[] = [
component: () => import('@/features/admin/views/AdminFinanceDetailsView.vue'),
meta: adminMeta,
},
{
path: adminPath('finance/disbursements'),
name: 'admin-finance-disbursements',
component: () => import('@/features/admin/views/AdminFinanceDisbursementsView.vue'),
meta: adminMeta,
},
{
path: adminPath('wallet-ledger'),
name: 'admin-wallet-ledger',