123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- import React, { Suspense, useEffect, useState } from 'react';
- import styles from './index.less';
- import * as datav from '@jiaminghi/data-view-react';
- import dataBoardTitle from '../../../public/assets/dataBoardTitle.png';
- import decoration_three from '../../../public/assets/decoration_three.png';
- import decoration_five from '../../../public/assets/decoration_five.png';
- import border from '../../../public/assets/border.png';
- import dataBoardBg_two from '../../../public/assets/dataBoardBg_two.png';
- import Slider from 'react-slick';
- import 'slick-carousel/slick/slick.css';
- import 'slick-carousel/slick/slick-theme.css';
- import {
- queryAreaData,
- queryDeviceChart,
- queryDeviceData,
- queryDeviceRunTime,
- queryHomeInfo,
- queryMapJson,
- queryUserChart,
- queryUserData,
- } from '@/services/dataBoardService';
- import PreloadImage from '@/components/PreloadImage';
- import { DoubleRightOutlined } from '@ant-design/icons';
- const LineChartsCommon = React.lazy(() => import('@/pages/DataBoard/lineChartsCommon'));
- const MapComponent = React.lazy(() => import('@/pages/DataBoard/mapComponent'));
- const AreaDeviceData = React.lazy(() => import('@/pages/DataBoard/areaDeviceData'));
- const SliderData = React.lazy(() => import('@/pages/DataBoard/sliderData'));
- // 数据大屏
- const DataBoard: React.FC = () => {
- const [deviceTypeValue, setDeviceTypeValue] = useState(1);
- const [userTypeValue, setUserTypeValue] = useState(1);
- const [userNum, setUserNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 28,
- fill: '#2ff8ff',
- },
- });
- const [homeNum, setHomeNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 28,
- fill: '#2ff8ff',
- },
- });
- const [onlineDeviceNum, setOnlineDeviceNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [offlineDeviceNum, setOfflineDeviceNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [deviceNum, setDeviceNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [errorDeviceNum, setErrorDeviceNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [masterControlNum, setMasterControlNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [subControlNum, setSubControlNum] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 20,
- fill: '#2ff8ff',
- },
- });
- const [deviceStatistics, setDeviceStatistics] = useState({
- number: [0],
- content: '{nt}',
- style: {
- fontSize: 33,
- fill: '#08c7f1',
- },
- });
- const [allRunTime, setAllRunTime] = useState({
- number: [0],
- content: '{nt}',
- toFixed: 2,
- style: {
- fontSize: 33,
- fill: '#ffb026',
- },
- });
- const [todayRunTime, setTodayRunTime] = useState({
- number: [0],
- content: '{nt}',
- toFixed: 2,
- style: {
- fontSize: 33,
- fill: '#0dde79',
- },
- });
- const [homeInfo, setHomeInfo] = useState([]);
- const [userChartsData, setUserChartsData] = useState([]);
- const [deviceChartsData, setDeviceChartsData] = useState([]);
- const [areaDeviceList, setAreaDeviceList] = useState([]);
- const [mapData, setMapData] = useState({
- company_name: '',
- });
- const settings = {
- dots: false, //圆点显示(false隐藏)
- infinite: true, //无限的环绕内容
- autoplay: true, //自动播放,速度默认为(3000毫秒)
- speed: 3000, //自动播放速度(毫秒)
- slidesToShow: 2, //在一帧中显示2张卡片
- slidesToScroll: 1, //一次滚动2张卡片
- variableWidth: true,
- };
- // 设备统计
- const getDeviceData = () => {
- queryDeviceData().then((res) => {
- if (res?.code === 0) {
- // 设备数
- setDeviceNum((data) => {
- data.number = [res.data.device_count];
- return { ...data };
- });
- // 故障设备数
- setErrorDeviceNum((data) => {
- data.number = [res.data.failure_device];
- return { ...data };
- });
- // 主控数量
- setMasterControlNum((data) => {
- data.number = [res.data.master_count];
- return { ...data };
- });
- // 分控数量
- setSubControlNum((data) => {
- data.number = [res.data.sub_count];
- return { ...data };
- });
- // 设备数统计
- setDeviceStatistics((data) => {
- data.number = [res.data.device_count];
- return { ...data };
- });
- }
- });
- };
- // 用户数据统计
- const userNumData = () => {
- queryUserData().then((res) => {
- if (res?.code === 0) {
- // 注册用户数
- setUserNum((data) => {
- data.number = [res.data.user_count];
- return { ...data };
- });
- // 家庭数量
- setHomeNum((data) => {
- data.number = [res.data.home_count];
- return { ...data };
- });
- // 在线设备数
- setOnlineDeviceNum((data) => {
- data.number = [res.data.device_online];
- return { ...data };
- });
- // 离线设备数
- setOfflineDeviceNum((data) => {
- data.number = [res.data.device_offline];
- return { ...data };
- });
- }
- });
- };
- // 设备运行时长统计
- const getRunTime = () => {
- queryDeviceRunTime().then((res) => {
- if (res.code === 0) {
- setAllRunTime((data) => {
- data.number = [res.data.total_run_time];
- return { ...data };
- });
- setTodayRunTime((data) => {
- data.number = [res.data.day_run_time];
- return { ...data };
- });
- }
- });
- };
- //地区设备数量Top5
- const getAreaData = () => {
- queryAreaData({ region_type: '1' }).then((res) => {
- if (res?.code === 0) {
- setAreaDeviceList(res.data);
- }
- });
- };
- // 设备增长趋势
- const deviceCharts = () => {
- queryDeviceChart({ time_type: deviceTypeValue }).then((res) => {
- if (res?.code === 0) {
- setDeviceChartsData(res.data);
- }
- });
- };
- // 用户增长趋势
- const userCharts = () => {
- queryUserChart({ time_type: userTypeValue }).then((res) => {
- if (res?.code === 0) {
- setUserChartsData(res.data);
- }
- });
- };
- // 查询家列表
- const getHomeListInfo = () => {
- queryHomeInfo().then((res) => {
- if (res.code === 0) {
- setHomeInfo(res.data);
- }
- });
- };
- const timerFun = (callback: () => void, interval: number | undefined) => {
- let timer: any = setTimeout(() => {
- callback();
- clearTimeout(timer);
- timer = null;
- timerFun(callback, interval);
- }, interval);
- };
- // 获取地图json数据
- const getMapJson = () => {
- queryMapJson().then((res) => {
- if (res && res.code === 0) {
- setMapData(res.data);
- }
- });
- };
- useEffect(() => {
- // 组件挂载时立即获取一次数据
- getAreaData();
- userNumData();
- getDeviceData();
- getRunTime();
- deviceCharts();
- userCharts();
- getHomeListInfo();
- getMapJson();
- timerFun(() => {
- getAreaData();
- userNumData();
- getDeviceData();
- }, 30 * 60 * 1000); // 30分钟
- timerFun(() => {
- getRunTime();
- getHomeListInfo();
- }, 1000 * 60 * 10); // 10分钟
- return () => {};
- }, []);
- // 设备增长趋势切换
- useEffect(() => {
- const timerId = setTimeout(() => {
- setDeviceTypeValue((prevValue) => (prevValue === 1 ? 2 : 1));
- deviceCharts();
- }, 1000 * 60 * 10); // 10分钟
- return () => {
- clearTimeout(timerId);
- };
- }, [deviceTypeValue]);
- // 用户增长趋势切换
- useEffect(() => {
- const timerId = setTimeout(() => {
- setUserTypeValue((prevValue) => (prevValue === 1 ? 2 : 1));
- userCharts();
- }, 1000 * 60 * 10); // 10分钟
- return () => {
- clearTimeout(timerId);
- };
- }, [userTypeValue]);
- return (
- <div className={styles.container}>
- <PreloadImage
- src={dataBoardBg_two}
- alt="背景边框"
- loading="lazy"
- style={{ position: 'absolute', bottom: 0 }}
- />
- {/* 顶部 */}
- <div className={styles.dataTitleItem}>
- <PreloadImage src={dataBoardTitle} alt="顶部标题背景" />
- <img src={decoration_three} style={{ width: '50%' }} alt="顶部标题背景装饰" />
- <div className={styles.title}>{mapData.company_name}</div>
- </div>
- {/* 中间内容 */}
- <div className={styles.dataBoardContent}>
- {/* 中间内容-----左侧 */}
- {/* 中间内容-----左侧--统计数据 */}
- <div className={styles.decoration_left_1}>
- <PreloadImage src={border} alt="边框" style={{ width: '480px', height: '300px' }} />
- <div className={styles.title_text}>统计数据</div>
- <div className={styles.statistics}>
- <div className={styles.user_data}>
- <div className={styles.statistics_title_text}>
- <DoubleRightOutlined style={{ fontSize: '17px', color: '#52ffff' }} />
- <span> 用户统计 </span>
- </div>
- <div className={styles.user_content}>
- <div className={styles.user_item}>
- <div className={styles.item_title}>注册用户数</div>
- <datav.DigitalFlop config={userNum} style={{ width: '170px', height: '50px' }} />
- </div>
- <div className={styles.user_item}>
- <div className={styles.item_title}>家庭数量</div>
- <datav.DigitalFlop
- config={homeNum}
- className={styles.item_content}
- style={{ width: '170px', height: '50px' }}
- />
- </div>
- </div>
- </div>
- <div className={styles.device_data}>
- <div className={styles.statistics_title_text}>
- <DoubleRightOutlined style={{ fontSize: '17px', color: '#52ffff' }} />
- <span> 设备统计 </span>
- </div>
- <div className={styles.device_content}>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={deviceNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>设备数</div>
- </div>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={onlineDeviceNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>在线设备数</div>
- </div>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={offlineDeviceNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>离线设备数</div>
- </div>
- </div>
- <div className={styles.device_content}>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={errorDeviceNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>故障设备数</div>
- </div>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={masterControlNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>主控数量</div>
- </div>
- <div className={styles.device_item}>
- <div className={styles.qiu}>
- <datav.DigitalFlop
- config={subControlNum}
- className={styles.device_num}
- style={{ width: '200px', height: '50px' }}
- />
- </div>
- <div className={styles.device_title}>分控数量</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- {/* 中间内容-----左侧--用户增长趋势*/}
- <div className={styles.decoration_left_2}>
- <PreloadImage src={border} alt="边框" style={{ width: '480px', height: '300px' }} />
- <div className={styles.title_text}>用户增长趋势</div>
- <div className={styles.user_charts}>
- {userChartsData && userChartsData.length ? (
- <Suspense fallback={<div>loading</div>}>
- <LineChartsCommon width={450} height={250} data={userChartsData} />
- </Suspense>
- ) : (
- <datav.Loading style={{ position: 'absolute' }}>Loading...</datav.Loading>
- )}
- </div>
- </div>
- {/* 中间内容-----地图 */}
- <div className={styles.decoration_map}>
- {/* 数据统计 */}
- <div style={{ display: 'flex', justifyContent: 'space-around' }}>
- <div className={styles.data_show}>
- <PreloadImage src={decoration_five} alt="背景边框" />
- <datav.DigitalFlop
- config={deviceStatistics}
- className={styles.data_show_num}
- style={{ width: '200px', height: '50px' }}
- />
- <div className={styles.data_show_title} style={{ color: '#08c7f1' }}>
- 设备数
- </div>
- </div>
- <div className={styles.data_show}>
- <PreloadImage src={decoration_five} alt="背景边框" />
- <datav.DigitalFlop
- config={allRunTime}
- className={styles.data_show_num}
- style={{ width: '200px', height: '50px' }}
- />
- <div className={styles.data_show_title} style={{ color: '#ffb026' }}>
- 总运行时长(小时)
- </div>
- </div>
- <div className={styles.data_show}>
- <PreloadImage src={decoration_five} alt="背景边框" />
- <datav.DigitalFlop
- config={todayRunTime}
- className={styles.data_show_num}
- style={{ width: '200px', height: '50px' }}
- />
- <div className={styles.data_show_title} style={{ color: '#0dde79' }}>
- 今日运行时长(小时)
- </div>
- </div>
- </div>
- {/* 地图 */}
- {areaDeviceList && areaDeviceList.length ? (
- <Suspense fallback={<div>loading</div>}>
- <MapComponent mapData={mapData} userData={userNum} areaList={areaDeviceList} />
- </Suspense>
- ) : (
- <datav.Loading style={{ position: 'absolute' }}>Loading...</datav.Loading>
- )}
- </div>
- {/* 中间内容-----右侧 */}
- {/* 中间内容-----右侧--地区设备数量统计 */}
- <div className={styles.decoration_right_3}>
- <PreloadImage src={border} alt="边框" style={{ width: '480px', height: '300px' }} />
- <div className={styles.title_text}>地区设备数量统计</div>
- {areaDeviceList && areaDeviceList.length && (
- <Suspense fallback={<div>loading</div>}>
- <AreaDeviceData data={areaDeviceList} />
- </Suspense>
- )}
- </div>
- {/* 中间内容-----右侧--设备增长趋势*/}
- <div className={styles.decoration_right_4}>
- <PreloadImage src={border} alt="边框" style={{ width: '480px', height: '300px' }} />
- <div className={styles.title_text}>设备增长趋势</div>
- {deviceChartsData && deviceChartsData.length ? (
- <Suspense fallback={<div>loading</div>}>
- <LineChartsCommon width={450} height={250} data={deviceChartsData} />
- </Suspense>
- ) : (
- <datav.Loading style={{ position: 'absolute' }}>Loading...</datav.Loading>
- )}
- </div>
- </div>
- {/* 底部轮播 */}
- <div className={styles.dataBottom}>
- <div className="swiper-content">
- {homeInfo && homeInfo.length ? (
- <Slider {...settings} className="swiper-container">
- {homeInfo.map((res) => {
- return (
- <Suspense key={res} fallback={<div>loading</div>}>
- <SliderData key={res} data={res} />
- </Suspense>
- );
- })}
- </Slider>
- ) : (
- <datav.Loading style={{ position: 'absolute' }}>Loading...</datav.Loading>
- )}
- </div>
- </div>
- </div>
- );
- };
- export default DataBoard;
|