/* * @Author: cclu 1106109051@qq.com * @Date: 2024-07-09 09:27:10 * @LastEditors: cclu 1106109051@qq.com * @LastEditTime: 2025-03-31 14:50:08 * @FilePath: \cloud-platform\src\pages\newDataAnalysis\vehicleOwner\index.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ 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, Tooltip } 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 { handleGetBayonetOwnerAHTreeList } from "../service"; import moment from 'moment/moment' import numeral from 'numeral' import pageData from './data' import AreaVehicle from "../areaVehicle"; import './style.less' import session from "@/utils/session"; import PageTitleBox from "@/components/PageTitleBox"; import AiDrawer from "@/components/AiDrawer"; import { handleChangeKeyTo, handleSetPublicLog } from "@/utils/format"; const vehicleOwner: React.FC<{ currentUser: CurrentUser }> = (props) => { const { currentUser, route } = props const downloadBtnRef = useRef() const actionRef = useRef(); const formRef = useRef(); const [reqDetailList, setReqDetailList] = useState(); // 合计项数据源 const [printOut, setPrintOut] = useState(); // 打印数据的内容 const [collapsible, setCollapsible] = useState(false) const [treeView, setTreeView] = useState() const [printIndex, setPrintIndex] = useState(new Date().getTime()) const [expandedRowKeys, setExpandedRowKeys] = useState(['null-null-undefined-undefined-undefined-undefined-null']) // 表格单行columns的展开行 const [columnsLoading, setColumnsLoading] = useState(false) // 树相关的属性和方法 const [selectedId, setSelectedId] = useState() // 导出的加载效果 const [showLoading, setShowLoading] = useState(false) // 是否显示打印的表格 const [showExportTable, setShowExportTable] = useState(false) // 表格的加载 const [tableLoading, setTableLoading] = useState(false) // 表格的加载文字 const [loadingText, setLoadingText] = useState() // 拿到点击行的数据 const [currentRow, setCurrentRow] = useState() // 显示详情抽屉 const [showDetail, setShowDetail] = useState(false) // 查询的条件 const [searchParams, setSearchParams] = useState() // 表格数据 const [tableData, setTableData] = useState() // 判断打印数据是否已经准备好了 const [isExportOk, setIsExportOk] = useState(true) // ai的抽屉 const [showAiDrawer, setShowAiDrawer] = useState(false) const paramsSort: any = { dataType: "统计类型", serverPartId: "服务区内码", statisticsStartMonth: "开始日期", statisticsEndMonth: "结束日期", rankNum: "省份或城市top", isSync: "是否异步执行" } // 拿到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 '' }) // 修改columns注意要适配 exportColumns 从合计开始 列要跟那边统一 const columns: any = [ { title: '统计时间', dataIndex: 'search_date', aiDataIndex: 'statisticsStartDate|statisticsEndDate', valueType: 'dateRange', hideInTable: true, hideInDescriptions: true, hideInSearch: false, initialValue: [moment().subtract(1, 'month'), moment().subtract(1, 'month')], search: { transform: (value: any) => { return { statisticsStartDate: value[0], statisticsEndDate: value[1], }; }, }, fieldProps: { disabledDate: (current: any) => current && !(current > moment().startOf('year') && current < moment().endOf('day').add(-1, 'day')), format: 'YYYY-MM', picker: "month", } }, { title:
{'中心/服务区'}
, dataIndex: 'ServerPartName', aiDataIndex: 'ServerPartName', aiTitle: "中心/服务区", hideInDescriptions: true, hideInSearch: true, fixed: 'left', width: 200, render: (_, record) => { return record?.ServerPartLevel === 0 ? { setCurrentRow({ ...record, startTime: searchParams?.statisticsStartDate, endTime: searchParams?.statisticsEndDate }) console.log('record', { ...record, startTime: searchParams?.statisticsStartDate, endTime: searchParams?.statisticsEndDate }); setShowDetail(true) }}>{record?.ProvinceName || record?.ServerPartName || record?.SPRegionTypeNAME || ''} : {record?.ProvinceName || record?.ServerPartName || record?.SPRegionTypeNAME || ''} } }, { title:
{'排行'}
, dataIndex: 'rankNum', aiDataIndex: 'rankNum', aiTitle: "排行", hideInDescriptions: true, hideInTable: true, valueType: 'select', valueEnum: { "5": 5, "10": 10, '': '全部' }, initialValue: "5", }, { title:
合计
, dataIndex: 'allSum', aiDataIndex: 'allSum', aiTitle: "合计", hideInDescriptions: true, hideInSearch: true, children: [ { title:
总量
, dataIndex: 'TotalCount', aiDataIndex: 'TotalCount', aiTitle: "总量", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, // sorter: (a, b) => a.TotalCount - b.TotalCount, // defaultSortOrder: 'descend' }, { title:
总量占比
, dataIndex: 'TotalCountRatio', aiDataIndex: 'TotalCountRatio', aiTitle: "总量占比", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, render: (_, record) => { return record?.TotalCountRatio ? `${record?.TotalCountRatio}%` : '' } }, { title:
小型车
, dataIndex: 'LightDutyTotalCount', aiDataIndex: 'LightDutyTotalCount', aiTitle: "小型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
中型车
, dataIndex: 'MidSizeTotalCount', aiDataIndex: 'MidSizeTotalCount', aiTitle: "中型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
大型车
, dataIndex: 'LargeTotalCount', aiDataIndex: 'LargeTotalCount', aiTitle: "大型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, } ] }, { title:
东南区
, aiTitle: "东南区", hideInDescriptions: true, hideInSearch: true, children: [ { title:
小型车
, dataIndex: 'EastLightDutyCount', aiDataIndex: 'EastLightDutyCount', aiTitle: "小型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
中型车
, dataIndex: 'EastMidSizeCount', aiDataIndex: 'EastMidSizeCount', aiTitle: "中型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
大型车
, dataIndex: 'EastLargeCount', aiDataIndex: 'EastLargeCount', aiTitle: "大型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, } ] }, { title:
西北区
, aiTitle: "西北区", hideInDescriptions: true, hideInSearch: true, children: [ { title:
小型车
, dataIndex: 'WestLightDutyCount', aiDataIndex: 'WestLightDutyCount', aiTitle: "小型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
中型车
, dataIndex: 'WestMidSizeCount', aiDataIndex: 'WestMidSizeCount', aiTitle: "中型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, }, { title:
大型车
, dataIndex: 'WestLargeCount', aiDataIndex: 'WestLargeCount', aiTitle: "大型车", hideInDescriptions: true, valueType: 'digit', align: 'right', width: 140, hideInSearch: true, } ] }, ] // 选择了多个片区 const [isMoreArea, setIsMoreArea] = useState(false) // 寻找展开的行 加上加载效果 const addLoadingRow = (name: string) => { const main = document.getElementsByClassName(`vehicleOwnerTable`)[0] const pageLoading = document.getElementsByClassName(`pageLoading`)[0] const row = main.getElementsByClassName(`${name}`)[0] console.log('row', row); const loadingBox = document.createElement('tr'); const span = document.createElement('span'); const Spin = pageLoading.cloneNode(true); // 深克隆DOM节点 span.innerText = '加载中...'; Spin.setAttribute('class', 'rowLoadingSpin'); span.setAttribute('class', 'span'); loadingBox.appendChild(Spin); loadingBox.appendChild(span); loadingBox.setAttribute('class', 'vehicleOwnerLoadingBox'); row?.parentNode.insertBefore(loadingBox, row.nextSibling) } // 寻找展开的行 去除加载效果 const removeLoadingRow = (name: string) => { const main = document.getElementsByClassName(`vehicleOwnerTable`)[0] const pageLoading = document.getElementsByClassName(`vehicleOwnerLoadingBox`)[0] pageLoading.remove() // 防止重复打印一个内容 } const exportColumns: any = [ { title:
管理中心
, dataIndex: 'SPRegionTypeNAME', hideInDescriptions: true, hideInSearch: true, }, { title:
服务区
, dataIndex: 'ServerPartName', hideInDescriptions: true, hideInSearch: true, }, { title:
归属省份
, dataIndex: 'ProvinceName', hideInDescriptions: true, hideInSearch: true, }, columns[3], columns[4], columns[5] ] 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 tfoot = main.querySelector('tfoot').cloneNode(true); // 深克隆DOM节点 const container = document.querySelector('#hiddenBox'); const titleBox = document.createElement('div'); const title = document.createElement('div'); title.innerText = `中心车辆归属地统计表` title.setAttribute('style', 'width:100%;text-align:center;font-size:20px;font-weight: 600;'); const timeText = document.createElement('div'); timeText.setAttribute('style', 'text-align:right;font-size:16px;font-weight: 400;width:100%') timeText.innerText = `统计时间:${moment(searchParams?.statisticsStartDate).format('YYYY年MM月')}${moment(searchParams?.statisticsStartDate).format('YYYY年MM月') === moment(searchParams?.statisticsEndDate).format('YYYY年MM月') ? '' : `至${moment(searchParams?.statisticsEndDate).format('YYYY年MM月')}`}` const footerBox = document.createElement('div'); const person = document.createElement('span'); const time = document.createElement('span'); person.innerText = `制单人:${currentUser?.Name}` time.innerText = `制单日期:${moment().format('YYYY年MM月DD日 HH:mm:ss')}` person.setAttribute('style', 'text-align:left;font-size:16px;font-weight: 400;width:50%') time.setAttribute('style', 'text-align:right;font-size:16px;font-weight: 400;width:50%') footerBox.appendChild(person); footerBox.appendChild(time); titleBox.appendChild(title) titleBox.appendChild(timeText) // titleBox.appendChild(footerBox) const tempTable = document.createElement('table'); tempTable.appendChild(titleBox); tempTable.appendChild(thead); tempTable.appendChild(tbody); tempTable.appendChild(tfoot); tempTable.setAttribute('id', 'table-to-xls-vehicleOwner'); // 给table添加id,值与按钮上的table字段对应 container.appendChild(tempTable); // 把创建的节点添加到页面容器中 setShowLoading(false) downloadBtnRef.current.handleDownload(); setShowExportTable(false) tempTable.remove() // 防止重复打印一个内容 } const otherFun = (e: any) => { console.log('e', e); // 判断选择了几个片区的地方 let area: number = 0 if (e.checkedNodes && e.checkedNodes.length > 0) { e.checkedNodes.forEach((item: any) => { if (item.type === 0) { area += 1 } }) } if (area > 1) { setIsMoreArea(true) } else { setIsMoreArea(false) } } // 点击ai分析执行的方法 const handleGetAIAnalysis = async () => { if (!selectedId) { message.error('请先选择服务区!') return } if (!(tableData && tableData.length > 0)) { actionRef.current?.reload() } setShowAiDrawer(true) } return (
{ // 打印报表 if (!reqDetailList || reqDetailList.length === 0) return; setPrintOut(el); }} > { showLoading ?
数据导出中...
: '' }
{ showExportTable && reqDetailList && reqDetailList.length > 0 ? { return {`制单人:${currentUser?.Name}`} {`制单日期:${moment().format('YYYY年MM月DD日 HH:mm:ss')}`} }} expandable={{ defaultExpandAllRows: true }} /> : '' }
{ return `${record?.SPRegionTypeId}-${record?.ServerPartId}-${record?.ServerPartName}-${record?.ProvinceName}` }} rowClassName={(record) => { return `${record?.SPRegionTypeId}-${record?.ServerPartId}-${record?.ServerPartName}-${record?.ProvinceName}` }} scroll={{ x: 'max-content', y: 'calc(100vh - 400px)' }} loading={tableLoading ? { spinning: tableLoading, tip: loadingText || '加载中...' } : false} headerTitle={} search={{ span: 6 }} dataSource={tableData} request={async (params) => { if (!selectedId) { return } let startTime1: number = new Date().getTime() let allStartTime: number = new Date().getTime() console.log('exportColumns', exportColumns); console.log('isMoreArea', isMoreArea); setIsExportOk(false) setTableLoading(true) setLoadingText('加载表格数据中,请稍后...') console.log('params', params); setSearchParams(params) const req: any = { dataType: 0, serverPartId: selectedId, statisticsStartMonth: params?.statisticsStartDate ? moment(params?.statisticsStartDate).format('YYYYMM') : '', statisticsEndMonth: params?.statisticsEndDate ? moment(params?.statisticsEndDate).format('YYYYMM') : '', rankNum: params?.rankNum || '' } setExpandedRowKeys(['null-null-undefined-undefined-undefined-undefined-null']) // 接口数据 const data = await handleGetBayonetOwnerAHTreeList(req) let endTime1: number = new Date().getTime() // 准备导出excel数据 let startTime2: number = new Date().getTime() const exportReq: any = { dataType: 0, serverPartId: selectedId, statisticsStartMonth: params?.statisticsStartDate ? moment(params?.statisticsStartDate).format('YYYYMM') : '', statisticsEndMonth: params?.statisticsEndDate ? moment(params?.statisticsEndDate).format('YYYYMM') : '', rankNum: params?.rankNum || '', isSync: false } let endTime2: number = 0 handleGetBayonetOwnerAHTreeList(exportReq).then(res => { if (res && res.length > 0) { const exportData = JSON.parse(JSON.stringify(res)) console.log('res', res); exportData.forEach((item: any) => { item.ServerPartName = ' ' item.ProvinceName = ' ' if (item.children && item.children.length > 0) { item.children.forEach((subItem: any) => { subItem.SPRegionTypeNAME = ' ' subItem.ProvinceName = ' ' subItem.TotalCountRatio = numeral((subItem.TotalCount / item.TotalCount) * 100).format('0.00') if (subItem.children && subItem.children.length > 0) { subItem.children.forEach((thirdItem: any) => { thirdItem.SPRegionTypeNAME = ' ' thirdItem.ServerPartName = ' ' thirdItem.TotalCountRatio = numeral((thirdItem.TotalCount / subItem.TotalCount) * 100).format('0.00') }) } }) } }) console.log('exportData', exportData); setReqDetailList(exportData) setIsExportOk(true) } else { setReqDetailList([]) setIsExportOk(true) } endTime2 = new Date().getTime() }) let allEndTime: number = new Date().getTime() // JSON数据 // const data: any = pageData console.log('data', data); setLoadingText('处理数据中,请稍后...') // 导出数据 console.log('datadatadatadatadatadata', data); const exportDataList: any = [] if (data && data.length > 0) { console.log('111'); data.forEach((item: any) => { if (item.children && item.children.length > 0) { item.children.forEach((subItem: any) => { subItem.TotalCountRatio = numeral((subItem.TotalCount / item.TotalCount) * 100).format('0.00') if (subItem.children && subItem.children.length > 0) { subItem.children.forEach((thirdItem: any) => { thirdItem.TotalCountRatio = numeral((thirdItem.TotalCount / subItem.TotalCount) * 100).format('0.00') }) } else { subItem.children = [] } }) } }) console.log('222'); if (isMoreArea) { let TotalCountSum: number = 0 let LightDutyTotalCountSum: number = 0 let MidSizeTotalCountSum: number = 0 let LargeTotalCountSum: number = 0 let EastLightDutyCountSum: number = 0 let EastMidSizeCountSum: number = 0 let EastLargeCountSum: number = 0 let WestLightDutyCountSum: number = 0 let WestMidSizeCountSum: number = 0 let WestLargeCountSum: number = 0 data.forEach((item: any) => { TotalCountSum += item.TotalCount LightDutyTotalCountSum += item.LightDutyTotalCount MidSizeTotalCountSum += item.MidSizeTotalCount LargeTotalCountSum += item.LargeTotalCount EastLightDutyCountSum += item.EastLightDutyCount EastMidSizeCountSum += item.EastMidSizeCount EastLargeCountSum += item.EastLargeCount WestLightDutyCountSum += item.WestLightDutyCount WestMidSizeCountSum += item.WestMidSizeCount WestLargeCountSum += item.WestLargeCount }) data.forEach((item: any) => { item.TotalCountRatio = numeral((item.TotalCount / TotalCountSum) * 100).format('0.00') }) data.unshift({ ServerPartName: '合计', TotalCountRatio: 100, TotalCount: TotalCountSum, LightDutyTotalCount: LightDutyTotalCountSum, MidSizeTotalCount: MidSizeTotalCountSum, LargeTotalCount: LargeTotalCountSum, EastLightDutyCount: EastLightDutyCountSum, EastMidSizeCount: EastMidSizeCountSum, EastLargeCount: EastLargeCountSum, WestLightDutyCount: WestLightDutyCountSum, WestMidSizeCount: WestMidSizeCountSum, WestLargeCount: WestLargeCountSum, }) } console.log('2131data', data); setTableLoading(false) setLoadingText('') setTableData(data) const logReq: any = await handleChangeKeyTo(req, paramsSort) const logReq2: any = await handleChangeKeyTo(exportReq, paramsSort) handleSetPublicLog({ desc: [ { url: '/CommercialApi/BigData/GetBayonetOwnerAHTreeList', params: logReq, time: (endTime1 - startTime1) / 1000, }, { url: '/CommercialApi/BigData/GetBayonetOwnerAHTreeList', params: logReq2, time: (endTime2 - startTime2) / 1000, } ], startTime: allStartTime, endTime: allEndTime, buttonType: 1 }) return { data, success: true } } setTableLoading(false) setLoadingText('') setReqDetailList([]) setTableData([]) return { data: [], success: true } }} toolbar={{ actions: [ , ] }} expandable={{ expandedRowKeys, onExpand: async (record, event) => { console.log('record', record) console.log('event', event) if (record) { if (expandedRowKeys && expandedRowKeys.length > 0) { const list: any = JSON.parse(JSON.stringify(expandedRowKeys)) list.push(`${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`) setExpandedRowKeys(list) } else { const list: any = [] list.push(`${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`) setExpandedRowKeys(list) } } else { const list: any = JSON.parse(JSON.stringify(expandedRowKeys)) const newList: any = list.filter((item) => item !== `${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`) console.log('newList', newList) setExpandedRowKeys(newList) } if (columnsLoading) { return } let isHave: boolean = true if (event.children && event.children.length > 0) { isHave = false } if (record && event.ServerPartId && isHave) { setColumnsLoading(true) console.log('`${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`', `${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`); addLoadingRow(`${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`) const req: any = { dataType: 0, serverPartId: event?.ServerPartId, statisticsStartMonth: searchParams?.statisticsStartDate ? moment(searchParams?.statisticsStartDate).format('YYYYMM') : '', statisticsEndMonth: searchParams?.statisticsEndDate ? moment(searchParams?.statisticsEndDate).format('YYYYMM') : '', rankNum: searchParams?.rankNum || '', isSync: false } // 接口数据 const data = await handleGetBayonetOwnerAHTreeList(req) console.log('data222', data); // 要的结果 let res: any = [] if (data && data.length > 0) { data.forEach((item: any) => { if (item.children && item.children.length > 0) { item.children.forEach((subItem: any) => { if (subItem.children && subItem.children.length > 0) { res = subItem.children res.forEach((resItem: any) => { resItem.TotalCountRatio = numeral((resItem.TotalCount / subItem.TotalCount) * 100).format('0.00') }) } }) } }) } if (tableData && tableData.length > 0) { const tableList: any = JSON.parse(JSON.stringify(tableData)) tableList.forEach((item: any) => { if (item.SPRegionTypeId === event.SPRegionTypeId) { if (item.children && item.children.length > 0) { item.children.forEach((subItem: any) => { if (subItem.ServerPartId === event.ServerPartId) { subItem.children = res } }) } } }) setTableData(tableList) } removeLoadingRow(`${event?.SPRegionTypeId}-${event?.ServerPartId}-${event?.ServerPartName}-${event?.ProvinceName}`) setColumnsLoading(false) } } }} />
{ setCurrentRow(undefined) setShowDetail(false) }} destroyOnClose title={`${currentRow?.ServerPartName || ''}车辆归属地统计表`} closable={false} bodyStyle={{ backgroundColor: "#f9f9f9", padding: 16 }} className={'vehicleDrawer'} >
) } export default connect(({ user }: ConnectState) => ({ currentUser: user.currentUser }))(vehicleOwner);