月度营收分析页面

This commit is contained in:
ylj20011123 2025-09-19 09:15:21 +08:00
parent f7e3cc66b0
commit fe7a7a82f6
6 changed files with 418 additions and 5 deletions

View File

@ -1631,6 +1631,11 @@ export default [
name: 'business/revenueQOQReport',
component: './reports/BusinessAnalysis/revenueQOQReport',
},
{
path: 'business/monthlyRevenueAnalysis',
name: 'business/monthlyRevenueAnalysis',
component: './reports/BusinessAnalysis/monthlyRevenueAnalysis',
},
{
path: 'region/business/revenueQOQReport',
name: 'region/business/revenueQOQReport',

View File

@ -1,6 +1,6 @@
{
"name": "ant-design-pro",
"version": "4.5.57",
"version": "4.5.58",
"private": true,
"description": "An out-of-box UI solution for enterprise applications",
"scripts": {

View File

@ -0,0 +1,385 @@
import { connect } from "umi";
import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect";
import React, { Children, useRef, useState } from "react";
import ProCard from "@ant-design/pro-card";
import { MenuFoldOutlined } from "@ant-design/icons";
import type { FormInstance } from "antd";
import { Button, message, Space, Spin, Tree } from "antd";
import useRequest from "@ahooksjs/use-request";
import { getServerpartTree } from "@/services/options";
import type { ActionType } from "@ant-design/pro-table";
import ProTable from "@ant-design/pro-table";
import LeftSelectTree from "@/pages/reports/settlementAccount/component/leftSelectTree";
import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
import { ValueType } from "exceljs";
import moment from 'moment'
import { handleGetBusinessItemSummary } from "../revenueQOQReport/service";
const monthlyRevenueAnalysis: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const downloadBtnRef = useRef<any>()
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const [reqDetailList, setReqDetailList] = useState<any>(); // 合计项数据源
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
const [collapsible, setCollapsible] = useState<boolean>(false)
const [treeView, setTreeView] = useState<any>()
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
// 导出的加载效果
const [showLoading, setShowLoading] = useState<boolean>(false)
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
// 查询的条件
const [searchParams, setSearchParams] = useState<any>()
// 表格表头 显示的时间
const [tableTitle, setTableTitle] = useState<any>({
thisMonthStart: "",
thisMonthEnd: "",
thisYearStart: "",
thisYearEnd: "",
thisYear: "",
lastYear: ""
})
const columns: any = [
{
title: '统计口径',
dataIndex: "DataType",
hideInTable: true,
valueType: 'select',
fieldProps: {
options: [
{ label: "全部", value: 3 },
{ label: "业态", value: 1 },
{ label: "中心", value: 2 },
]
},
initialValue: 3
},
{
title: '统计月份',
dataIndex: 'searchMonth',
valueType: "date",
hideInTable: true,
initialValue: moment(),
fieldProps: {
picker: "month",
format: 'YYYY-MM',
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: "Item_Name",
hideInSearch: true,
ellipsis: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: "Serverpart_Name",
hideInSearch: true,
ellipsis: true,
},
{
title: `本月${tableTitle?.thisMonthStart && tableTitle?.thisMonthEnd ? `(${tableTitle?.thisMonthStart}-${tableTitle?.thisMonthEnd})` : ""}`,
dataIndex: "RevenueAmount",
hideInSearch: true,
align: 'center',
children: [
{
title: <div style={{ textAlign: 'center' }}>{`${tableTitle?.lastYear}`}</div>,
dataIndex: "RevenueAmountFirst",
hideInSearch: true,
ellipsis: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["RevenueAmount", "curData"],
hideInSearch: true,
align: 'right',
valueType: 'digit',
ellipsis: true,
},
]
},
{
title: <div style={{ textAlign: 'center' }}>{`${tableTitle?.thisYear}`}</div>,
dataIndex: "RevenueAmountSecond",
hideInSearch: true,
ellipsis: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["RevenueAmount", "compareData"],
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["RevenueAmount", "increaseData"],
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: "RevenueAmount.increaseRate",
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
render: (_, record) => {
return record?.RevenueAmount?.increaseRate ? `${record?.RevenueAmount?.increaseRate}%` : "-"
}
},
]
},
]
},
{
title: `年度累计${tableTitle?.thisYearStart && tableTitle?.thisYearEnd ? `(${tableTitle?.thisYearStart}-${tableTitle?.thisYearEnd})` : ""}`,
dataIndex: "ACCRevenueAmount",
hideInSearch: true,
align: 'center',
children: [
{
title: <div style={{ textAlign: 'center' }}>{`${tableTitle?.lastYear}`}</div>,
dataIndex: "ACCRevenueAmountFirst",
hideInSearch: true,
ellipsis: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["ACCRevenueAmount", "curData"],
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
},
]
},
{
title: <div style={{ textAlign: 'center' }}>{`${tableTitle?.thisYear}`}</div>,
dataIndex: "ACCRevenueAmountSecond",
hideInSearch: true,
ellipsis: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["ACCRevenueAmount", "compareData"],
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: ["ACCRevenueAmount", "increaseData"],
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: "ACCRevenueAmount.increaseRate",
hideInSearch: true,
ellipsis: true,
align: 'right',
valueType: 'digit',
render: (_, record) => {
return record?.ACCRevenueAmount?.increaseRate ? `${record?.ACCRevenueAmount?.increaseRate}%` : "-"
}
},
]
},
]
}
]
return (
<div ref={(el) => {
// 打印报表
if (!reqDetailList || reqDetailList.length === 0) return;
setPrintOut(el);
}} >
{
showLoading ?
<div
style={{
width: '100%',
height: '100%',
background: 'rgba(0,0,0,0.1)',
position: 'fixed',
zIndex: 5,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '15px 20px 10px',
background: '#fff',
borderRadius: '8px',
width: '200px'
}}>
<Spin />
<span style={{ marginLeft: '5px' }}>...</span>
</div>
</div> : ''
}
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
<div style={{
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true
}}
rowKey={'LineIndex'}
scroll={{ x: "100%", y: "calc(100vh - 410px)" }}
headerTitle={<PageTitleBox props={props} />} // 列表表头
search={{ span: 6 }}
request={async (params) => {
if (!selectedId) {
return
}
console.log('paramsparamsparamsparams', params);
console.log('currentUsercurrentUsercurrentUser', currentUser);
const req: any = {
DataType: params?.DataType || 3,
ProvinceCode: currentUser?.ProvinceCode,
ServerpartId: selectedId,
StartDate: params?.searchMonth ? moment(params?.searchMonth).startOf('M').format('YYYY-MM-DD') : "",
EndDate: params?.searchMonth ? new Date(moment().subtract(1, 'd').format('YYYY-MM-DD')).getTime() < new Date(moment(params?.searchMonth).endOf('M').format('YYYY-MM-DD')).getTime() ? moment().subtract(1, 'd').format('YYYY-MM-DD') : moment(params?.searchMonth).endOf('M').format('YYYY-MM-DD') : "",
}
setSearchParams(params)
const data = await handleGetBusinessItemSummary(req)
if (params?.searchMonth) {
setTableTitle(
{
thisMonthStart: moment(params?.searchMonth).startOf('M').format('MM.DD'),
thisMonthEnd: new Date(moment().subtract(1, 'd').format('YYYY-MM-DD')).getTime() < new Date(moment(params?.searchMonth).endOf('M').format('YYYY-MM-DD')).getTime() ? moment().subtract(1, 'd').format('MM.DD') : moment(params?.searchMonth).endOf('M').format('MM.DD'),
thisYearStart: moment(params?.searchMonth).startOf('y').format('MM.DD'),
thisYearEnd: new Date(moment().subtract(1, 'd').format('YYYY-MM-DD')).getTime() < new Date(moment(params?.searchMonth).endOf('M').format('YYYY-MM-DD')).getTime() ? moment().subtract(1, 'd').format('MM.DD') : moment(params?.searchMonth).endOf('M').format('MM.DD'),
thisYear: moment(params?.searchMonth).format('YYYY'),
lastYear: moment(params?.searchMonth).subtract(1, 'y').format('YYYY')
}
)
}
console.log('data', data);
if (data && data.length > 0) {
let list: any = JSON.parse(JSON.stringify(data))
list.forEach((item: any) => {
// 处理百分号
item.RevenueAmount.increaseRate = item.RevenueAmount?.increaseRate ? item.RevenueAmount?.increaseRate + '%' : ""
item.ACCRevenueAmount.increaseRate = item.ACCRevenueAmount?.increaseRate ? item.ACCRevenueAmount?.increaseRate + '%' : ""
// 处理数字的千分号
item.RevenueAmount.curData = item.RevenueAmount.curData.toLocaleString() || 0
item.RevenueAmount.compareData = item.RevenueAmount.compareData.toLocaleString() || 0
item.RevenueAmount.increaseData = item.RevenueAmount.increaseData.toLocaleString() || 0
item.ACCRevenueAmount.curData = item.ACCRevenueAmount.curData.toLocaleString() || 0
item.ACCRevenueAmount.compareData = item.ACCRevenueAmount.compareData.toLocaleString() || 0
item.ACCRevenueAmount.increaseData = item.ACCRevenueAmount.increaseData.toLocaleString() || 0
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
// 处理百分号
subItem.RevenueAmount.increaseRate = subItem.RevenueAmount?.increaseRate ? subItem.RevenueAmount?.increaseRate + '%' : ""
subItem.ACCRevenueAmount.increaseRate = subItem.ACCRevenueAmount?.increaseRate ? subItem.ACCRevenueAmount?.increaseRate + '%' : ""
// 处理数字的千分号
subItem.RevenueAmount.curData = subItem.RevenueAmount.curData.toLocaleString() || 0
subItem.RevenueAmount.compareData = subItem.RevenueAmount.compareData.toLocaleString() || 0
subItem.RevenueAmount.increaseData = subItem.RevenueAmount.increaseData.toLocaleString() || 0
subItem.ACCRevenueAmount.curData = subItem.ACCRevenueAmount.curData.toLocaleString() || 0
subItem.ACCRevenueAmount.compareData = subItem.ACCRevenueAmount.compareData.toLocaleString() || 0
subItem.ACCRevenueAmount.increaseData = subItem.ACCRevenueAmount.increaseData.toLocaleString() || 0
})
}
})
setReqDetailList(list)
return { data, success: true }
}
setReqDetailList([])
return { data: [], success: true }
}}
toolbar={{
actions: [
// <span style={{ visibility: 'hidden' }}>
// <ReactHTMLTableToExcel
// buttonText={'导出excel'}
// ref={downloadBtnRef}
// table="table-to-xls-monthlyRevenueAnalysis"
// filename={`单品销售排行统计${searchParams?.StartDate}-${searchParams?.EndDate}`}
// sheet="sheet1"
// />
// </span>,
<Button
key="new"
type="primary"
onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) {
exportXlsxFromProColumnsExcelJS(columns,
reqDetailList,
`月度营收分析${searchParams?.searchMonth ? moment(searchParams?.searchMonth).format('YYYYMM') : ""}`,
{
topTitle: `服务区${searchParams?.searchMonth ? moment(searchParams?.searchMonth).format('MM') : ""}月营业额统计表`, // 顶部大标题
}
)
} else {
message.error('暂无数据可导出!')
}
}}
>
excel
</Button>
]
}}
/>
</div>
</div>
</div >
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(monthlyRevenueAnalysis);

View File

@ -67,3 +67,26 @@ export async function handleGetRevenueYOYQOQByDate(params: any) {
const treeTable = wrapTreeNode(data.Result_Data.List);
return treeTable
}
// 获取安徽驿达月度营收分析
export async function handleGetBusinessItemSummary(params: any) {
const data = await request('/Revenue/GetBusinessItemSummary', {
method: 'GET',
params
})
if (data.Result_Code !== 100) {
return {
data: [],
otherData: '',
current: 1,
pageSize: 20,
total: 0,
success: true,
};
}
const treeTable = wrapTreeNode(data.Result_Data.List);
return treeTable
}

View File

@ -667,7 +667,7 @@ export const handleSetPublicLog = (obj: any) => {
BUSINESSMAN_NAME: currentUser.BusinessManName,
SOURCE_PLATFORM: '驿商云平台',
USER_LOGINIP: basicInfo.ip,
USER_LOGINPLACE: `${basicInfo.country}${basicInfo.prov}${basicInfo.city}${basicInfo.district}`,
USER_LOGINPLACE: `${basicInfo.country || ""}${basicInfo.prov || ""}${basicInfo.city || ""}${basicInfo.district || ""}`,
BROWSER_VERSION: browserVersion,
OPERATING_SYSTEM: systemBasin
}

View File

@ -1,4 +1,4 @@
// 由 scripts/writeVersion.js 自动生成
export const VERSION = "4.5.57";
export const GIT_HASH = "8f8b347";
export const BUILD_TIME = "2025-09-18T01:29:44.333Z";
export const VERSION = "4.5.58";
export const GIT_HASH = "f7e3cc6";
export const BUILD_TIME = "2025-09-18T14:27:48.181Z";