feat: 迭代

This commit is contained in:
2026-05-26 21:27:48 +08:00
parent 4c7a1e06a8
commit d1147713f8
43 changed files with 1137 additions and 883 deletions
+9
View File
@@ -186,3 +186,12 @@ export function getMerchantReport(merchantId: number, params: any) {
export function exportReport(type: string, params: any) {
return request.get(`/api/admin/finance/reports/export/${type}`, { params, responseType: 'blob' });
}
// 服务费管理
export function getServiceFeeStatistics() {
return request.get('/api/admin/finance/reports/service-fees/statistics');
}
export function getServiceFeeList(params: any) {
return request.get('/api/admin/finance/reports/service-fees/list', { params });
}
@@ -238,7 +238,7 @@ const InviteManage: React.FC = () => {
<InputNumber min={0.01} max={1} step={0.01} prefix="¥" style={{ width: '100%' }} />
</Form.Item>
<Form.Item label="最高返现金额" name="maxCashback" rules={[{ required: true }]} extra="单笔返现最高金额">
<InputNumber min={10} max={500} step={10} prefix="¥" style={{ width: '100%' }} />
<InputNumber min={10} max={5000} step={10} prefix="¥" style={{ width: '100%' }} />
</Form.Item>
<Form.Item label="提现门槛" name="withdrawThreshold" rules={[{ required: true }]} extra="用户余额满多少元可以申请提现">
<InputNumber min={1} max={100} step={1} prefix="¥" style={{ width: '100%' }} />
@@ -240,7 +240,7 @@ const BankCards: React.FC = () => {
label="卡片名称"
rules={[{ required: true, message: '请输入卡片名称' }]}
>
<Input placeholder="例如:主账户、备用账户" />
<Input placeholder="例如:PLATFORM_MAIN (平台主账户)、PLATFORM_BACKUP (平台备用账户)" />
</Form.Item>
<Form.Item
name="bankName"
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { Card, Row, Col, Statistic, Table, Tag } from 'antd';
import { WalletOutlined, ArrowUpOutlined, ArrowDownOutlined, DollarOutlined, TeamOutlined } from '@ant-design/icons';
import { getFinancialOverview, getPlatformTransactions } from '@/api/finance';
import { getAccountDisplayName } from '@/utils/accountNameMap';
import type { ColumnsType } from 'antd/es/table';
interface FinancialOverview {
@@ -14,11 +15,11 @@ interface FinancialOverview {
platformTotalExpense: number;
totalUserBalance: number;
totalMerchantBalance: number;
totalMerchantPendingSettlement: number;
userCount: number;
merchantCount: number;
todayIncome: number;
todayExpense: number;
todayOrders: number;
}
interface Transaction {
@@ -116,18 +117,19 @@ const FinanceDashboard: React.FC = () => {
{/* 系统总账户金额 - 突出显示 */}
<Card style={{ marginBottom: 24, background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }}>
<Statistic
title={<span style={{ color: '#fff', fontSize: 16 }}></span>}
title={<span style={{ color: '#fff', fontSize: 16 }}></span>}
value={Number(overview.systemTotalAmount || 0)}
prefix={<WalletOutlined style={{ color: '#fff' }} />}
suffix={<span style={{ color: '#fff' }}></span>}
suffix={<span style={{ color: '#fff' }}> ({getAccountDisplayName('SYSTEM_MAIN')})</span>}
precision={2}
valueStyle={{ color: '#fff', fontSize: 36, fontWeight: 'bold' }}
/>
<div style={{ color: 'rgba(255,255,255,0.8)', fontSize: 12, marginTop: 8 }}>
¥{Number(overview.totalUserPaid || 0).toFixed(2)}- 退¥{Number(overview.totalRefund || 0).toFixed(2)}- ¥{Number(overview.totalWithdrawn || 0).toFixed(2)}
{/* <div style={{ color: 'rgba(255,255,255,0.9)', fontSize: 13, marginTop: 8, fontWeight: 500 }}>
商家账户余额(¥{Number(overview.totalMerchantBalance || 0).toFixed(2)}+ 用户账户余额(¥{Number(overview.totalUserBalance || 0).toFixed(2)}+ 平台净收益(¥{Number(overview.platformBalance || 0).toFixed(2)}
</div>
<div style={{ color: 'rgba(255,255,255,0.6)', fontSize: 11, marginTop: 4 }}>
= ¥{Number(overview.totalMerchantBalance || 0).toFixed(2)}+ ¥{Number(overview.totalUserBalance || 0).toFixed(2)}+ ¥{Number(overview.platformBalance || 0).toFixed(2)}
*/}
<div style={{ color: 'rgba(255,255,255,0.7)', fontSize: 11, marginTop: 6 }}>
balance = ¥{Number(overview.totalUserPaid || 0).toFixed(2)}- 退¥{Number(overview.totalRefund || 0).toFixed(2)}- ¥{Number(overview.totalWithdrawn || 0).toFixed(2)}= ¥{(Number(overview.totalUserPaid || 0) - Number(overview.totalRefund || 0) - Number(overview.totalWithdrawn || 0)).toFixed(2)}
</div>
</Card>
@@ -180,11 +182,16 @@ const FinanceDashboard: React.FC = () => {
<Col span={6}>
<Card>
<Statistic
title="今日订单数"
value={overview.todayOrders}
suffix="单"
valueStyle={{ color: '#722ed1' }}
title="商家待结算金额"
value={overview.totalMerchantPendingSettlement}
precision={2}
prefix={<DollarOutlined />}
suffix="元"
valueStyle={{ color: '#ff9800' }}
/>
<div style={{ fontSize: 12, color: '#999', marginTop: 8 }}>
</div>
</Card>
</Col>
</Row>
@@ -3,7 +3,7 @@ import { Card, Table, DatePicker, Space, Tag, Button, Statistic, Row, Col, messa
import { DownloadOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { formatMoney, formatDateTime } from '@rent/shared-utils';
import { getFinancialOverview, getMerchantTransactions } from '@/api/finance';
import { getServiceFeeStatistics, getServiceFeeList } from '@/api/finance';
import type { Dayjs } from 'dayjs';
const { RangePicker } = DatePicker;
@@ -45,7 +45,7 @@ const ServiceFees: React.FC = () => {
const fetchStatistics = async () => {
try {
const res = await getFinancialOverview({});
const res = await getServiceFeeStatistics();
if (res?.data) {
setStatistics({
todayCommission: res.data?.todayCommission || 0,
@@ -72,7 +72,7 @@ const ServiceFees: React.FC = () => {
params.endDate = dateRange[1].format('YYYY-MM-DD');
}
const res = await getMerchantTransactions(params);
const res = await getServiceFeeList(params);
if (res?.data) {
setDataSource(res.data?.list || []);
setPagination({
@@ -0,0 +1,31 @@
/**
* 账户名称映射工具
* 数据库存储英文常量,前端显示中文名称
*/
export const ACCOUNT_NAMES = {
SYSTEM_MAIN: 'SYSTEM_MAIN',
PLATFORM_MAIN: 'PLATFORM_MAIN',
PLATFORM_BACKUP: 'PLATFORM_BACKUP',
} as const;
export const ACCOUNT_NAME_MAP: Record<string, string> = {
SYSTEM_MAIN: '系统总账户',
PLATFORM_MAIN: '平台主账户',
PLATFORM_BACKUP: '平台备用账户',
};
/**
* 将英文账户名称转换为中文显示名称
*/
export function getAccountDisplayName(accountName: string): string {
return ACCOUNT_NAME_MAP[accountName] || accountName;
}
/**
* 将中文显示名称转换为英文账户名称
*/
export function getAccountConstName(displayName: string): string {
const entry = Object.entries(ACCOUNT_NAME_MAP).find(([_, value]) => value === displayName);
return entry ? entry[0] : displayName;
}