表格右侧生成总览热力图

react实现对表格某列数据实现总览(表格总览热力图)

在这里插入图片描述
如图左侧,一张普通的数据表,其中有一项为每行数据的最终判定结果,当有很多条数据时,可以选择在右侧生成一个热力图,将左侧的表中的判定结果映射到右侧,形成一个总览,我们可以直接通过右侧的颜色直接定位到那些是异常,哪些为正常,并实现通过点击右侧区域,左边表格定位到右侧热力图对应的位置!

实现原理

颜色效果:通过css3中的样式控制:background: linear-gradient(${colors})

点击了解linear-gradient

其本质是将一个空的div中

<div 
	id="scrollDiv" 
	style={{ height: '55vh', overflow: 'hidden', background: `linear-gradient(${colors})` }}
    onClick={(event) => scrollRow(event)}/>

其中的colors为拼接的字符串

 //定义一个颜色数组字符串的默认值
    const colorsInnitial = (data: any) => {
        let _colors = ''
        data.map((item: any, index: number) => {
            if (item.furNo == "1") {
                _colors = _colors + ',' + 'rgb(172, 81, 99)'
            } else if (item.furNo == "2") {
                _colors = _colors + ',' + 'rgb(75, 152, 110)'
            } else if (item.furNo == "3") {
                _colors = _colors + ',' + 'rgb(34, 25, 129)'
            } else {
                _colors = _colors + ',' + 'white'
            }
        })
        //'to bottom'渐变的方向从上到下
        _colors = 'to bottom' + _colors
        return _colors
    }
点击效果:通过点击位置的高度百分比,去定位左侧表格中的滚动条的百分比
 //拿到整个点击区域
    let scrollDiv = document.getElementById("scrollDiv")

    //定义点击事件
    const scrollRow = (event: any) => {
        let scrollPercentage = 0
        if (scrollDiv) {
            scrollPercentage = (event.clientY - scrollDiv.getBoundingClientRect().top) / scrollDiv.offsetHeight
        }
        if (AreaAlarmMsg.length) {
            handleScroll(scrollPercentage)
        }
    }

    //  获取左侧表格 通过传入的点击区域的百分比参数 确定左侧表格的导航条滚动位置
    const handleScroll = (percent: number) => {
        let scrolls = document.getElementsByClassName("ant-table-body")
        scrolls[0].scrollTop = (percent * scrolls[0].scrollHeight)
    }

//完整代码

import React, { useState, useEffect } from 'react'
import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons'
import { Tag, Modal, Button, message, Table, Breadcrumb, Row, Col, BackTop } from 'antd'
import { connect } from 'dva'
import lodash from 'lodash'
import moment from 'moment'
import "./style.less"
import { SearchCondition } from './fragments/searchCondition'
import { EmbaraseSection } from './fragments/embaraseSection'
import DispatchEvent from "../tools/dispatchEvent"
import PublicEvent from './services/publicEvent'
import axios from 'axios'
import ReactEcharts from 'echarts-for-react'
import { areaheatMapData } from './data/heatMap'
import { LinechartGroupModel } from '../automaticJudgement/models/linechartGroupModel'

let startDay: string = moment(new Date()).add(-1, "days").format("YYYY-MM-DD")
let startTime: string = startDay + ' 00:00:00'
let endedTime: string = startDay + ' 24:00:00'
const dispatcher: DispatchEvent = new DispatchEvent()
const waitList: string[] = ["StatisticsEmbaraseThemeView"]
let waitIndex: number = 0

const Index = (props: any) => {
    const thisViewName: string = "StatisticsMainView"
    const [searchConditionDisplay, setSearchConditionDisplay] = useState("none")
    const [isLoading, setIsLoading] = useState(false)
    let isSearchShow = false;
    const [AreaAlarmMsg, setAreaAlarmMsg] = useState([])
    const [AlarmMesByArea, setAlarmMesByArea] = useState([])
    const [isShowDetails, setShowDetails] = useState(false)
    const [colors, setColors] = useState('')
    //分页
    const [tableBasicPagination, setTableBasicPagination] = useState({
        total: 0,
        showSizeChanger: true,
        showQuickJumper: true,
        showTotal: (total: any) => {
            return "共 " + total + " 项"
        },
        defaultPageSize: 200
    })

    const [searchRow, setSearchRow] = useState<any>({
        coiltype: "",
        thickMin: 0,
        thickMax: 0,
        orderNo: "",
        group: "",
        widthMin: 0,
        widthMax: 0,
        matId: "",
        theme: "",
        startTime: startTime,
        endedTime: endedTime,
    })

    //前一天的区域报警归类统计信息列
    const columns = [
        {
            title: '序号',
            key: 'sort',
            width: 50,
            ellipsis: true,
            render: (text: any, row: any, index: any) => {
                return <div>{index + 1}</div>
            }
        },
        {
            title: '卷号',
            dataIndex: 'coilNo',
            key: 'coilNo',
            width: 100,
            ellipsis: true,
        },
        {
            title: '班组',
            // dataIndex:'group',
            key: 'group',
            width: 80,
            ellipsis: true,
            render: (text: any, record: any) => {
                let group = "甲组"
                switch (record.group) {
                    case "1": group = "甲组"
                        break;
                    case "2": group = "乙组"
                        break;
                    case "3": group = "丙组"
                        break;
                    case "4": group = "丁组"
                        break;
                }
                return <div>{group}</div>
            }
        },
        {
            title: '班次',
            // dataIndex:'shift',
            key: 'shift',
            width: 80,
            ellipsis: true,
            render: (text: any, record: any) => {
                let shift = "白班"
                switch (record.shift) {
                    case "2": shift = "小夜班"
                        break;
                    case "3": shift = "大夜班"
                        break;
                    case "1": shift = "白班"
                        break;
                }
                return <div>{shift}</div>
            }
        },
        {
            title: '区域报警详情',
            children: [
                {
                    title: 'FUC1报警',
                    key: 'FUC1',
                    width: 80,
                    ellipsis: true,
                    render: (row: any, rocord: any) => {
                        if (rocord.furNo == 1) {
                            return <Tag style={{ fontSize: 18 }} color='rgb(172, 81, 99)'>{"1号炉 : " + rocord.fuc}</Tag>
                        } else {
                            return <div>{'非1号炉轧制'}</div>
                        }
                    }
                },
                {
                    title: 'FUC2报警',
                    // dataIndex:'FUC2',
                    key: 'FUC2',
                    width: 80,
                    ellipsis: true,
                    render: (row: any, rocord: any) => {
                        if (rocord.furNo == 2) {
                            return <Tag style={{ fontSize: 18 }} color="rgb(75, 152, 110)">{"2号炉 : " + rocord.fuc}</Tag>
                        } else {
                            return <div>{'非2号炉轧制'}</div>
                        }
                    }
                },
                {
                    title: 'FUC3报警',
                    // dataIndex:'FUC3',
                    key: 'FUC3',
                    width: 80,
                    ellipsis: true,
                    render: (row: any, rocord: any) => {
                        if (rocord.furNo == 3) {
                            return <Tag style={{ fontSize: 18 }} color="rgb(34, 25, 129)">{"3号炉 : " + rocord.fuc}</Tag>
                        } else {
                            return <div>{'非3号炉轧制'}</div>
                        }
                    }
                },
                {
                    title: 'R1报警',
                    dataIndex: 'r1',
                    key: 'r1',
                    width: 80,
                    ellipsis: true,
                },
                {
                    title: 'R2报警',
                    dataIndex: 'r2',
                    key: 'R2',
                    width: 80,
                    ellipsis: true,
                },
                {
                    title: '精轧区域',
                    dataIndex: 'fm',
                    key: 'fm',
                    width: 80,
                    ellipsis: true,
                },
                {
                    title: '层冷卷取区域',
                    dataIndex: 'ctc',
                    key: 'ctc',
                    width: 80,
                    ellipsis: true,
                },
                {
                    title: '总报警',
                    key: 'total',
                    width: 80,
                    ellipsis: true,
                    render : (record: any)=>{
                        let count = 0
                        count = record.fuc*1 + record.r1 + record.r2 + record.fm + record.ctc
                        return <div>{count}</div>

                    },
                },
            ]
        },
        {
            title: '操作',
            dataIndex: 'opeator',
            key: 'opeator',
            width: 80,
            ellipsis: true,
            render: (row: any, record: any) => {
                return <div>
                    <Button
                        onClick={() => {
                            setShowDetails(true)
                            let coilNo = record.coilNo
                            getAlarmMesByArea(coilNo)
                        }}
                        type="default"
                        style={{ background: 'rgb(75, 152, 110)', width: '80%' }}>查看</Button>
                </div>
            }
        },
        {
            title: '生产时间',
            // dataIndex:'date',
            key: 'date',
            width: 120,
            ellipsis: true,
            render: (record: any) => {
                return <div>{moment(record.date).format('YYYY:MM:DD HH:mm:ss')}</div>
            }
        },
    ]
    //单卷的报警详细情况
    const coilColumns = [
        {
            title: '序号',
            key: 'sort',
            width: 50,
            ellipsis: true,
            render: (text: any, row: any, index: any) => {
                return <div>{index + 1}</div>
            }
        },
        {
            title: '区域名称',
            key: 'area',
            dataIndex: 'area',
            width: 80,
            ellipsis: true,

        },
        {
            title: '规则名称',
            key: 'ruleName',
            dataIndex: 'ruleName',
            width: 120,
            ellipsis: true,

        },
        {
            title: '钢种',
            key: 'steelGrade',
            dataIndex: 'steelGrade',
            width: 100,
            ellipsis: true,

        },
        {
            title: '报警ID',
            key: 'alarmId',
            // dataIndex:'alarmId',
            width: 100,
            ellipsis: true,
            render: (record: any) => {
                if (record.alarmId == null || record.alarmId == 0) {
                    record.alarmId = '暂未配置'
                }
                return <div>{record.alarmId}</div>
            }

        },
        {
            title: '报警等级',
            key: 'level',
            // dataIndex:'level',
            width: 80,
            ellipsis: true,
            render: (record: any) => {
                switch (record.level) {
                    case 0:
                        record.level = '正常'
                        break
                    case 1:
                        record.level = '轻微'
                        break
                    case 2:
                        record.level = '中等'
                        break
                    case 3:
                        record.level = '严重'
                        break
                }
                return <div>{record.level}</div>
            }

        },
        {
            title: '报警建议',
            key: 'advice',
            // dataIndex:'advice',
            width: 120,
            ellipsis: true,
            render: (record: any) => {
                let advice = '暂无'
                if (record.advice != null && record.advice != 0) {
                    advice = record.advice
                }
                return <div>{advice}</div>
            }

        },
        {
            title: '报警时间',
            key: 'date',
            // dataIndex:'date',
            width: 200,
            ellipsis: true,
            render: (record: any) => {
                return <div>{moment(record.date).format('YYYY:MM:DD HH:mm:ss')}</div>
            }
        },
    ]

    //定义一个颜色数组字符串的默认值
    const colorsInnitial = (data: any) => {
        let _colors = ''
        data.map((item: any, index: number) => {
            if (item.furNo == "1") {
                _colors = _colors + ',' + 'rgb(172, 81, 99)'
            } else if (item.furNo == "2") {
                _colors = _colors + ',' + 'rgb(75, 152, 110)'
            } else if (item.furNo == "3") {
                _colors = _colors + ',' + 'rgb(34, 25, 129)'
            } else {
                _colors = _colors + ',' + 'white'
            }
        })
        _colors = 'to bottom' + _colors
        return _colors
    }

    const getAreaAlarmMsg = async (startTime: any, endedTime: any) => {
        setIsLoading(true)
        axios.post('http://170.0.35.145:9876/alarmResultService/getAreaAlarmMsg', { begin: startTime, end: endedTime }).then((response) => {
            const data = response.data.data
            tableBasicPagination.total = response.data.data.length
            setColors(colorsInnitial(data))
            setTableBasicPagination(tableBasicPagination)
            setAreaAlarmMsg(data)
        }).catch(() => {
            message.error("请求昨日的区域报警总览状况")
        }).finally(() => {
            setIsLoading(false)
        })
    }

    //拿到整个点击区域
    let scrollDiv = document.getElementById("scrollDiv")

    //定义点击事件
    const scrollRow = (event: any) => {
        let scrollPercentage = 0
        if (scrollDiv) {
            scrollPercentage = (event.clientY - scrollDiv.getBoundingClientRect().top) / scrollDiv.offsetHeight
        }
        if (AreaAlarmMsg.length) {
            handleScroll(scrollPercentage)
        }
    }

    //  导航条滚动
    const handleScroll = (percent: number) => {
        let scrolls = document.getElementsByClassName("ant-table-body")
        scrolls[0].scrollTop = (percent * scrolls[0].scrollHeight)
    }

    useEffect(() => {
        getAreaAlarmMsg(startTime, endedTime)
    }, [])

    const getAlarmMesByArea = async (coilNo: any) => {
        setIsLoading(true)
        axios.post('http://170.0.35.145:9876/alarmResultService/getAlarmMesByArea', { coilNo: coilNo }).then((response) => {
            const data = response.data.data
            setAlarmMesByArea(data)
            tableBasicPagination.total = response.data.data.length;
            setTableBasicPagination(tableBasicPagination);
        }).catch(() => {
            message.error("单日报警详情界面表数据失败")
        }).finally(() => {
            setIsLoading(false)
        })
    }

    useEffect(() => {
        getAlarmMesByArea
    }, [])

    useEffect(() => {
        dispatcher.attachment(thisViewName)
        dispatcher.waitList(waitList, (viewName: string) => {
            waitIndex++

            if (waitIndex >= waitList.length) {
                startProcess()
            }
        })
        dispatcher.listen(PublicEvent.searchView.query, (_: any, dataRow: any) => {
            setSearchRow(lodash.clone(dataRow))
            console.log(dataRow)
            startTime = dataRow.startTime
            endedTime = dataRow.endedTime
            getAreaAlarmMsg(startTime, endedTime)
        })
    }, [])

    useEffect(() => {
        startProcess()
    }, [searchRow])

    const startProcess = () => {
        dispatcher.send(thisViewName, PublicEvent.mainView.start, searchRow)
    }

    return (
        <div id="uxFetcher" style={{ minWidth: "1400px", overflow: "hidden", height: "calc(100vh - 96px)", minHeight: 600, margin: "-16px" }}>
            <div style={{ padding: "12px 24px 12px 8px", background: "#1a357a" }}>
                <Breadcrumb style={{ padding: 0 }}>
                    <Breadcrumb.Item>首页</Breadcrumb.Item>
                    <Breadcrumb.Item>单卷全过程参数预警</Breadcrumb.Item>
                    <Breadcrumb.Item>区域工艺精度</Breadcrumb.Item>
                </Breadcrumb>
            </div>
            <div style={{ height: "calc(100% - 64px)", width: "100%", overflow: "auto", marginTop: 8 }}>
                <div style={{ width: "100%", padding: 0, background: "rgb(26, 53, 122)" }}>
                    <div style={{ padding: 8 }}>
                        <Button icon={<SearchOutlined />} style={{ padding: 0 }} size="small" type="text" onClick={() => {
                            setSearchConditionDisplay("block")
                        }}>查询条件</Button>
                        <Button icon={<ReloadOutlined />} size="small" type="text" onClick={() => {

                        }}>重置条件</Button>
                        {/* <Button icon={<ExportOutlined />} size="small" type="text" onClick={() => {
                            
                        }}>导出</Button> */}
                    </div>

                    <div style={{ height: 64, display: searchConditionDisplay, position: "absolute", zIndex: 999, width: "100%", paddingTop: 0, borderTop: "1px solid #001f6b", borderBottom: "1px solid #001f6b", background: "#1a357a", padding: "4px 8px", boxShadow: "0 4px 4px #001c65" }}>
                        <SearchCondition dispatcher={dispatcher} onClose={() => {
                            setSearchConditionDisplay("none")
                        }} visible={isSearchShow} startTime={startTime} endedTime={endedTime}></SearchCondition>
                    </div>
                </div>
                <div style={{ width: "100%", marginTop: 8, height: "30%", float: "left", background: "#1a357a" }}>
                    <EmbaraseSection dispatcher={dispatcher}></EmbaraseSection>
                </div>
                <div style={{ width: "100%", marginTop: 8, minHeight: '55vh', float: "left", background: "#1a357a" }}>
                    <Row gutter={16}>
                        <Col style={{ width: "95%" }}>
                            <Table
                                id='ant-table-body'
                                columns={columns}
                                dataSource={AreaAlarmMsg}
                                loading={isLoading}
                                pagination={tableBasicPagination}
                                bordered
                                scroll={{ y: 520 }}
                            />
                        </Col>
                        <Col id='areaHeatMap' style={{ width: '5%', paddingLeft: 6, height: '100%' }}>
                            {console.log(222, colors)}
                            <div id="scrollDiv" style={{ height: '55vh', overflow: 'hidden', background: `linear-gradient(${colors})` }}
                                onClick={(event) => scrollRow(event)}
                            />
                        </Col>
                    </Row>

                    <Modal
                        title="当日所有报警记录"
                        wrapClassName="vertical-center-modal"
                        visible={isShowDetails}
                        onOk={() => setShowDetails(false)}
                        onCancel={() => setShowDetails(false)}
                        width='85%'
                    >
                        <Table
                            columns={coilColumns}
                            dataSource={AlarmMesByArea}
                            bordered
                            pagination={tableBasicPagination}
                            loading={isLoading}
                            scroll={{ y: 800 }}
                        />
                    </Modal>
                </div>
            </div>
        </div>
    )
}


export default connect(() => { }, () => { })(Index)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值