ylj20011123 cee81d5037 update
2025-09-23 19:14:35 +08:00

542 lines
25 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 { connect } from "umi";
import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect";
import React, { 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 ReactHTMLTableToExcel from "react-html-table-to-excel";
import LeftSelectTree from "@/pages/reports/settlementAccount/component/leftSelectTree";
import moment from 'moment'
import session from "@/utils/session";
import { handleCorrectShopCigarette, handleGetCigaretteReport } from "../../Finance/service";
import { formatTreeData, handleGetSumRow } from "@/utils/format";
import PageTitleBox from "@/components/PageTitleBox";
import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun";
const cigaretteReport: 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 [btnLoading, setBtnLoading] = useState<boolean>(false)
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
// 导出的加载效果
const [showLoading, setShowLoading] = useState<boolean>(false)
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
// 查询的条件
const [searchParams, setSearchParams] = useState<any>()
const serverpartObj: any = session.get('serverpartObj')
const [columnsStateMap, setColumnsStateMap] = useState<any>({
sumDifferent_Price_More: { show: false },
sumDifferent_Price_Less: { show: false },
ADifferent_Price_More: { show: false },
ADifferent_Price_Less: { show: false },
BDifferent_Price_More: { show: false },
BDifferent_Price_Less: { show: false },
sumCashPay_Amount: { show: false },
sumMobilePay_Amount: { show: false },
ACashPay_Amount: { show: false },
AMobilePay_Amount: { show: false },
BCashPay_Amount: { show: false },
BMobilePay_Amount: { show: false },
});
const columns: any = [
{
title: '服务区',
dataIndex: 'ServerpartIds',
valueType: 'select',
hideInTable: true,
// valueEnum: serverpartObj,
request: () => {
const serverpartList: any = session.get('serverpartList')
return serverpartList
},
fieldProps: {
showSearch: true,
filterOption: (input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase()),
}
},
{
title: '统计时间',
dataIndex: 'search_date',
valueType: 'dateRange',
hideInTable: true,
hideInDescriptions: true,
search: {
transform: (value) => {
return {
// format中的格式决定入参内容
StartDate: value[0],
EndDate: value[1],
};
},
},
initialValue: [moment().subtract(1, 'day').startOf('month'), moment().subtract(1, 'day')],
fieldProps: {
disabledDate: (current: any) => current > moment().subtract(1, 'days'),
allowClear: false
},
},
{
title: '统计类型',
dataIndex: 'DataSourceType',
valueType: 'select',
hideInTable: true,
valueEnum: {
"1": '日结',
"2": "自然日"
},
initialValue: "2",
},
{
title: '统计日期',
width: 150,
dataIndex: 'Statistics_Date',
hideInSearch: true,
align: 'center',
sorter: (a, b) => new Date(a.Statistics_Date).getTime() - new Date(b.Statistics_Date).getTime(),
defaultSortOrder: 'descend'
},
{
title: '合计',
dataIndex: 'sum',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumRevenue_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumCigarette_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumDifferent_Price_More',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumDifferent_Price_Less',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumCashPay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'sumMobilePay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
]
},
{
title: <div style={{ textAlign: 'center' }}>{currentUser?.ProvinceCode === '340000' ? '东(南)区' : 'A区'}</div>,
dataIndex: 'ARevenue',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'ARevenue_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'ACigarette_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'ADifferent_Price_More',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'ADifferent_Price_Less',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'ACashPay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'AMobilePay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
]
},
{
title: <div style={{ textAlign: 'center' }}>{currentUser?.ProvinceCode === '340000' ? '西(北)区' : 'B区'}</div>,
dataIndex: 'BRevenue',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BRevenue_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BCigarette_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BDifferent_Price_More',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BDifferent_Price_Less',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BCashPay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 120,
dataIndex: 'BMobilePay_Amount',
hideInSearch: true,
valueType: 'digit',
align: 'right'
},
]
}
]
const exportTable = (e) => {
e.stopPropagation(); // 防止Collapse组件收起
const main = document.getElementsByClassName(`saleReportHideBox${printIndex}`)[0]
const thead = main.querySelector('thead').cloneNode(true); // 深克隆DOM节点
const tbody = main.querySelector('tbody').cloneNode(true); // 深克隆DOM节点
const container = document.querySelector('#hiddenBox');
const tempTable = document.createElement('table');
tempTable.appendChild(thead);
tempTable.appendChild(tbody);
tempTable.setAttribute('id', 'table-to-xls-cigaretteReport'); // 给table添加id值与按钮上的table字段对应
container.appendChild(tempTable); // 把创建的节点添加到页面容器中
setShowLoading(false)
downloadBtnRef.current.handleDownload();
setShowExportTable(false)
tempTable.remove() // 防止重复打印一个内容
}
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 className={`saleReportHideBox${printIndex}`} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
{
showExportTable && reqDetailList && reqDetailList.length > 0 ?
<ProTable
columns={columns}
dataSource={reqDetailList}
pagination={false}
expandable={{
defaultExpandAllRows: true
}}
/> : ''
}
</div>
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<div style={{
width: '100%',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true
}}
scroll={{ x: 'max-content', y: 'calc(100vh - 470px)' }}
headerTitle={<PageTitleBox props={props} />}
search={{ span: 6 }}
request={async (params) => {
if (!params?.ServerpartIds) {
return
}
const req: any = {
DataSourceType: params?.DataSourceType || '',
StartDate: params?.StartDate ? moment(params?.StartDate).format('YYYY-MM-DD') : '',
EndDate: params?.EndDate ? moment(params?.EndDate).format('YYYY-MM-DD') : '',
ServerpartIds: params?.ServerpartIds
}
setSearchParams(params)
const data = await handleGetCigaretteReport(req)
if (data && data.length > 0) {
let res: any = []
data.forEach((item: any) => {
if (item.TotalRevenue) {
item.sumCigarette_Amount = item.TotalRevenue.Cigarette_Amount
item.sumDifferent_Price_More = item.TotalRevenue.Different_Price_More
item.sumDifferent_Price_Less = item.TotalRevenue.Different_Price_Less
item.sumCashPay_Amount = item.TotalRevenue.CashPay_Amount
item.sumMobilePay_Amount = item.TotalRevenue.MobilePay_Amount
item.sumRevenue_Amount = item.TotalRevenue.Revenue_Amount
}
if (item.RegionARevenue) {
item.ACigarette_Amount = item.RegionARevenue.Cigarette_Amount
item.ADifferent_Price_More = item.RegionARevenue.Different_Price_More
item.ADifferent_Price_Less = item.RegionARevenue.Different_Price_Less
item.ACashPay_Amount = item.RegionARevenue.CashPay_Amount
item.AMobilePay_Amount = item.RegionARevenue.MobilePay_Amount
item.ARevenue_Amount = item.RegionARevenue.Revenue_Amount
}
if (item.RegionBRevenue) {
item.BCigarette_Amount = item.RegionBRevenue.Cigarette_Amount
item.BDifferent_Price_More = item.RegionBRevenue.Different_Price_More
item.BDifferent_Price_Less = item.RegionBRevenue.Different_Price_Less
item.BCashPay_Amount = item.RegionBRevenue.CashPay_Amount
item.BMobilePay_Amount = item.RegionBRevenue.MobilePay_Amount
item.BRevenue_Amount = item.RegionBRevenue.Revenue_Amount
}
res.push(item)
})
let result: any = handleGetSumRow(res, ['sumRevenue_Amount', 'sumCigarette_Amount', 'sumDifferent_Price_More', 'sumDifferent_Price_Less', 'sumCashPay_Amount', 'sumMobilePay_Amount', 'ARevenue_Amount', 'ACigarette_Amount', 'ADifferent_Price_More', 'ADifferent_Price_Less', 'ACashPay_Amount', 'AMobilePay_Amount', 'BRevenue_Amount', 'BCigarette_Amount', 'BDifferent_Price_More', 'BDifferent_Price_Less', 'BCashPay_Amount', 'BMobilePay_Amount'], 'Statistics_Date')
let fieldData: any = [
"sumRevenue_Amount",
"sumCigarette_Amount",
"sumDifferent_Price_More",
"sumDifferent_Price_Less",
"sumCashPay_Amount",
"sumMobilePay_Amount",
"ARevenue_Amount",
"ACigarette_Amount",
"ADifferent_Price_More",
"ADifferent_Price_Less",
"ACashPay_Amount",
"AMobilePay_Amount",
"BRevenue_Amount",
"BCigarette_Amount",
"BDifferent_Price_More",
"BDifferent_Price_Less",
"BCashPay_Amount",
"BMobilePay_Amount",
]
let enumList: any = []
let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(result)), fieldData, enumList, [], [])
setReqDetailList(newPrintData)
return { data: result, success: true }
}
setReqDetailList([])
return { data: [], success: true }
}}
toolbar={{
actions: [
// <span style={{ visibility: 'hidden' }}>
// <ReactHTMLTableToExcel
// buttonText={'导出excel'}
// ref={downloadBtnRef}
// table="table-to-xls-cigaretteReport"
// filename={`香烟报表${searchParams?.StartDate}-${searchParams?.EndDate}`}
// sheet="sheet1"
// />
// </span>,
<Button type="primary" loading={btnLoading} onClick={async (e) => {
if (!searchParams?.ServerpartIds) {
message.error('请选择服务区!')
}
let day: any = moment(searchParams?.EndDate).diff(searchParams?.StartDate, 'd') + 1
console.log('day', day);
if (day > 30) {
message.error('选择时间不能超过30天')
return
}
const req: any = {
ServerpartShopId: searchParams?.ServerpartIds,
StartDate: searchParams?.StartDate,
EndDate: searchParams?.EndDate,
UserName: currentUser?.Name
}
setBtnLoading(true)
const data = await handleCorrectShopCigarette(req)
setBtnLoading(false)
console.log('data', data);
if (data.Result_Code === 100) {
message.success('重新生成成功!')
actionRef.current?.reload()
} else {
message.error(data.Result_Desc)
}
}}>
</Button>,
<Button
key="new"
type="primary"
onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) {
// 尝试一下 导出新方法
exportXlsxFromProColumnsExcelJS(columns,
reqDetailList,
`香烟营收报表${searchParams?.StartDate}-${searchParams?.EndDate}`,
// {
// topTitle: `单品销售排行统计`, // 顶部大标题
// }
)
} else {
message.error('暂无数据可导出!')
}
// if (reqDetailList && reqDetailList.length > 0) {
// setShowLoading(true)
// setTimeout(() => {
// setShowExportTable(true)
// setTimeout(() => {
// exportTable(e)
// }, 100)
// }, 100)
// } else {
// message.error('暂无数据可导出!')
// }
}}
>
excel
</Button>
]
}}
columnsState={{
value: columnsStateMap,
onChange: setColumnsStateMap,
}}
/>
</div>
</div>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(cigaretteReport);