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
6c311207
Commit
6c311207
authored
Mar 22, 2024
by
陈龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:升级历史曲线、统计曲线的错误空值交互;剔除预测值的曲线
parent
30223b18
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
724 additions
and
582 deletions
+724
-582
SingleChart.js
packages/extend-components/EC_HistoryView/src/SingleChart.js
+12
-5
index.js
packages/extend-components/EC_HistoryView/src/apis/index.js
+4
-5
index.js
packages/extend-components/EC_HistoryView/src/demos/index.js
+47
-2
index.js
packages/extend-components/EC_HistoryView/src/index.js
+18
-8
Basic.tsx
...-components/EC_StatisticalHistoryView/src/demos/Basic.tsx
+8
-3
index.js
.../extend-components/EC_StatisticalHistoryView/src/index.js
+635
-559
No files found.
packages/extend-components/EC_HistoryView/src/SingleChart.js
View file @
6c311207
...
...
@@ -24,7 +24,8 @@ const SingleChart = memo((props) => {
lineDataType
,
showBoxOption
,
special
,
predicateData
predicateData
,
emptyOrError
}
=
props
;
const
chartRef
=
useRef
();
const
timerRef
=
useRef
();
...
...
@@ -57,10 +58,16 @@ const SingleChart = memo((props) => {
return
specialTypeChartOptionGenerator
({
dataSource
,
config
});
}
let
_option
=
optionGenerator
(
dataSource
,
null
,
contrast
,
contrastOption
,
smooth
,
config
,
lineDataType
,
predicateData
);
let
isEmpty
=
_option
.
series
.
length
===
0
;
if
(
isEmpty
)
{
_option
.
yAxis
.
max
=
100
;
_option
.
yAxis
.
min
=
0
;
if
(
emptyOrError
.
empty
||
emptyOrError
.
error
)
{
if
(
isArray
(
_option
.
yAxis
))
{
_option
.
yAxis
.
forEach
(
item
=>
{
item
.
max
=
100
;
item
.
min
=
0
;
})
}
else
{
_option
.
yAxis
.
max
=
100
;
_option
.
yAxis
.
min
=
0
;
}
}
return
_option
;
},
[
dataSource
,
smooth
,
curveCenter
,
chartType
,
predicateData
]);
...
...
packages/extend-components/EC_HistoryView/src/apis/index.js
View file @
6c311207
...
...
@@ -69,7 +69,7 @@ export function getSensorType() {
export
function
getPredicateSensor
(
params
)
{
return
request
({
url
:
`
${
baseUrl
}
/PandaWater/CityWater/PiZhou
/GetPredicateSensor`
,
url
:
`
${
monitorDeviceUrl
}
/GetPredicateSensor`
,
method
:
REQUEST_METHOD_GET
,
params
})
...
...
@@ -84,10 +84,10 @@ export function getStatisticsInfo(data) {
});
}
export
function
getSensorsRealName
(
data
)
{
export
function
getSensorsRealName
(
data
)
{
return
request
({
url
:
`
${
baseUrl
}
/PandaMonitor/Monitor/Device/GetStaticRealName`
,
url
:
`
${
baseUrl
}
/PandaMonitor/Monitor/Device/GetStaticRealName`
,
method
:
REQUEST_METHOD_POST
,
data
,
})
}
\ No newline at end of file
}
packages/extend-components/EC_HistoryView/src/demos/index.js
View file @
6c311207
...
...
@@ -211,17 +211,62 @@ import { MobileHistoryChart } from '../mobile';
];*/
const
deviceParams
=
[
// 新乐,水厂数据异常的问题
{
/*
{
"deviceCode": "SC00000004",
"sensors": "进水瞬时流量,1#出水瞬时流量,2#出水瞬时流量",
"deviceType": "水厂"
}
}*/
/* {
"deviceCode": "EGJZ00000073",
"sensors": "进水压力",
"deviceType": "二供机组"
}*/
/* {
"deviceCode": "EGJZ00000006",
"sensors": "进水压力",
"deviceType": "二供机组"
}*/
/* {
"deviceCode": "EGBF00000002",
"deviceType": "二供泵房",
"sensors": "进水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000005",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000001",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000004",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000003",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000002",
"sensors": "出水压力"
}*/
// 182:8088 报警设备
/* {
"deviceCode": "XMYL00000043",
"sensors": "进水压力",
"deviceType": "熊猫压力表"
}*/
{
"deviceCode"
:
"LLJ00000001"
,
"sensors"
:
"瞬时流量"
,
"deviceType"
:
"流量计"
}
]
const
Demo
=
()
=>
{
return
(
...
...
packages/extend-components/EC_HistoryView/src/index.js
View file @
6c311207
...
...
@@ -376,7 +376,11 @@ const HistoryView = (props) => {
const
[
predicateDevice
,
setPredicateDevice
]
=
useState
(
null
);
const
[
predicateData
,
setPredicateData
]
=
useState
([]);
const
[
predicateTime
,
setPredicateTime
]
=
useState
(
null
);
// 需要处理默认数据,确保图表能够一直显示坐标轴。用来存储当前的请求状态。
const
emptyOrError
=
useRef
({
empty
:
true
,
error
:
true
})
// 这部分功能有问题,等待解决后上线 2024年3月13日
const
[
discreteDeviceType
,
setDiscreteDeviceType
]
=
useState
([
'水厂'
])
// 历史数据相关的特征描述
...
...
@@ -1170,6 +1174,7 @@ const HistoryView = (props) => {
Promise
.
all
(
requestArr
)
.
then
((
results
)
=>
{
setLoading
(
false
);
emptyOrError
.
current
.
error
=
false
;
if
(
results
.
length
)
{
let
data
=
[];
let
_predicateData
=
[];
...
...
@@ -1234,6 +1239,9 @@ const HistoryView = (props) => {
}
});
setLoading
(
false
);
if
(
data
.
length
!==
0
)
{
emptyOrError
.
current
.
empty
=
false
;
}
handleTableData
(
data
)
setChartDataSource
(
data
);
setPredicateData
(
_predicateData
);
...
...
@@ -1356,6 +1364,7 @@ const HistoryView = (props) => {
<
div
className
=
{
`
${
prefixCls
}
-content`
}
>
{
grid
===
true
?
(
<
GridChart
emptyOrError
=
{
emptyOrError
.
current
}
curveCenter
=
{
curveCenter
}
prefixCls
=
{
prefixCls
}
dataSource
=
{
chartDataSource
}
...
...
@@ -1370,6 +1379,7 @@ const HistoryView = (props) => {
/
>
)
:
(
<
SingleChart
emptyOrError
=
{
emptyOrError
.
current
}
dateRange
=
{
dateRange
}
showBoxOption
=
{
showBoxOption
}
lineDataType
=
{
lineDataType
}
...
...
@@ -1432,29 +1442,29 @@ const HistoryView = (props) => {
// 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
let
_request1
=
getPointAddressEntry
(
_params
);
let
_request2
=
getSensorType
();
let
_request3
=
getPredicateSensor
({
deviceCode
,
sensors
});
await
Promise
.
all
([
_request0
,
_request1
,
_request2
,
_request3
]).
then
((
result
)
=>
{
//
let _request3 = getPredicateSensor({deviceCode, sensors});
await
Promise
.
all
([
_request0
,
_request1
,
_request2
]).
then
((
result
)
=>
{
if
(
result
)
{
let
_res0
=
result
[
0
];
let
_res1
=
result
[
1
];
let
_res2
=
result
[
2
];
let
_res3
=
result
[
3
];
//
let _res3 = result[3];
let
_checkboxData
=
[...
checkboxData
];
// 单设备单曲线时,查询是否配置为预测点
if
(
_res3
.
code
===
0
&&
_res3
.
data
)
{
/*
if (_res3.code === 0 && _res3.data) {
// 1. 如果是单曲线,并且配置了预测,那么默认开启预测;
// 2024年3月11日 物联预测功能支撑后,再开发这部分
/*
_checkboxData.push({
_checkboxData.push({
key: 'predicate',
label: '数据预测',
checked: true,
showInCurve: true,
showInTable: true,
})
*/
})
setPredicateDevice({..._res3.data, deviceType: '预测'});
} else {
setPredicateDevice(null);
}
}
*/
// 查字典配置
if
(
_res0
.
code
===
0
)
{
let
_opt
=
_res0
.
data
.
reduce
((
final
,
cur
)
=>
{
...
...
packages/extend-components/EC_StatisticalHistoryView/src/demos/Basic.tsx
View file @
6c311207
...
...
@@ -9,11 +9,17 @@ const Demo = () => {
// deviceType: '加压泵站',
// statisticType: '',
// }
const
params
=
{
/*
const params = {
deviceCode: 'LLJ00000001',
sensors: '今日水量',
deviceType: '流量计',
statisticType: '',
} */
const
params
=
{
deviceCode
:
'EGBF00000023'
,
sensors
:
'今日供水量'
,
deviceType
:
'二供泵房'
,
statisticType
:
''
,
}
return
(
<>
...
...
@@ -24,4 +30,4 @@ const Demo = () => {
);
};
export
default
Demo
;
\ No newline at end of file
export
default
Demo
;
packages/extend-components/EC_StatisticalHistoryView/src/index.js
View file @
6c311207
import
React
,
{
useState
,
useEffect
,
useRef
,
useContext
}
from
'react'
;
import
React
,
{
useState
,
useEffect
,
useRef
,
useContext
}
from
'react'
;
import
classNames
from
'classnames'
;
import
moment
from
'moment'
;
import
Empty
from
'@wisdom-components/empty'
;
import
LoadBox
from
'@wisdom-components/loadbox'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
{
ExportExcel
}
from
'@wisdom-components/exportexcel'
;
import
{
ConfigProvider
,
Select
,
DatePicker
,
Radio
,
Table
,
Button
}
from
'antd'
;
import
{
VerticalAlignBottomOutlined
}
from
'@ant-design/icons'
;
import
{
BasicChart
}
from
'@wisdom-components/basicchart'
;
import
{
getStatisticsInfo
}
from
'./apis'
;
import
{
ExportExcel
}
from
'@wisdom-components/exportexcel'
;
import
{
ConfigProvider
,
Select
,
DatePicker
,
Radio
,
Table
,
Button
}
from
'antd'
;
import
{
VerticalAlignBottomOutlined
}
from
'@ant-design/icons'
;
import
{
BasicChart
}
from
'@wisdom-components/basicchart'
;
import
{
getStatisticsInfo
}
from
'./apis'
;
import
'./index.less'
;
const
StatisticalHistoryView
=
(
props
)
=>
{
const
{
getPrefixCls
}
=
useContext
(
ConfigProvider
.
ConfigContext
);
const
prefixCls
=
getPrefixCls
(
'ec-statistical-history-view'
);
const
chartRef
=
useRef
(
null
);
const
defaultOptionRef
=
useRef
({
title
:
{
show
:
false
,
text
:
''
,
},
tooltip
:
false
,
grid
:
{
containLabel
:
true
,
left
:
20
,
right
:
20
,
// top: 20,
bottom
:
10
,
},
toolbox
:
{
show
:
false
,
},
xAxis
:
[
{
type
:
'time'
,
axisTick
:
{
alignWithLabel
:
true
,
const
{
getPrefixCls
}
=
useContext
(
ConfigProvider
.
ConfigContext
);
const
prefixCls
=
getPrefixCls
(
'ec-statistical-history-view'
);
const
chartRef
=
useRef
(
null
);
const
defaultOptionRef
=
useRef
({
title
:
{
show
:
false
,
text
:
''
,
},
boundaryGap
:
false
,
splitLine
:
{
show
:
true
,
lineStyle
:
{
type
:
'dashed'
,
},
tooltip
:
false
,
grid
:
{
containLabel
:
true
,
left
:
20
,
right
:
20
,
// top: 20,
bottom
:
10
,
},
},
],
yAxis
:
[
{
type
:
'value'
,
max
:
100
,
min
:
0
,
position
:
'left'
,
alignTicks
:
true
,
axisLine
:
{
show
:
true
,
toolbox
:
{
show
:
false
,
},
axisLabel
:
{
formatter
:
'{value}'
,
},
},
],
series
:[{
type
:
'line'
,
data
:[
[
moment
(
moment
().
format
(
'YYYY-MM-DD 00:00:00'
)).
valueOf
(),
null
],
[
moment
(
moment
().
format
(
'YYYY-MM-DD 23:59:59'
)).
valueOf
(),
null
],
]
}]
});
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
historyRender
,
setHistoryRender
]
=
useState
(
true
);
const
[
historyParams
,
setHistoryParams
]
=
useState
({});
const
[
columns
,
setColumns
]
=
useState
([
{
title
:
'时间'
,
dataIndex
:
'pt'
,
align
:
'center'
,
width
:
100
,
fixed
:
'left'
,
},
]);
const
[
dataSource
,
setDataSource
]
=
useState
([]);
const
[
options
,
setOptions
]
=
useState
({});
const
[
dateValue
,
setDateValue
]
=
useState
(
'today'
);
const
[
picker
,
setPicker
]
=
useState
(
'day'
);
const
[
time
,
setTime
]
=
useState
({
startTime
:
''
,
endTime
:
''
});
const
[
dateTime
,
setDateTime
]
=
useState
(
moment
().
format
(
'YYYY-MM-DD HH:mm:ss'
));
// 时间切换筛选
const
onTimeChange
=
(
e
)
=>
{
setDateValue
(
e
.
target
.
value
);
};
// 自定义时间类型
const
onPickerChange
=
(
value
)
=>
{
setPicker
(
value
);
let
start
=
moment
(
dateTime
).
subtract
(
2
,
value
).
startOf
(
value
).
format
(
'YYYY-MM-DD 00:00:00'
);
let
end
=
moment
(
dateTime
).
endOf
(
value
).
format
(
'YYYY-MM-DD 23:59:59'
);
setTime
({
startDate
:
start
,
endDate
:
end
});
};
// 自定义时间选择
const
onDateChange
=
(
value
,
dateString
)
=>
{
setDateTime
(
dateString
);
const
start
=
moment
(
value
).
subtract
(
2
,
picker
).
startOf
(
picker
).
format
(
'YYYY-MM-DD 00:00:00'
);
const
end
=
moment
(
value
).
endOf
(
picker
).
format
(
'YYYY-MM-DD 23:59:59'
);
setTime
({
startDate
:
start
,
endDate
:
end
});
};
const
exportExcelBtn
=
(
e
)
=>
{
if
(
!
dataSource
.
length
)
return
false
;
const
sheetFilter
=
columns
.
map
((
item
)
=>
{
return
item
.
dataIndex
;
});
const
sheetHeader
=
columns
.
map
((
item
)
=>
{
return
item
.
title
;
});
const
sheetData
=
dataSource
.
map
((
item
)
=>
{
return
{
pt
:
item
.
pt
,
value0
:
String
(
item
.
value0
),
value1
:
String
(
item
.
value1
),
value2
:
String
(
item
.
value2
),
};
xAxis
:
[
{
type
:
'time'
,
axisTick
:
{
alignWithLabel
:
true
,
},
boundaryGap
:
false
,
splitLine
:
{
show
:
true
,
lineStyle
:
{
type
:
'dashed'
,
},
},
},
],
yAxis
:
[
{
type
:
'value'
,
max
:
100
,
min
:
0
,
position
:
'left'
,
alignTicks
:
true
,
axisLine
:
{
show
:
true
,
},
axisLabel
:
{
formatter
:
'{value}'
,
},
},
],
series
:
[{
type
:
'line'
,
data
:
[
[
moment
(
moment
().
format
(
'YYYY-MM-DD 00:00:00'
)).
valueOf
(),
null
],
[
moment
(
moment
().
format
(
'YYYY-MM-DD 23:59:59'
)).
valueOf
(),
null
],
]
}]
});
ExportExcel
({
name
:
`
${
props
?.
deviceParams
?.
sensors
||
''
}
指标数据
`,
content: [
// 用来判定是否是初始化、是否时报错
const
emptyOrError
=
useRef
({
empty
:
true
,
error
:
true
})
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
historyRender
,
setHistoryRender
]
=
useState
(
true
);
const
[
historyParams
,
setHistoryParams
]
=
useState
({});
const
[
columns
,
setColumns
]
=
useState
([
{
sheetData: sheetData
,
sheetName: 'sheet1
',
sheetFilter: sheetFilter
,
sheetHeader: sheetHeader
,
columnWidths: [10, 10, 10, 10]
,
title
:
'时间'
,
dataIndex
:
'pt
'
,
align
:
'center'
,
width
:
100
,
fixed
:
'left'
,
},
],
});
};
]);
const
[
dataSource
,
setDataSource
]
=
useState
([]);
const
[
options
,
setOptions
]
=
useState
({});
const
[
dateValue
,
setDateValue
]
=
useState
(
'today'
);
const
[
picker
,
setPicker
]
=
useState
(
'day'
);
const
[
time
,
setTime
]
=
useState
({
startTime
:
''
,
endTime
:
''
});
const
[
dateTime
,
setDateTime
]
=
useState
(
moment
().
format
(
'YYYY-MM-DD HH:mm:ss'
));
// 获取历史统计数据
const getHistoryData = async () => {
const { deviceCode = '', sensors = '', deviceType = '', statisticType = '' } = historyParams;
const nameTypeList = [];
if (!deviceCode || !sensors) return setOptions(null);
nameTypeList.push({
name: sensors,
type: statisticType || 'Sub',
});
const params = {
pageIndex: 1,
pageSize: 999,
nameTypeList: nameTypeList,
accountName: deviceType,
dateFrom: time.startDate,
dateTo: time.endDate,
deviceCode: deviceCode,
dateType: picker,
// 时间切换筛选
const
onTimeChange
=
(
e
)
=>
{
setDateValue
(
e
.
target
.
value
);
};
// 自定义时间类型
const
onPickerChange
=
(
value
)
=>
{
setPicker
(
value
);
let
start
=
moment
(
dateTime
).
subtract
(
2
,
value
).
startOf
(
value
).
format
(
'YYYY-MM-DD 00:00:00'
);
let
end
=
moment
(
dateTime
).
endOf
(
value
).
format
(
'YYYY-MM-DD 23:59:59'
);
setTime
({
startDate
:
start
,
endDate
:
end
});
};
setLoading(true);
let results = null;
try {
results = await getStatisticsInfo(params);
} catch (err) {
return setLoading(false);
}
setLoading(false);
const list = results?.data?.list || [];
const dataList = list.length ? list[0] : {};
const dNameDataList = dataList.dNameDataList ? dataList.dNameDataList : [];
const data = dNameDataList.length ? dNameDataList[0] : null;
if (!data) return setOptions(null);
dataMenthod(data);
};
const dataMenthod = (data) => {
const { nameDate } = data;
let time0 = '',
time1 = '',
time2 = '';
let data0 = [],
data1 = [],
data2 = [];
let timeName = [];
switch (dateValue) {
case 'today':
time0 = moment(time.endDate).subtract(0, 'day').format('YYYY-MM-DD');
time1 = moment(time.endDate).subtract(1, 'day').format('YYYY-MM-DD');
time2 = moment(time.endDate).subtract(2, 'day').format('YYYY-MM-DD');
timeName = [].concat(dayName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY-MM-DD');
const pt = moment(item.time).format('HH时');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
// 自定义时间选择
const
onDateChange
=
(
value
,
dateString
)
=>
{
setDateTime
(
dateString
);
const
start
=
moment
(
value
).
subtract
(
2
,
picker
).
startOf
(
picker
).
format
(
'YYYY-MM-DD 00:00:00'
);
const
end
=
moment
(
value
).
endOf
(
picker
).
format
(
'YYYY-MM-DD 23:59:59'
);
setTime
({
startDate
:
start
,
endDate
:
end
});
};
const
exportExcelBtn
=
(
e
)
=>
{
if
(
!
dataSource
.
length
)
return
false
;
const
sheetFilter
=
columns
.
map
((
item
)
=>
{
return
item
.
dataIndex
;
});
break;
case 'thisWeek':
time0 = moment(time.endDate).subtract(0, 'week').format('WW');
time1 = moment(time.endDate).subtract(1, 'week').format('WW');
time2 = moment(time.endDate).subtract(2, 'week').format('WW');
timeName = [].concat(weekName);
nameDate.forEach((item) => {
const times = moment(item.time).format('WW');
const pt = getWeek(item.time);
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
const
sheetHeader
=
columns
.
map
((
item
)
=>
{
return
item
.
title
;
});
break;
case 'thisMonth':
time0 = moment(time.endDate).subtract(0, 'month').format('YYYY-MM');
time1 = moment(time.endDate).subtract(1, 'month').format('YYYY-MM');
time2 = moment(time.endDate).subtract(2, 'month').format('YYYY-MM');
timeName = [].concat(monthName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY-MM');
const pt = moment(item.time).format('DD日');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
const
sheetData
=
dataSource
.
map
((
item
)
=>
{
return
{
pt
:
item
.
pt
,
value0
:
String
(
item
.
value0
),
value1
:
String
(
item
.
value1
),
value2
:
String
(
item
.
value2
),
};
});
break;
case 'thisYear':
time0 = moment(time.endDate).subtract(0, 'year').format('YYYY');
time1 = moment(time.endDate).subtract(1, 'year').format('YYYY');
time2 = moment(time.endDate).subtract(2, 'year').format('YYYY');
timeName = [].concat(yearName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY');
const pt = moment(item.time).format('MM月');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
ExportExcel
({
name
:
`
${
props
?.
deviceParams
?.
sensors
||
''
}
指标数据
`,
content: [
{
sheetData: sheetData,
sheetName: 'sheet1',
sheetFilter: sheetFilter,
sheetHeader: sheetHeader,
columnWidths: [10, 10, 10, 10],
},
],
});
break;
case 'customer':
const style = picker === 'day' ? 'HH时' : picker === 'month' ? 'DD日' : 'MM月';
const format = picker === 'day' ? 'YYYY-MM-DD' : picker === 'month' ? 'YYYY-MM' : 'YYYY';
time0 = moment(time.endDate).subtract(0, picker).format(format);
time1 = moment(time.endDate).subtract(1, picker).format(format);
time2 = moment(time.endDate).subtract(2, picker).format(format);
timeName = [].concat([time0, time1, time2]);
nameDate.forEach((item) => {
const times = moment(item.time).format(format);
const pt = moment(item.time).format(style);
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
};
// 生成对应的数据结构
const returnDataStructure = (dateFrom, dateTo, dateType, dateValue) => {
//
let length = new Array(3).fill(false);
let finalData = [];
if (dateType === 'day') {
let days = length.map((item, index) => {
return moment(dateTo).subtract(index, 'days').format('YYYY-MM-DD')
});
let hours = new Array(24).fill(false).map((item, index) => {
return index < 10 ? `
0
$
{
index
}
` : index;
})
days.forEach(day => {
hours.forEach(hour => {
finalData.push(`
$
{
day
}
$
{
hour
}
`);
})
})
}
if (dateType === 'month') {
let months = length.map((item, index) => {
return moment(dateTo).subtract(index, 'months').format('YYYY-MM')
});
let days = new Array(31).fill(false).map((item, index) => {
return index < 9 ? `
0
$
{
index
+
1
}
` : index + 1;
})
months.forEach(month => {
days.forEach(day => {
finalData.push(`
$
{
month
}
$
{
day
}
`);
})
})
}
if (dateType === 'year') {
let years = length.map((item, index) => {
return moment(dateTo).subtract(index, 'years').format('YYYY')
});
let months = new Array(12).fill(false).map((item, index) => {
return index < 9 ? `
0
$
{
index
+
1
}
` : index + 1;
})
years.forEach(year => {
months.forEach(month => {
finalData.push(`
$
{
year
}
$
{
month
}
`);
})
})
}
return finalData.map(item => {
return {
time: item,
value: null,
}
});
break;
};
const handleDataForEmptyOrError = () => {
let _data = returnDataStructure(time.startDate, time.endDate, picker, dateValue);
dataMenthod({nameDate: _data, dName: props?.deviceParams?.sensors ?? ''});
}
const dataChart = {
data: [data0, data1, data2],
name: timeName,
// 获取历史统计数据
const getHistoryData = async () => {
const {deviceCode = '', sensors = '', deviceType = '', statisticType = ''} = historyParams;
const nameTypeList = [];
if (!deviceCode || !sensors) return setOptions(null);
nameTypeList.push({
name: sensors,
type: statisticType || 'Sub',
});
const params = {
pageIndex: 1,
pageSize: 999,
nameTypeList: nameTypeList,
accountName: deviceType,
dateFrom: time.startDate,
dateTo: time.endDate,
deviceCode: deviceCode,
dateType: picker,
};
setLoading(true);
let results = null;
try {
results = await getStatisticsInfo(params);
emptyOrError.current.error = false;
} catch (err) {
if (historyParams.sensors) {
handleDataForEmptyOrError()
}
return setLoading(false);
}
setLoading(false);
const list = results?.data?.list || [];
if (list.length === 0) {
handleDataForEmptyOrError()
}
const dataList = list.length ? list[0] : {};
const dNameDataList = dataList.dNameDataList ? dataList.dNameDataList : [];
const data = dNameDataList.length ? dNameDataList[0] : null;
if (!data) return setOptions(null);
dataMenthod(data);
};
const _data = [data0, data1, data2].sort((a, b) => {
return b.length - a.length;
})
const dataTable = _data[0].map((item, index) => {
return {
...item,
value0: data0[index] ? data0[index]?.value === 0 || data0[index]?.value ? data0[index]?.value : '-' : '',
value1: data1[index] ? data1[index]?.value === 0 || data1[index]?.value ? data1[index]?.value : '-' : '',
value2: data2[index] ? data2[index]?.value === 0 || data2[index]?.value ? data2[index]?.value : '-' : '',
};
});
renderChart(dataChart, data);
renderTable(dataTable, timeName);
};
const renderChart = (dataInfo, data) => {
if (!dataInfo) return setOptions(null);
const { unit, dName } = data;
const series = [];
let xData = [];
dataInfo.data.forEach((item, index) => {
const config = !index && dName.indexOf('流量') > -1 ? { areaStyle: {} } : {};
const style = index ? { lineStyle: { normal: { type: 'dashed' } } } : {};
const list = {
name: dataInfo.name[index],
type: 'line',
smooth: true,
...config,
...style,
data: item.map((arr) => {
return {
name: arr.pt,
value: arr.value,
};
}),
};
series.push(list);
xData = item.map((arr) => {
return arr.pt;
});
});
const option = {
title: {
show: false,
text: '',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
grid: {
containLabel: true,
left: 20,
right: 20,
// top: 20,
bottom: 10,
},
toolbox: {
show: false,
},
legend: {
left: 'center',
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
boundaryGap: false,
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
},
},
data: xData,
},
],
yAxis: [
{
type: 'value',
name: unit,
position: 'left',
alignTicks: true,
axisLine: {
show: true,
},
axisLabel: {
formatter: '{value}',
},
},
],
series: series,
const dataMenthod = (data) => {
const {nameDate} = data;
nameDate.forEach(item => {
if (item.value !== null) emptyOrError.current.empty = false;
})
let time0 = '',
time1 = '',
time2 = '';
let data0 = [],
data1 = [],
data2 = [];
let timeName = [];
switch (dateValue) {
case 'today':
time0 = moment(time.endDate).subtract(0, 'day').format('YYYY-MM-DD');
time1 = moment(time.endDate).subtract(1, 'day').format('YYYY-MM-DD');
time2 = moment(time.endDate).subtract(2, 'day').format('YYYY-MM-DD');
timeName = [].concat(dayName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY-MM-DD');
const pt = moment(item.time).format('HH时');
if (times === time0) data0.push({...item, pt: pt});
if (times === time1) data1.push({...item, pt: pt});
if (times === time2) data2.push({...item, pt: pt});
});
break;
case 'thisWeek':
time0 = moment(time.endDate).subtract(0, 'week').format('WW');
time1 = moment(time.endDate).subtract(1, 'week').format('WW');
time2 = moment(time.endDate).subtract(2, 'week').format('WW');
timeName = [].concat(weekName);
nameDate.forEach((item) => {
const times = moment(item.time).format('WW');
const pt = getWeek(item.time);
if (times === time0) data0.push({...item, pt: pt});
if (times === time1) data1.push({...item, pt: pt});
if (times === time2) data2.push({...item, pt: pt});
});
break;
case 'thisMonth':
time0 = moment(time.endDate).subtract(0, 'month').format('YYYY-MM');
time1 = moment(time.endDate).subtract(1, 'month').format('YYYY-MM');
time2 = moment(time.endDate).subtract(2, 'month').format('YYYY-MM');
timeName = [].concat(monthName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY-MM');
const pt = moment(item.time).format('DD日');
if (times === time0) data0.push({...item, pt: pt});
if (times === time1) data1.push({...item, pt: pt});
if (times === time2) data2.push({...item, pt: pt});
});
break;
case 'thisYear':
time0 = moment(time.endDate).subtract(0, 'year').format('YYYY');
time1 = moment(time.endDate).subtract(1, 'year').format('YYYY');
time2 = moment(time.endDate).subtract(2, 'year').format('YYYY');
timeName = [].concat(yearName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY');
const pt = moment(item.time).format('MM月');
if (times === time0) data0.push({...item, pt: pt});
if (times === time1) data1.push({...item, pt: pt});
if (times === time2) data2.push({...item, pt: pt});
});
break;
case 'customer':
const style = picker === 'day' ? 'HH时' : picker === 'month' ? 'DD日' : 'MM月';
const format = picker === 'day' ? 'YYYY-MM-DD' : picker === 'month' ? 'YYYY-MM' : 'YYYY';
time0 = moment(time.endDate).subtract(0, picker).format(format);
time1 = moment(time.endDate).subtract(1, picker).format(format);
time2 = moment(time.endDate).subtract(2, picker).format(format);
timeName = [].concat([time0, time1, time2]);
nameDate.forEach((item) => {
const times = moment(item.time).format(format);
const pt = moment(item.time).format(style);
if (times === time0) data0.push({...item, pt: pt});
if (times === time1) data1.push({...item, pt: pt});
if (times === time2) data2.push({...item, pt: pt});
});
break;
}
const dataChart = {
data: [data0, data1, data2],
name: timeName,
};
const _data = [data0, data1, data2].sort((a, b) => {
return b.length - a.length;
})
const dataTable = _data[0].map((item, index) => {
return {
...item,
value0: data0[index] ? data0[index]?.value === 0 || data0[index]?.value ? data0[index]?.value : '-' : '',
value1: data1[index] ? data1[index]?.value === 0 || data1[index]?.value ? data1[index]?.value : '-' : '',
value2: data2[index] ? data2[index]?.value === 0 || data2[index]?.value ? data2[index]?.value : '-' : '',
};
});
renderChart(dataChart, data);
renderTable(dataTable, timeName);
};
setOptions(option);
};
const renderTable = (dataInfo, timeName) => {
const dataIndex = ['value0', 'value1', 'value2'];
const column1 = [
{
title: '时间',
dataIndex: 'pt',
align: 'center',
width: 100,
fixed: 'left',
},
];
const column2 = timeName.map((item, index) => {
return {
title: item,
dataIndex: dataIndex[index],
align: 'center',
};
});
const column = column1.concat(column2);
setColumns(column);
setDataSource(dataInfo);
};
const renderChart = (dataInfo, data) => {
if (!dataInfo) return setOptions(null);
const {unit, dName} = data;
const series = [];
let xData = [];
dataInfo.data.forEach((item, index) => {
const config = !index && dName.indexOf('流量') > -1 ? {areaStyle: {}} : {};
const style = index ? {lineStyle: {normal: {type: 'dashed'}}} : {};
const list = {
name: dataInfo.name[index],
type: 'line',
smooth: true,
...config,
...style,
data: item.map((arr) => {
return {
name: arr.pt,
value: arr.value,
};
}),
};
series.push(list);
xData = item.map((arr) => {
return arr.pt;
});
});
let showMinMax = emptyOrError.current.empty && emptyOrError.current.error;
const option = {
title: {
show: false,
text: '',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
grid: {
containLabel: true,
left: 20,
right: 20,
// top: 20,
bottom: 10,
},
toolbox: {
show: false,
},
legend: {
left: 'center',
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
boundaryGap: false,
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
},
},
data: xData,
},
],
yAxis: [
{
type: 'value',
name: unit,
position: 'left',
alignTicks: true,
axisLine: {
show: true,
},
axisLabel: {
formatter: '{value}',
},
...(showMinMax ? {min: 0, max: 100} : {})
},
],
series: series,
};
setOptions(option);
};
const getWeek = (date) => {
const weekTime = moment(date).day();
switch (weekTime) {
case 1:
return '周一';
break;
case 2:
return '周二';
break;
case 3:
return '周三';
break;
case 4:
return '周四';
break;
case 5:
return '周五';
break;
case 6:
return '周六';
break;
case 0:
return '周日';
break;
}
};
const renderTable = (dataInfo, timeName) => {
const dataIndex = ['value0', 'value1', 'value2'];
const column1 = [
{
title: '时间',
dataIndex: 'pt',
align: 'center',
width: 100,
fixed: 'left',
},
];
const column2 = timeName.map((item, index) => {
return {
title: item,
dataIndex: dataIndex[index],
align: 'center',
};
});
const column = column1.concat(column2);
setColumns(column);
setDataSource(dataInfo);
};
const Summary = (currentData) => {
return (
<Table.Summary.Row>
{columns.map((item, index) => {
let sum = 0;
currentData.reduce((prev, next) => {
sum += next[item.dataIndex] === '-' || next[item.dataIndex] === '' ? 0 : next[item.dataIndex];
}, 0);
return (
<Table.Summary.Cell key={item.dataIndex} index={index} align={'center'}>
{index === 0 ? '总计' : sum.toFixed(0)}
</Table.Summary.Cell>
);
})}
</Table.Summary.Row>
);
};
const getWeek = (date) => {
const weekTime = moment(date).day();
switch (weekTime) {
case 1:
return '周一';
break;
case 2:
return '周二';
break;
case 3:
return '周三';
break;
case 4:
return '周四';
break;
case 5:
return '周五';
break;
case 6:
return '周六';
break;
case 0:
return '周日';
break;
}
};
useEffect(() => {
setHistoryParams(props.deviceParams || {});
}, [props.deviceParams]);
const Summary = (currentData) => {
return (
<Table.Summary.Row>
{columns.map((item, index) => {
let sum = 0;
currentData.reduce((prev, next) => {
sum += next[item.dataIndex] === '-' || next[item.dataIndex] === '' ? 0 : next[item.dataIndex];
}, 0);
return (
<Table.Summary.Cell key={item.dataIndex} index={index} align={'center'}>
{index === 0 ? '总计' : sum.toFixed(0)}
</Table.Summary.Cell>
);
})}
</Table.Summary.Row>
);
};
useEffect(() => {
if (props?.deviceParams?.sensors) {
handleDataForEmptyOrError()
}
}, [])
useEffect(() => {
setHistoryParams(props.deviceParams || {});
}, [props.deviceParams]);
useEffect(() => {
let start = '',
end = '';
switch (dateValue) {
case 'today':
start = moment().subtract(2, 'day').format('YYYY-MM-DD 00:00:00');
end = moment().format('YYYY-MM-DD 23:59:59');
setPicker('day');
break;
case 'thisWeek':
start = moment().startOf('week').subtract(2, 'week').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('week').format('YYYY-MM-DD 23:59:59');
setPicker('month');
break;
case 'thisMonth':
start = moment().startOf('month').subtract(2, 'month').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('month').format('YYYY-MM-DD 23:59:59');
setPicker('month');
break;
case 'thisYear':
start = moment().startOf('year').subtract(2, 'year').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('year').format('YYYY-MM-DD 23:59:59');
setPicker('year');
break;
case 'customer':
start = moment(dateTime).startOf(picker).subtract(2, picker).format('YYYY-MM-DD 00:00:00');
end = moment(dateTime).endOf(picker).format('YYYY-MM-DD 23:59:59');
break;
}
setTime({ startDate: start, endDate: end
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dateValue]);
useEffect(() => {
let start = '',
end = '';
switch (dateValue) {
case 'today':
start = moment().subtract(2, 'day').format('YYYY-MM-DD 00:00:00');
end = moment().format('YYYY-MM-DD 23:59:59');
setPicker('day');
break;
case 'thisWeek':
start = moment().startOf('week').subtract(2, 'week').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('week').format('YYYY-MM-DD 23:59:59');
setPicker('month');
break;
case 'thisMonth':
start = moment().startOf('month').subtract(2, 'month').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('month').format('YYYY-MM-DD 23:59:59');
setPicker('month');
break;
case 'thisYear':
start = moment().startOf('year').subtract(2, 'year').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('year').format('YYYY-MM-DD 23:59:59');
setPicker('year');
break;
case 'customer':
start = moment(dateTime).startOf(picker).subtract(2, picker).format('YYYY-MM-DD 00:00:00');
end = moment(dateTime).endOf(picker).format('YYYY-MM-DD 23:59:59');
break;
}
setTime({startDate: start, endDate: end
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dateValue]);
useEffect(() => {
getHistoryData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [time, historyParams, picker]);
useEffect(() => {
getHistoryData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [time, historyParams, picker]);
return (
<div className={classNames(prefixCls)}>
<div className={classNames(`
$
{
prefixCls
}
-
box
`)}>
<div className={classNames(`
$
{
prefixCls
}
-
header
`)}>
<div className={classNames(`
$
{
prefixCls
}
-
time
`)}>
<span>时间选择:</span>
<Radio.Group value={dateValue} defaultValue={dateList[0].key} onChange={onTimeChange}>
{dateList.map((item) => (
<Radio.Button key={item.key} value={item.key}>
{item.name}
</Radio.Button>
))}
</Radio.Group>
{dateValue === 'customer' && (
<>
<Select
defaultValue="day"
value={picker}
options={timeList}
onChange={onPickerChange}
className={classNames(`
$
{
prefixCls
}
-
select
`)}
/>
<DatePicker onChange={onDateChange} value={moment(dateTime)} picker={picker} allowClear={false}/>
</>
return (
<div className={classNames(prefixCls)}>
<div className={classNames(`
$
{
prefixCls
}
-
box
`)}>
<div className={classNames(`
$
{
prefixCls
}
-
header
`)}>
<div className={classNames(`
$
{
prefixCls
}
-
time
`)}>
<span>时间选择:</span>
<Radio.Group value={dateValue} defaultValue={dateList[0].key} onChange={onTimeChange}>
{dateList.map((item) => (
<Radio.Button key={item.key} value={item.key}>
{item.name}
</Radio.Button>
))}
</Radio.Group>
{dateValue === 'customer' && (
<>
<Select
defaultValue="day"
value={picker}
options={timeList}
onChange={onPickerChange}
className={classNames(`
$
{
prefixCls
}
-
select
`)}
/>
<DatePicker onChange={onDateChange} value={moment(dateTime)} picker={picker}
allowClear={false}/>
</>
)}
</div>
<Button
className={classNames(`
$
{
prefixCls
}
-
down
-
load
`)}
type="primary"
onClick={exportExcelBtn}
disabled={!dataSource.length}
>
<VerticalAlignBottomOutlined/>
下载
</Button>
</div>
<div className={classNames(`
$
{
prefixCls
}
-
content
`)}>
{
<>
<div className={classNames(`
$
{
prefixCls
}
-
chart
`)}>
{
<BasicChart
ref={chartRef}
option={(!options || !options?.series) ? defaultOptionRef.current : options}
notMerge
style={{width: '100%', height: '100%'}}
/>
}
</div>
<div className={classNames(`
$
{
prefixCls
}
-
table
`)}>
<BasicTable
dataSource={dataSource}
columns={columns}
pagination={false}
bordered={true}
onRow={(record, index) => {
return {
onMouseEnter: (event) => {
let seriesIndex = 0;
const dataIndex = ['value0', 'value1', 'value2'];
seriesIndex = dataIndex.findIndex((item) => {
return record[item] !== '-';
});
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'showTip',
seriesIndex: seriesIndex,
dataIndex: index,
});
}, // 鼠标移入行
onMouseLeave: (event) => {
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'hideTip',
dataIndex: index,
});
}, // 鼠标移出行
};
}}
scroll={{x: '100%', y: 'calc(100% - 40px)'}}
summary={Summary}
/>
</div>
</>
}
</div>
</div>
{loading && (
<div className={classNames(`
$
{
prefixCls
}
-
load
-
box
`)}>
<LoadBox spinning={loading}/>
</div>
)}
</div>
<Button
className={classNames(`
$
{
prefixCls
}
-
down
-
load
`)}
type="primary"
onClick={exportExcelBtn}
disabled={!dataSource.length}
>
<VerticalAlignBottomOutlined />
下载
</Button>
</div>
<div className={classNames(`
$
{
prefixCls
}
-
content
`)}>
{
<>
<div className={classNames(`
$
{
prefixCls
}
-
chart
`)}>
{
<BasicChart
ref={chartRef}
option={(!options||!options?.series) ? defaultOptionRef.current : options}
notMerge
style={{ width: '100%', height: '100%' }}
/>
}
</div>
<div className={classNames(`
$
{
prefixCls
}
-
table
`)}>
<BasicTable
dataSource={dataSource}
columns={columns}
pagination={false}
bordered={true}
onRow={(record, index) => {
return {
onMouseEnter: (event) => {
let seriesIndex = 0;
const dataIndex = ['value0', 'value1', 'value2'];
seriesIndex = dataIndex.findIndex((item) => {
return record[item] !== '-';
});
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'showTip',
seriesIndex: seriesIndex,
dataIndex: index,
});
}, // 鼠标移入行
onMouseLeave: (event) => {
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'hideTip',
dataIndex: index,
});
}, // 鼠标移出行
};
}}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
summary={Summary}
/>
</div>
</>
}
</div>
</div>
{loading && (
<div className={classNames(`
$
{
prefixCls
}
-
load
-
box
`)}>
<LoadBox spinning={loading} />
</div>
)}
</div>
);
);
};
export default StatisticalHistoryView;
const dateList = [
{
key: 'today',
name: '今日',
},
// {
// key: 'thisWeek',
// name: '本周',
// },
{
key: 'thisMonth',
name: '本月',
},
{
key: 'thisYear',
name: '今年',
},
{
key: 'customer',
name: '自定义',
},
{
key: 'today',
name: '今日',
},
// {
// key: 'thisWeek',
// name: '本周',
// },
{
key: 'thisMonth',
name: '本月',
},
{
key: 'thisYear',
name: '今年',
},
{
key: 'customer',
name: '自定义',
},
];
const timeList = [
{
value: 'day',
label: '日',
},
{
value: 'month',
label: '月',
},
{
value: 'year',
label: '年',
},
{
value: 'day',
label: '日',
},
{
value: 'month',
label: '月',
},
{
value: 'year',
label: '年',
},
];
const dayName = ['今日', '昨日', '前日'];
...
...
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