542 lines
25 KiB
TypeScript
542 lines
25 KiB
TypeScript
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);
|