Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wisdom-components
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
wisdom-components
Commits
89f89959
Commit
89f89959
authored
Sep 15, 2023
by
陈龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 升级历史曲线
parent
ff4ddada
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
250 additions
and
153 deletions
+250
-153
SingleChart.js
packages/extend-components/EC_HistoryView/src/SingleChart.js
+123
-120
index.js
packages/extend-components/EC_HistoryView/src/apis/index.js
+16
-0
index.js
packages/extend-components/EC_HistoryView/src/demos/index.js
+25
-3
index.js
packages/extend-components/EC_HistoryView/src/index.js
+86
-30
utils.js
packages/extend-components/EC_HistoryView/src/utils.js
+0
-0
No files found.
packages/extend-components/EC_HistoryView/src/SingleChart.js
View file @
89f89959
import
React
,
{
memo
,
useEffect
,
useMemo
,
useRef
}
from
'react'
;
import
{
BasicChart
}
from
'@wisdom-components/basicchart'
;
import
React
,
{
memo
,
useEffect
,
useMemo
,
useRef
}
from
'react'
;
import
{
BasicChart
}
from
'@wisdom-components/basicchart'
;
import
PandaEmpty
from
'@wisdom-components/empty'
;
import
optionGenerator
,
{
alarmMarkLine
,
minMaxMarkPoint
,
offlineArea
}
from
'./utils'
;
import
{
isArray
,
cloneDeep
}
from
'lodash'
;
import
optionGenerator
,
{
alarmMarkLine
,
minMaxMarkPoint
,
offlineArea
}
from
'./utils'
;
import
{
isArray
,
cloneDeep
}
from
'lodash'
;
const
SingleChart
=
memo
((
props
)
=>
{
const
{
dataSource
,
contrast
=
false
,
contrastOption
=
'day'
,
smooth
=
true
,
curveCenter
,
showGridLine
=
true
,
deviceAlarmSchemes
,
chartType
,
lineDataType
,
showBoxOption
,
}
=
props
;
const
chartRef
=
useRef
();
const
{
dataSource
,
contrast
=
false
,
contrastOption
=
'day'
,
smooth
=
true
,
curveCenter
,
showGridLine
=
true
,
deviceAlarmSchemes
,
chartType
,
lineDataType
,
showBoxOption
,
special
}
=
props
;
const
chartRef
=
useRef
();
const
option
=
useMemo
(()
=>
{
const
config
=
{
needUnit
:
true
,
curveCenter
,
showGridLine
,
deviceAlarmSchemes
,
showMarkLine
:
true
,
showPoint
:
true
,
chartType
,
// justLine,
showBoxOption
,
};
return
optionGenerator
(
dataSource
,
null
,
contrast
,
contrastOption
,
smooth
,
config
,
lineDataType
);
},
[
dataSource
,
smooth
,
curveCenter
,
chartType
]);
useEffect
(()
=>
{
chartRef
.
current
?.
resize
?.();
const
chart
=
chartRef
.
current
?.
getEchartsInstance
?.();
function
hander
(
params
)
{
const
{
selected
}
=
params
;
const
count
=
Object
.
values
(
selected
||
{}).
filter
((
item
)
=>
item
).
length
;
const
option
=
cloneDeep
(
chart
.
getOption
());
const
needMarkLine
=
count
===
1
;
// 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55
let
_tempDataArray
=
dataSource
.
filter
((
item
)
=>
item
.
sensorName
===
'是否在线'
);
option
.
series
.
forEach
((
item
,
index
)
=>
{
let
_data
=
_tempDataArray
.
find
((
offline
)
=>
offline
.
stationCode
===
item
.
stationCode
);
let
offlineAreas
=
offlineArea
(
_data
);
if
(
offlineAreas
.
data
?.
length
)
{
option
.
markArea
=
null
;
item
.
markArea
=
offlineAreas
;
}
if
(
needMarkLine
&&
selected
[
item
.
name
])
{
item
.
markLine
=
alarmMarkLine
(
dataSource
[
index
],
index
,
[
dataSource
[
index
]],
const
option
=
useMemo
(()
=>
{
const
config
=
{
needUnit
:
true
,
curveCenter
,
showGridLine
,
deviceAlarmSchemes
,
);
item
.
markPoint
=
minMaxMarkPoint
(
dataSource
[
index
],
index
,
[
dataSource
[
index
]]);
}
else
{
item
.
markLine
=
{};
item
.
markPoint
=
{};
showMarkLine
:
true
,
showPoint
:
true
,
chartType
,
// justLine,
showBoxOption
,
special
};
return
optionGenerator
(
dataSource
,
null
,
contrast
,
contrastOption
,
smooth
,
config
,
lineDataType
);
},
[
dataSource
,
smooth
,
curveCenter
,
chartType
]);
useEffect
(()
=>
{
chartRef
.
current
?.
resize
?.();
const
chart
=
chartRef
.
current
?.
getEchartsInstance
?.();
function
hander
(
params
)
{
const
{
selected
}
=
params
;
const
count
=
Object
.
values
(
selected
||
{}).
filter
((
item
)
=>
item
).
length
;
const
option
=
cloneDeep
(
chart
.
getOption
());
const
needMarkLine
=
count
===
1
;
// 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55
let
_tempDataArray
=
dataSource
.
filter
((
item
)
=>
item
.
sensorName
===
'是否在线'
);
option
.
series
.
forEach
((
item
,
index
)
=>
{
let
_data
=
_tempDataArray
.
find
((
offline
)
=>
offline
.
stationCode
===
item
.
stationCode
);
let
offlineAreas
=
offlineArea
(
_data
);
if
(
offlineAreas
.
data
?.
length
)
{
option
.
markArea
=
null
;
item
.
markArea
=
offlineAreas
;
}
if
(
needMarkLine
&&
selected
[
item
.
name
])
{
item
.
markLine
=
alarmMarkLine
(
dataSource
[
index
],
index
,
[
dataSource
[
index
]],
deviceAlarmSchemes
,
);
item
.
markPoint
=
minMaxMarkPoint
(
dataSource
[
index
],
index
,
[
dataSource
[
index
]]);
}
else
{
item
.
markLine
=
{};
item
.
markPoint
=
{};
}
});
chart
.
setOption
(
option
,
true
);
}
});
chart
.
setOption
(
option
,
true
);
}
if
(
!
chart
)
return
;
chart
.
on
(
'legendselectchanged'
,
hander
);
return
()
=>
{
chart
.
off
(
'legendselectchanged'
,
hander
);
};
},
[
dataSource
,
deviceAlarmSchemes
]);
// 网格开关,不更新整个图表
useEffect
(()
=>
{
const
chart
=
chartRef
.
current
?.
getEchartsInstance
?.();
if
(
!
chart
)
return
;
const
option
=
chart
.
getOption
();
// 交互指针
const
tooltip
=
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
showGridLine
?
'cross'
:
'line'
,
},
};
// 网格线
const
axisConfig
=
{
minorTick
:
{
show
:
showGridLine
,
splitNumber
:
2
,
},
minorSplitLine
:
{
show
:
showGridLine
,
lineStyle
:
{
type
:
'dashed'
,
},
},
splitLine
:
{
show
:
showGridLine
,
},
};
let
yAxis
=
axisConfig
;
if
(
isArray
(
option
.
yAxis
))
{
yAxis
=
option
.
yAxis
.
map
((
item
)
=>
({
...
axisConfig
}));
}
let
xAxis
=
axisConfig
;
chart
.
setOption
({
xAxis
,
yAxis
,
tooltip
,
});
},
[
showGridLine
]);
if
(
!
chart
)
return
;
chart
.
on
(
'legendselectchanged'
,
hander
);
return
()
=>
{
chart
.
off
(
'legendselectchanged'
,
hander
);
};
},
[
dataSource
,
deviceAlarmSchemes
]);
// 网格开关,不更新整个图表
useEffect
(()
=>
{
const
chart
=
chartRef
.
current
?.
getEchartsInstance
?.();
if
(
!
chart
)
return
;
const
option
=
chart
.
getOption
();
// 交互指针
const
tooltip
=
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
showGridLine
?
'cross'
:
'line'
,
},
};
// 网格线
const
axisConfig
=
{
minorTick
:
{
show
:
showGridLine
,
splitNumber
:
2
,
},
minorSplitLine
:
{
show
:
showGridLine
,
lineStyle
:
{
type
:
'dashed'
,
},
},
splitLine
:
{
show
:
showGridLine
,
},
};
let
yAxis
=
axisConfig
;
if
(
isArray
(
option
.
yAxis
))
{
yAxis
=
option
.
yAxis
.
map
((
item
)
=>
({...
axisConfig
}));
}
let
xAxis
=
axisConfig
;
chart
.
setOption
({
xAxis
,
yAxis
,
tooltip
,
});
},
[
showGridLine
]);
// 数据都为空显示缺省页
const
isEmpty
=
useMemo
(
()
=>
!
dataSource
||
!
dataSource
.
length
||
!
dataSource
.
find
((
e
)
=>
e
.
dataModel
&&
e
.
dataModel
.
length
>
0
),
[
dataSource
],
);
return
isEmpty
?
(
<
PandaEmpty
/>
)
:
(
<
BasicChart
ref
=
{
chartRef
}
option
=
{
option
}
notMerge
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
/
>
);
// 数据都为空显示缺省页
const
isEmpty
=
useMemo
(
()
=>
!
dataSource
||
!
dataSource
.
length
||
!
dataSource
.
find
((
e
)
=>
e
.
dataModel
&&
e
.
dataModel
.
length
>
0
),
[
dataSource
],
);
return
isEmpty
?
(
<
PandaEmpty
/>
)
:
(
<
BasicChart
ref
=
{
chartRef
}
option
=
{
option
}
notMerge
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
/
>
);
});
export
default
SingleChart
;
packages/extend-components/EC_HistoryView/src/apis/index.js
View file @
89f89959
...
...
@@ -7,6 +7,22 @@ const baseUrl = typeof DUMI_TYPE !== 'undefined' && DUMI_TYPE === 'dumi' ? '/api
const
monitorDeviceUrl
=
`
${
baseUrl
}
/PandaMonitor/Monitor/Device`
;
// 获取单个设备的配置信息
export
function
getPointAddress
(
params
)
{
return
request
({
url
:
`/PandaMonitor/Monitor/PointAddress/GetPointAddress`
,
method
:
REQUEST_METHOD_GET
,
params
});
}
// 获取点表信息
export
function
getPointAddressEntry
(
params
)
{
return
request
({
url
:
`/PandaMonitor/Monitor/PointAddress/GetPointAddressEntry`
,
method
:
REQUEST_METHOD_GET
,
params
});
}
// 获取历史数据
export
function
getHistoryInfo
(
data
)
{
...
...
packages/extend-components/EC_HistoryView/src/demos/index.js
View file @
89f89959
...
...
@@ -3,13 +3,21 @@ import HistoryView from '../index';
import
{
MobileHistoryChart
}
from
"../mobile"
;
const
deviceParams
=
[
/*10.182*/
/* {
deviceCode: 'EGBF00000141',
// sensors: '进水压力,出水瞬时流量,出水累计流量',
sensors: '进水压力',
deviceType: '二供泵房',
deviceType: '
熊猫
二供泵房',
pointAddressID: 208,
}, */
},*/
/* {
deviceCode: 'EGJZ00000197',
// sensors: '进水压力,出水瞬时流量,出水累计流量',
sensors: '1#变频器运行频率',
deviceType: '二供机组',
// pointAddressID: 208,
}*/
/* {
"deviceCode": "SYJ00000008",
"sensors": "瞬时流量",
...
...
@@ -73,6 +81,21 @@ const deviceParams = [
"sensors"
:
"瞬时流量"
,
"deviceType"
:
"流量计"
}
/*邳州*/
/* {
deviceCode: 'EGJZ00000027',
sensors: '2#变频器运行频率',
deviceType: '二供机组',
}*/
/*确山*/
/*泵3状态*/
/* {
// EGJZ00000003
deviceCode: 'EGJZ00000003',
// sensors: '3#频率',
sensors: '出1累计流量',
deviceType: '二供机组',
}*/
];
const
Demo
=
()
=>
{
return
(
...
...
@@ -81,7 +104,6 @@ const Demo = () => {
<
HistoryView
deviceParams
=
{
deviceParams
}
defaultModel
=
"curve"
/>
<
/div
>
<
/div
>
);
};
...
...
packages/extend-components/EC_HistoryView/src/index.js
View file @
89f89959
...
...
@@ -24,11 +24,18 @@ import _ from 'lodash';
import
TimeRangePicker
from
'@wisdom-components/timerangepicker'
;
import
PandaEmpty
from
'@wisdom-components/empty'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
{
getHistoryInfo
,
getDeviceAlarmScheme
,
getExportDeviceHistoryUrl
,
getDictionaryInfoAll
}
from
'./apis'
;
import
{
getHistoryInfo
,
getDeviceAlarmScheme
,
getExportDeviceHistoryUrl
,
getDictionaryInfoAll
,
getPointAddress
,
getPointAddressEntry
}
from
'./apis'
;
import
SingleChart
from
'./SingleChart'
;
import
GridChart
from
'./GridChart'
;
import
'./index.less'
;
import
{
globalConfig
}
from
'antd/lib/config-provider'
;
const
{
RangePicker
}
=
DatePicker
;
const
{
Option
}
=
Select
;
...
...
@@ -108,12 +115,12 @@ const CheckboxData = [
},
{
key
:
'ignoreOutliers'
,
label
:
'
曲线降噪
'
,
label
:
'
去除异常值
'
,
type
:
'updateIgnoreOutliers'
,
checked
:
false
,
showInCurve
:
true
,
showInTable
:
true
,
tooltip
:
'
本算法采用递推平均滤波法(滑动平均滤波法)对采样数据进行均值化平滑处理
。'
,
tooltip
:
'
采用递推平均滤波法(滑动平均滤波法)对采样数据中的异常离群值进行识别与去除
。'
,
hasSub
:
true
},
{
...
...
@@ -302,6 +309,8 @@ const HistoryView = (props) => {
const
[
shortcutsValue
,
setShortcutsValue
]
=
useState
(
''
);
const
[
shortcutsDatePickerArr
,
setShortcutsDatePickerArr
]
=
useState
([]);
const
[
percent
,
setPercent
]
=
useState
(
0
);
// 频率指标特殊业务
const
[
special1
,
setSpecial1
]
=
useState
(
null
);
// 选择的时间范围值
const
dateRange
=
useMemo
(()
=>
{
if
(
timeValue
===
'customer'
)
{
...
...
@@ -565,7 +574,8 @@ const HistoryView = (props) => {
<
div
key
=
{
child
.
key
}
className
=
{
classNames
(
`
${
prefixCls
}
-contrast-list`
)}
>
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-contrast-wrap`
)}
>
<
DatePicker
picker
=
{
contrastOption
}
key
=
{
child
.
key
}
picker
=
{
contrastOption
===
'day'
?
undefined
:
contrastOption
}
value
=
{
child
.
value
}
onChange
=
{(
date
,
dateString
)
=>
onContrastPickerChange
(
date
,
dateString
,
child
)}
style
=
{{
width
:
130
,
border
:
!
shortcutsValue
?
'1px solid #1890ff'
:
''
}}
...
...
@@ -922,10 +932,16 @@ const HistoryView = (props) => {
deviceParams
.map((item) => {
let _item = {...item};
_item.sensors =
item.sensors && !item.sensors.includes('是否在线')
? item.sensors + ',是否在线'
: item.sensors;
// 历史曲线中,是否在线暂时去除,不显示 要显示是否在线解开这里即可 2023-09-15
/* _item.sensors =
item.sensors && !item.sensors.includes('是否在线')
? item.sensors + ',是否在线'
: item.sensors;*/
_item.sensors = item.sensors;
// special 业务
if (special1) {
_item.sensors += `
,
$
{
special1
.
name
}
`;
}
return _item;
})
.forEach((i) => {
...
...
@@ -972,7 +988,12 @@ const HistoryView = (props) => {
deviceParams.forEach((p) => {
// 返回数据按查询指标顺序排序
const sensors = p.sensors?.split(',') ?? [];
if (sensors?.length) sensors.push('是否在线');
if (sensors?.length) {
sensors.push('是否在线');
if (special1) {
sensors.push(special1.name);
}
}
const list = sensors.map((s) => {
const dataItem = res.data.find(
(d) => d.stationCode === p.deviceCode && d.sensorName === s,
...
...
@@ -1117,6 +1138,9 @@ const HistoryView = (props) => {
contrast
=
{
timeValue
===
'contrast'
}
contrastOption
=
{
contrastOption
}
deviceAlarmSchemes
=
{
deviceAlarmSchemes
}
special
=
{{
special1
,
// 频率业务
}}
/
>
)}
<
/div
>
...
...
@@ -1132,26 +1156,57 @@ const HistoryView = (props) => {
// 非单曲线、单指标不执行
if
(
deviceParams
?.
length
!==
1
||
(
deviceParams
?.
length
===
1
&&
deviceParams
?.[
0
]?.
sensors
?.
split
(
','
)?.
length
>
1
))
return
setCompleteInit
(
true
);
setLoading
(
true
);
await
getDictionaryInfoAll
({
const
{
deviceCode
,
deviceType
,
sensors
}
=
deviceParams
[
0
];
let
_id
=
(
await
getPointAddress
({
code
:
deviceCode
}))?.
data
?.[
0
]?.
id
;
let
_params
=
{
deviceType
:
deviceType
};
if
(
_id
)
_params
.
versionId
=
_id
;
let
_request0
=
getDictionaryInfoAll
({
level
:
'组件_ec_historyview'
}).
then
(
res
=>
{
if
(
res
.
code
===
0
)
{
let
_opt
=
res
.
data
.
reduce
((
final
,
cur
)
=>
{
final
[
cur
.
fieldName
]
=
cur
.
fieldValue
return
final
},
{});
let
_checkboxData
=
[...
checkboxData
].
map
(
item
=>
{
let
_item
=
{...
item
};
if
(
_opt
[
item
.
label
]
!==
undefined
)
{
_item
.
checked
=
_opt
[
item
.
label
]
===
'true'
});
let
_request1
=
getPointAddressEntry
(
_params
);
await
Promise
.
all
([
_request0
,
_request1
]).
then
(
result
=>
{
if
(
result
)
{
let
_res0
=
result
[
0
];
let
_res1
=
result
[
1
];
// 查字典配置
if
(
_res0
.
code
===
0
)
{
let
_opt
=
_res0
.
data
.
reduce
((
final
,
cur
)
=>
{
final
[
cur
.
fieldName
]
=
cur
.
fieldValue
return
final
},
{});
let
_checkboxData
=
[...
checkboxData
].
map
(
item
=>
{
let
_item
=
{...
item
};
if
(
_opt
[
item
.
label
]
!==
undefined
)
{
_item
.
checked
=
_opt
[
item
.
label
]
===
'true'
}
return
_item
;
});
setCheckboxData
(
_checkboxData
);
}
// 查点表配置
if
(
_res1
.
code
===
0
)
{
let
_sensorConfig
=
_res1
.
data
.
find
(
item
=>
item
.
name
.
trim
()
===
sensors
.
trim
());
let
_statusName
=
_sensorConfig
.
statusName
;
if
(
_statusName
)
{
let
_statusConfig
=
_res1
.
data
.
find
(
item
=>
item
.
name
.
trim
()
===
_statusName
.
trim
());
let
_valDesc
=
_statusConfig
.
valDesc
;
setSpecial1
({
name
:
_statusName
,
valDesc
:
_valDesc
.
split
(
';'
).
reduce
((
final
,
cur
)
=>
{
let
_arr
=
cur
.
split
(
':'
);
final
[
_arr
[
0
]]
=
_arr
[
1
];
return
final
},
{})
});
}
return
_item
;
});
setCheckboxData
(
_checkboxData
);
}
}
}).
catch
(
err
=>
{
setLoading
(
false
);
})
});
setCompleteInit
(
true
);
};
useEffect
(()
=>
{
...
...
@@ -1184,10 +1239,11 @@ const HistoryView = (props) => {
(
loading
||
percent
!==
0
)
?
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-progressWrapper`
)}
>
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-contentWrapper`
)}
>
{
lineDataType
===
'原始曲线'
||
lineDataType
===
'特征曲线'
&&
moment
(
dateRange
?.[
0
]?.
dateTo
).
diff
(
moment
(
dateRange
?.[
0
]?.
dateFrom
),
'days'
)
>=
30
?
<><
Progress
percent
=
{
percent
}
steps
=
{
20
}
className
=
{
classNames
(
`
${
prefixCls
}
-progress`
,
`
${
prefixCls
}
-blink-2`
)}
showInfo
=
{
false
}
/
>
lineDataType
===
'原始曲线'
||
lineDataType
===
'特征曲线'
&&
moment
(
dateRange
?.[
0
]?.
dateTo
).
diff
(
moment
(
dateRange
?.[
0
]?.
dateFrom
),
'days'
)
>=
30
?
<>
<
Progress
percent
=
{
percent
}
steps
=
{
20
}
className
=
{
classNames
(
`
${
prefixCls
}
-progress`
,
`
${
prefixCls
}
-blink-2`
)}
showInfo
=
{
false
}
/
>
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-tip`
)}
>
加载中
...
<
/div
>
<
/> : <Spin spinning={loading || false}/
>
}
...
...
packages/extend-components/EC_HistoryView/src/utils.js
View file @
89f89959
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment