hejianhao
2025-12-24 0bb1565db353c37548fbe862bbe6c5d660d44b76
feat(财务): 新增汇总统计页面及功能

添加财务管理菜单项和汇总统计页面,包含访问量、订单数和金额的统计图表
实现日期范围筛选和数据展示功能
2个文件已添加
2个文件已修改
328 ■■■■■ 已修改文件
management/config/routes.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/locales/zh-CN/menu.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/finance/summaryStatistics/index.jsx 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/finance/summaryStatistics/service.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/config/routes.ts
@@ -231,6 +231,11 @@
        "path": "/finance/integralSettlement/detail",
        "component": "./finance/integralSettlement/detail",
        "hideInMenu": true
      },
      {
        "name": "汇总统计",
        "path": "/finance/summaryStatistics",
        "component": "./finance/summaryStatistics"
      }
    ]
  },
management/src/locales/zh-CN/menu.ts
@@ -53,4 +53,7 @@
  'menu.order.bigGiftPackageOrder': '大礼包订单列表',
  'menu.order.physicalGoodsOrder': '实物商品订单',
  'menu.order.refundAudit': '退款申请审核',
  'menu.finance': '财务管理',
  'menu.finance.integralSettlement': '积分结算',
  'menu.finance.summaryStatistics': '汇总统计',
};
management/src/pages/finance/summaryStatistics/index.jsx
New file
@@ -0,0 +1,311 @@
import React, { useState, useEffect } from 'react';
import { PageContainer } from '@ant-design/pro-components';
import { Card, Row, Col, DatePicker, Space, Spin, Button } from 'antd';
import { LineChart, ColumnChart } from '@ant-design/plots';
import moment from 'moment';
import { getSummaryStatistics } from './service';
// 客户访问量统计组件
const VisitStatsCard = ({ data }) => {
  const { visitStats } = data || {};
  if (!visitStats) {
    return null;
  }
  const config = {
    data: visitStats.trend || [],
    xField: 'date',
    yField: 'value',
    columnStyle: {
      fill: '#5B8FF9',
    },
    meta: {
      date: {
        alias: '日期',
      },
      value: {
        alias: '访问量',
      },
    },
    interactions: [
      {
        type: 'active-region',
        enable: false,
      },
    ],
  };
  return (
    <Card>
      <Row gutter={[16, 16]}>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 24, fontWeight: 'bold', color: '#5B8FF9' }}>
              {visitStats.total?.toLocaleString() || 0}
            </div>
            <div style={{ color: '#666' }}>总量</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{
              fontSize: 24,
              fontWeight: 'bold',
              color: visitStats.rate >= 0 ? '#52C41A' : '#FF4D4F'
            }}>
              {visitStats.rate >= 0 ? '+' : ''}{visitStats.rate?.toFixed(2) || 0}%
            </div>
            <div style={{ color: '#666' }}>环比增长率</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ height: 200 }}>
            <ColumnChart {...config} />
          </div>
        </Col>
      </Row>
    </Card>
  );
};
// 订单数统计组件(X、Y轴互换)
const OrderCountCard = ({ data }) => {
  const { orderCountStats } = data || {};
  if (!orderCountStats) {
    return null;
  }
  const config = {
    data: orderCountStats.trend || [],
    xField: 'value',
    yField: 'date',
    columnStyle: {
      fill: '#FAC858',
    },
    meta: {
      date: {
        alias: '日期',
      },
      value: {
        alias: '订单数',
      },
    },
    interactions: [
      {
        type: 'active-region',
        enable: false,
      },
    ],
  };
  return (
    <Card>
      <Row gutter={[16, 16]}>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 24, fontWeight: 'bold', color: '#FAC858' }}>
              {orderCountStats.total?.toLocaleString() || 0}
            </div>
            <div style={{ color: '#666' }}>总量</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{
              fontSize: 24,
              fontWeight: 'bold',
              color: orderCountStats.rate >= 0 ? '#52C41A' : '#FF4D4F'
            }}>
              {orderCountStats.rate >= 0 ? '+' : ''}{orderCountStats.rate?.toFixed(2) || 0}%
            </div>
            <div style={{ color: '#666' }}>环比增长率</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ height: 200 }}>
            <ColumnChart {...config} />
          </div>
        </Col>
      </Row>
    </Card>
  );
};
// 订单金额统计组件
const OrderAmountCard = ({ data }) => {
  const { orderAmountStats } = data || {};
  if (!orderAmountStats) {
    return null;
  }
  const config = {
    data: orderAmountStats.trend || [],
    xField: 'date',
    yField: 'value',
    color: '#91CC75',
    meta: {
      date: {
        alias: '日期',
      },
      value: {
        alias: '金额',
      },
    },
  };
  return (
    <Card>
      <Row gutter={[16, 16]}>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 24, fontWeight: 'bold', color: '#91CC75' }}>
              ¥{(orderAmountStats.total || 0).toLocaleString()}
            </div>
            <div style={{ color: '#666' }}>总量</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ textAlign: 'center' }}>
            <div style={{
              fontSize: 24,
              fontWeight: 'bold',
              color: orderAmountStats.rate >= 0 ? '#52C41A' : '#FF4D4F'
            }}>
              {orderAmountStats.rate >= 0 ? '+' : ''}{orderAmountStats.rate?.toFixed(2) || 0}%
            </div>
            <div style={{ color: '#666' }}>环比增长率</div>
          </div>
        </Col>
        <Col span={8}>
          <div style={{ height: 200 }}>
            <LineChart {...config} />
          </div>
        </Col>
      </Row>
    </Card>
  );
};
// 订单月度统计组件
const MonthlyStatsCard = ({ data }) => {
  const { monthlyStats } = data || {};
  if (!monthlyStats || monthlyStats.length === 0) {
    return null;
  }
  // 为每个月份创建两个数据点(订单数和订单金额)
  const chartData = monthlyStats.map(item => [
    { month: item.month, type: '订单数', value: item.orderCount },
    { month: item.month, type: '订单金额', value: item.orderAmount },
  ]).flat();
  const config = {
    data: chartData,
    xField: 'month',
    yField: 'value',
    seriesField: 'type',
    isGroup: true,
    columnStyle: {
      radius: [4, 4, 0, 0],
    },
    meta: {
      month: {
        alias: '月份',
      },
      value: {
        alias: '数量',
      },
    },
    interactions: [
      {
        type: 'active-region',
        enable: false,
      },
    ],
  };
  return (
    <Card title="订单月度统计">
      <div style={{ height: 400 }}>
        <ColumnChart {...config} />
      </div>
    </Card>
  );
};
const SummaryStatistics = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState(null);
  const [dateRange, setDateRange] = useState([null, null]);
  // 获取统计数据
  const fetchData = async () => {
    setLoading(true);
    try {
      const response = await getSummaryStatistics({
        startDate: dateRange[0],
        endDate: dateRange[1],
      });
      setData(response);
    } catch (error) {
      console.error('获取统计数据失败:', error);
    } finally {
      setLoading(false);
    }
  };
  useEffect(() => {
    fetchData();
  }, [dateRange]);
  const handleDateChange = (dates) => {
    if (dates && dates[0] && dates[1]) {
      setDateRange([dates[0].format('YYYY-MM-DD'), dates[1].format('YYYY-MM-DD')]);
    } else {
      setDateRange([null, null]);
    }
  };
  return (
    <PageContainer>
      <div style={{ marginBottom: 24 }}>
        <Space>
          <DatePicker.RangePicker
            value={dateRange.map(date => date ? moment(date) : null)}
            onChange={handleDateChange}
            style={{ width: 300 }}
          />
          <Button onClick={fetchData} type="primary">查询</Button>
        </Space>
      </div>
      {loading ? (
        <div style={{ textAlign: 'center', padding: 100 }}>
          <Spin size="large" />
        </div>
      ) : (
        <>
          <Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
            <Col span={8}>
              <VisitStatsCard data={data} />
            </Col>
            <Col span={8}>
              <OrderCountCard data={data} />
            </Col>
            <Col span={8}>
              <OrderAmountCard data={data} />
            </Col>
          </Row>
          <MonthlyStatsCard data={data} />
        </>
      )}
    </PageContainer>
  );
};
export default SummaryStatistics;
management/src/pages/finance/summaryStatistics/service.js
New file
@@ -0,0 +1,9 @@
import { request } from '@umijs/max';
// 获取汇总统计数据
export async function getSummaryStatistics(params) {
  return request('/dashboard-statistics/overview', {
    method: 'POST',
    data: params,
  });
}