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 { Drawer } from "antd"; import { Button, Spin } from "antd"; import { message, Space, Tree } from "antd"; import useRequest from "@ahooksjs/use-request"; import { getFieldEnum, getServerpartTree, handleCallLogs } from "@/services/options"; import type { ActionType } from "@ant-design/pro-table"; import ProTable from "@ant-design/pro-table"; import { handleGetExamineList } from "@/pages/examine/examineList/service"; import moment from "moment"; import { handleGetGetRevenueYOYQOQ, handleGetGetRevenueYOYQOQByDate, handleGetMOM } from "@/pages/reports/BusinessAnalysis/revenueYOYQOQReport/service"; import ReactHTMLTableToExcel from "react-html-table-to-excel"; import search from "@/pages/BussinessProject/search"; import session from "@/utils/session"; import { handleGetShopShortNames, handleGetShopShortNamesGet } from "@/pages/reports/BusinessAnalysis/transactionAnalysis/service"; import CarTrafficChart from "./components/CarTrafficChart"; import PageTitleBox from "@/components/PageTitleBox"; import { formatTreeData } from "@/utils/format"; import { exportXlsxFromProColumnsExcelJS } from "@/utils/exportExcelFun"; const revenueYOYQOQReport: React.FC<{ currentUser: CurrentUser }> = (props) => { const { currentUser } = props const downloadBtnRef = useRef() const actionRef = useRef(); const actionByDateRef = useRef(); const formRef = useRef(); const formByDateRef = useRef(); const [reqDetailList, setReqDetailList] = useState(); // 合计项数据源 const [printOut, setPrintOut] = useState(); // 打印数据的内容 const [collapsible, setCollapsible] = useState(false) const [treeView, setTreeView] = useState() // 查询的条件 const [searchParams, setSearchParams] = useState() // 加载服务区树 const { loading: treeLoading, data: treeViews } = useRequest(async () => { const data = await getServerpartTree(currentUser?.ProvinceCode, currentUser?.CityAuthority, true, true, true) setTreeView(data) return data }) // 导出的加载效果 const [showLoading, setShowLoading] = useState(false) // 是否显示打印的表格 const [showExportTable, setShowExportTable] = useState(false) // 树相关的属性和方法 const [selectedId, setSelectedId] = useState() // 第一次进来默认的表格方法不调用 const [isFirst, setIsFirst] = useState(true) const businessTypeObj = session.get("BUSINESSTYPEObj") const [columnsStateMap, setColumnsStateMap] = useState({ // Business_Type:{show:false}, ShopTrade: { show: false } }) const [columnsDailyStateMap, setColumnsDailyStateMap] = useState({ MERCHANTS_NAME: { show: false }, ShopTrade: { show: false } }) // 展示自营业态 const [showSelfBusiness, setShowSelfBusiness] = useState(true) // 自营业态的选择列表 const [shopNamesList, setShopNamesList] = useState() // 显示每日流水抽屉 const [showDailyDrawer, setShowDailyDrawer] = useState(false) const [currentRow, setCurrentRow] = useState() const [printIndex, setPrintIndex] = useState(new Date().getTime()) const SHOPTRADEObj = session.get('SHOPTRADEObj') // 实收金额数据 const [amountReceivedData, setAmountReceivedData] = useState() // 销售数量数据 const [salesQuantityData, setSalesQuantityData] = useState() // 客单数量数据 const [customerOrdersData, setCustomerOrdersData] = useState() const BUSINESSTYPEObj = session.get('BUSINESSTYPEObj') const columns: any = [ // { // title: '序号', // dataIndex: 'index', // valueType: 'index', // hideInSearch: true, // fixed: 'left', // width: 140, // }, { title: '服务区名称', width: 170, dataIndex: 'Name', fixed: 'left', ellipsis: true, align: 'center', hideInSearch: true, render: (_, record) => { return showDailyDrawer ? record?.Name : { console.log('record', record) if (moment(searchParams?.StartDate).format('YYYY-MM-DD') !== moment(searchParams?.EndDate).format('YYYY-MM-DD')) { if (record?.Name === '合计') { let id: string = '' if (record?.children && record?.children.length > 0) { record?.children.forEach((item: any) => { if (item?.children && item?.children.length > 0) { item?.children.forEach((subItem: any) => { if (id) { id += `,${subItem.Id}` } else { id = subItem.Id } }) } }) } setCurrentRow({ ...record, Id: id }) } else if (record?.Name && record?.Name.indexOf('管理中心') !== -1) { let id: string = '' if (record?.children && record?.children.length > 0) { record?.children.forEach((item: any) => { if (id) { id += `,${item.Id}` } else { id = item.Id } }) } setCurrentRow({ ...record, Id: id }) } else { setCurrentRow(record) } setShowDailyDrawer(true) } }}>{record?.Name} } }, { title: '经营商户', width: 120, ellipsis: true, align: 'center', dataIndex: 'MERCHANTS_NAME', hideInSearch: true, }, { dataIndex: 'ShowShop', title: '统计类型', valueType: "select", hideInTable: true, valueEnum: { 1: '门店', 0: '服务区', 2: '日度' }, initialValue: '1', }, // { // dataIndex: 'ShowShop', // title:'统计类型', // valueType: "radioButton", // fixed: true, // initialValue: '1', // valueEnum: { // 1: '门店', // 0: '服务区' // }, // hideInTable: true, // fieldProps: { // onChange: (event: any) => { // formRef.current?.submit() // }, // labelCol: { span: 0 }, // wrapperCol: { span: 24 } // }, // }, { title: '统计时间', dataIndex: 'search_date', valueType: 'dateRange', hideInTable: true, hideInDescriptions: true, initialValue: [moment().subtract(1, 'months'), moment().add(-1, 'day')], search: { transform: (value) => { return { StartDate: value[0], EndDate: value[1], }; }, }, fieldProps: { disabledDate: (current: any) => current && current > moment().endOf('day') } }, { title: '经营模式', dataIndex: 'businessType', valueType: 'select', hideInTable: true, valueEnum: BUSINESSTYPEObj, fieldProps: { mode: "multiple", onChange: async (e) => { console.log('e', e) const flag = e.filter(item => item === '1000')?.toString() || '' console.log('flag', flag) if (flag) { setShowSelfBusiness(false) // handleGetShopNamesList(selectedId) } else { setShowSelfBusiness(true) // setShopNamesList({}) } } } }, { title: '自营业态', dataIndex: 'shopNames', hideInTable: true, hideInSearch: showSelfBusiness, valueType: 'select', valueEnum: shopNamesList, // request: async () => { // return await getFieldEnum({ FieldExplainField: 'BUSINESSTYPE' }) // }, fieldProps: { multiple: true, showSearch: true, filterOption: (input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase()), } }, { title: '外接系统', dataIndex: 'targetSystem', valueType: 'select', hideInTable: true, valueEnum: { "": '全部', 1: "是", 0: "否" }, initialValue: "" }, { title: '', dataIndex: 'SearchKeyValue', hideInTable: true, fieldProps: { placeholder: "请输入商户/品牌/门店/服务区" } }, { dataIndex: 'ShopTrade', title: '商品业态', align: 'center', width: 120, valueType: 'select', hideInSearch: true, request: async () => { // 这里要手动添加枚举字段(从下面这些字典中选择一个):商品业态[BUSINESSTYPE] const options = await getFieldEnum({ FieldExplainField: 'BUSINESSTYPE' }); return options; }, }, { title: '实收金额', dataIndex: '', hideInSearch: true, children: [ { title:
本期
, width: 120, dataIndex: 'CASHPAY_CURR', hideInSearch: true, valueType: 'digit', align: 'right', sorter: (a, b) => a.CASHPAY_CURR - b.CASHPAY_CURR, defaultSortOrder: 'descend', }, { title:
环比
, width: 120, dataIndex: 'CASHPAY_MONTH', align: 'right', hideInSearch: true, valueType: 'digit' }, { title:
同比
, width: 120, dataIndex: 'CASHPAY_YEAR', valueType: 'digit', align: 'right', hideInSearch: true }, { title:
环比率
, width: 120, dataIndex: 'MOM_YEARASHPAY_MONTH', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_YEARASHPAY_MONTH ? `${record?.MOM_YEARASHPAY_MONTH}%` : '-' } }, { title:
同比率
, width: 120, dataIndex: 'MOM_YEARASHPAY_YEAR', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_YEARASHPAY_YEAR ? `${record?.MOM_YEARASHPAY_YEAR}%` : '-' } }, ] }, { title: '销售数量', dataIndex: '', hideInSearch: true, children: [ { title:
本期
, width: 120, dataIndex: 'TOTALCOUNT_CURR', valueType: 'digit', align: 'right', hideInSearch: true }, { title:
环比
, width: 120, dataIndex: 'TOTALCOUNT_MONTH', valueType: 'digit', align: 'right', hideInSearch: true }, { title:
同比
, width: 120, dataIndex: 'TOTALCOUNT_YEAR', valueType: 'digit', align: 'right', hideInSearch: true, }, { title:
环比率
, width: 120, dataIndex: 'MOM_TOTALCOUNT_MONTH', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_TOTALCOUNT_MONTH ? `${record?.MOM_TOTALCOUNT_MONTH}%` : '-' } }, { title:
同比率
, width: 120, dataIndex: 'MOM_TOTALCOUNT_YEAR', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_TOTALCOUNT_YEAR ? `${record?.MOM_TOTALCOUNT_YEAR}%` : '-' } }, ] }, { title: '客单数量', dataIndex: '', hideInSearch: true, children: [ { title:
本期
, width: 120, dataIndex: 'TICKETCOUNT_CURR', valueType: 'digit', align: 'right', hideInSearch: true }, { title:
环比
, width: 120, dataIndex: 'TICKETCOUNT_MONTH', valueType: 'digit', align: 'right', hideInSearch: true }, { title:
同比
, width: 120, dataIndex: 'TICKETCOUNT_YEAR', valueType: 'digit', align: 'right', hideInSearch: true, }, { title:
环比率
, width: 120, dataIndex: 'MOM_TICKETCOUNT_MONTH', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_TICKETCOUNT_MONTH ? `${record?.MOM_TICKETCOUNT_MONTH}%` : '-' } }, { title:
同比率
, width: 120, dataIndex: 'MOM_TICKETCOUNT_YEAR', hideInSearch: true, align: 'right', render: (_, record) => { return record?.MOM_TICKETCOUNT_YEAR ? `${record?.MOM_TICKETCOUNT_YEAR}%` : '-' } } ] }, ] // 导出excel方法 const exportTable = (e) => { e.stopPropagation(); // 防止Collapse组件收起 const main = document.getElementsByClassName(`revenueYOYQOQReportHideBox${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-revenueYOYQOQReport'); // 给table添加id,值与按钮上的table字段对应 container.appendChild(tempTable); // 把创建的节点添加到页面容器中 setShowLoading(false) downloadBtnRef.current.handleDownload(); setShowExportTable(false) tempTable.remove() // 防止重复打印一个内容 } // 自营业态的选择的列表方法 const handleGetShopNamesList = async (id: any) => { const req: any = { ProvinceCode: currentUser?.USER_PROVINCE, BusinessType: 1000, ServerpartId: id || selectedId } const data = await handleGetShopShortNamesGet(req) console.log('data', data) if (data && data.length > 0) { const obj: any = {} if (data && data.length > 0) { data.forEach((item: any) => { obj[item] = item }) } setShopNamesList(obj) } } return (
{ // 打印报表 if (!reqDetailList || reqDetailList.length === 0) return; setPrintOut(el); }}> { showLoading ?
数据导出中...
: '' }
{ showExportTable && reqDetailList && reqDetailList.length > 0 ? : '' }
{ setCollapsible(!collapsible) }} />} colSpan={!collapsible ? "300px" : "60px"} title={!collapsible ? "请选择服务区" : ""} headerBordered collapsed={collapsible} > {treeView && treeView.length > 0 ? { const selectedIds = info.checkedNodes.filter(n => n?.type === 1) setSelectedId(selectedIds.map(n => n?.value)?.toString() || '') handleGetShopNamesList(selectedIds.map(n => n?.value)?.toString() || '') // actionRef?.current?.reload() // getData(selectedIds.map(n => n?.value)?.toString() || '') }} // switcherIcon={} /> : ''}
{ return `${record?.index}-${record?.Id}-${record?.Name}-${record?.SERVERPART_ID}` }} columns={columns} bordered search={{ span: 6, defaultCollapsed: false, }} scroll={{ x: 1700, y: 'calc(100vh - 470px)' }} headerTitle={} request={async (params) => { if (isFirst) { setIsFirst(false) return } if (!selectedId) { message.error('请选择服务区') return } setSearchParams(params) handleCallLogs() const req = { ServerpartIds: selectedId || '', startDate: params?.StartDate, endDate: params?.EndDate, businessType: params?.businessType || '',// 经营模式 ShowShop: params.ShowShop === '1', targetSystem: params.targetSystem || '', shopNames: params.shopNames || '', SearchKeyName: "MerchantName,Brand,Shop,Serverpart", SearchKeyValue: params?.SearchKeyValue || '' } const data = await handleGetGetRevenueYOYQOQ(req) console.log('data', data) let list: any = [] if (data && data.length > 0) { list = JSON.parse(JSON.stringify(data)) list.forEach((item: any, index: number) => { item.index = index + 1 // CASHPAY_CURRSUM+=item.CASHPAY_CURR // CASHPAY_MONTHSUM+=item.CASHPAY_MONTH // CASHPAY_YEARSUM+=item.CASHPAY_YEAR // // TOTALCOUNT_CURRSUM+=item.TOTALCOUNT_CURR // TOTALCOUNT_MONTHSUM+=item.TOTALCOUNT_MONTH // TOTALCOUNT_YEARSUM+=item.TOTALCOUNT_YEAR // // TICKETCOUNT_CURRSUM+=item.TICKETCOUNT_CURR // TICKETCOUNT_MONTHSUM+=item.TICKETCOUNT_MONTH // TICKETCOUNT_YEARSUM+=item.TICKETCOUNT_YEAR if (item.children && item.children.length > 0) { item.children.forEach((subItem: any, subIndex: number) => { subItem.index = subIndex + 1 if (subItem.children && subItem.children.length > 0) { subItem.children.forEach((thirdItem: any, thirdIndex: number) => { thirdItem.index = thirdIndex + 1 if (thirdItem.children && thirdItem.children.length > 0) { thirdItem.children.forEach((fourthItem: any, fourthIndex: number) => { fourthItem.index = fourthIndex + 1 }) } }) } }) } }) } let fieldData: any = [ "CASHPAY_CURR", "CASHPAY_MONTH", "CASHPAY_YEAR", "TOTALCOUNT_CURR", "TOTALCOUNT_MONTH", "TOTALCOUNT_YEAR", "TICKETCOUNT_CURR", "TICKETCOUNT_MONTH", "TICKETCOUNT_YEAR", ] let enumList: any = ["ShopTrade"] let newPrintData: any = formatTreeData(JSON.parse(JSON.stringify(list)), fieldData, enumList, [SHOPTRADEObj], ["MOM_YEARASHPAY_MONTH", "MOM_YEARASHPAY_YEAR", "MOM_TOTALCOUNT_MONTH", "MOM_TOTALCOUNT_YEAR", "MOM_TICKETCOUNT_MONTH", "MOM_TICKETCOUNT_YEAR"]) setReqDetailList(newPrintData) return { data: list, success: true } }} pagination={false} toolbar={{ actions: [ // // // , ] }} columnsState={{ value: columnsStateMap, onChange: setColumnsStateMap, }} />
{ setCurrentRow(undefined); setShowDailyDrawer(false); }} bodyStyle={{ backgroundColor: "#f9f9f9", padding: 16 }} destroyOnClose closable={false} >
{/* { */} {/* amountReceivedData && amountReceivedData.length>0? */} {/* */} {/* :'' */} {/* } */} {/* { */} {/* salesQuantityData && salesQuantityData.length>0? */} {/* */} {/* :'' */} {/* } */} {/* { */} {/* customerOrdersData && customerOrdersData.length>0? */} {/* */} {/* :'' */} {/* } */} { return `${record?.index}-${record?.Id}-${record?.Name}-${record?.SERVERPART_ID}` }} columns={columns} bordered search={false} options={false} pagination={false} headerTitle={currentRow?.Name === '合计' ? '合计' : `${currentRow?.SPREGIONTYPE_NAME}${currentRow?.SERVERPART_NAME ? `-${currentRow?.SERVERPART_NAME}` : ''}${currentRow?.SHOPNAME ? `-${currentRow?.SHOPNAME}` : ''}`} request={async (params) => { console.log('currentRow', currentRow) const req = { ServerpartIds: currentRow?.SHOPID ? '' : currentRow?.Id, ServerpartShopId: currentRow?.SHOPID ? currentRow?.SHOPID : '', startDate: searchParams?.StartDate, endDate: searchParams?.EndDate, businessType: searchParams?.businessType || '',// 经营模式 // ShowShop: searchParams.ShowShop==='1', targetSystem: searchParams.targetSystem || '', shopNames: searchParams.shopNames || '', SearchKeyName: "MerchantName,Brand,Shop,Serverpart", SearchKeyValue: searchParams?.SearchKeyValue || '' } const data = await handleGetGetRevenueYOYQOQByDate(req) console.log('data22222', data) if (data && data.length > 0) { // 实收金额数组 const amountReceivedList: any = [] // 销售数量数组 const salesQuantity: any = [] // 客单数量数组 const customerOrders: any = [] data.forEach((item: any) => { if (item.children && item.children.length > 0) { item.children.forEach((subItem: any) => { amountReceivedList.push({ time: subItem.Name, value: subItem.CASHPAY_CURR, category: '本期实收金额' }) amountReceivedList.push({ time: subItem.Name, value: subItem.CASHPAY_MONTH, category: '本期环比' }) amountReceivedList.push({ time: subItem.Name, value: subItem.CASHPAY_YEAR, category: '本期同比' }) salesQuantity.push({ time: subItem.Name, value: subItem.TOTALCOUNT_CURR, category: '本期销售数量' }) salesQuantity.push({ time: subItem.Name, value: subItem.TOTALCOUNT_MONTH, category: '本期环比' }) salesQuantity.push({ time: subItem.Name, value: subItem.TOTALCOUNT_YEAR, category: '本期同比' }) customerOrders.push({ time: subItem.Name, value: subItem.TICKETCOUNT_CURR, category: '本期客单数量' }) customerOrders.push({ time: subItem.Name, value: subItem.TICKETCOUNT_MONTH, category: '本期环比' }) customerOrders.push({ time: subItem.Name, value: subItem.TICKETCOUNT_YEAR, category: '本期同比' }) }) } }) setAmountReceivedData(amountReceivedList) setSalesQuantityData(salesQuantity) setCustomerOrdersData(customerOrders) return { data, success: true } } return { data: [], success: true } }} scroll={{ x: 1700 }} columnsState={{ value: columnsDailyStateMap, onChange: setColumnsDailyStateMap, }} />
) } export default connect(({ user }: ConnectState) => ({ currentUser: user.currentUser }))(revenueYOYQOQReport);