feat(adminfinance): 新增预计收入指标并优化明细查询性能
- 财务看板增加预计收入与待结算订单数统计 - 明细列表 COUNT 改为仅扫描 rental_orders 主表,避免 5-JOIN 子查询 - 统一前后端结算差异判定阈值为常量 5 分 - 修复日期选择器使用 UTC 日期导致东八区凌晨偏移前一天的问题
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
|
||||
// 结算差异判定阈值(分)。号主应得与实际入账差额绝对值达到此值即标红。
|
||||
// 与后端 settlementDiffThresholdCent 保持一致,改口径时两端同步。
|
||||
export const SETTLEMENT_DIFF_THRESHOLD_CENT = 5
|
||||
|
||||
export interface FinanceSummary {
|
||||
total_flow_amount_cent: number
|
||||
total_refund_amount_cent: number
|
||||
@@ -10,10 +14,12 @@ export interface FinanceSummary {
|
||||
owner_should_income_amount_cent: number
|
||||
owner_wallet_income_amount_cent: number
|
||||
settlement_diff_amount_cent: number
|
||||
estimated_income_amount_cent: number
|
||||
successful_pay_count: number
|
||||
successful_refund_count: number
|
||||
pending_refund_count: number
|
||||
settled_order_count: number
|
||||
pending_settle_order_count: number
|
||||
financial_exception_count: number
|
||||
}
|
||||
|
||||
@@ -27,6 +33,7 @@ export interface FinanceDailyItem {
|
||||
owner_should_income_amount_cent: number
|
||||
owner_wallet_income_amount_cent: number
|
||||
settlement_diff_amount_cent: number
|
||||
estimated_income_amount_cent: number
|
||||
successful_pay_count: number
|
||||
successful_refund_count: number
|
||||
pending_refund_count: number
|
||||
|
||||
@@ -4,11 +4,12 @@ import { computed, onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import {
|
||||
fetchFinanceDashboard,
|
||||
SETTLEMENT_DIFF_THRESHOLD_CENT,
|
||||
type FinanceDashboard,
|
||||
type FinanceDailyItem,
|
||||
} from '@/features/admin/api/adminFinance'
|
||||
import { formatCentWithSymbol } from '@/shared/utils/money'
|
||||
import { formatDateTime } from '@/shared/utils/time'
|
||||
import { formatDateTime, formatInputDate } from '@/shared/utils/time'
|
||||
|
||||
const loading = ref(false)
|
||||
const dashboard = ref<FinanceDashboard | null>(null)
|
||||
@@ -44,16 +45,14 @@ function defaultEndDate() {
|
||||
return formatInputDate(new Date())
|
||||
}
|
||||
|
||||
function formatInputDate(date: Date) {
|
||||
return date.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
function diffType(value: number) {
|
||||
return Math.abs(Number(value || 0)) >= 5 ? 'danger' : 'success'
|
||||
return Math.abs(Number(value || 0)) >= SETTLEMENT_DIFF_THRESHOLD_CENT ? 'danger' : 'success'
|
||||
}
|
||||
|
||||
function rowDiffClass(row: FinanceDailyItem) {
|
||||
return Math.abs(Number(row.settlement_diff_amount_cent || 0)) >= 5 ? 'amount-danger' : ''
|
||||
return Math.abs(Number(row.settlement_diff_amount_cent || 0)) >= SETTLEMENT_DIFF_THRESHOLD_CENT
|
||||
? 'amount-danger'
|
||||
: ''
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -130,6 +129,11 @@ function rowDiffClass(row: FinanceDailyItem) {
|
||||
</strong>
|
||||
<small>{{ dashboard.summary.financial_exception_count }} 个异常订单</small>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span>预计收入</span>
|
||||
<strong>{{ moneyCent(dashboard.summary.estimated_income_amount_cent) }}</strong>
|
||||
<small>{{ dashboard.summary.pending_settle_order_count }} 个待结算订单</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" class="table-panel" :data="dailyItems">
|
||||
@@ -157,11 +161,17 @@ function rowDiffClass(row: FinanceDailyItem) {
|
||||
<span :class="rowDiffClass(row)">{{ moneyCent(row.settlement_diff_amount_cent) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收款/退款/结算" min-width="170">
|
||||
<template #default="{ row }">
|
||||
{{ row.successful_pay_count }} / {{ row.successful_refund_count }} /
|
||||
{{ row.settled_order_count }}
|
||||
</template>
|
||||
<el-table-column label="预计收入" width="130">
|
||||
<template #default="{ row }">{{ moneyCent(row.estimated_income_amount_cent) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="销售数量" width="110">
|
||||
<template #default="{ row }">{{ row.successful_pay_count }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退款数量" width="110">
|
||||
<template #default="{ row }">{{ row.successful_refund_count }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算数量" width="110">
|
||||
<template #default="{ row }">{{ row.settled_order_count }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import { fetchFinanceDetails, type FinanceDetail } from '@/features/admin/api/adminFinance'
|
||||
import {
|
||||
fetchFinanceDetails,
|
||||
SETTLEMENT_DIFF_THRESHOLD_CENT,
|
||||
type FinanceDetail,
|
||||
} from '@/features/admin/api/adminFinance'
|
||||
import { adminPath } from '@/shared/utils/adminPath'
|
||||
import { formatCentWithSymbol } from '@/shared/utils/money'
|
||||
import { orderStatusLabel } from '@/shared/utils/statusLabels'
|
||||
import { formatDateTime } from '@/shared/utils/time'
|
||||
import { formatDateTime, formatInputDate } from '@/shared/utils/time'
|
||||
import AdminTablePagination from '../components/AdminTablePagination.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
@@ -102,10 +106,6 @@ function defaultStartDate() {
|
||||
function defaultEndDate() {
|
||||
return formatInputDate(new Date())
|
||||
}
|
||||
|
||||
function formatInputDate(date: Date) {
|
||||
return date.toISOString().slice(0, 10)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -236,7 +236,10 @@ function formatInputDate(date: Date) {
|
||||
}}</span>
|
||||
<span
|
||||
class="amount-text amount-cell"
|
||||
:class="{ 'amount-danger': Math.abs(row.settlement_diff_amount_cent) >= 5 }"
|
||||
:class="{
|
||||
'amount-danger':
|
||||
Math.abs(row.settlement_diff_amount_cent) >= SETTLEMENT_DIFF_THRESHOLD_CENT,
|
||||
}"
|
||||
>
|
||||
{{ moneyCent(row.settlement_diff_amount_cent) }}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user