Commit b32e0a32 authored by 程恺文's avatar 程恺文

修改

parent 56a7c085
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/alarmscrollassembly@1.12.0...@wisdom-components/alarmscrollassembly@1.12.1) (2023-05-16) ## [1.12.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/alarmscrollassembly@1.12.0...@wisdom-components/alarmscrollassembly@1.12.1) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/alarmscrollassembly **Note:** Version bump only for package @wisdom-components/alarmscrollassembly
# [1.12.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/alarmscrollassembly@1.11.2...@wisdom-components/alarmscrollassembly@1.12.0) (2023-05-12) # [1.12.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/alarmscrollassembly@1.11.2...@wisdom-components/alarmscrollassembly@1.12.0) (2023-05-12)
### Features ### Features
......
...@@ -190,7 +190,7 @@ AlarmScrollAssembly.defaultProps = { ...@@ -190,7 +190,7 @@ AlarmScrollAssembly.defaultProps = {
prefix: '', prefix: '',
showTotal: true, showTotal: true,
interval: 5, interval: 5,
userAccess:false userAccess: false,
}; };
AlarmScrollAssembly.propTypes = { AlarmScrollAssembly.propTypes = {
deviceType: PropTypes.string, deviceType: PropTypes.string,
......
...@@ -129,9 +129,9 @@ ...@@ -129,9 +129,9 @@
width: 120px; width: 120px;
max-width: 120px; max-width: 120px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #333333; color: #333333;
white-space: nowrap;
text-overflow: ellipsis;
} }
.location { .location {
...@@ -158,11 +158,11 @@ ...@@ -158,11 +158,11 @@
display: inline-block; display: inline-block;
width: 120px; width: 120px;
max-width: 120px; max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 10px; margin-left: 10px;
overflow: hidden;
color: #333333; color: #333333;
white-space: nowrap;
text-overflow: ellipsis;
} }
} }
......
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.5.7](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicchart@1.5.6...@wisdom-components/basicchart@1.5.7) (2023-05-16) ## [1.5.7](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicchart@1.5.6...@wisdom-components/basicchart@1.5.7) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/basicchart **Note:** Version bump only for package @wisdom-components/basicchart
## [1.5.6](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicchart@1.5.5...@wisdom-components/basicchart@1.5.6) (2023-05-12) ## [1.5.6](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicchart@1.5.5...@wisdom-components/basicchart@1.5.6) (2023-05-12)
### Bug Fixes ### Bug Fixes
......
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.5](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.4...@wisdom-components/videoslidermodal@1.1.5) (2023-05-16) ## [1.1.5](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.4...@wisdom-components/videoslidermodal@1.1.5) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/videoslidermodal **Note:** Version bump only for package @wisdom-components/videoslidermodal
## [1.1.4](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.3...@wisdom-components/videoslidermodal@1.1.4) (2023-05-16) ## [1.1.4](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.3...@wisdom-components/videoslidermodal@1.1.4) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/videoslidermodal **Note:** Version bump only for package @wisdom-components/videoslidermodal
## [1.1.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.2...@wisdom-components/videoslidermodal@1.1.3) (2023-05-12) ## [1.1.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/videoslidermodal@1.1.2...@wisdom-components/videoslidermodal@1.1.3) (2023-05-12)
**Note:** Version bump only for package @wisdom-components/videoslidermodal **Note:** Version bump only for package @wisdom-components/videoslidermodal
......
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.2.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.2.1...@wisdom-components/VmsVideo@1.2.2) (2023-05-16) ## [1.2.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.2.1...@wisdom-components/VmsVideo@1.2.2) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/VmsVideo **Note:** Version bump only for package @wisdom-components/VmsVideo
## [1.2.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.2.0...@wisdom-components/VmsVideo@1.2.1) (2023-05-16) ## [1.2.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.2.0...@wisdom-components/VmsVideo@1.2.1) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/VmsVideo **Note:** Version bump only for package @wisdom-components/VmsVideo
# [1.2.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.1.13...@wisdom-components/VmsVideo@1.2.0) (2023-05-12) # [1.2.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/VmsVideo@1.1.13...@wisdom-components/VmsVideo@1.2.0) (2023-05-12)
### Features ### Features
......
...@@ -37,13 +37,13 @@ group: ...@@ -37,13 +37,13 @@ group:
| | record 是否显示录制按钮 | boolean | true | | | record 是否显示录制按钮 | boolean | true |
| VideoParam 参数 | --- | --- | --- | | VideoParam 参数 | --- | --- | --- |
| fullUrl | 完整 url,接入 flv 或者三方的链接 | string | "" | | fullUrl | 完整 url,接入 flv 或者三方的链接 | string | "" |
| username | 账号 | string | "6c44c8e92d1c4d75a9818756025df550" | | username | 账号 | string | "6c44c8e92d1c4d75a9818756025df550" |
| password | 密码 | string | "78b7dc88f9f4bf19c2b1aabfdd995244" | | password | 密码 | string | "78b7dc88f9f4bf19c2b1aabfdd995244" |
| address | 地址 | string | "123638446" | | address | 地址 | string | "123638446" |
| protocol | 协议类型 | string | "萤石 EZOPEN" | | protocol | 协议类型 | string | "萤石 EZOPEN" |
| gateway | 是否走网关 | boolean | false | | gateway | 是否走网关 | boolean | false |
| pandavmsHost | pandavms后端主机地址 eg | string | ws://172.16.19.19:8080/ | | pandavmsHost | pandavms 后端主机地址 eg | string | ws://172.16.19.19:8080/ |
| useFullUrl | 是否为完整 url,是,则取 fullUrl,否,则会用 pandavmsHostid 去拼接 | boolean | false | | useFullUrl | 是否为完整 url,是,则取 fullUrl,否,则会用 pandavmsHostid 去拼接 | boolean | false |
| id | 摄像头唯一标识,一串 GUID | string | "" | | id | 摄像头唯一标识,一串 GUID | string | "" |
| name | 摄像头名称 | string | "" | | name | 摄像头名称 | string | "" |
| dataRate | 码率,Main 为主码流,Sub 为辅码流,与消耗网络有关,主码流消耗最高,**由于拼接方式不定,改为是字符串传入** | string | 'Sub' | | dataRate | 码率,Main 为主码流,Sub 为辅码流,与消耗网络有关,主码流消耗最高,**由于拼接方式不定,改为是字符串传入** | string | 'Sub' |
......
...@@ -46,8 +46,8 @@ const Demo1 = (props) => { ...@@ -46,8 +46,8 @@ const Demo1 = (props) => {
dataRate: 'Sub', // Main 主码流 Sub 子码流 dataRate: 'Sub', // Main 主码流 Sub 子码流
pandavmsHost: `ws://192.168.8.27:9876/`, // pandavms后端主机地址 eg: ws://172.16.19.19:8080/ pandavmsHost: `ws://192.168.8.27:9876/`, // pandavms后端主机地址 eg: ws://172.16.19.19:8080/
address: '236644034', address: '236644034',
width:952, width: 952,
height:500, height: 500,
}; };
/* { /* {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 634665781 634665781@qq.com * @Author: 634665781 634665781@qq.com
* @Date: 2023-04-11 13:40:18 * @Date: 2023-04-11 13:40:18
* @LastEditors: 634665781 634665781@qq.com * @LastEditors: 634665781 634665781@qq.com
* @LastEditTime: 2023-05-16 16:23:33 * @LastEditTime: 2023-05-17 09:45:01
* @FilePath: \wisdom-components\packages\base-components\VmsVideo\src\index.jsx * @FilePath: \wisdom-components\packages\base-components\VmsVideo\src\index.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -36,9 +36,9 @@ import style from './index.less'; ...@@ -36,9 +36,9 @@ import style from './index.less';
const Video = (props, ref) => { const Video = (props, ref) => {
const _video = useRef(null); const _video = useRef(null);
const Players = useRef(null); const Players = useRef(null);
const { VideoInfo, JessibucaObj,gateway } = props; const { VideoInfo, JessibucaObj, gateway } = props;
let baseUrl = `ws://${window.location.host}/jessica`; let baseUrl = `ws://${window.location.host}/jessica`;
let keyID =VideoInfo.id+'_'+new Date().getTime() let keyID = VideoInfo.id + '_' + new Date().getTime();
let _VideoInfo = { let _VideoInfo = {
title: '摄像头', title: '摄像头',
// dataRate: 1, // dataRate: 1,
...@@ -48,6 +48,7 @@ const Video = (props, ref) => { ...@@ -48,6 +48,7 @@ const Video = (props, ref) => {
}; };
const getToken = async () => { const getToken = async () => {
let PlayersA =''
axios axios
.post( .post(
`https://open.ys7.com/api/lapp/token/get?appKey=${VideoInfo.username}&appSecret=${VideoInfo.password}`, `https://open.ys7.com/api/lapp/token/get?appKey=${VideoInfo.username}&appSecret=${VideoInfo.password}`,
...@@ -61,14 +62,14 @@ const Video = (props, ref) => { ...@@ -61,14 +62,14 @@ const Video = (props, ref) => {
.then(function (response) { .then(function (response) {
let accessToken = response.data.data.accessToken; let accessToken = response.data.data.accessToken;
let PlayersA = new EZUIKit.EZUIKitPlayer({ PlayersA = new EZUIKit.EZUIKitPlayer({
id: keyID, // 视频容器ID id: keyID, // 视频容器ID
accessToken: accessToken, accessToken: accessToken,
url: `ezopen://open.ys7.com/${VideoInfo.address}/1.hd.live`, url: `ezopen://open.ys7.com/${VideoInfo.address}/1.hd.live`,
templete: 'simple', templete: 'simple',
footer: ['talk', 'broadcast', 'hd', 'fullScreen'], footer: ['talk', 'broadcast', 'hd', 'fullScreen'],
width:VideoInfo.width||952, width: VideoInfo.width || 952,
height:VideoInfo.height||500 height: VideoInfo.height || 500,
}); });
PlayersA.pause = PlayersA.stop; PlayersA.pause = PlayersA.stop;
...@@ -77,7 +78,7 @@ const Video = (props, ref) => { ...@@ -77,7 +78,7 @@ const Video = (props, ref) => {
.catch(function (error) { .catch(function (error) {
console.log(error); console.log(error);
PlayersA.stop() PlayersA.stop();
}); });
}; };
...@@ -89,7 +90,8 @@ const Video = (props, ref) => { ...@@ -89,7 +90,8 @@ const Video = (props, ref) => {
} else { } else {
getToken(); getToken();
} }
const CommonPath = (VideoInfo.gateway || window?.globalConfig?.hasGateWay) ? 'PandaCore/GateWay/Video/' : ''; // 配置了gateway或者pc端web配置中有gateway const CommonPath =
VideoInfo.gateway || window?.globalConfig?.hasGateWay ? 'PandaCore/GateWay/Video/' : ''; // 配置了gateway或者pc端web配置中有gateway
VideoInfo.url = VideoInfo.useFullUrl VideoInfo.url = VideoInfo.useFullUrl
? VideoInfo.fullUrl ? VideoInfo.fullUrl
: (VideoInfo.pandavmsHost || 'ws://' + location.host + '/') + : (VideoInfo.pandavmsHost || 'ws://' + location.host + '/') +
......
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.57](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_configurationview@1.4.56...@wisdom-components/ec_configurationview@1.4.57) (2023-05-16) ## [1.4.57](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_configurationview@1.4.56...@wisdom-components/ec_configurationview@1.4.57) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/ec_configurationview **Note:** Version bump only for package @wisdom-components/ec_configurationview
## [1.4.56](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_configurationview@1.4.55...@wisdom-components/ec_configurationview@1.4.56) (2023-05-15) ## [1.4.56](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_configurationview@1.4.55...@wisdom-components/ec_configurationview@1.4.56) (2023-05-15)
### Bug Fixes ### Bug Fixes
......
...@@ -75,4 +75,4 @@ export function getVideoDetail(params) { ...@@ -75,4 +75,4 @@ export function getVideoDetail(params) {
method: REQUEST_METHOD_GET, method: REQUEST_METHOD_GET,
params, params,
}); });
} }
\ No newline at end of file
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_historyview@1.11.0...@wisdom-components/ec_historyview@1.11.1) (2023-05-16) ## [1.11.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_historyview@1.11.0...@wisdom-components/ec_historyview@1.11.1) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/ec_historyview **Note:** Version bump only for package @wisdom-components/ec_historyview
# [1.11.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_historyview@1.10.0...@wisdom-components/ec_historyview@1.11.0) (2023-05-12) # [1.11.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_historyview@1.10.0...@wisdom-components/ec_historyview@1.11.0) (2023-05-12)
### Features ### Features
......
...@@ -15,7 +15,7 @@ const SimgleChart = memo((props) => { ...@@ -15,7 +15,7 @@ const SimgleChart = memo((props) => {
deviceAlarmSchemes, deviceAlarmSchemes,
chartType, chartType,
// justLine, // justLine,
showBoxOption showBoxOption,
} = props; } = props;
const chartRef = useRef(); const chartRef = useRef();
...@@ -29,7 +29,7 @@ const SimgleChart = memo((props) => { ...@@ -29,7 +29,7 @@ const SimgleChart = memo((props) => {
showPoint: true, showPoint: true,
chartType, chartType,
// justLine, // justLine,
showBoxOption showBoxOption,
}; };
return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config); return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config);
}, [dataSource, smooth, curveCenter]); }, [dataSource, smooth, curveCenter]);
...@@ -44,9 +44,9 @@ const SimgleChart = memo((props) => { ...@@ -44,9 +44,9 @@ const SimgleChart = memo((props) => {
const option = cloneDeep(chart.getOption()); const option = cloneDeep(chart.getOption());
const needMarkLine = count === 1; const needMarkLine = count === 1;
// 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55 // 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55
let _tempDataArray = dataSource.filter(item => item.sensorName === '是否在线'); let _tempDataArray = dataSource.filter((item) => item.sensorName === '是否在线');
option.series.forEach((item, index) => { option.series.forEach((item, index) => {
let _data = _tempDataArray.find(offline => offline.stationCode === item.stationCode); let _data = _tempDataArray.find((offline) => offline.stationCode === item.stationCode);
let offlineAreas = offlineArea(_data); let offlineAreas = offlineArea(_data);
if (offlineAreas.data?.length) { if (offlineAreas.data?.length) {
option.markArea = null; option.markArea = null;
......
...@@ -23,11 +23,7 @@ const deviceParams = [ ...@@ -23,11 +23,7 @@ const deviceParams = [
}, },
]; ];
const Demo = () => { const Demo = () => {
return ( return <div style={{ height: 700 }}>{/*<HistoryView deviceParams={deviceParams} grid />*/}</div>;
<div style={{ height: 700 }}>
{/*<HistoryView deviceParams={deviceParams} grid />*/}
</div>
);
}; };
export default Demo; export default Demo;
import React, {useContext, useEffect, useMemo, useState} from 'react'; import React, { useContext, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { import {
Checkbox, Checkbox,
ConfigProvider, ConfigProvider,
DatePicker, DatePicker,
Radio, Radio,
Select, Select,
Spin, Spin,
Tabs, Tabs,
Tooltip, Tooltip,
Button, Button,
} from 'antd'; } from 'antd';
import { import {
CloseCircleFilled, CloseCircleFilled,
PlusCircleOutlined, PlusCircleOutlined,
QuestionCircleFilled, QuestionCircleFilled,
DownloadOutlined, DownloadOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import moment from 'moment'; import moment from 'moment';
import _ from 'lodash'; import _ from 'lodash';
import TimeRangePicker from '@wisdom-components/timerangepicker'; import TimeRangePicker from '@wisdom-components/timerangepicker';
import PandaEmpty from '@wisdom-components/empty'; import PandaEmpty from '@wisdom-components/empty';
import BasicTable from '@wisdom-components/basictable'; import BasicTable from '@wisdom-components/basictable';
import {getHistoryInfo, getDeviceAlarmScheme, getExportDeviceHistoryUrl} from './apis'; import { getHistoryInfo, getDeviceAlarmScheme, getExportDeviceHistoryUrl } from './apis';
import SimgleChart from './SingleChart'; import SimgleChart from './SingleChart';
import GridChart from './GridChart'; import GridChart from './GridChart';
import './index.less'; import './index.less';
import {globalConfig} from 'antd/lib/config-provider'; import { globalConfig } from 'antd/lib/config-provider';
const {RangePicker} = DatePicker; const { RangePicker } = DatePicker;
const {Option} = Select; const { Option } = Select;
const startFormat = 'YYYY-MM-DD 00:00:00'; const startFormat = 'YYYY-MM-DD 00:00:00';
const endFormat = 'YYYY-MM-DD 23:59:59'; const endFormat = 'YYYY-MM-DD 23:59:59';
...@@ -38,50 +38,50 @@ const timeFormat = 'YYYY-MM-DD HH:mm:ss'; ...@@ -38,50 +38,50 @@ const timeFormat = 'YYYY-MM-DD HH:mm:ss';
const dateFormat = 'YYYYMMDD'; const dateFormat = 'YYYYMMDD';
const timeList = [ const timeList = [
{ {
key: 'twelveHours', key: 'twelveHours',
name: '近12小时', name: '近12小时',
}, },
{ {
key: 'roundClock', key: 'roundClock',
name: '近24小时', name: '近24小时',
}, },
{ {
key: 'oneWeek', key: 'oneWeek',
name: '近1周', name: '近1周',
}, },
{ {
key: 'oneMonth', key: 'oneMonth',
name: '近1月', name: '近1月',
}, },
]; ];
const CheckboxData = [ const CheckboxData = [
{ {
key: 'curveCenter', key: 'curveCenter',
label: '曲线居中', label: '曲线居中',
checked: false, checked: false,
showInCurve: true, showInCurve: true,
showInTable: false, showInTable: false,
}, },
{ {
key: 'chartGrid', key: 'chartGrid',
label: '图表网格', label: '图表网格',
checked: true, checked: true,
showInCurve: true, showInCurve: true,
showInTable: false, showInTable: false,
}, },
{ {
key: 'ignoreOutliers', key: 'ignoreOutliers',
label: '数据滤波', label: '数据滤波',
type: 'updateIgnoreOutliers', type: 'updateIgnoreOutliers',
checked: false, checked: false,
showInCurve: true, showInCurve: true,
showInTable: true, showInTable: true,
tooltip: '本算法采用递推平均滤波法(滑动平均滤波法)对采样数据进行均值化平滑处理。', tooltip: '本算法采用递推平均滤波法(滑动平均滤波法)对采样数据进行均值化平滑处理。',
}, },
// 需求变更,剔除 // 需求变更,剔除
/* { /* {
key: 'justLine', key: 'justLine',
label: '仅查看曲线', label: '仅查看曲线',
type: '', type: '',
...@@ -89,807 +89,824 @@ const CheckboxData = [ ...@@ -89,807 +89,824 @@ const CheckboxData = [
showInCurve: false, showInCurve: false,
showInTable: false, showInTable: false,
},*/ },*/
{ {
key: 'dataThin', key: 'dataThin',
label: '数据抽稀', label: '数据抽稀',
type: 'updateDataThin', type: 'updateDataThin',
checked: true, checked: true,
showInCurve: false, showInCurve: false,
showInTable: true, showInTable: true,
}, },
]; ];
const timeIntervalList = [ const timeIntervalList = [
{ {
key: '5', key: '5',
zoom: '5', zoom: '5',
unit: 'min', unit: 'min',
name: '5分钟', name: '5分钟',
}, },
{ {
key: '10', key: '10',
zoom: '10', zoom: '10',
unit: 'min', unit: 'min',
name: '10分钟', name: '10分钟',
}, },
{ {
key: '30', key: '30',
zoom: '30', zoom: '30',
unit: 'min', unit: 'min',
name: '30分钟', name: '30分钟',
}, },
{ {
key: '1', key: '1',
zoom: '1', zoom: '1',
unit: 'h', unit: 'h',
name: '1小时', name: '1小时',
}, },
{ {
key: '2', key: '2',
zoom: '2', zoom: '2',
unit: 'h', unit: 'h',
name: '2小时', name: '2小时',
}, },
{ {
key: '4', key: '4',
zoom: '4', zoom: '4',
unit: 'h', unit: 'h',
name: '4小时', name: '4小时',
}, },
{ {
key: '6', key: '6',
zoom: '6', zoom: '6',
unit: 'h', unit: 'h',
name: '6小时', name: '6小时',
}, },
{ {
key: '12', key: '12',
zoom: '12', zoom: '12',
unit: 'h', unit: 'h',
name: '12小时', name: '12小时',
}, },
]; ];
const updateTime = (key) => { const updateTime = (key) => {
let start = ''; let start = '';
let end = ''; let end = '';
if (Array.isArray(key)) { if (Array.isArray(key)) {
start = moment(key[0]).format(timeFormat); start = moment(key[0]).format(timeFormat);
end = moment(key[1]).format(timeFormat); end = moment(key[1]).format(timeFormat);
} else { } else {
switch (key) { switch (key) {
case 'twelveHours': case 'twelveHours':
start = moment().subtract(12, 'hour').format(timeFormat); start = moment().subtract(12, 'hour').format(timeFormat);
end = moment().format(timeFormat); end = moment().format(timeFormat);
break; break;
case 'roundClock': case 'roundClock':
start = moment().subtract(24, 'hour').format(timeFormat); start = moment().subtract(24, 'hour').format(timeFormat);
end = moment().format(timeFormat); end = moment().format(timeFormat);
break; break;
case 'oneWeek': case 'oneWeek':
start = moment().subtract(7, 'day').format(timeFormat); start = moment().subtract(7, 'day').format(timeFormat);
end = moment().format(timeFormat); end = moment().format(timeFormat);
break; break;
case 'oneMonth': case 'oneMonth':
start = moment().subtract(30, 'day').format(timeFormat); start = moment().subtract(30, 'day').format(timeFormat);
end = moment().format(timeFormat); end = moment().format(timeFormat);
break; break;
}
} }
return [ }
{ return [
dateFrom: start, {
dateTo: end, dateFrom: start,
}, dateTo: end,
]; },
];
}; };
const DefaultDatePicker = (value) => [ const DefaultDatePicker = (value) => [
{ {
key: 1, key: 1,
value: moment(), value: moment(),
}, },
{ {
key: 2, key: 2,
value: moment().subtract(1, value), value: moment().subtract(1, value),
}, },
]; ];
const handleBatchTime = (arr, cOption) => { const handleBatchTime = (arr, cOption) => {
let newArr = []; let newArr = [];
arr.forEach((child) => { arr.forEach((child) => {
if (child.value) { if (child.value) {
newArr.push({ newArr.push({
dateFrom: moment(child.value).startOf(cOption).format(startFormat), dateFrom: moment(child.value).startOf(cOption).format(startFormat),
dateTo: moment(child.value).endOf(cOption).format(endFormat), dateTo: moment(child.value).endOf(cOption).format(endFormat),
}); });
} }
}); });
newArr = _.uniqWith(newArr, _.isEqual); // 去掉重复日期时间 newArr = _.uniqWith(newArr, _.isEqual); // 去掉重复日期时间
return newArr; return newArr;
}; };
const timeColumn = { const timeColumn = {
title: '采集时间', title: '采集时间',
dataIndex: 'time', dataIndex: 'time',
key: 'time', key: 'time',
width: 170, width: 170,
fixed: 'left', fixed: 'left',
ellipsis: true, ellipsis: true,
align: 'center', align: 'center',
}; };
const HistoryView = (props) => { const HistoryView = (props) => {
const {getPrefixCls} = useContext(ConfigProvider.ConfigContext); const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('history-view'); const prefixCls = getPrefixCls('history-view');
const { const {
title, title,
grid, grid,
defaultChecked, defaultChecked,
tableProps, tableProps,
deviceParams, deviceParams,
defaultModel, defaultModel,
showModels, showModels,
needMarkLine, needMarkLine,
} = props; } = props;
const isBoxPlots = deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1; const isBoxPlots =
const [loading, setLoading] = useState(false); deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1;
const [activeTabKey, setActiveTabKey] = useState(defaultModel); const [loading, setLoading] = useState(false);
const [activeTabKey, setActiveTabKey] = useState(defaultModel);
// 时间模式: 自定义模式/同期对比模式
const [timeValue, setTimeValue] = useState('customer'); // 时间模式: 自定义模式/同期对比模式
const [timeValue, setTimeValue] = useState('customer');
// 自定义模式
const [customerChecked, setCustomerChecked] = useState(defaultChecked); // 时间快速选择类型值 // 自定义模式
const [customerTime, setCustomerTime] = useState(); // 自定义时间选择值 const [customerChecked, setCustomerChecked] = useState(defaultChecked); // 时间快速选择类型值
const [customerTime, setCustomerTime] = useState(); // 自定义时间选择值
// 同期对比模式
const [contrastOption, setContrastOption] = useState('day'); // 对比时间类型: 日/月 // 同期对比模式
const [datePickerArr, setDatePickerArr] = useState(DefaultDatePicker('day')); // 对比时间段配置值 const [contrastOption, setContrastOption] = useState('day'); // 对比时间类型: 日/月
const [datePickerArr, setDatePickerArr] = useState(DefaultDatePicker('day')); // 对比时间段配置值
const [checkboxData, setCheckboxData] = useState(() => [...CheckboxData]); // 曲线设置项
const [dataThinKey, setDataThinKey] = useState(timeIntervalList[0].key); // 曲线抽稀时间设置 const [checkboxData, setCheckboxData] = useState(() => [...CheckboxData]); // 曲线设置项
const [dataThinKey, setDataThinKey] = useState(timeIntervalList[0].key); // 曲线抽稀时间设置
const [columns, setColumns] = useState([]);
const [tableData, setTableData] = useState([]); const [columns, setColumns] = useState([]);
const [chartDataSource, setChartDataSource] = useState([]); const [tableData, setTableData] = useState([]);
const [chartDataSource, setChartDataSource] = useState([]);
const [chartType, setChartType] = useState('lineChart');
const [showBoxOption, setShowBoxOption] = useState(true); const [chartType, setChartType] = useState('lineChart');
// 选择的时间范围值 const [showBoxOption, setShowBoxOption] = useState(true);
const dateRange = useMemo(() => { // 选择的时间范围值
if (timeValue === 'customer') { const dateRange = useMemo(() => {
return updateTime(customerChecked || customerTime); if (timeValue === 'customer') {
} else { return updateTime(customerChecked || customerTime);
return handleBatchTime(datePickerArr, contrastOption); } else {
} return handleBatchTime(datePickerArr, contrastOption);
}, [contrastOption, customerChecked, customerTime, datePickerArr, timeValue]); }
}, [contrastOption, customerChecked, customerTime, datePickerArr, timeValue]);
const configDependence = checkboxData
.filter((item) => ['curveCenter', 'chartGrid'].indexOf(item.key) === -1) const configDependence = checkboxData
.map((item) => item.checked) .filter((item) => ['curveCenter', 'chartGrid'].indexOf(item.key) === -1)
.join(','); .map((item) => item.checked)
// 数据配置 .join(',');
const dataConfig = useMemo(() => { // 数据配置
const initial = { const dataConfig = useMemo(() => {
ignoreOutliers: false, const initial = {
dataThin: false, ignoreOutliers: false,
zoom: '', // 数据抽稀时间 dataThin: false,
unit: '', // 数据抽稀时间单位 zoom: '', // 数据抽稀时间
}; unit: '', // 数据抽稀时间单位
// 曲线居中,过滤异常值,数据抽稀
const config = checkboxData.reduce(
(pre, item) => (item.key !== 'curveCenter' && (pre[item.key] = item.checked), pre),
initial,
);
// 数据抽稀时间单位
const dataThin = timeIntervalList.find((item) => item.key === dataThinKey);
config.zoom = activeTabKey === 'curve' ? '' : dataThin?.zoom ?? '';
config.unit = activeTabKey === 'curve' ? '' : dataThin?.unit ?? '';
config.dataThin = activeTabKey === 'curve' ? true : config.dataThin; // 曲线强制抽稀
return config;
}, [configDependence, dataThinKey, activeTabKey]);
// 图表居中
const [curveCenter, chartGrid] = useMemo(() => {
const curveCenter = checkboxData.find((item) => item.key === 'curveCenter')?.checked;
const chartGrid = checkboxData.find((item) => item.key === 'chartGrid')?.checked;
return [curveCenter, chartGrid];
}, [checkboxData]);
// 自定义模式: 快速选择
const onCustomerTimeChange = (key) => {
setCustomerChecked(key);
!!customerTime && setCustomerTime(null);
};
// 自定义模式: 自定义时间选择
const onCustomerRangeChange = (value) => {
if (!value) {
// 时间清空,回到默认时间选择
setCustomerChecked(defaultChecked);
setCustomerTime(value);
} else {
setCustomerChecked(null);
setCustomerTime(value);
}
};
// 同期对比模式: 选择(日/月)
const onContrastChange = (value) => {
setContrastOption(value);
setDatePickerArr([...DefaultDatePicker(value)]);
};
// 同期对比模式: 时间段选择
const onContrastPickerChange = (date, dateString, item) => {
const arr = [...datePickerArr];
arr.forEach((child) => {
if (child.key === item.key) {
child.value = date;
}
});
setDatePickerArr(arr);
};
// 同期对比模式: 新增日期选择组件
const handleAddDatePicker = () => {
setDatePickerArr([
...datePickerArr,
{
key: datePickerArr[datePickerArr.length - 1].key + 1,
value: '',
},
]);
}; };
// 曲线居中,过滤异常值,数据抽稀
const config = checkboxData.reduce(
(pre, item) => (item.key !== 'curveCenter' && (pre[item.key] = item.checked), pre),
initial,
);
// 数据抽稀时间单位
const dataThin = timeIntervalList.find((item) => item.key === dataThinKey);
config.zoom = activeTabKey === 'curve' ? '' : dataThin?.zoom ?? '';
config.unit = activeTabKey === 'curve' ? '' : dataThin?.unit ?? '';
config.dataThin = activeTabKey === 'curve' ? true : config.dataThin; // 曲线强制抽稀
return config;
}, [configDependence, dataThinKey, activeTabKey]);
// 图表居中
const [curveCenter, chartGrid] = useMemo(() => {
const curveCenter = checkboxData.find((item) => item.key === 'curveCenter')?.checked;
const chartGrid = checkboxData.find((item) => item.key === 'chartGrid')?.checked;
return [curveCenter, chartGrid];
}, [checkboxData]);
// 自定义模式: 快速选择
const onCustomerTimeChange = (key) => {
setCustomerChecked(key);
!!customerTime && setCustomerTime(null);
};
// 自定义模式: 自定义时间选择
const onCustomerRangeChange = (value) => {
if (!value) {
// 时间清空,回到默认时间选择
setCustomerChecked(defaultChecked);
setCustomerTime(value);
} else {
setCustomerChecked(null);
setCustomerTime(value);
}
};
// 同期对比模式: 删除日期选择组件 // 同期对比模式: 选择(日/月)
const handleDeleteDatePicker = (index) => { const onContrastChange = (value) => {
const arr = [...datePickerArr]; setContrastOption(value);
arr.splice(index, 1); setDatePickerArr([...DefaultDatePicker(value)]);
setDatePickerArr(arr); };
};
// 时间设置切换(自定义/同期对比) // 同期对比模式: 时间段选择
const onTimeSetChange = (e) => { const onContrastPickerChange = (date, dateString, item) => {
setTimeValue(e.target.value); const arr = [...datePickerArr];
if (e.target.value === 'contrast') { arr.forEach((child) => {
// 同期对比 if (child.key === item.key) {
onContrastChange(contrastOption); child.value = date;
setShowBoxOption(false); }
setChartType('lineChart'); });
onCheckboxChange({target: {value: false}}, 'chartType'); setDatePickerArr(arr);
onCheckboxChange({target: {value: false}}, 'ignoreOutliers'); };
} else {
// 自定义 // 同期对比模式: 新增日期选择组件
// 不需要处理 const handleAddDatePicker = () => {
setShowBoxOption(true); setDatePickerArr([
onCheckboxChange({target: {value: true}}, 'chartType'); ...datePickerArr,
} {
}; key: datePickerArr[datePickerArr.length - 1].key + 1,
value: '',
},
]);
};
// 同期对比模式: 删除日期选择组件
const handleDeleteDatePicker = (index) => {
const arr = [...datePickerArr];
arr.splice(index, 1);
setDatePickerArr(arr);
};
// 时间设置切换(自定义/同期对比)
const onTimeSetChange = (e) => {
setTimeValue(e.target.value);
if (e.target.value === 'contrast') {
// 同期对比
onContrastChange(contrastOption);
setShowBoxOption(false);
setChartType('lineChart');
onCheckboxChange({ target: { value: false } }, 'chartType');
onCheckboxChange({ target: { value: false } }, 'ignoreOutliers');
} else {
// 自定义
// 不需要处理
setShowBoxOption(true);
onCheckboxChange({ target: { value: true } }, 'chartType');
}
};
const renderTimeOption = () => { const renderTimeOption = () => {
return ( return (
<div className={classNames(`${prefixCls}-date`)}> <div className={classNames(`${prefixCls}-date`)}>
<div className={classNames(`${prefixCls}-label`)}>时间选择</div> <div className={classNames(`${prefixCls}-label`)}>时间选择</div>
<Radio.Group value={timeValue} onChange={onTimeSetChange}> <Radio.Group value={timeValue} onChange={onTimeSetChange}>
<Radio.Button value="customer">自定义</Radio.Button> <Radio.Button value="customer">自定义</Radio.Button>
<Radio.Button value="contrast">同期对比</Radio.Button> <Radio.Button value="contrast">同期对比</Radio.Button>
</Radio.Group> </Radio.Group>
{timeValue === 'customer' && ( // 自定义 {timeValue === 'customer' && ( // 自定义
<> <>
<TimeRangePicker <TimeRangePicker
onChange={onCustomerTimeChange} onChange={onCustomerTimeChange}
value={customerChecked} value={customerChecked}
dataSource={timeList} dataSource={timeList}
/> />
<RangePicker <RangePicker
className={classNames(`${prefixCls}-custime-customer`)} className={classNames(`${prefixCls}-custime-customer`)}
onChange={onCustomerRangeChange} onChange={onCustomerRangeChange}
value={customerTime} value={customerTime}
showTime showTime
/> />
</> </>
)} )}
{timeValue === 'contrast' && ( // 同期对比 {timeValue === 'contrast' && ( // 同期对比
<> <>
<Select value={contrastOption} style={{width: 60}} onChange={onContrastChange}> <Select value={contrastOption} style={{ width: 60 }} onChange={onContrastChange}>
<Option value="day"></Option> <Option value="day"></Option>
<Option value="month"></Option> <Option value="month"></Option>
</Select> </Select>
{datePickerArr.map((child, index) => ( {datePickerArr.map((child, index) => (
<div key={child.key} className={classNames(`${prefixCls}-contrast-list`)}> <div key={child.key} className={classNames(`${prefixCls}-contrast-list`)}>
<div className={classNames(`${prefixCls}-contrast-wrap`)}> <div className={classNames(`${prefixCls}-contrast-wrap`)}>
<DatePicker <DatePicker
picker={contrastOption} picker={contrastOption}
value={child.value} value={child.value}
onChange={(date, dateString) => onContrastPickerChange(date, dateString, child)} onChange={(date, dateString) => onContrastPickerChange(date, dateString, child)}
/> />
{datePickerArr.length > 2 && ( {datePickerArr.length > 2 && (
<div <div
className={classNames(`${prefixCls}-contrast-delete`)} className={classNames(`${prefixCls}-contrast-delete`)}
onClick={() => handleDeleteDatePicker(index)} onClick={() => handleDeleteDatePicker(index)}
> >
<CloseCircleFilled/> <CloseCircleFilled />
</div> </div>
)} )}
</div> </div>
{index < datePickerArr.length - 1 && ( {index < datePickerArr.length - 1 && (
<div className={classNames(`${prefixCls}-contrast-connect`)}></div> <div className={classNames(`${prefixCls}-contrast-connect`)}></div>
)}
</div>
))}
{datePickerArr.length < 5 && <PlusCircleOutlined onClick={handleAddDatePicker}/>}
</>
)} )}
</div> </div>
); ))}
}; {datePickerArr.length < 5 && <PlusCircleOutlined onClick={handleAddDatePicker} />}
</>
// 曲线设置项选择/取消 )}
const onCheckboxChange = (e, key, showJustLine) => { </div>
let data = [...checkboxData]; );
// let _index = data.findIndex(item => item.key === 'justLine'); // 仅查看曲线会在勾选了数据滤波后展示 };
let _index1 = data.findIndex(item => item.key === 'ignoreOutliers'); // 仅查看曲线会在勾选了数据滤波后展示
data.forEach((item) => { // 曲线设置项选择/取消
if (item.key === key) { const onCheckboxChange = (e, key, showJustLine) => {
item.checked = e.target.checked; let data = [...checkboxData];
} // let _index = data.findIndex(item => item.key === 'justLine'); // 仅查看曲线会在勾选了数据滤波后展示
}); let _index1 = data.findIndex((item) => item.key === 'ignoreOutliers'); // 仅查看曲线会在勾选了数据滤波后展示
if (key === 'ignoreOutliers') { data.forEach((item) => {
// 需求变更,仅查看曲线剔除 if (item.key === key) {
/* if (showJustLine) { item.checked = e.target.checked;
}
});
if (key === 'ignoreOutliers') {
// 需求变更,仅查看曲线剔除
/* if (showJustLine) {
data[_index].showInCurve = e.target.checked; data[_index].showInCurve = e.target.checked;
data[_index].checked = e.target.checked; data[_index].checked = e.target.checked;
} else {*/ } else {*/
data[_index1].showInCurve = true; data[_index1].showInCurve = true;
// data[_index1].checked = false; // data[_index1].checked = false;
// } // }
} }
if (key === 'chartType') { if (key === 'chartType') {
data[_index1].showInCurve = e.target.value; data[_index1].showInCurve = e.target.value;
data[_index1].checked = false; data[_index1].checked = false;
// data[_index].showInCurve = false; // data[_index].showInCurve = false;
// data[_index].checked = false; // data[_index].checked = false;
} }
setCheckboxData(data); setCheckboxData(data);
}; };
// 数据抽稀时间间隔 // 数据抽稀时间间隔
const onTimeIntervalChange = (value) => { const onTimeIntervalChange = (value) => {
setDataThinKey(value); setDataThinKey(value);
}; };
const renderCheckbox = (child, showJustLine) => { const renderCheckbox = (child, showJustLine) => {
const curveAccess = activeTabKey === 'curve' && child.showInCurve; const curveAccess = activeTabKey === 'curve' && child.showInCurve;
const tableAccess = activeTabKey === 'table' && child.showInTable; const tableAccess = activeTabKey === 'table' && child.showInTable;
const gridOptions = ['curveCenter']; const gridOptions = ['curveCenter'];
if (grid && curveAccess && gridOptions.indexOf(child.key) === -1) return null;
return (
(curveAccess || tableAccess) && (
<>
<Checkbox checked={child.checked} onChange={(e) => onCheckboxChange(e, child.key)}>
{child.label}
</Checkbox>
{child.tooltip && (
<Tooltip title={child.tooltip}>
<QuestionCircleFilled className={`${prefixCls}-question`}/>
</Tooltip>
)}
</>
)
);
};
const renderCurveOption = (isChart, isSingle) => { if (grid && curveAccess && gridOptions.indexOf(child.key) === -1) return null;
return ( return (
<div className={classNames(`${prefixCls}-cover`)} style={isChart && isSingle ? {width: '100%'} : {}}> (curveAccess || tableAccess) && (
{ <>
isChart && isSingle && showBoxOption ? <> <Checkbox checked={child.checked} onChange={(e) => onCheckboxChange(e, child.key)}>
<div className={classNames(`${prefixCls}-label`)}>曲线形态</div> {child.label}
<Radio.Group value={chartType} style={{marginRight: 16}} onChange={(e) => { </Checkbox>
let _value = e.target.value; {child.tooltip && (
setChartType(_value); <Tooltip title={child.tooltip}>
onCheckboxChange({target: {value: _value !== 'boxChart'}}, 'chartType') <QuestionCircleFilled className={`${prefixCls}-question`} />
}}> </Tooltip>
<Radio.Button value={'lineChart'}>线形图</Radio.Button> )}
<Radio.Button value={'boxChart'}>箱线图</Radio.Button> </>
</Radio.Group></> : '' )
} );
<div className={classNames(`${prefixCls}-label`)}>曲线设置</div> };
{checkboxData.map((child) => {
const box = renderCheckbox(child, (isChart && isSingle)); const renderCurveOption = (isChart, isSingle) => {
if (!box) return null; return (
return ( <div
<div key={child.key} className={`${prefixCls}-cover-item`}> className={classNames(`${prefixCls}-cover`)}
{box} style={isChart && isSingle ? { width: '100%' } : {}}
</div> >
); {isChart && isSingle && showBoxOption ? (
})} <>
{activeTabKey === 'table' && ( <div className={classNames(`${prefixCls}-label`)}>曲线形态</div>
<Select <Radio.Group
value={dataThinKey} value={chartType}
style={{width: 90}} style={{ marginRight: 16 }}
onChange={onTimeIntervalChange} onChange={(e) => {
disabled={!dataConfig.dataThin} let _value = e.target.value;
> setChartType(_value);
{timeIntervalList.map((child) => ( onCheckboxChange({ target: { value: _value !== 'boxChart' } }, 'chartType');
<Option key={child.key} unit={child.unit} value={child.key}> }}
{child.name} >
</Option> <Radio.Button value={'lineChart'}>线形图</Radio.Button>
))} <Radio.Button value={'boxChart'}>箱线图</Radio.Button>
</Select> </Radio.Group>
)} </>
) : (
''
)}
<div className={classNames(`${prefixCls}-label`)}>曲线设置</div>
{checkboxData.map((child) => {
const box = renderCheckbox(child, isChart && isSingle);
if (!box) return null;
return (
<div key={child.key} className={`${prefixCls}-cover-item`}>
{box}
</div> </div>
); );
}; })}
{activeTabKey === 'table' && (
<Select
value={dataThinKey}
style={{ width: 90 }}
onChange={onTimeIntervalChange}
disabled={!dataConfig.dataThin}
>
{timeIntervalList.map((child) => (
<Option key={child.key} unit={child.unit} value={child.key}>
{child.name}
</Option>
))}
</Select>
)}
</div>
);
};
const exportExcelBtn = () => {
deviceParams.forEach((i, r) => {
let timeFrom = dateRange[r]?.dateFrom || moment().format(startFormat);
let timeTo = dateRange[r]?.dateTo || moment().format(timeFormat);
let fileName = `数据报表-${i.deviceType}-${i.deviceCode}-${moment(timeFrom).format(
dateFormat,
)}${moment(timeTo).format(dateFormat)}`;
getExportDeviceHistoryUrl({
deviceType: i.deviceType,
deviceCode: i.deviceCode,
quotas: i.sensors,
startTime: timeFrom,
endTime: timeTo,
fileName: fileName,
})
.then((res) => {
if (res && res.code === -1) return message.error(res.msg);
const url = `${window.location.origin}/PandaCore/GCK/FileHandleContoller/Download/name?name=${res.data}&_site=${globalConfig?.userInfo?.site}`;
const aDom = document.createElement('a');
aDom.href = url;
aDom.click();
aDom.remove();
})
.catch((err) => {});
});
};
const exportExcelBtn = () => { const handleTableData = (data) => {
deviceParams.forEach((i, r) => { const ignoreOutliers = checkboxData.find((item) => item.key === 'ignoreOutliers').checked;
let timeFrom = dateRange[r]?.dateFrom || moment().format(startFormat); const dataIndexAccess = (dataItem, index) => {
let timeTo = dateRange[r]?.dateTo || moment().format(timeFormat); const { stationCode, sensorName } = dataItem;
let fileName = `数据报表-${i.deviceType}-${i.deviceCode}-${moment(timeFrom).format( return `${stationCode}-${sensorName}-${index}`;
dateFormat,
)}${moment(timeTo).format(dateFormat)}`;
getExportDeviceHistoryUrl({
deviceType: i.deviceType,
deviceCode: i.deviceCode,
quotas: i.sensors,
startTime: timeFrom,
endTime: timeTo,
fileName: fileName,
})
.then((res) => {
if (res && res.code === -1) return message.error(res.msg);
const url = `${window.location.origin}/PandaCore/GCK/FileHandleContoller/Download/name?name=${res.data}&_site=${globalConfig?.userInfo?.site}`;
const aDom = document.createElement('a');
aDom.href = url;
aDom.click();
aDom.remove();
})
.catch((err) => {
});
});
}; };
const handleTableData = (data) => { let format = timeFormat;
const ignoreOutliers = checkboxData.find((item) => item.key === 'ignoreOutliers').checked; if (timeValue === 'contrast') {
const dataIndexAccess = (dataItem, index) => { format = contrastOption === 'day' ? '2020-01-01 HH:mm:00' : '2020-01-DD HH:mm:00';
const {stationCode, sensorName} = dataItem; }
return `${stationCode}-${sensorName}-${index}`;
};
let format = timeFormat;
if (timeValue === 'contrast') {
format = contrastOption === 'day' ? '2020-01-01 HH:mm:00' : '2020-01-DD HH:mm:00';
}
// 处理表头数据
const columnsData = data.map((item, index) => {
const {stationCode, equipmentName, sensorName, unit, dataModel} = item;
const dataIndex = dataIndexAccess(item, index);
let col = {
title: `${equipmentName}-${sensorName}${unit ? `(${unit})` : ''}`,
dataIndex: dataIndex,
key: dataIndex,
ellipsis: true,
align: 'center',
};
// 同期对比
if (timeValue === 'contrast' && dataModel[0]) {
const time = item.dataModel[0].pt
.slice(0, contrastOption === 'day' ? 10 : 7)
.replace(/-/g, '');
col.title = `${equipmentName}-${sensorName}-${time}`;
}
return col;
});
// 格式化时间对齐数据, 生成行数
const timeData = {};
const buildDefaultData = (time) => { // 处理表头数据
const obj = {key: time, time: time}; const columnsData = data.map((item, index) => {
data.forEach((item, index) => { const { stationCode, equipmentName, sensorName, unit, dataModel } = item;
const dataIndex = dataIndexAccess(item, index); const dataIndex = dataIndexAccess(item, index);
obj[dataIndex] = ''; let col = {
}); title: `${equipmentName}-${sensorName}${unit ? `(${unit})` : ''}`,
return obj; dataIndex: dataIndex,
}; key: dataIndex,
data.forEach((item, index) => { ellipsis: true,
const {stationCode, sensorName, dataModel} = item; align: 'center',
dataModel.forEach((data) => { };
const formatTime = moment(data.pt).format(format); // 同期对比
if (timeValue === 'contrast' && dataModel[0]) {
let time = formatTime; const time = item.dataModel[0].pt
if (timeValue === 'contrast') { .slice(0, contrastOption === 'day' ? 10 : 7)
time = time.slice(contrastOption === 'day' ? 11 : 8, 16); .replace(/-/g, '');
} col.title = `${equipmentName}-${sensorName}-${time}`;
}
timeData[formatTime] = timeData[formatTime] || buildDefaultData(time); return col;
}); });
});
// 处理表格数据 // 格式化时间对齐数据, 生成行数
data.forEach((child, index) => { const timeData = {};
const {dataModel} = child;
const dataIndex = dataIndexAccess(child, index);
dataModel.forEach((value, j) => {
const formatTime = moment(value.pt).format(format);
const dataRow = timeData[formatTime];
if (dataRow) {
dataRow[dataIndex] = value.pv === null || value.pv === undefined ? '' : value.pv;
}
});
});
const timeSort = (a, b) => {
let aa = a,
bb = b;
if (timeValue === 'contrast') {
aa = a.slice(contrastOption === 'day' ? 11 : 8, 16);
bb = b.slice(contrastOption === 'day' ? 11 : 8, 16);
}
return aa.localeCompare(bb);
};
const times = Object.keys(timeData).sort(timeSort);
const tableData = times.map((time) => timeData[time]);
setColumns([timeColumn, ...columnsData]);
setTableData(tableData);
};
const [deviceAlarmSchemes, setDeviceAlarmSchemes] = useState([]); const buildDefaultData = (time) => {
const beforChangeParams = (value = {}) => { const obj = { key: time, time: time };
if (!needMarkLine) return Promise.resolve(); data.forEach((item, index) => {
return getDeviceAlarmScheme({ const dataIndex = dataIndexAccess(item, index);
data: deviceParams.map((item) => ({ obj[dataIndex] = '';
deviceType: item.deviceType, });
deviceCode: item.deviceCode, return obj;
pointAddressID: item.pointAddressID,
sensorName: item.sensors,
})),
})
.then((res) => {
if (res.code === 0) setDeviceAlarmSchemes(res.data || []);
else setDeviceAlarmSchemes([]);
return Promise.resolve();
})
.catch((err) => {
setDeviceAlarmSchemes([]);
return Promise.resolve();
});
}; };
data.forEach((item, index) => {
const { stationCode, sensorName, dataModel } = item;
dataModel.forEach((data) => {
const formatTime = moment(data.pt).format(format);
const handleDataThinKey = (diffDays) => { let time = formatTime;
// edit by zy 根据选择的时长控制抽稀频度 if (timeValue === 'contrast') {
if (diffDays >= 7 && diffDays < 15) { time = time.slice(contrastOption === 'day' ? 11 : 8, 16);
return {unit: 'h', zoom: '2'};
} else if (diffDays >= 15 && diffDays < 30) {
return {unit: 'h', zoom: '4'};
} else if (diffDays >= 30) {
return {unit: 'h', zoom: '6'};
} else if (diffDays < 7 && diffDays >= 2) {
return {unit: 'min', zoom: '40'};
} else if (diffDays < 2 && diffDays >= 1) {
return {unit: 'min', zoom: '30'};
} else {
return {unit: 'min', zoom: '10'};
} }
};
// 处理接口服务参数的变化 timeData[formatTime] = timeData[formatTime] || buildDefaultData(time);
const onChangeParams = (value = {}) => { });
const {dateRange, isDilute, ignoreOutliers, zoom, unit} = value; });
const requestArr = [];
const acrossTables = []; // 处理表格数据
deviceParams.map(item => { data.forEach((child, index) => {
let _item = {...item}; const { dataModel } = child;
_item.sensors = (item.sensors && !item.sensors.includes('是否在线')) ? item.sensors + ',是否在线' : item.sensors; const dataIndex = dataIndexAccess(child, index);
return _item; dataModel.forEach((value, j) => {
}).forEach((i) => { const formatTime = moment(value.pt).format(format);
if (i.sensors && i.deviceCode && i.deviceCode) const dataRow = timeData[formatTime];
acrossTables.push(_.omit(i, ['pointAddressID'])); if (dataRow) {
}); dataRow[dataIndex] = value.pv === null || value.pv === undefined ? '' : value.pv;
if (!acrossTables?.length) {
handleTableData([]);
setChartDataSource([]);
return;
} }
dateRange.forEach((item) => { });
// let _showLine = checkboxData.find(item => item.key === 'justLine'); });
const param = { const timeSort = (a, b) => {
isDilute, let aa = a,
zoom, bb = b;
unit, if (timeValue === 'contrast') {
ignoreOutliers, aa = a.slice(contrastOption === 'day' ? 11 : 8, 16);
// isVertical: false, // 是否查询竖表 bb = b.slice(contrastOption === 'day' ? 11 : 8, 16);
dateFrom: item.dateFrom, }
dateTo: item.dateTo, return aa.localeCompare(bb);
acrossTables,
isBoxPlots: isBoxPlots
};
let diffDays = moment(item.dateTo).diff(moment(item.dateFrom), 'days');
let zoomParam = activeTabKey === 'curve' ? handleDataThinKey(diffDays) : {};
requestArr.push(getHistoryInfo({...param, ...zoomParam}));
});
setLoading(true);
Promise.all(requestArr).then((results) => {
if (results.length) {
let data = [];
results.forEach((res, index) => {
const {dateFrom, dateTo} = dateRange?.[index] ?? {};
if (res.code === 0 && res.data.length) {
res.data.forEach((d) => {
d.dateFrom = dateFrom;
d.dateTo = dateTo;
});
deviceParams.forEach((p) => {
// 返回数据按查询指标顺序排序
const sensors = p.sensors?.split(',') ?? [];
const list = sensors.map((s) => {
const dataItem = res.data.find(
(d) => d.stationCode === p.deviceCode && d.sensorName === s,
);
dataItem.dateFrom = dateFrom;
dataItem.dateTo = dateTo;
return dataItem;
});
data = data.concat(list);
});
}
});
setLoading(false);
handleTableData(data);
setChartDataSource(data);
}
});
}; };
const times = Object.keys(timeData).sort(timeSort);
useEffect(() => { const tableData = times.map((time) => timeData[time]);
const {dataThin, ignoreOutliers, zoom, unit} = dataConfig; setColumns([timeColumn, ...columnsData]);
beforChangeParams().finally(() => { setTableData(tableData);
onChangeParams({ };
isDilute: dataThin,
ignoreOutliers, const [deviceAlarmSchemes, setDeviceAlarmSchemes] = useState([]);
zoom, const beforChangeParams = (value = {}) => {
unit, if (!needMarkLine) return Promise.resolve();
dateRange, return getDeviceAlarmScheme({
isBoxPlots: isBoxPlots data: deviceParams.map((item) => ({
deviceType: item.deviceType,
deviceCode: item.deviceCode,
pointAddressID: item.pointAddressID,
sensorName: item.sensors,
})),
})
.then((res) => {
if (res.code === 0) setDeviceAlarmSchemes(res.data || []);
else setDeviceAlarmSchemes([]);
return Promise.resolve();
})
.catch((err) => {
setDeviceAlarmSchemes([]);
return Promise.resolve();
});
};
const handleDataThinKey = (diffDays) => {
// edit by zy 根据选择的时长控制抽稀频度
if (diffDays >= 7 && diffDays < 15) {
return { unit: 'h', zoom: '2' };
} else if (diffDays >= 15 && diffDays < 30) {
return { unit: 'h', zoom: '4' };
} else if (diffDays >= 30) {
return { unit: 'h', zoom: '6' };
} else if (diffDays < 7 && diffDays >= 2) {
return { unit: 'min', zoom: '40' };
} else if (diffDays < 2 && diffDays >= 1) {
return { unit: 'min', zoom: '30' };
} else {
return { unit: 'min', zoom: '10' };
}
};
// 处理接口服务参数的变化
const onChangeParams = (value = {}) => {
const { dateRange, isDilute, ignoreOutliers, zoom, unit } = value;
const requestArr = [];
const acrossTables = [];
deviceParams
.map((item) => {
let _item = { ...item };
_item.sensors =
item.sensors && !item.sensors.includes('是否在线')
? item.sensors + ',是否在线'
: item.sensors;
return _item;
})
.forEach((i) => {
if (i.sensors && i.deviceCode && i.deviceCode)
acrossTables.push(_.omit(i, ['pointAddressID']));
});
if (!acrossTables?.length) {
handleTableData([]);
setChartDataSource([]);
return;
}
dateRange.forEach((item) => {
// let _showLine = checkboxData.find(item => item.key === 'justLine');
const param = {
isDilute,
zoom,
unit,
ignoreOutliers,
// isVertical: false, // 是否查询竖表
dateFrom: item.dateFrom,
dateTo: item.dateTo,
acrossTables,
isBoxPlots: isBoxPlots,
};
let diffDays = moment(item.dateTo).diff(moment(item.dateFrom), 'days');
let zoomParam = activeTabKey === 'curve' ? handleDataThinKey(diffDays) : {};
requestArr.push(getHistoryInfo({ ...param, ...zoomParam }));
});
setLoading(true);
Promise.all(requestArr).then((results) => {
if (results.length) {
let data = [];
results.forEach((res, index) => {
const { dateFrom, dateTo } = dateRange?.[index] ?? {};
if (res.code === 0 && res.data.length) {
res.data.forEach((d) => {
d.dateFrom = dateFrom;
d.dateTo = dateTo;
}); });
deviceParams.forEach((p) => {
// 返回数据按查询指标顺序排序
const sensors = p.sensors?.split(',') ?? [];
const list = sensors.map((s) => {
const dataItem = res.data.find(
(d) => d.stationCode === p.deviceCode && d.sensorName === s,
);
dataItem.dateFrom = dateFrom;
dataItem.dateTo = dateTo;
return dataItem;
});
data = data.concat(list);
});
}
}); });
}, [dateRange, dataConfig, deviceParams, chartType]); setLoading(false);
handleTableData(data);
const renderPanel = (model) => { setChartDataSource(data);
if (model === 'curve') { }
return ( });
<> };
<div className={`${prefixCls}-options`}>
{renderTimeOption()} useEffect(() => {
{renderCurveOption(true, (deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1))} const { dataThin, ignoreOutliers, zoom, unit } = dataConfig;
</div> beforChangeParams().finally(() => {
<div className={`${prefixCls}-content`}> onChangeParams({
{!chartDataSource.length ? ( isDilute: dataThin,
<PandaEmpty/> ignoreOutliers,
) : grid === true ? ( zoom,
<GridChart unit,
curveCenter={curveCenter} dateRange,
prefixCls={prefixCls} isBoxPlots: isBoxPlots,
dataSource={chartDataSource} });
contrast={timeValue === 'contrast'} });
contrastOption={contrastOption} }, [dateRange, dataConfig, deviceParams, chartType]);
deviceAlarmSchemes={deviceAlarmSchemes}
/> const renderPanel = (model) => {
) : ( if (model === 'curve') {
<SimgleChart return (
showBoxOption={showBoxOption} <>
curveCenter={curveCenter} <div className={`${prefixCls}-options`}>
showGridLine={chartGrid} {renderTimeOption()}
prefixCls={prefixCls} {renderCurveOption(
dataSource={chartDataSource} true,
// justLine={!!checkboxData.find(item => item.key === 'justLine' && item.checked)} deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1,
chartType={isBoxPlots ? chartType : null} )}
contrast={timeValue === 'contrast'} </div>
contrastOption={contrastOption} <div className={`${prefixCls}-content`}>
deviceAlarmSchemes={deviceAlarmSchemes} {!chartDataSource.length ? (
/> <PandaEmpty />
)} ) : grid === true ? (
</div> <GridChart
</> curveCenter={curveCenter}
); prefixCls={prefixCls}
} dataSource={chartDataSource}
if (model === 'table') { contrast={timeValue === 'contrast'}
return ( contrastOption={contrastOption}
<> deviceAlarmSchemes={deviceAlarmSchemes}
<div className={`${prefixCls}-options`}> />
{renderTimeOption()} ) : (
{renderCurveOption()} <SimgleChart
</div> showBoxOption={showBoxOption}
<div className={`${prefixCls}-content`}> curveCenter={curveCenter}
{chartDataSource.length > 0 ? ( showGridLine={chartGrid}
<BasicTable prefixCls={prefixCls}
dataSource={tableData} dataSource={chartDataSource}
columns={columns} // justLine={!!checkboxData.find(item => item.key === 'justLine' && item.checked)}
{...tableProps} chartType={isBoxPlots ? chartType : null}
pagination={false} contrast={timeValue === 'contrast'}
onChange={() => { contrastOption={contrastOption}
}} deviceAlarmSchemes={deviceAlarmSchemes}
/> />
) : ( )}
<PandaEmpty/> </div>
)} </>
</div> );
</> }
); if (model === 'table') {
} return (
}; <>
<div className={`${prefixCls}-options`}>
return ( {renderTimeOption()}
<div className={classNames(prefixCls)}> {renderCurveOption()}
<Spin spinning={loading} wrapperClassName={classNames(`${prefixCls}-spin`)}> </div>
{showModels.length === 1 && ( <div className={`${prefixCls}-content`}>
<div className={`${prefixCls}-single-panel`}>{renderPanel(showModels[0])}</div> {chartDataSource.length > 0 ? (
)} <BasicTable
{showModels.length > 1 && ( dataSource={tableData}
<Tabs columns={columns}
activeKey={activeTabKey} {...tableProps}
onChange={(key) => setActiveTabKey(key)} pagination={false}
centered onChange={() => {}}
tabBarExtraContent={{ />
left: <h3>{title}</h3>, ) : (
right: ( <PandaEmpty />
<div className={`${prefixCls}-extra-right`}> )}
{activeTabKey === 'table' && ( </div>
<Button type="link" onClick={exportExcelBtn}> </>
<DownloadOutlined/> );
下载 }
</Button> };
)}
</div> return (
), <div className={classNames(prefixCls)}>
}} <Spin spinning={loading} wrapperClassName={classNames(`${prefixCls}-spin`)}>
> {showModels.length === 1 && (
<Tabs.TabPane key="curve" tab="曲线"> <div className={`${prefixCls}-single-panel`}>{renderPanel(showModels[0])}</div>
{renderPanel('curve')} )}
</Tabs.TabPane> {showModels.length > 1 && (
<Tabs.TabPane key="table" tab="表格"> <Tabs
{renderPanel('table')} activeKey={activeTabKey}
</Tabs.TabPane> onChange={(key) => setActiveTabKey(key)}
</Tabs> centered
)} tabBarExtraContent={{
</Spin> left: <h3>{title}</h3>,
</div> right: (
); <div className={`${prefixCls}-extra-right`}>
{activeTabKey === 'table' && (
<Button type="link" onClick={exportExcelBtn}>
<DownloadOutlined />
下载
</Button>
)}
</div>
),
}}
>
<Tabs.TabPane key="curve" tab="曲线">
{renderPanel('curve')}
</Tabs.TabPane>
<Tabs.TabPane key="table" tab="表格">
{renderPanel('table')}
</Tabs.TabPane>
</Tabs>
)}
</Spin>
</div>
);
}; };
HistoryView.propTypes = { HistoryView.propTypes = {
grid: PropTypes.bool, grid: PropTypes.bool,
title: PropTypes.string, title: PropTypes.string,
defaultChecked: PropTypes.oneOf(['twelveHours', 'roundClock', 'oneWeek', 'oneMonth']), defaultChecked: PropTypes.oneOf(['twelveHours', 'roundClock', 'oneWeek', 'oneMonth']),
tableProps: PropTypes.object, tableProps: PropTypes.object,
deviceParams: PropTypes.arrayOf( deviceParams: PropTypes.arrayOf(
PropTypes.objectOf({ PropTypes.objectOf({
deviceCode: PropTypes.string, deviceCode: PropTypes.string,
sensors: PropTypes.string, sensors: PropTypes.string,
deviceType: PropTypes.string, deviceType: PropTypes.string,
pointAddressID: PropTypes.number, // 可选,配置了将会查询相关报警方案配置 pointAddressID: PropTypes.number, // 可选,配置了将会查询相关报警方案配置
}), }),
), ),
defaultModel: PropTypes.oneOf(['curve', 'table']), defaultModel: PropTypes.oneOf(['curve', 'table']),
showModels: PropTypes.arrayOf(PropTypes.oneOf(['curve', 'table'])), showModels: PropTypes.arrayOf(PropTypes.oneOf(['curve', 'table'])),
}; };
HistoryView.defaultProps = { HistoryView.defaultProps = {
grid: false, grid: false,
title: '指标曲线', title: '指标曲线',
defaultChecked: 'roundClock', defaultChecked: 'roundClock',
tableProps: {}, tableProps: {},
defaultModel: 'curve', defaultModel: 'curve',
showModels: ['curve', 'table'], showModels: ['curve', 'table'],
needMarkLine: true, needMarkLine: true,
}; };
export default HistoryView; export default HistoryView;
import moment from 'moment'; import moment from 'moment';
import _, {isArray} from 'lodash'; import _, { isArray } from 'lodash';
/** 轴宽度, 用于计算多轴显示时, 轴线偏移和绘图区域尺寸 */ /** 轴宽度, 用于计算多轴显示时, 轴线偏移和绘图区域尺寸 */
const axisWidth = 40; const axisWidth = 40;
const COLOR = { const COLOR = {
NORMAL: '#1685FF', NORMAL: '#1685FF',
UPER: '#fa8c16', UPER: '#fa8c16',
UPUPER: '#FF0000', UPUPER: '#FF0000',
// LOWER: '#13c2c2', // LOWER: '#13c2c2',
// LOWLOWER: '#2f54eb', // LOWLOWER: '#2f54eb',
LOWER: '#fa8c16', LOWER: '#fa8c16',
LOWLOWER: '#FF0000', LOWLOWER: '#FF0000',
AVG: '#00B8B1', AVG: '#00B8B1',
}; };
/** /**
* 图表系列名称格式化 * 图表系列名称格式化
...@@ -22,13 +22,13 @@ const COLOR = { ...@@ -22,13 +22,13 @@ const COLOR = {
* @returns * @returns
*/ */
const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => { const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => {
const {equipmentName, sensorName, unit, dataModel, dateFrom, dateTo} = data; const { equipmentName, sensorName, unit, dataModel, dateFrom, dateTo } = data;
let name = nameWithSensor ? `${equipmentName}-${sensorName}` : equipmentName; let name = nameWithSensor ? `${equipmentName}-${sensorName}` : equipmentName;
if (contrast) { if (contrast) {
const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, ''); const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, '');
name = `${name}-${time}`; name = `${name}-${time}`;
} }
return name; return name;
}; };
/** /**
...@@ -40,12 +40,15 @@ const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => { ...@@ -40,12 +40,15 @@ const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => {
* @returns 图表系列数据, [[DateTime, value]] * @returns 图表系列数据, [[DateTime, value]]
*/ */
const dataAccessor = (data, contrast, contrastOption) => { const dataAccessor = (data, contrast, contrastOption) => {
const {dataModel} = data; const { dataModel } = data;
let _currentYear = moment().format('YYYY'); let _currentYear = moment().format('YYYY');
const formatStr = contrastOption === 'day' ? `${_currentYear}-01-01 HH:mm:00` : `${_currentYear}-01-DD HH:mm:00`; const formatStr =
return dataModel.filter(item => item.sensorName !== '是否在线').map((item) => { contrastOption === 'day' ? `${_currentYear}-01-01 HH:mm:00` : `${_currentYear}-01-DD HH:mm:00`;
const time = contrast ? moment(item.pt).format(formatStr) : item.pt; return dataModel
return [moment(time).valueOf(), item.pv]; .filter((item) => item.sensorName !== '是否在线')
.map((item) => {
const time = contrast ? moment(item.pt).format(formatStr) : item.pt;
return [moment(time).valueOf(), item.pv];
}); });
}; };
...@@ -56,8 +59,8 @@ const dataAccessor = (data, contrast, contrastOption) => { ...@@ -56,8 +59,8 @@ const dataAccessor = (data, contrast, contrastOption) => {
* @returns Null/areaStyle, 为null显示曲线图, 为areaStyle对象显示为面积图. * @returns Null/areaStyle, 为null显示曲线图, 为areaStyle对象显示为面积图.
*/ */
const areaStyleFormatter = (data) => { const areaStyleFormatter = (data) => {
const {sensorName} = data; const { sensorName } = data;
return sensorName && sensorName.indexOf('流量') > -1 ? {} : null; return sensorName && sensorName.indexOf('流量') > -1 ? {} : null;
}; };
/** /**
...@@ -67,110 +70,110 @@ const areaStyleFormatter = (data) => { ...@@ -67,110 +70,110 @@ const areaStyleFormatter = (data) => {
* @returns * @returns
*/ */
const minMax = (data) => { const minMax = (data) => {
const {dataModel} = data; const { dataModel } = data;
let min = Number.MAX_SAFE_INTEGER; let min = Number.MAX_SAFE_INTEGER;
let max = Number.MIN_SAFE_INTEGER; let max = Number.MIN_SAFE_INTEGER;
dataModel.forEach((item) => { dataModel.forEach((item) => {
min = Math.min(min, item.pv ?? 0); min = Math.min(min, item.pv ?? 0);
max = Math.max(max, item.pv ?? 0); max = Math.max(max, item.pv ?? 0);
}); });
return [min, max]; return [min, max];
}; };
const markLineItem = (name, value, color) => { const markLineItem = (name, value, color) => {
return { return {
name: name, name: name,
yAxis: value, yAxis: value,
value: value, value: value,
lineStyle: { lineStyle: {
color: color || '#000', color: color || '#000',
}, },
label: { label: {
position: 'insideEndTop', position: 'insideEndTop',
color: color || '#000', color: color || '#000',
formatter: function () { formatter: function () {
return `${name}:${value}`; return `${name}:${value}`;
}, },
}, },
}; };
}; };
export const alarmMarkLine = (dataItem, index, dataSource, schemes) => { export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
// 只有一个数据曲线时显示markline // 只有一个数据曲线时显示markline
if (!dataItem || !schemes || dataSource.length !== 1) return {}; if (!dataItem || !schemes || dataSource.length !== 1) return {};
const {deviceType, stationCode, sensorName, decimalPoint} = dataItem; const { deviceType, stationCode, sensorName, decimalPoint } = dataItem;
const curSchemes = schemes.filter( const curSchemes = schemes.filter(
(item) => (item) =>
item.deviceCode === stationCode && item.deviceCode === stationCode &&
item.sensorName === sensorName && item.sensorName === sensorName &&
item.valueType === '直接取值', item.valueType === '直接取值',
); );
const data = []; const data = [];
curSchemes.forEach((scheme) => { curSchemes.forEach((scheme) => {
const {hLimit, hhLimit, lLimit, llLimit} = scheme; const { hLimit, hhLimit, lLimit, llLimit } = scheme;
lLimit !== null && lLimit !== void 0 && data.push(markLineItem('低限', lLimit, '#fa8c16')); lLimit !== null && lLimit !== void 0 && data.push(markLineItem('低限', lLimit, '#fa8c16'));
hLimit !== null && hLimit !== void 0 && data.push(markLineItem('高限', hLimit, '#fa8c16')); hLimit !== null && hLimit !== void 0 && data.push(markLineItem('高限', hLimit, '#fa8c16'));
llLimit !== null && llLimit !== void 0 && data.push(markLineItem('低低限', llLimit, '#FF0000')); llLimit !== null && llLimit !== void 0 && data.push(markLineItem('低低限', llLimit, '#FF0000'));
hhLimit !== null && hhLimit !== void 0 && data.push(markLineItem('高高限', hhLimit, '#FF0000')); hhLimit !== null && hhLimit !== void 0 && data.push(markLineItem('高高限', hhLimit, '#FF0000'));
}); });
data.push({ data.push({
name: '平均线', name: '平均线',
type: 'average', type: 'average',
lineStyle: { lineStyle: {
color: '#00b8b1', color: '#00b8b1',
type: 'solid', type: 'solid',
}, },
label: { label: {
position: 'insideEndTop', position: 'insideEndTop',
color: '#00b8b1', color: '#00b8b1',
formatter: function (param) { formatter: function (param) {
return `平均值:${param.value}`; return `平均值:${param.value}`;
}, },
}, },
}); });
return { return {
symbol: ['none', 'none'], symbol: ['none', 'none'],
data, data,
}; };
}; };
export const minMaxMarkPoint = (dataItem, index, dataSource) => { export const minMaxMarkPoint = (dataItem, index, dataSource) => {
// 只有一个数据曲线时显示markline // 只有一个数据曲线时显示markline
if (!dataItem || dataSource.length !== 1) return {}; if (!dataItem || dataSource.length !== 1) return {};
const data = []; const data = [];
data.push({type: 'min', name: '最小: ',}); data.push({ type: 'min', name: '最小: ' });
data.push({type: 'max', name: '最大: ',}); data.push({ type: 'max', name: '最大: ' });
return { return {
symbolSize: 1, symbolSize: 1,
symbolOffset: [0, '50%'], symbolOffset: [0, '50%'],
label: { label: {
formatter: '{b|{b} }{c|{c}}', formatter: '{b|{b} }{c|{c}}',
backgroundColor: backgroundColor:
window.globalConfig && window.globalConfig &&
window.globalConfig && window.globalConfig &&
window.globalConfig.variableTheme?.primaryColor window.globalConfig.variableTheme?.primaryColor
? window.globalConfig.variableTheme.primaryColor ? window.globalConfig.variableTheme.primaryColor
: '#0087F7', : '#0087F7',
borderColor: '#ccc', borderColor: '#ccc',
borderWidth: 1, borderWidth: 1,
borderRadius: 4, borderRadius: 4,
padding: [2, 10], padding: [2, 10],
lineHeight: 22, lineHeight: 22,
position: 'top', position: 'top',
distance: 10, distance: 10,
rich: { rich: {
b: { b: {
color: '#fff', color: '#fff',
},
c: {
color: '#fff',
fontSize: 16,
fontWeight: 700,
},
},
}, },
data, c: {
}; color: '#fff',
fontSize: 16,
fontWeight: 700,
},
},
},
data,
};
}; };
/** /**
...@@ -179,27 +182,27 @@ export const minMaxMarkPoint = (dataItem, index, dataSource) => { ...@@ -179,27 +182,27 @@ export const minMaxMarkPoint = (dataItem, index, dataSource) => {
* @param {any} axis * @param {any} axis
*/ */
export const decorateAxisGridLine = (axis, showGrid) => { export const decorateAxisGridLine = (axis, showGrid) => {
if (!axis) return; if (!axis) return;
axis.minorTick = { axis.minorTick = {
lineStyle: { lineStyle: {
color: '#e2e2e2', color: '#e2e2e2',
}, },
...(axis.minorTick || {}), ...(axis.minorTick || {}),
show: showGrid, show: showGrid,
splitNumber: 2, splitNumber: 2,
}; };
axis.minorSplitLine = { axis.minorSplitLine = {
lineStyle: { lineStyle: {
color: '#e2e2e2', color: '#e2e2e2',
type: 'dashed', type: 'dashed',
}, },
...(axis.minorSplitLine || {}), ...(axis.minorSplitLine || {}),
show: showGrid, show: showGrid,
}; };
axis.splitLine = { axis.splitLine = {
...(axis.splitLine || {}), ...(axis.splitLine || {}),
show: showGrid, show: showGrid,
}; };
}; };
/** /**
...@@ -208,35 +211,35 @@ export const decorateAxisGridLine = (axis, showGrid) => { ...@@ -208,35 +211,35 @@ export const decorateAxisGridLine = (axis, showGrid) => {
* @param {any} dataItem * @param {any} dataItem
*/ */
export const offlineArea = (dataItem) => { export const offlineArea = (dataItem) => {
if (!dataItem) return {}; if (!dataItem) return {};
const {dataModel} = dataItem; const { dataModel } = dataItem;
let datas = new Array(); let datas = new Array();
let offlineData = []; let offlineData = [];
let hasOffline = false; let hasOffline = false;
dataModel.forEach((item, index) => { dataModel.forEach((item, index) => {
if (!item.pv && !hasOffline) { if (!item.pv && !hasOffline) {
offlineData = [ offlineData = [
{ {
name: '离线', name: '离线',
xAxis: new Date(item.pt), xAxis: new Date(item.pt),
},
];
hasOffline = true;
} else if ((item.pv && hasOffline)) {
offlineData.push({
xAxis: new Date(item.pt),
});
datas.push(offlineData);
offlineData = [];
hasOffline = false;
}
});
return {
itemStyle: {
color: '#eee',
}, },
data: datas, ];
}; hasOffline = true;
} else if (item.pv && hasOffline) {
offlineData.push({
xAxis: new Date(item.pt),
});
datas.push(offlineData);
offlineData = [];
hasOffline = false;
}
});
return {
itemStyle: {
color: '#eee',
},
data: datas,
};
}; };
/** /**
...@@ -250,104 +253,107 @@ export const offlineArea = (dataItem) => { ...@@ -250,104 +253,107 @@ export const offlineArea = (dataItem) => {
* @param {any} config 额外配置信息 * @param {any} config 额外配置信息
*/ */
const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth, config) => { const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth, config) => {
const needUnit = _.get(config, 'needUnit', false); const needUnit = _.get(config, 'needUnit', false);
const curveCenter = _.get(config, 'curveCenter', false); const curveCenter = _.get(config, 'curveCenter', false);
const nameWithSensor = _.get(config, 'nameWithSensor', true); const nameWithSensor = _.get(config, 'nameWithSensor', true);
const showGridLine = _.get(config, 'showGridLine', true); const showGridLine = _.get(config, 'showGridLine', true);
const showMarkLine = _.get(config, 'showMarkLine', false); const showMarkLine = _.get(config, 'showMarkLine', false);
const showPoint = _.get(config, 'showPoint', false); const showPoint = _.get(config, 'showPoint', false);
const deviceAlarmSchemes = _.get(config, 'deviceAlarmSchemes', []); const deviceAlarmSchemes = _.get(config, 'deviceAlarmSchemes', []);
const chartType = _.get(config, 'chartType', null); const chartType = _.get(config, 'chartType', null);
// const justLine = _.get(config, 'justLine', false); // const justLine = _.get(config, 'justLine', false);
const showBoxOption = _.get(config, 'showBoxOption', false); const showBoxOption = _.get(config, 'showBoxOption', false);
// 自定义属性 // 自定义属性
const restOption = _.pick(cusOption, ['title', 'legend']); const restOption = _.pick(cusOption, ['title', 'legend']);
// 一种指标一个y轴 // 一种指标一个y轴
const yAxisMap = new Map(); const yAxisMap = new Map();
dataSource.forEach((item, index) => { dataSource.forEach((item, index) => {
const {sensorName, unit} = item; const { sensorName, unit } = item;
const key = sensorName; const key = sensorName;
if (!yAxisMap.has(key)) { if (!yAxisMap.has(key)) {
const i = yAxisMap.size; const i = yAxisMap.size;
const axis = { const axis = {
type: 'value', type: 'value',
name: needUnit ? unit : null, name: needUnit ? unit : null,
position: i % 2 === 0 ? 'left' : 'right', position: i % 2 === 0 ? 'left' : 'right',
offset: Math.floor(i / 2) * axisWidth, offset: Math.floor(i / 2) * axisWidth,
axisLabel: { axisLabel: {
formatter: (value) => (value > 100000 ? `${value / 1000}k` : value), formatter: (value) => (value > 100000 ? `${value / 1000}k` : value),
}, },
axisLine: { axisLine: {
show: true, show: true,
}, },
nameTextStyle: { nameTextStyle: {
align: i % 2 === 0 ? 'right' : 'left', align: i % 2 === 0 ? 'right' : 'left',
}, },
minorTick: { minorTick: {
lineStyle: { lineStyle: {
color: '#e2e2e2', color: '#e2e2e2',
}, },
}, },
minorSplitLine: { minorSplitLine: {
lineStyle: { lineStyle: {
color: '#e2e2e2', color: '#e2e2e2',
type: 'dashed', type: 'dashed',
}, },
}, },
}; };
yAxisMap.set(key, axis); yAxisMap.set(key, axis);
} }
// 曲线居中 // 曲线居中
if (curveCenter && item.dataModel && item.dataModel.length > 0) { if (curveCenter && item.dataModel && item.dataModel.length > 0) {
const [min, max] = minMax(item); const [min, max] = minMax(item);
const axis = yAxisMap.get(key); const axis = yAxisMap.get(key);
axis.min = axis.min === void 0 ? min : Math.min(min, axis.min); axis.min = axis.min === void 0 ? min : Math.min(min, axis.min);
axis.max = axis.max === void 0 ? max : Math.max(max, axis.max); axis.max = axis.max === void 0 ? max : Math.max(max, axis.max);
} }
// 网格显示 // 网格显示
const axis = yAxisMap.get(key); const axis = yAxisMap.get(key);
decorateAxisGridLine(axis, showGridLine); decorateAxisGridLine(axis, showGridLine);
}); });
const yAxis = yAxisMap.size > 0 ? [...yAxisMap.values()] : {type: 'value'}; const yAxis = yAxisMap.size > 0 ? [...yAxisMap.values()] : { type: 'value' };
// 根据y轴个数调整边距 // 根据y轴个数调整边距
const leftNum = Math.ceil(yAxisMap.size / 2); const leftNum = Math.ceil(yAxisMap.size / 2);
const rightNum = Math.floor(yAxisMap.size / 2); const rightNum = Math.floor(yAxisMap.size / 2);
const grid = { const grid = {
top: needUnit ? 80 : 60, top: needUnit ? 80 : 60,
left: 10 + leftNum * axisWidth, left: 10 + leftNum * axisWidth,
right: rightNum === 0 ? 20 : rightNum * axisWidth, right: rightNum === 0 ? 20 : rightNum * axisWidth,
bottom: 60 bottom: 60,
}; };
const headTemplate = (param) => { const headTemplate = (param) => {
if (!param) return ''; if (!param) return '';
const {name, axisValueLabel, axisType, axisValue} = param; const { name, axisValueLabel, axisType, axisValue } = param;
const timeFormat = 'YYYY-MM-DD HH:mm:ss'; const timeFormat = 'YYYY-MM-DD HH:mm:ss';
const text = const text =
axisType === 'xAxis.time' ? moment(axisValue).format(timeFormat) : name || axisValueLabel; axisType === 'xAxis.time' ? moment(axisValue).format(timeFormat) : name || axisValueLabel;
return `<div style="border-bottom: 1px solid #F0F0F0; color: #808080; margin-bottom: 5px; padding-bottom: 5px;">${text}</div>`; return `<div style="border-bottom: 1px solid #F0F0F0; color: #808080; margin-bottom: 5px; padding-bottom: 5px;">${text}</div>`;
}; };
const seriesTemplate = (param, unit) => { const seriesTemplate = (param, unit) => {
if (!param) return ''; if (!param) return '';
console.log(param); console.log(param);
const {value, encode} = param; const { value, encode } = param;
// const val = value[encode.y[0]]; // const val = value[encode.y[0]];
const _unit = unit || 'Mpa'; const _unit = unit || 'Mpa';
const color = '#008CFF'; const color = '#008CFF';
if (!isArray(value)) return ` <div style="display: flex; align-items: center;"> if (!isArray(value))
return ` <div style="display: flex; align-items: center;">
<span>${param.seriesName}</span><span style="display:inline-block;">:</span> <span>${param.seriesName}</span><span style="display:inline-block;">:</span>
<span style="color:${color};margin: 0 5px 0 auto;">${value?.toFixed(3) ?? '-'}</span> <span style="color:${color};margin: 0 5px 0 auto;">${value?.toFixed(3) ?? '-'}</span>
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div>`; </div>`;
return param.componentSubType !== 'candlestick' ? `<div style="display: flex; align-items: center;"> return param.componentSubType !== 'candlestick'
? `<div style="display: flex; align-items: center;">
<span>${param.seriesName}</span><span style="display:inline-block;">:</span> <span>${param.seriesName}</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${value[1] ?? '-'}</span> <span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${value[1] ?? '-'}</span>
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div>` : ` </div>`
: `
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span>首值</span><span style="display:inline-block;">:</span> <span>首值</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${value[1] ?? '-'}</span> <span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${value[1] ?? '-'}</span>
...@@ -369,236 +375,256 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -369,236 +375,256 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div> </div>
`; `;
}; };
const tooltipAccessor = (unit) => { const tooltipAccessor = (unit) => {
return { return {
formatter: function (params, ticket, callback) { formatter: function (params, ticket, callback) {
let tooltipHeader = ''; let tooltipHeader = '';
let tooltipContent = ''; let tooltipContent = '';
if (isArray(params)) { if (isArray(params)) {
tooltipHeader = headTemplate(params[0]); tooltipHeader = headTemplate(params[0]);
params.forEach((param) => { params.forEach((param) => {
tooltipContent += seriesTemplate(param, unit); tooltipContent += seriesTemplate(param, unit);
}); });
} else { } else {
tooltipHeader = headTemplate(params); tooltipHeader = headTemplate(params);
tooltipContent += seriesTemplate(params, unit); tooltipContent += seriesTemplate(params, unit);
} }
return ` return `
<div> <div>
${tooltipHeader} ${tooltipHeader}
<div>${tooltipContent}</div> <div>${tooltipContent}</div>
</div> </div>
`; `;
} },
}
}; };
// 根据"指标名称"分类yAxis };
const yAxisInterator = (() => { // 根据"指标名称"分类yAxis
const map = new Map(); const yAxisInterator = (() => {
let current = -1; const map = new Map();
const get = (name) => (map.has(name) ? map.get(name) : map.set(name, ++current).get(name)); let current = -1;
return {get}; const get = (name) => (map.has(name) ? map.get(name) : map.set(name, ++current).get(name));
})(); return { get };
let _offlineData = []; })();
let series = dataSource.filter(item => { let _offlineData = [];
if (item.sensorName === '是否在线') { let series = dataSource
_offlineData.push(item); .filter((item) => {
} if (item.sensorName === '是否在线') {
return item.sensorName !== '是否在线'; _offlineData.push(item);
}).map((item, index) => { }
const {sensorName, unit} = item; return item.sensorName !== '是否在线';
const name = nameFormatter(item, contrast, contrastOption, nameWithSensor); })
const data = dataAccessor(item, contrast, contrastOption); .map((item, index) => {
const type = 'line'; const { sensorName, unit } = item;
const areaStyle = areaStyleFormatter(item); const name = nameFormatter(item, contrast, contrastOption, nameWithSensor);
const yAxisIndex = yAxisInterator.get(sensorName); const data = dataAccessor(item, contrast, contrastOption);
const markLine = showMarkLine ? alarmMarkLine(item, index, dataSource, deviceAlarmSchemes) : {}; const type = 'line';
const markPoint = showPoint ? minMaxMarkPoint(item, index, dataSource) : {}; const areaStyle = areaStyleFormatter(item);
let markArea = null; const yAxisIndex = yAxisInterator.get(sensorName);
// 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55 const markLine = showMarkLine
let _offlineAreasData = _offlineData.map(item => { ? alarmMarkLine(item, index, dataSource, deviceAlarmSchemes)
let _item = {...item}; : {};
_item.dataModel = item.dataModel.map(d => { const markPoint = showPoint ? minMaxMarkPoint(item, index, dataSource) : {};
let _d = {...d}; let markArea = null;
_d.pv = 0; // 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55
return _d let _offlineAreasData = _offlineData
}) .map((item) => {
return _item let _item = { ...item };
}).find(offline => offline.stationCode === item.stationCode) _item.dataModel = item.dataModel.map((d) => {
let offlineAreas = offlineArea(_offlineAreasData); let _d = { ...d };
if (offlineAreas.data?.length) { _d.pv = 0;
restOption.markArea = null; return _d;
markArea = offlineAreas; });
} return _item;
return { })
notMerge: true, .find((offline) => offline.stationCode === item.stationCode);
name, let offlineAreas = offlineArea(_offlineAreasData);
type, if (offlineAreas.data?.length) {
data, restOption.markArea = null;
areaStyle, markArea = offlineAreas;
yAxisIndex, }
smooth, return {
unit, notMerge: true,
markLine, name,
markPoint, type,
markArea, data,
}; areaStyle,
yAxisIndex,
smooth,
unit,
markLine,
markPoint,
markArea,
};
}); });
// 由于series更新后,没有的数据曲线仍然停留在图表区上,导致图表可视区范围有问题 // 由于series更新后,没有的数据曲线仍然停留在图表区上,导致图表可视区范围有问题
const min = Math.min( const min = Math.min(
...series.map((item) => item.data?.[0]?.[0]).filter((item) => item !== undefined), ...series.map((item) => item.data?.[0]?.[0]).filter((item) => item !== undefined),
); );
const max = Math.max( const max = Math.max(
...series ...series
.map((item) => item.data?.[item.data.length - 1]?.[0]) .map((item) => item.data?.[item.data.length - 1]?.[0])
.filter((item) => item !== undefined), .filter((item) => item !== undefined),
); );
let xAxis = {type: 'time', min, max}; let xAxis = { type: 'time', min, max };
decorateAxisGridLine(xAxis, showGridLine); decorateAxisGridLine(xAxis, showGridLine);
const tooltipTimeFormat = !contrast const tooltipTimeFormat = !contrast
? 'YYYY-MM-DD HH:mm:ss' ? 'YYYY-MM-DD HH:mm:ss'
: contrastOption === 'day' : contrastOption === 'day'
? 'HH:mm' ? 'HH:mm'
: 'DD HH:mm'; : 'DD HH:mm';
let tooltip = { let tooltip = {
timeFormat: tooltipTimeFormat, timeFormat: tooltipTimeFormat,
// trigger: 'axis', // trigger: 'axis',
// axisPointer: { // axisPointer: {
// type: 'cross' // type: 'cross'
// } // }
}; };
// 增加箱线图的逻辑,单曲线才存在 // 增加箱线图的逻辑,单曲线才存在
if (chartType && showBoxOption) { if (chartType && showBoxOption) {
if (chartType === 'boxChart') { if (chartType === 'boxChart') {
const otherData = dataSource?.[0]?.dataModel.map(item => { const otherData =
const {firstPV, lastPV, maxPV, minPV, pt} = item; dataSource?.[0]?.dataModel.map((item) => {
return [moment(pt).valueOf(), firstPV, lastPV, minPV, maxPV] const { firstPV, lastPV, maxPV, minPV, pt } = item;
}) || []; //当存在othersData的时候,只是单曲线 return [moment(pt).valueOf(), firstPV, lastPV, minPV, maxPV];
// xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD HH:mm:ss'))}; }) || []; //当存在othersData的时候,只是单曲线
xAxis = {type: 'time'}; // xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD HH:mm:ss'))};
decorateAxisGridLine(xAxis, showGridLine); xAxis = { type: 'time' };
let unit = '' decorateAxisGridLine(xAxis, showGridLine);
series = series.map(item => { let unit = '';
if (item.unit) unit = item.unit; series = series.map((item) => {
let _item = {...item, symbol: 'none'}; if (item.unit) unit = item.unit;
/* _item.data = _item?.data?.map(d => { let _item = { ...item, symbol: 'none' };
/* _item.data = _item?.data?.map(d => {
return d[1] || null return d[1] || null
}) || [];*/ }) || [];*/
return _item; return _item;
}) });
series.push({ series.push({
type: 'candlestick', type: 'candlestick',
name: '箱线图', name: '箱线图',
symbol: 'none', symbol: 'none',
data: otherData, data: otherData,
itemStyle: { itemStyle: {
color: '#FFA200', color: '#FFA200',
color0: '#44CD00', color0: '#44CD00',
borderColor: '#FFA200', borderColor: '#FFA200',
borderColor0: '#44CD00' borderColor0: '#44CD00',
} },
}); });
tooltip = tooltipAccessor(unit) tooltip = tooltipAccessor(unit);
} else { } else {
let _maxData = []; let _maxData = [];
let _minData = []; let _minData = [];
let _currentYear = moment().format('YYYY'); let _currentYear = moment().format('YYYY');
const formatStr = contrastOption === 'day' ? `${_currentYear}-01-01 HH:mm:00` : `${_currentYear}-01-DD HH:mm:00`;// 用来做同期对比,把日期拉到同一区间 const formatStr =
let _maxValues = []; contrastOption === 'day'
dataSource?.[0]?.dataModel.forEach(item => { ? `${_currentYear}-01-01 HH:mm:00`
const {firstPV, lastPV, maxPV, minPV, pt} = item; : `${_currentYear}-01-DD HH:mm:00`; // 用来做同期对比,把日期拉到同一区间
_maxValues.push(maxPV); let _maxValues = [];
let time = contrast ? moment(pt).format(formatStr) : pt; dataSource?.[0]?.dataModel.forEach((item) => {
_maxData.push([moment(time).valueOf(), (maxPV - minPV).toFixed(2)]); const { firstPV, lastPV, maxPV, minPV, pt } = item;
_minData.push([moment(time).valueOf(), minPV]); _maxValues.push(maxPV);
}); //当存在othersData的时候,只是单曲线 let time = contrast ? moment(pt).format(formatStr) : pt;
// xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD HH:mm:ss'))}; _maxData.push([moment(time).valueOf(), (maxPV - minPV).toFixed(2)]);
xAxis = {type: 'time'}; _minData.push([moment(time).valueOf(), minPV]);
decorateAxisGridLine(xAxis, showGridLine); }); //当存在othersData的时候,只是单曲线
let _unit = '' // xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD HH:mm:ss'))};
series = series.map(item => { xAxis = { type: 'time' };
_unit = item.unit; decorateAxisGridLine(xAxis, showGridLine);
let _item = {...item, symbol: 'none'}; let _unit = '';
/* _item.data = _item?.data?.map(d => { series = series.map((item) => {
_unit = item.unit;
let _item = { ...item, symbol: 'none' };
/* _item.data = _item?.data?.map(d => {
return d[1] || null return d[1] || null
}) || [];*/ }) || [];*/
return _item; return _item;
}); });
console.log(series); console.log(series);
[[..._minData], [..._maxData]].forEach((item, index) => { [[..._minData], [..._maxData]].forEach((item, index) => {
series.push({ series.push({
name: index === 0 ? '最小值' : '最大值', name: index === 0 ? '最小值' : '最大值',
type: 'line', type: 'line',
data: item, data: item,
lineStyle: { lineStyle: {
opacity: 0 opacity: 0,
}, },
...(index !== 0 ? { ...(index !== 0
areaStyle: { ? {
color: series?.[0]?.itemStyle?.color ?? '#65a0d1', areaStyle: {
opacity: 0.2, color: series?.[0]?.itemStyle?.color ?? '#65a0d1',
} opacity: 0.2,
} : {}), },
stack: 'confidence-band', }
symbol: 'none' : {}),
}); stack: 'confidence-band',
}) symbol: 'none',
tooltip = { });
formatter: (e) => { });
return `<div> tooltip = {
formatter: (e) => {
return `<div>
${headTemplate(e[0])} ${headTemplate(e[0])}
<div> <div>
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span>${e[0].seriesName}</span><span style="display:inline-block;">:</span> <span>${
<span style="color: ${COLOR.NORMAL};margin: 0 5px 0 auto;">${e[0]?.value?.[1] ?? '-'}</span> e[0].seriesName
}</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.NORMAL};margin: 0 5px 0 auto;">${
e[0]?.value?.[1] ?? '-'
}</span>
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div> </div>
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span>最小值</span><span style="display:inline-block;">:</span> <span>最小值</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${e[1]?.value?.[1] ?? '-'}</span> <span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${
e[1]?.value?.[1] ?? '-'
}</span>
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div> </div>
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<span>最大值</span><span style="display:inline-block;">:</span> <span>最大值</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${_maxValues[e[2].dataIndex] ?? '-'}</span> <span style="color: ${COLOR.AVG};margin: 0 5px 0 auto;">${
_maxValues[e[2].dataIndex] ?? '-'
}</span>
<span style="font-size: 12px;">${_unit}</span> <span style="font-size: 12px;">${_unit}</span>
</div> </div>
</div> </div>
</div>` </div>`;
}
}
}
}
restOption.dataZoom = [
{
show: true,
bottom: 10,
start: 0,
end: 100,
height: 28,
type: 'inside',
zoomOnMouseWheel: true
}, },
{ };
show: true, }
bottom: 10, }
start: 0, restOption.dataZoom = [
end: 100, {
height: 28, show: true,
type: 'slider', bottom: 10,
zoomOnMouseWheel: true start: 0,
} end: 100,
]; height: 28,
xAxis.minInterval = 3600 * 1 * 1000 type: 'inside',
return { zoomOnMouseWheel: true,
yAxis, },
grid, {
xAxis, show: true,
series, bottom: 10,
tooltip, start: 0,
...restOption, end: 100,
}; height: 28,
type: 'slider',
zoomOnMouseWheel: true,
},
];
xAxis.minInterval = 3600 * 1 * 1000;
return {
yAxis,
grid,
xAxis,
series,
tooltip,
...restOption,
};
}; };
export default optionGenerator; export default optionGenerator;
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.4](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_quotaselect@1.4.3...@wisdom-components/ec_quotaselect@1.4.4) (2023-05-16) ## [1.4.4](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_quotaselect@1.4.3...@wisdom-components/ec_quotaselect@1.4.4) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/ec_quotaselect **Note:** Version bump only for package @wisdom-components/ec_quotaselect
## [1.4.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_quotaselect@1.4.2...@wisdom-components/ec_quotaselect@1.4.3) (2023-05-15) ## [1.4.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_quotaselect@1.4.2...@wisdom-components/ec_quotaselect@1.4.3) (2023-05-15)
### Bug Fixes ### Bug Fixes
......
...@@ -422,7 +422,8 @@ const QuotaSelect = ({ ...@@ -422,7 +422,8 @@ const QuotaSelect = ({
checked={item.checked} checked={item.checked}
disabled={ disabled={
((selectData.length > maximum || selectData.length === maximum) && ((selectData.length > maximum || selectData.length === maximum) &&
!item.checked)||disabledList.includes(item.title) !item.checked) ||
disabledList.includes(item.title)
} }
onChange={(e) => handleCheckboxChange(e, item)} onChange={(e) => handleCheckboxChange(e, item)}
> >
...@@ -481,7 +482,7 @@ QuotaSelect.defaultProps = { ...@@ -481,7 +482,7 @@ QuotaSelect.defaultProps = {
onModalOk: () => {}, onModalOk: () => {},
onModalClose: () => {}, onModalClose: () => {},
defaultSelect: 'emphasis', defaultSelect: 'emphasis',
disabledList:[], disabledList: [],
}; };
QuotaSelect.propTypes = { QuotaSelect.propTypes = {
......
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_realtimeinfo@1.6.0...@wisdom-components/ec_realtimeinfo@1.6.1) (2023-05-16) ## [1.6.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_realtimeinfo@1.6.0...@wisdom-components/ec_realtimeinfo@1.6.1) (2023-05-16)
**Note:** Version bump only for package @wisdom-components/ec_realtimeinfo **Note:** Version bump only for package @wisdom-components/ec_realtimeinfo
# [1.6.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_realtimeinfo@1.5.0...@wisdom-components/ec_realtimeinfo@1.6.0) (2023-05-11) # [1.6.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/ec_realtimeinfo@1.5.0...@wisdom-components/ec_realtimeinfo@1.6.0) (2023-05-11)
### Features ### Features
......
...@@ -53,7 +53,8 @@ const RealTimeInfo = (props) => { ...@@ -53,7 +53,8 @@ const RealTimeInfo = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('realtime-info'); const prefixCls = getPrefixCls('realtime-info');
const { deviceParams, infoData, user, placeholder, defaultTargetValue, modalTitle, buttonText } = props; const { deviceParams, infoData, user, placeholder, defaultTargetValue, modalTitle, buttonText } =
props;
const [isModalVisible, setIsModalVisible] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false);
const [targetValue, setTargetValue] = useState(defaultTargetValue); // 重点/全部 const [targetValue, setTargetValue] = useState(defaultTargetValue); // 重点/全部
...@@ -114,11 +115,13 @@ const RealTimeInfo = (props) => { ...@@ -114,11 +115,13 @@ const RealTimeInfo = (props) => {
if (infoData) { if (infoData) {
let devices = [infoData.aName]; let devices = [infoData.aName];
infoData.child?.forEach(function (val) { infoData.child?.forEach(function (val) {
let k = devices.find(function (a) { return a == val.aName }); let k = devices.find(function (a) {
return a == val.aName;
});
if (!k) { if (!k) {
devices.push(val.aName); devices.push(val.aName);
} }
}) });
deviceType = devices.join(','); deviceType = devices.join(',');
} else { } else {
deviceType = deviceType =
...@@ -127,7 +130,6 @@ const RealTimeInfo = (props) => { ...@@ -127,7 +130,6 @@ const RealTimeInfo = (props) => {
: '二供泵房,二供机组'; : '二供泵房,二供机组';
} }
const configReq = getMonitorConfig({ const configReq = getMonitorConfig({
params: { params: {
user, user,
...@@ -339,10 +341,10 @@ RealTimeInfo.defaultProps = { ...@@ -339,10 +341,10 @@ RealTimeInfo.defaultProps = {
user: null, user: null,
deviceParams: [], deviceParams: [],
deviceRealInfoParams: {}, deviceRealInfoParams: {},
deviceConfService: () => { }, deviceConfService: () => {},
pointAddressEntryService: () => { }, pointAddressEntryService: () => {},
sensorTypeService: () => { }, sensorTypeService: () => {},
deviceRealInfoService: () => { }, deviceRealInfoService: () => {},
}; };
RealTimeInfo.propTypes = { RealTimeInfo.propTypes = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment