| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- import { PageContainer } from '@ant-design/pro-layout';
- import { Card } from 'antd';
- import { useEffect, useRef, useState } from 'react';
- import './index.less';
- import Service from './service';
- import encodeQuery from '@/utils/encodeQuery';
- import { useRequest } from 'umi';
- import DashBoard, { DashBoardTopCard } from '@/components/DashBoard';
- import type { EChartsOption } from 'echarts';
- import Echarts from '@/components/DashBoard/echarts';
- // import moment from 'moment';
- import { AMap } from '@/components';
- import { Marker } from 'react-amap';
- import { EnvironmentOutlined } from '@ant-design/icons';
- import SystemConst from '@/utils/const';
- type RefType = {
- getValues: Function;
- };
- const service = new Service('device/instance');
- const DeviceBoard = () => {
- const [deviceOnline, setDeviceOnline] = useState(0);
- const [deviceOffline, setDeviceOffline] = useState(0);
- const [productPublish, setProductPublish] = useState(0);
- const [productUnPublish, setProductUnPublish] = useState(0);
- const [options, setOptions] = useState<EChartsOption>({});
- const [onlineOptions, setOnlineOptions] = useState<EChartsOption>({});
- const [yesterdayCount, setYesterdayCount] = useState(0);
- const [deviceOptions, setDeviceOptions] = useState<EChartsOption>({});
- const [month, setMonth] = useState(0);
- const [day, setDay] = useState(0);
- const [point, setPoint] = useState([]);
- const [amapKey, setAmapKey] = useState<any>();
- const ref = useRef<RefType>();
- const { data: deviceTotal } = useRequest(service.deviceCount, {
- formatResult: (res) => res.result,
- });
- const { data: productTotal } = useRequest(service.productCount, {
- defaultParams: [{}],
- formatResult: (res) => res.result,
- });
- //设备数量
- const deviceStatus = async () => {
- const onlineRes = await service.deviceCount(encodeQuery({ terms: { state: 'online' } }));
- if (onlineRes.status === 200) {
- setDeviceOnline(onlineRes.result);
- }
- const offlineRes = await service.deviceCount(encodeQuery({ terms: { state: 'offline' } }));
- if (offlineRes.status === 200) {
- setDeviceOffline(offlineRes.result);
- }
- };
- //产品数量
- const productStatus = async () => {
- const pusblish = await service.productCount({
- terms: [
- {
- column: 'state',
- value: '1',
- },
- ],
- });
- if (pusblish.status === 200) {
- setProductPublish(pusblish.result);
- }
- const unpublish = await service.productCount({
- terms: [
- {
- column: 'state',
- value: '0',
- },
- ],
- });
- if (unpublish.status === 200) {
- setProductUnPublish(unpublish.result);
- }
- };
- //当前在线
- const getOnline = async () => {
- const res = await service.dashboard([
- {
- dashboard: 'device',
- object: 'session',
- measurement: 'online',
- dimension: 'agg',
- group: 'aggOnline',
- params: {
- state: 'online',
- limit: 15,
- from: 'now-15d',
- time: '1d',
- format: 'yyyy-MM-dd',
- },
- },
- ]);
- if (res.status === 200) {
- const x = res.result.map((item: any) => item.data.timeString).reverse();
- const y = res.result.map((item: any) => item.data.value);
- setYesterdayCount(y?.[1]);
- setOnlineOptions({
- xAxis: {
- type: 'category',
- data: x,
- show: false,
- },
- yAxis: {
- type: 'value',
- show: false,
- },
- grid: {
- top: '5%',
- bottom: 0,
- },
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow',
- },
- },
- series: [
- {
- name: '在线数',
- data: y.reverse(),
- type: 'bar',
- itemStyle: {
- color: '#2F54EB',
- },
- },
- ],
- });
- }
- };
- //今日设备消息量
- const getDevice = async () => {
- const res = await service.dashboard([
- {
- dashboard: 'device',
- object: 'message',
- measurement: 'quantity',
- dimension: 'agg',
- group: 'today',
- params: {
- time: '1h',
- format: 'yyyy-MM-dd HH:mm:ss',
- limit: 24,
- from: 'now-1d',
- },
- },
- {
- dashboard: 'device',
- object: 'message',
- measurement: 'quantity',
- dimension: 'agg',
- group: 'oneday',
- params: {
- time: '1d',
- format: 'yyyy-MM-dd',
- from: 'now-1d',
- },
- },
- {
- dashboard: 'device',
- object: 'message',
- measurement: 'quantity',
- dimension: 'agg',
- group: 'thisMonth',
- params: {
- time: '1M',
- format: 'yyyy-MM',
- limit: 1,
- from: 'now-1M',
- },
- },
- ]);
- if (res.status === 200) {
- const thisMonth = res.result.find((item: any) => item.group === 'thisMonth').data.value;
- const oneDay = res.result.find((item: any) => item.group === 'oneday').data.value;
- setDay(oneDay);
- setMonth(thisMonth);
- const today = res.result.filter((item: any) => item.group === 'today');
- const x = today.map((item: any) => item.data.timeString).reverse();
- const y = today.map((item: any) => item.data.value).reverse();
- setDeviceOptions({
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow',
- },
- },
- xAxis: {
- type: 'category',
- boundaryGap: false,
- show: false,
- data: x,
- },
- yAxis: {
- type: 'value',
- show: false,
- },
- grid: {
- top: '2%',
- bottom: 0,
- },
- series: [
- {
- name: '消息量',
- data: y,
- type: 'line',
- smooth: true,
- color: '#685DEB',
- areaStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- {
- offset: 0,
- color: '#685DEB', // 100% 处的颜色
- },
- {
- offset: 1,
- color: '#FFFFFF', // 0% 处的颜色
- },
- ],
- global: false, // 缺省为 false
- },
- },
- },
- ],
- });
- }
- };
- const getEcharts = async () => {
- const data = ref.current!.getValues();
- if (data && data.time.type !== 'today') {
- const res = await service.dashboard([
- {
- dashboard: 'device',
- object: 'message',
- measurement: 'quantity',
- dimension: 'agg',
- group: 'device_msg',
- params: {
- time: '1d',
- format: 'yyyy.MM.dd',
- limit: Math.ceil((data.time.end - data.time.start) / (1 * 24 * 3600 * 1000) + 1),
- // from: moment(data.time.start).format('yyyy-MM-DD HH:MM:SS'),
- // to: moment(data.time.end).format('yyyy-MM-DD HH:MM:SS'),
- from: data.time.start,
- to: data.time.end,
- },
- },
- ]);
- if (res.status === 200) {
- const x = res.result.map((item: any) => item.data.timeString).reverse();
- const y = res.result.map((item: any) => item.data.value).reverse();
- setOptions({
- xAxis: {
- type: 'category',
- data: x,
- },
- yAxis: {
- type: 'value',
- },
- tooltip: {
- trigger: 'axis',
- // axisPointer: {
- // type: 'shadow',
- // },
- },
- grid: {
- top: '2%',
- bottom: '5%',
- left: '2%',
- right: '2%',
- },
- series: [
- {
- name: '消息量',
- data: y,
- type: 'line',
- smooth: true,
- color: '#685DEB',
- areaStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- {
- offset: 0,
- color: '#685DEB', // 100% 处的颜色
- },
- {
- offset: 1,
- color: '#FFFFFF', // 0% 处的颜色
- },
- ],
- global: false, // 缺省为 false
- },
- },
- },
- ],
- });
- }
- } else {
- const res = await service.dashboard([
- {
- dashboard: 'device',
- object: 'message',
- measurement: 'quantity',
- dimension: 'agg',
- group: 'device_msg',
- params: {
- time: '1h',
- format: 'yyyy.MM.dd HH:MM:SS',
- limit: 24,
- from: data.time.start,
- to: data.time.end,
- },
- },
- ]);
- if (res.status === 200) {
- const x = res.result.map((item: any) => item.data.timeString).reverse();
- const y = res.result.map((item: any) => item.data.value).reverse();
- setOptions({
- xAxis: {
- type: 'category',
- data: x,
- },
- yAxis: {
- type: 'value',
- },
- tooltip: {
- trigger: 'axis',
- },
- grid: {
- top: '2%',
- bottom: '5%',
- left: '2%',
- right: '2%',
- },
- series: [
- {
- name: '消息量',
- data: y,
- type: 'line',
- smooth: true,
- color: '#685DEB',
- areaStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- {
- offset: 0,
- color: '#685DEB', // 100% 处的颜色
- },
- {
- offset: 1,
- color: '#FFFFFF', // 0% 处的颜色
- },
- ],
- global: false, // 缺省为 false
- },
- },
- },
- ],
- });
- }
- }
- };
- //地图数据
- const geo = async (data?: any) => {
- const res = await service.getGeo(data);
- if (res.status === 200) {
- setPoint(res.result.features);
- }
- };
- useEffect(() => {
- deviceStatus();
- productStatus();
- getOnline();
- getDevice();
- geo({});
- }, []);
- useEffect(() => {
- const api = localStorage.getItem(SystemConst.AMAP_KEY);
- setAmapKey(api);
- }, [localStorage.getItem(SystemConst.AMAP_KEY)]);
- return (
- <PageContainer>
- <div className={'device-dash-board'}>
- <DashBoardTopCard>
- <DashBoardTopCard.Item
- title={'产品数量'}
- value={productTotal}
- footer={[
- {
- title: '已发布',
- value: productPublish,
- status: 'success',
- },
- {
- title: '未发布',
- value: productUnPublish,
- status: 'error',
- },
- ]}
- span={6}
- >
- <img src={require('/public/images/device/device-product.png')} />
- </DashBoardTopCard.Item>
- <DashBoardTopCard.Item
- title={'设备数量'}
- value={deviceTotal}
- footer={[
- {
- title: '在线',
- value: deviceOnline,
- status: 'success',
- },
- {
- title: '离线',
- value: deviceOffline,
- status: 'error',
- },
- ]}
- span={6}
- >
- <img src={require('/public/images/device/device-number.png')} />
- </DashBoardTopCard.Item>
- <DashBoardTopCard.Item
- title={'当前在线'}
- value={deviceOnline}
- footer={[
- {
- title: '昨日在线',
- value: yesterdayCount,
- },
- ]}
- span={6}
- >
- <Echarts options={onlineOptions} />
- </DashBoardTopCard.Item>
- <DashBoardTopCard.Item
- title={'今日设备消息量'}
- value={day}
- footer={[
- {
- title: '当月设备消息量',
- value: month,
- },
- ]}
- span={6}
- >
- <Echarts options={deviceOptions} />
- </DashBoardTopCard.Item>
- </DashBoardTopCard>
- <DashBoard
- title={'设备消息'}
- options={options}
- ref={ref}
- height={500}
- defaultTime={'week'}
- showTime={true}
- showTimeTool={true}
- onParamsChange={getEcharts}
- />
- {amapKey && (
- <Card style={{ marginTop: 10 }}>
- <div
- style={{
- fontSize: '16px',
- fontWeight: 'bold',
- marginBottom: 10,
- }}
- >
- 设备分布
- </div>
- <div>
- <AMap
- AMapUI
- style={{
- height: 500,
- width: '100%',
- }}
- >
- {point.map((item: any) => (
- //@ts-ignore
- <Marker
- position={{
- longitude: item.geometry.coordinates?.[0],
- latitude: item.geometry.coordinates?.[1],
- }}
- >
- <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
- <div
- style={{
- backgroundColor: '#666666',
- color: 'white',
- textAlign: 'center',
- marginBottom: 5,
- }}
- >
- {item.properties.deviceName}
- </div>
- <div>
- <EnvironmentOutlined style={{ color: 'blue', fontSize: 22 }} />
- </div>
- </div>
- </Marker>
- ))}
- </AMap>
- </div>
- </Card>
- )}
- </div>
- </PageContainer>
- );
- };
- export default DeviceBoard;
|