2025-06-13 19:18:28 +08:00

1129 lines
43 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useRef, useState } from "react";
import type { CurrentUser } from "@/models/user";
import { connect } from "umi";
import type { ConnectState } from "@/models/connect";
import { MenuFoldOutlined } from "@ant-design/icons";
import { Button, Col, Descriptions, Drawer, Row, Tree, Typography, message, Tooltip } from "antd";
import ProCard from "@ant-design/pro-card";
import useRequest from "@ahooksjs/use-request";
import { getServerpartTree } from "@/services/options";
import type { ActionType } from "@ant-design/pro-table";
import type { ProFormInstance } from "@ant-design/pro-form";
import ProTable from '@ant-design/pro-table';
import { handleGetServerpartDetail, handleGetSpringTableList } from "@/pages/reports/Finance/SpringFestival/service";
import moment from "moment";
import numeral from "numeral";
import { exportExcelReceivedSum } from "@/utils/utils";
import ReactHTMLTableToExcel from "react-html-table-to-excel";
import session from "@/utils/session";
import PageTitleBox from "@/components/PageTitleBox";
import AiDrawer from "@/components/AiDrawer";
import { handleChangeKeyTo, handleSetPublicLog } from "@/utils/format";
const { Text } = Typography;
const SpringFestival: React.FC<{ currentUser?: CurrentUser }> = (props) => {
const actionRef = useRef<ActionType>();
const formRef = useRef<ProFormInstance>();
const downloadBtnRef = useRef<any>()
const actionDetailRef = useRef<ActionType>();
const formDetailRef = useRef<ProFormInstance>();
const { currentUser, route } = props
// 左侧树展开还是收缩
const [collapsible, setCollapsible] = useState<boolean>(false)
const [selectedId, setSelectedId] = useState<string>()
const [activeKey, setActiveKey] = useState<1 | 2>(2); // 统计类型 1 当日 2 累计
// 展开服务区详情抽屉
const [showDetail, setShowDetail] = useState<boolean>(false)
// 当前选中的服务区行数据
const [currentRow, setCurrentRow] = useState<any>()
// 拿到外面表格的日期
const [searchDate, setSearchDate] = useState<any>()
// 服务区详情里面的汇总信息
const [summaryInfo, setSummaryInfo] = useState<any>()
// 获取用户服务区权限树
const { loading: treeLoading, data: treeView } = useRequest(async () => {
return getServerpartTree(currentUser?.ProvinceCode, currentUser?.CityAuthority, true, false, true, null, 1000)
})
const [reqDetailList, setReqDetailList] = useState<any[]>(); // 导出excel表格
const [filename, setFilename] = useState<string>()
const [festivalType, setFestivalType] = useState<any>("0")
// 给详情抽屉里面的查询时间
const [detailEndTime, setDetailEndTime] = useState<any>()
const [detailStartTime, setDetailStartTime] = useState<any>()
// 表格的搜索参数
const [searchParams, setSearchParams] = useState<any>()
// 表格的加載效果
const [tableLoading, setTableLoading] = useState<any>()
// 判断是否点击了表格的查询按钮
const clickTableBtnRef = useRef<boolean>(false)
// 表格数据
const [tableData, setTableData] = useState<any>()
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
// ai的抽屉
const [showAiDrawer, setShowAiDrawer] = useState<boolean>(false)
// 节日类型表
const festivalList: any = [
{ label: "25年元旦", value: 1, HolidayType: 1, curYear: 2025, compareYear: 2024, startTime: "2024-12-31", endTime: "2025-01-02" },
{ label: "25年春运", value: 2, HolidayType: 2, curYear: 2025, compareYear: 2024, startTime: "2025-01-14", endTime: "2025-02-23" },
{ label: "25年清明", value: 3, HolidayType: 3, curYear: 2025, compareYear: 2024, startTime: "2025-04-03", endTime: "2025-04-07" },
{ label: "25年劳动", value: 4, HolidayType: 4, curYear: 2025, compareYear: 2024, startTime: "2025-04-30", endTime: "2025-05-06" },
{ label: "25年端午", value: 5, HolidayType: 5, curYear: 2025, compareYear: 2024, startTime: "2025-05-30", endTime: "2025-06-03" },
{ label: "25年暑运", value: 6, HolidayType: 6, curYear: 2025, compareYear: 2024, startTime: "2025-06-30", endTime: "2025-08-31" },
{ label: "25年国庆", value: 7, HolidayType: 8, curYear: 2025, compareYear: 2024, startTime: "2025-09-30", endTime: "2025-10-09" },
{ label: "24年元旦", value: 8, HolidayType: 1, curYear: 2024, compareYear: 2023, startTime: "2023-12-31", endTime: "2024-01-02" },
{ label: "24年春运", value: 9, HolidayType: 2, curYear: 2024, compareYear: 2023, startTime: "2024-01-26", endTime: "2024-03-05" },
{ label: "24年清明", value: 10, HolidayType: 3, curYear: 2024, compareYear: 2023, startTime: "2024-04-03", endTime: "2024-04-07" },
{ label: "24年劳动", value: 11, HolidayType: 4, curYear: 2024, compareYear: 2023, startTime: "2024-04-30", endTime: "2024-05-06" },
{ label: "24年端午", value: 12, HolidayType: 5, curYear: 2024, compareYear: 2023, startTime: "2024-06-07", endTime: "2024-06-11" },
{ label: "24年暑运", value: 13, HolidayType: 6, curYear: 2024, compareYear: 2023, startTime: "2024-06-30", endTime: "2024-08-31" },
{ label: "24年中秋", value: 14, HolidayType: 7, curYear: 2024, compareYear: 2023, startTime: "2024-09-14", endTime: "2024-09-18" },
{ label: "24年国庆", value: 15, HolidayType: 8, curYear: 2024, compareYear: 2023, startTime: "2024-09-30", endTime: "2024-10-08" },
]
const paramsSort: any = {
calcType: "计算方式",
pushProvinceCode: "省份编码",
curYear: "本年年份",
HolidayType: "节日类型",
StatisticsDate: "统计日期",
compareYear: "历年年份",
CurStartDate: "统计开始日期",
ServerpartId: "服务区内码",
businessRegion: "经营区域",
SortStr: "排序字段",
IsYOYCompare: "是否对比同期数据"
}
// 当前选择节日的整个对象值
const [currentFestivalObj, setCurrentFestivalObj] = useState<any>()
// 给日期显示的对象 点了搜索 才更新值
const [showCurrentFestivalObj, setShowCurrentFestivalObj] = useState<any>()
// 拿到headerTitle
const { loading: headerTitleLoading, data: tableHeaderTitle } = useRequest(async () => {
const menu = session.get('menu')
if (menu && menu.length > 0) {
let obj: any = {}
menu.forEach((item: any) => {
if (item.path === route.path) {
obj = item
}
})
console.log('obj', obj);
return obj.name || ''
}
return ''
})
// 拿到表格数据的方法
const handleGetTableData = async (params: any) => {
console.log('handleGetTableData', params);
console.log('currentFestivalObj', currentFestivalObj);
let startTime: number = new Date().getTime()
setTableLoading(true)
const req = {
calcType: 2,
pushProvinceCode: '340000',
curYear: currentFestivalObj.curYear,
compareYear: currentFestivalObj.compareYear,
HolidayType: currentFestivalObj.HolidayType || '0',
StatisticsDate: params.StatisticsDate ? moment(params.StatisticsDate).format('YYYY-MM-DD') : '',
CurStartDate: params.CurStartDate ? moment(params.CurStartDate).format('YYYY-MM-DD') : '',
ServerpartId: selectedId || '',
businessRegion: 1,
}
console.log('params', params)
setSearchParams(params)
setDetailEndTime(params.StatisticsDate)
setDetailStartTime(params.CurStartDate)
const data = await handleGetSpringTableList(req)
setShowCurrentFestivalObj(currentFestivalObj)
const list: any = []
if (data.data && data.data.length > 0) {
data.data.forEach((item: any) => {
list.push({
SPRegionTypeId: item.SPRegionTypeId,
SPRegionTypeName: item.SPRegionTypeName,
ServerpartId: item.ServerpartId,
ServerpartName: item.ServerpartName,
RevenueINCcur: item.RevenueINC.curYearData,
RevenueINClYear: item.RevenueINC.lYearData,
RevenueINCcrease: item.RevenueINC.increaseData,
RevenueINCRate: item.RevenueINC.increaseRate,
AccountINCCcur: item.AccountINC.curYearData,
AccountINClYear: item.AccountINC.lYearData,
AccountINCcrease: item.AccountINC.increaseData,
AccountINCRate: item.AccountINC.increaseRate,
BayonetINCINCCcur: item.BayonetINC.curYearData,
BayonetINClYear: item.BayonetINC.lYearData,
BayonetINCcrease: item.BayonetINC.increaseData,
BayonetINCRate: item.BayonetINC.increaseRate,
})
// list.push({
// SPRegionTypeId:item.SPRegionTypeId,
// SPRegionTypeName:item.SPRegionTypeName,
// ServerpartId:item.ServerpartId,
// ServerpartName:item.ServerpartName,
// ...item.BayonetINC
// })
})
}
setReqDetailList(list);
setTableData(list);
console.log('list', list)
setTableLoading(false)
clickTableBtnRef.current = false
let endTime: number = new Date().getTime()
const logReq: any = await handleChangeKeyTo(req, paramsSort)
console.log('logReq', logReq);
handleSetPublicLog({
desc: [
{
url: '/CommercialApi/Revenue/GetServerpartINCAnalysis', params: logReq, time: (endTime - startTime) / 1000,
}
],
startTime: startTime,
endTime: endTime,
buttonType: 1
})
}
const columns: any = [
// {
// dataIndex: 'DataType',
// // title: '统计方式',
// valueType: "radioButton",
// initialValue: '1',
// // colSize: 1,
// // colSpan: 4,
// valueEnum: {
// 2: { text: '累计' },
// 1: { text: '当日' },
// },
// hideInTable: true,
// fieldProps: {
// onChange: (event: any) => {
// setActiveKey(event.target.value)
// formRef.current?.submit()
// },
// labelCol: { span: 3, offset: 24 },
// // wrapperCol: { span: 24 }
// },
// },
// {
// title: '统计类型',
// dataIndex: 'FilterType',
// valueType: "select",
// initialValue: '1',
// valueEnum: {
// 3: { text: '入区车流' },
// 2: { text: '营业收入' },
// 1: { text: '对客销售' },
// },
// hideInTable: true,
// },
{
title: '序号',
dataIndex: 'index',
key: 'index',
valueType: 'index',
align: 'center',
hideInSearch: true,
width: 70,
},
{
title: '服务区',
dataIndex: 'ServerpartName',
aiDataIndex: "ServerpartName",
hideInSearch: true,
align: 'center',
render: (_, record) => {
return <a style={{ cursor: 'pointer' }} onClick={() => {
setCurrentRow(record)
setShowDetail(true)
formDetailRef.current?.setFieldsValue({ STATISTICS_DATE: searchDate })
}}>{record.ServerpartName.split('服务区')[0]}</a>
}
},
{
title: '节日类型',
dataIndex: 'HolidayType',
aiDataIndex: "HolidayType",
hideInTable: true,
valueType: 'select',
userEnum: {
1: "元旦",
2: "春运",
3: "清明",
4: "劳动",
5: "端午",
6: "暑运",
7: "中秋",
8: "国庆"
},
// valueEnum: {
// 2: "春运",
// 3: "清明",
// 4: "劳动节",
// },
request: async () => {
if (showExportTable) {
return
}
console.log('festivalList', festivalList);
const res: any = []
const lastDay: any = moment().subtract(1, 'd').format('YYYY-MM-DD')
let defaultValueObj: any = {}
festivalList.forEach((item: any) => {
if ((new Date(item.startTime).getTime() < new Date(lastDay).getTime() && new Date(lastDay).getTime() < new Date(item.endTime).getTime())) {
res.push(item)
defaultValueObj = item
if (new Date(lastDay).getTime() <= new Date(item.endTime).getTime()) {
defaultValueObj.endTime = lastDay
} else {
defaultValueObj.endTime = item.endTime
}
} else if (new Date(item.endTime).getTime() < new Date(lastDay).getTime()) {
res.push(item)
}
})
console.log('defaultValue', defaultValueObj);
console.log('res', res);
setTimeout(() => {
setCurrentFestivalObj(defaultValueObj)
setShowCurrentFestivalObj(defaultValueObj)
formRef.current?.setFieldsValue({
HolidayType: defaultValueObj.value,
CurStartDate: defaultValueObj.startTime,
StatisticsDate: defaultValueObj.endTime,
})
})
return res
},
// initialValue: "3",
fieldProps: {
onChange: (e) => {
console.log('e', e);
const lastDay: any = moment().subtract(1, 'd').format('YYYY-MM-DD')
let defaultValueObj: any = {}
festivalList.forEach((item: any) => {
if (item.value === e) {
defaultValueObj = item
}
})
if (new Date(lastDay).getTime() <= new Date(defaultValueObj.endTime).getTime()) {
defaultValueObj.endTime = lastDay
} else {
defaultValueObj.endTime = defaultValueObj.endTime
}
setTimeout(() => {
setCurrentFestivalObj(defaultValueObj)
formRef.current?.setFieldsValue({
HolidayType: defaultValueObj.value,
CurStartDate: defaultValueObj.startTime,
StatisticsDate: defaultValueObj.endTime,
})
})
// setFestivalType(e)
// if (e === "2") {
// formRef.current?.setFieldsValue({ CurStartDate: moment("2024-01-26") })
// if (new Date("2024-03-05").getTime() > new Date(moment().add(-1, "day").format('YYYY-MM-DD')).getTime()) {
// formRef.current?.setFieldsValue({ StatisticsDate: moment().add(-1, "day") })
// } else {
// formRef.current?.setFieldsValue({ StatisticsDate: moment("2024-03-05") })
// }
// } else if (e === "4") {
// formRef.current?.setFieldsValue({ CurStartDate: moment("2024-04-30") })
// if (new Date("2024-05-06").getTime() > new Date(moment().add(-1, "day").format('YYYY-MM-DD')).getTime()) {
// formRef.current?.setFieldsValue({ StatisticsDate: moment().add(-1, "day") })
// } else {
// formRef.current?.setFieldsValue({ StatisticsDate: moment("2024-05-06") })
// }
// } else {
// formRef.current?.setFieldsValue({ CurStartDate: moment("2024-04-03") })
// if (new Date("2024-04-07").getTime() > new Date(moment().add(-1, "day").format('YYYY-MM-DD')).getTime()) {
// formRef.current?.setFieldsValue({ StatisticsDate: moment().add(-1, "day") })
// } else {
// formRef.current?.setFieldsValue({ StatisticsDate: moment("2024-04-07") })
// }
// }
}
}
},
{
title: '开始日期',
dataIndex: 'CurStartDate',
aiDataIndex: "CurStartDate",
hideInTable: true,
valueType: 'date',
// initialValue: startTime || moment().subtract(1, 'days'),
// fieldProps: {
// disabledDate: festivalType === "2" ?
// (current: any) => current && !(current > moment('2024-01-25') && current < moment('2024-03-06')) :
// festivalType === "3" ?
// (current: any) => current && !(current > moment('2024-04-02') && current < moment('2024-04-08') && current < moment().add(1, "day")) :
// festivalType === "4" ?
// (current: any) => current && !(current > moment('2024-04-29') && current < moment('2024-05-07')) :
// (current: any) => current > moment()
// }
},
{
title: '截止日期',
dataIndex: 'StatisticsDate',
aiDataIndex: "StatisticsDate",
hideInTable: true,
valueType: 'date',
// initialValue: new Date(endTime).getTime() > new Date(moment().add(-1, "day").format('YYYY-MM-DD')).getTime() ? moment().add(-1, "day").format('YYYY-MM-DD') : endTime,
// fieldProps: {
// disabledDate: festivalType === "2" ?
// (current: any) => current && !(current > moment('2024-01-25') && current < moment('2024-03-06')) :
// festivalType === "3" ?
// (current: any) => current && !(current > moment('2024-04-02') && current < moment('2024-04-08') && current < moment().add(1, "day")) :
// festivalType === "4" ?
// (current: any) => current && !(current > moment('2024-04-29') && current < moment('2024-05-07')) :
// (current: any) => current > moment()
// }
},
// {
// title: '统计时间',
// dataIndex: 'STATISTICS_DATE',
// hideInTable: true,
// valueType: 'date',
// initialValue: moment(),
// fieldProps: {
// disabledDate: festivalType==="2"?
// (current: any) => current && !(current > moment('2024-01-26')&& current < moment('2024-03-25')):
// festivalType==="3"?(current: any) => current && !(current > moment('2024-04-03')&& current < moment('2024-04-07')&& current < moment().add(1,"day")):''
// }
// },
{
title: '对客销售',
dataIndex: 'RevenueINC',
aiDataIndex: "RevenueINC",
hideInSearch: true,
children: [
{
title: `${showCurrentFestivalObj?.curYear}`,
dataIndex: 'RevenueINCcur',
aiDataIndex: "RevenueINCcur",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.RevenueINCcur - b.RevenueINCcur,
hideInSearch: true,
},
{
title: `${showCurrentFestivalObj?.compareYear}`,
dataIndex: 'RevenueINClYear',
aiDataIndex: "RevenueINClYear",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.RevenueINClYear - b.RevenueINClYear,
hideInSearch: true
},
{
title: '增长',
dataIndex: 'RevenueINCcrease',
aiDataIndex: "RevenueINCcrease",
align: 'right',
valueType: 'digit',
hideInSearch: true,
sorter: (a, b) => a.RevenueINCcrease - b.RevenueINCcrease,
defaultSortOrder: 'descend',
},
{
title: '增幅',
dataIndex: 'RevenueINCRate',
aiDataIndex: "RevenueINCRate",
align: 'center',
hideInSearch: true,
sorter: (a, b) => a.RevenueINCRate - b.RevenueINCRate,
render: (_, record) => {
return <span style={{ color: record.RevenueINCRate > 0 ? '#e83944' : record.RevenueINCRate < 0 ? '#0e9976' : '' }}>
{record.RevenueINCRate > 0 ? '+' : record.RevenueINCRate < 0 ? '' : ''}
{record.RevenueINCRate ? `${record.RevenueINCRate}%` : ''}
</span>
}
}
]
},
{
title: '营业收入',
dataIndex: 'AccountINC',
aiDataIndex: "AccountINC",
hideInSearch: true,
children: [
{
title: `${showCurrentFestivalObj?.curYear}`,
dataIndex: 'AccountINCCcur',
aiDataIndex: "AccountINCCcur",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.AccountINCCcur - b.AccountINCCcur,
hideInSearch: true
},
{
title: `${showCurrentFestivalObj?.compareYear}`,
dataIndex: 'AccountINClYear',
aiDataIndex: "AccountINClYear",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.AccountINClYear - b.AccountINClYear,
hideInSearch: true
},
{
title: '增长',
dataIndex: 'AccountINCcrease',
aiDataIndex: "AccountINCcrease",
align: 'right',
valueType: 'digit',
hideInSearch: true,
sorter: (a, b) => a.AccountINCcrease - b.AccountINCcrease,
},
{
title: '增幅',
dataIndex: 'AccountINCRate',
aiDataIndex: "AccountINCRate",
align: 'center',
hideInSearch: true,
sorter: (a, b) => a.AccountINCRate - b.AccountINCRate,
render: (_, record) => {
return <span style={{ color: record.AccountINCRate > 0 ? '#e83944' : record.AccountINCRate < 0 ? '#0e9976' : '' }}>
{record.AccountINCRate > 0 ? '+' : record.AccountINCRate < 0 ? '' : ''}
{record.AccountINCRate ? `${record.AccountINCRate}%` : ''}
</span>
}
}
]
},
{
title: '入区车流',
dataIndex: 'BayonetINC',
aiDataIndex: "BayonetINC",
hideInSearch: true,
children: [
{
title: `${showCurrentFestivalObj?.curYear}`,
dataIndex: 'BayonetINCINCCcur',
aiDataIndex: "BayonetINCINCCcur",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.BayonetINCINCCcur - b.BayonetINCINCCcur,
hideInSearch: true
},
{
title: `${showCurrentFestivalObj?.compareYear}`,
dataIndex: 'BayonetINClYear',
aiDataIndex: "BayonetINClYear",
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.BayonetINClYear - b.BayonetINClYear,
hideInSearch: true
},
{
title: '增长',
dataIndex: 'BayonetINCcrease',
aiDataIndex: "BayonetINCcrease",
align: 'right',
valueType: 'digit',
hideInSearch: true,
sorter: (a, b) => a.BayonetINCcrease - b.BayonetINCcrease,
},
{
title: '增幅',
dataIndex: 'BayonetINCRate',
aiDataIndex: "BayonetINCRate",
align: 'center',
hideInSearch: true,
sorter: (a, b) => a.BayonetINCRate - b.BayonetINCRate,
render: (_, record) => {
return <span style={{ color: record.BayonetINCRate > 0 ? '#e83944' : record.BayonetINCRate < 0 ? '#0e9976' : '' }}>
{record.BayonetINCRate > 0 ? '+' : record.BayonetINCRate < 0 ? '' : ''}
{record.BayonetINCRate ? `${record.BayonetINCRate}%` : ''}
</span>
}
}
]
},
]
const exportColumns: any = [
{
title: '序号',
dataIndex: 'index',
key: 'index',
valueType: 'index',
align: 'center',
width: 70,
},
{
title: '服务区',
dataIndex: 'ServerpartName',
hideInSearch: true,
align: 'center',
render: (_, record) => {
return <a style={{ cursor: 'pointer' }} onClick={() => {
setCurrentRow(record)
setShowDetail(true)
formDetailRef.current?.setFieldsValue({ STATISTICS_DATE: searchDate })
}}>{record.ServerpartName.split('服务区')[0]}</a>
}
},
...columns.slice(5)
]
const detailColumns: any = [
// {
// dataIndex: 'DataType',
// // title: '统计方式',
// valueType: "radioButton",
// initialValue: activeKey?activeKey.toString():'1',
// // colSize: 1,
// // colSpan: 4,
// valueEnum: {
// 2: { text: '累计' },
// 1: { text: '当日' },
// },
// hideInTable: true,
// fieldProps: {
// onChange: (event: any) => {
// setActiveKey(event.target.value)
// formRef.current?.submit()
// },
// labelCol: { span: 3, offset: 24 },
// // wrapperCol: { span: 24 }
// },
//
// },
{
title: '序号',
dataIndex: 'index',
key: 'index',
valueType: 'index',
align: 'center',
width: 70,
},
{
title: '门店',
dataIndex: 'ServerpartShopName',
hideInSearch: true,
align: 'center',
width: 250,
ellipsis: true,
},
{
title: '开始日期',
dataIndex: 'CurStartDate',
hideInTable: true,
valueType: 'date',
initialValue: detailStartTime || moment().subtract(1, 'days'),
},
{
title: '截止日期',
dataIndex: 'StatisticsDate',
hideInTable: true,
valueType: 'date',
initialValue: detailEndTime || moment().subtract(1, 'days'),
},
{
title: '对客销售',
dataIndex: 'RevenueINC',
hideInSearch: true,
children: [
{
title: `${showCurrentFestivalObj?.curYear}`,
dataIndex: 'RevenueINCcur',
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.RevenueINCcur - b.RevenueINCcur,
hideInSearch: true
},
{
title: `${showCurrentFestivalObj?.compareYear}`,
dataIndex: 'RevenueINClYear',
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.RevenueINClYear - b.RevenueINClYear,
hideInSearch: true
},
{
title: '增长',
dataIndex: 'RevenueINCcrease',
align: 'right',
valueType: 'digit',
hideInSearch: true,
sorter: (a, b) => a.RevenueINCcrease - b.RevenueINCcrease,
defaultSortOrder: 'descend',
},
{
title: '增幅',
dataIndex: 'RevenueINCRate',
align: 'center',
hideInSearch: true,
sorter: (a, b) => a.RevenueINCRate - b.RevenueINCRate,
render: (_, record) => {
return <span style={{ color: record.RevenueINCRate > 0 ? '#e83944' : record.RevenueINCRate < 0 ? '#0e9976' : '' }}>
{record.RevenueINCRate > 0 ? '+' : record.RevenueINCRate < 0 ? '' : ''}
{record.RevenueINCRate ? `${record.RevenueINCRate}%` : ''}
</span>
}
}
]
},
{
title: '营业收入',
dataIndex: 'AccountINC',
hideInSearch: true,
children: [
{
title: `${showCurrentFestivalObj?.curYear}`,
dataIndex: 'AccountINCCcur',
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.AccountINCCcur - b.AccountINCCcur,
hideInSearch: true
},
{
title: `${showCurrentFestivalObj?.compareYear}`,
dataIndex: 'AccountINClYear',
align: 'right',
valueType: 'digit',
sorter: (a, b) => a.AccountINClYear - b.AccountINClYear,
hideInSearch: true
},
{
title: '增长',
dataIndex: 'AccountINCcrease',
align: 'right',
valueType: 'digit',
hideInSearch: true,
sorter: (a, b) => a.AccountINCcrease - b.AccountINCcrease,
},
{
title: '增幅',
dataIndex: 'AccountINCRate',
align: 'center',
hideInSearch: true,
sorter: (a, b) => a.AccountINCRate - b.AccountINCRate,
render: (_, record) => {
return <span style={{ color: record.AccountINCRate > 0 ? '#e83944' : record.AccountINCRate < 0 ? '#0e9976' : '' }}>
{record.AccountINCRate > 0 ? '+' : record.AccountINCRate < 0 ? '' : ''}
{record.AccountINCRate ? `${record.AccountINCRate}%` : ''}
</span>
}
}
]
},
]
const exportTable = (e) => {
e.stopPropagation(); // 防止Collapse组件收起
const hideDiv = document.getElementsByClassName('hideDiv')[0]
const antTableContent = hideDiv.getElementsByClassName('ant-table-content')[0]
const thead = antTableContent.querySelector('thead').cloneNode(true); // 深克隆DOM节点
const tbody = antTableContent.querySelector('tbody').cloneNode(true); // 深克隆DOM节点
const container = document.querySelector('#hiddenBox');
const tempTable = document.createElement('table'); // <table></table>
tempTable.appendChild(thead); // <table><thead></thead></table>
tempTable.appendChild(tbody);
tempTable.setAttribute('id', 'table-to-xls-SpringFestival'); // <table><thead></thead><tbody></tbody></table>
// if (activeKey === 1) {
// tempTable.setAttribute('id', 'table-to-xls-SpringFestival'); // 给table添加id值与按钮上的table字段对应
// } else {
// tempTable.setAttribute('id', 'table-to-xls1');
// }
container.appendChild(tempTable); // 把创建的节点添加到页面容器中
downloadBtnRef.current.handleDownload();
setShowExportTable(false)
tempTable.remove() // 防止重复打印一个内容
}
// 找到当前时间已经过了 但是最近的一项
const handleGetNearFestival = () => {
const currentTime = new Date(); // 获取当前时间
// 1. 过滤出所有已经开始的服务区startTime <= 当前时间)
const passedServices = festivalList.filter((service: any) => {
const startTime = new Date(service.startTime);
return startTime <= currentTime;
});
// 2. 按 startTime 降序排序(最近的排在最前面)
passedServices.sort((a: any, b: any) => {
const dateA: any = new Date(a.startTime);
const dateB: any = new Date(b.startTime);
return dateB - dateA; // 降序
});
// 3. 返回最近的一个(如果有的话)
console.log('passedServices', passedServices);
if (passedServices && passedServices.length > 0) {
const obj: any = passedServices[0]
console.log('obj', obj);
console.log('formRef', formRef);
setTimeout(() => {
setCurrentFestivalObj({ ...obj, HolidayType: obj?.value })
setShowCurrentFestivalObj({ ...obj, HolidayType: obj?.value })
formRef.current?.setFieldsValue({
HolidayType: obj?.value,
CurStartDate: obj?.startTime,
StatisticsDate: obj?.endTime,
})
}, 100)
}
return passedServices.length > 0 ? passedServices[0] : null;
}
const handleGetAIAnalysis = async () => {
if (!selectedId) {
message.error('请先选择服务区!')
return
}
if (!(tableData && tableData.length > 0)) {
clickTableBtnRef.current = true
formRef.current?.submit();
}
setShowAiDrawer(true)
}
useEffect(() => {
handleGetNearFestival()
}, [])
return (
<div className={'springFestivalBox'} style={{ background: '#fff', display: 'flex' }}>
<ProCard
className="pageTable-leftnav"
style={{ width: !collapsible ? "240px" : "60px" }}
headStyle={{ width: !collapsible ? "240px" : "60px" }}
bodyStyle={{ padding: 0, paddingTop: 20, paddingLeft: 20, width: !collapsible ? "240px" : "60px" }}
extra={<MenuFoldOutlined onClick={() => {
setCollapsible(!collapsible)
}} />}
colSpan={!collapsible ? "240px" : "60px"}
title={!collapsible ? "可筛选门店" : ""}
headerBordered
collapsed={collapsible}
>
{treeView && treeView.length > 0 ? <Tree
checkable
treeData={!treeLoading ? [{
label: '全部',
value: 0,
key: '0-0',
children: treeView
}] : []}
fieldNames={{
title: "label",
key: "key"
}}
blockNode
defaultExpandedKeys={['0-0']}
onCheck={(checkedKeys: React.Key[] | any, info) => {
const selectedIds = info.checkedNodes.filter(n => n?.type === 1)
setSelectedId(selectedIds.map(n => n?.value)?.toString() || '')
// actionRef?.current?.reload()
}}
/> : ''}
</ProCard>
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
<div className={'hideDiv'} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
{
showExportTable && reqDetailList && reqDetailList.length > 0 ?
<ProTable
columns={exportColumns}
dataSource={reqDetailList}
pagination={false}
expandable={{
defaultExpandAllRows: true
}}
>
</ProTable> : ''
}
</div>
<ProCard
style={{ width: !collapsible ? "calc(100% - 240px)" : "calc(100% - 60px)" }}
>
<ProTable
style={{ padding: 0 }}
formRef={formRef}
actionRef={actionRef}
search={{
span: 6,
labelWidth: 100,
defaultCollapsed: false,
optionRender: ({ searchText }, { form }) => {
return [
<Button
key="reset"
onClick={() => {
formRef.current?.resetFields();
}}
>
</Button>,
<Button
key="sub"
type={'primary'}
loading={tableLoading}
onClick={() => {
clickTableBtnRef.current = true
formRef.current?.submit();
}}
>
</Button>
]
}
}}
loading={tableLoading}
headerTitle={<PageTitleBox props={props} showAI={true} AIFun={handleGetAIAnalysis} />}
id={'table-to-xls'}
columns={columns}
bordered={true}
scroll={{ y: 'calc(100vh - 450px)' }}
pagination={false}
dataSource={tableData}
request={async (params) => {
console.log('params', params)
if (!selectedId) {
setReqDetailList([])
return
}
if (clickTableBtnRef.current) {
if (params.STATISTICS_DATE) {
setSearchDate(params.STATISTICS_DATE)
} else {
setReqDetailList([])
setSearchDate(undefined)
}
handleGetTableData(params)
}
// return {data: list || [], success: true,}
}}
toolbar={{
actions: [
<span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel
buttonText={'导出excel'}
ref={downloadBtnRef}
// table={activeKey === 1 ? 'table-to-xls0' : 'table-to-xls1'}
table="table-to-xls-SpringFestival"
filename={`${showCurrentFestivalObj?.label}营收分析_${moment(showCurrentFestivalObj?.startTime
).format('YYYY-MM-DD')}-${moment(showCurrentFestivalObj?.endTime).format('YYYY-MM-DD')}`}
sheet="sheet1"
/>
</span>,
<Button
key="new"
type="primary"
onClick={async (e) => {
if (reqDetailList && reqDetailList.length > 0) {
setTimeout(() => {
setShowExportTable(true)
setTimeout(() => {
exportTable(e)
}, 100)
}, 100)
} else {
message.error('暂无数据可导出!')
}
// const nowColumns = columns.filter(n => !n.hideInTable)
// const fat = nowColumns.map((n: any, index: number) => {
// if (n?.children) {
// return n?.children.map((m: { title: any; }) => {
// const title = index === 0 ? m.title : n.title + m.title
// return { ...m, title }
// })
// }
// return n
// })
// if (reqDetailList && reqDetailList.length>0){
// const list: any = JSON.parse(JSON.stringify(reqDetailList))
// list.forEach((item: any,index: number)=>{
// item.index = index + 1
// })
// const curDate = moment(formRef.current?.getFieldValue('STATISTICS_DATE')).format('YYYYMMDD')
// const success = await exportExcelReceivedSum(
// fat.flat(),
// list || [],
// `春运营收分析_${curDate}`,
// );
// if (success.message !== 'ok') {
// message.info({ content: success.message });
// }
// }else{
// message.error('暂无数据可导出!')
// }
}}
>
excel
</Button>
],
}}
/>
</ProCard >
<Drawer
width="80%"
visible={showDetail} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setShowDetail(false);
setCurrentRow(undefined)
}}
destroyOnClose
bodyStyle={{ backgroundColor: "#f9f9f9", padding: 0 }}
closable={false}
>
<ProTable
actionRef={actionDetailRef}
formRef={formDetailRef}
columns={detailColumns}
bordered={true}
// params={{ STATISTICS_DATE: searchDate || moment().subtract(1, 'days') }}
headerTitle={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}
strong>{currentRow ? currentRow.ServerpartName : ''}</Text>}
scroll={{ y: 'calc(100vh - 450px)' }}
pagination={false}
search={{
span: 8,
}}
request={async (params) => {
const req = {
calcType: 2,
pushProvinceCode: '340000',
curYear: showCurrentFestivalObj?.curYear,
compareYear: showCurrentFestivalObj?.compareYear,
HolidayType: showCurrentFestivalObj.HolidayType || '0',
StatisticsDate: detailEndTime ? moment(detailEndTime).format('YYYY-MM-DD') : '',
ServerpartId: currentRow.ServerpartId || '',
CurStartDate: detailStartTime ? moment(detailStartTime).format('YYYY-MM-DD') : ''
}
const data = await handleGetServerpartDetail(req)
console.log('data', data)
setSummaryInfo({
RevenueINC: data.RevenueINC,
AccountINC: data.AccountINC,
BayonetINC: data.BayonetINC,
})
const list: any = []
if (data.ShopINCList && data.ShopINCList.length > 0) {
data.ShopINCList.forEach((item: any) => {
list.push({
...item,
RevenueINCcur: item.RevenueINC?.curYearData,
RevenueINClYear: item.RevenueINC?.lYearData,
RevenueINCcrease: item.RevenueINC?.increaseData,
RevenueINCRate: item.RevenueINC?.increaseRate,
AccountINCCcur: item.AccountINC?.curYearData,
AccountINClYear: item.AccountINC?.lYearData,
AccountINCcrease: item.AccountINC?.increaseData,
AccountINCRate: item.AccountINC?.increaseRate,
})
})
}
console.log('list', list)
return { data: list || [], success: true, }
}}
tableExtraRender={
(_, data) => {
if (data) {
return <div style={{ paddingLeft: 24 }}>
<Row>
<Col span={24}>
<Descriptions
title={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}></Text>}
size="small" className="commity-sale-description" column={4}
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}
style={{ marginBottom: 16 }}
>
<Descriptions.Item
label={`${showCurrentFestivalObj?.curYear}`}>{numeral(summaryInfo?.RevenueINC?.curYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label={`${showCurrentFestivalObj?.compareYear}`}>{numeral(summaryInfo?.RevenueINC?.lYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增长">{numeral(summaryInfo?.RevenueINC?.increaseData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增幅">{`${summaryInfo?.RevenueINC?.increaseRate || '-'}%`}</Descriptions.Item>
</Descriptions>
{
summaryInfo?.AccountINC?.curYearData || summaryInfo?.AccountINC?.lYearData ||
summaryInfo?.AccountINC?.increaseData || summaryInfo?.AccountINC?.increaseRate ?
<Descriptions
title={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}></Text>}
size="small" className="commity-sale-description" column={4}
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}
style={{ marginBottom: 16 }}
>
<Descriptions.Item
label={`${showCurrentFestivalObj?.curYear}`}>{numeral(summaryInfo?.AccountINC?.curYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label={`${showCurrentFestivalObj?.compareYear}`}>{numeral(summaryInfo?.AccountINC?.lYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增长">{numeral(summaryInfo?.AccountINC?.increaseData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增幅">{`${summaryInfo?.AccountINC?.increaseRate || '-'}%`}</Descriptions.Item>
</Descriptions> : ''
}
<Descriptions
title={<Text type="success" style={{ color: "#1890ff", fontSize: 14 }}></Text>}
size="small" className="commity-sale-description" column={4}
contentStyle={{ fontWeight: "bolder" }} labelStyle={{ color: "#00000073" }}
style={{ marginBottom: 16 }}
>
<Descriptions.Item
label={`${showCurrentFestivalObj?.curYear}`}>{numeral(summaryInfo?.BayonetINC?.curYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label={`${showCurrentFestivalObj?.compareYear}`}>{numeral(summaryInfo?.BayonetINC?.lYearData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增长">{numeral(summaryInfo?.BayonetINC?.increaseData).format('0,0.00')}</Descriptions.Item>
<Descriptions.Item
label="增幅">{`${summaryInfo?.BayonetINC?.increaseRate || '-'}%`}</Descriptions.Item>
</Descriptions>
</Col>
</Row>
</div>
}
}
}
>
</ProTable>
</Drawer>
<AiDrawer showDrawer={showAiDrawer} setShowDrawer={setShowAiDrawer} selectedId={selectedId}
haveSearch={true} tableColumns={columns} searchParams={searchParams} props={props} tableData={tableData} />
</div >
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(SpringFestival);