Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
DC-TOM
Project
Project
Details
Activity
Releases
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
刘照晖
DC-TOM
Commits
c3807a12
Commit
c3807a12
authored
May 28, 2025
by
Cai Wei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(*): 布袋监测连调
parent
f61d456b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
407 additions
and
326 deletions
+407
-326
chart.js
src/utils/chart.js
+4
-0
bag-monitoring.vue
src/views/dustMonitoring/bag-monitoring.vue
+392
-325
index.vue
src/views/dustMonitoring/index.vue
+11
-0
index.vue
src/views/dustOverview/index.vue
+0
-1
No files found.
src/utils/chart.js
View file @
c3807a12
...
@@ -132,6 +132,7 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
...
@@ -132,6 +132,7 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
top
:
"3%"
,
top
:
"3%"
,
containLabel
:
true
,
containLabel
:
true
,
},
},
// x轴的文字去除年月日
xAxis
:
{
xAxis
:
{
type
:
"category"
,
type
:
"category"
,
boundaryGap
:
false
,
boundaryGap
:
false
,
...
@@ -145,6 +146,9 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
...
@@ -145,6 +146,9 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
fontSize
:
12
,
fontSize
:
12
,
interval
:
"auto"
,
interval
:
"auto"
,
rotate
:
0
,
rotate
:
0
,
formatter
:
function
(
value
)
{
return
value
.
split
(
' '
)[
1
];
}
},
},
axisTick
:
{
axisTick
:
{
show
:
false
,
show
:
false
,
...
...
src/views/dustMonitoring/bag-monitoring.vue
View file @
c3807a12
...
@@ -4,49 +4,69 @@
...
@@ -4,49 +4,69 @@
<div
class=
"select-container"
>
<div
class=
"select-container"
>
<span>
检测仪器
</span>
<span>
检测仪器
</span>
<el-select
v-model=
"selectedDevice"
placeholder=
"1#布袋检测仪"
>
<el-select
v-model=
"selectedDevice"
placeholder=
"1#布袋检测仪"
>
<el-option
v-for=
"item in deviceList"
:key=
"item.deviceNo"
:label=
"item.deviceName"
:value=
"item.deviceNo"
></el-option>
<el-option
v-for=
"item in deviceList"
:key=
"item.deviceNo"
:label=
"item.deviceName"
:value=
"item.deviceNo"
></el-option>
</el-select>
</el-select>
</div>
</div>
<div
class=
"title"
>
BME布袋监测
</div>
<div
class=
"title"
>
BME布袋监测
</div>
</div>
</div>
<div
class=
"chart-container"
>
<div
class=
"chart-container"
>
<div
class=
"chart-wrapper"
ref=
"chartRef"
v-if=
"chartData.xData.length > 0"
></div>
<div
class=
"chart-wrapper"
ref=
"chartRef"
></div>
<div
class=
"chart-wrapper
"
v-else
>
<div
class=
"chart-wrapper
no-data"
v-if=
"chartData.xData.length === 0"
>
<div
class=
"no-data-text"
>
暂无数据
</div>
<div
class=
"no-data-text"
>
暂无数据
</div>
</div>
</div>
</div>
<div
class=
"data-panel"
:class=
"
{ 'collapsed': !isPanelOpen }">
<div
class=
"panel-toggle"
:class=
"
{ 'collapsed-icon': !isPanelOpen, 'expanded-icon': isPanelOpen }" @click="togglePanel">
<div
class=
"data-panel"
:class=
"
{ collapsed: !isPanelOpen }">
<el-icon
v-if=
"isPanelOpen"
><ArrowRightBold
/></el-icon>
<div
<el-icon
v-if=
"!isPanelOpen"
><ArrowLeftBold
/></el-icon>
class=
"panel-toggle"
:class=
"
{
'collapsed-icon': !isPanelOpen,
'expanded-icon': isPanelOpen,
}"
@click="togglePanel"
>
<el-icon
v-if=
"isPanelOpen"
><ArrowRightBold
/></el-icon>
<el-icon
v-if=
"!isPanelOpen"
><ArrowLeftBold
/></el-icon>
</div>
<div
class=
"data-box"
>
<div
class=
"data-item"
>
<div>
时间:
{{
currentData
.
time
}}
</div>
<div>
仓室:
{{
currentData
.
compartNo
}}
</div>
<div>
反吹:
{{
currentData
.
blowBack
}}
</div>
</div>
</div>
<div
class=
"data-box"
>
<div
class=
"data-item"
>
<div
class=
"data-item"
>
<div>
时间:
{{
currentData
.
time
||
'-'
}}
</div>
<div>
DI3:
{{
currentData
.
di3
}}
</div>
<div>
仓室:
{{
currentData
.
compartName
}}
</div>
<div>
反吹:
{{
currentData
.
blowBack
}}
</div>
</div>
<div
class=
"data-item"
>
<div>
排:
{{
currentData
.
row
}}
</div>
<div>
排:
{{
currentData
.
row
}}
</div>
<div>
实时值:
{{
currentData
.
realData
}}
</div>
<div>
实时值:
{{
currentData
.
realData
}}
</div>
</div>
<div
class=
"data-item"
>
<div>
基线值:
{{
currentData
.
baseline
}}
</div>
<div>
基线值:
{{
currentData
.
baseline
}}
</div>
<div>
Delay:
{{
currentData
.
delay
}}
</div>
<div>
totaltime:
{{
currentData
.
totalTime
}}
</div>
</div>
<div
class=
"data-item"
>
<div>
next:
{{
currentData
.
next
}}
</div>
<div>
valve:
{{
currentData
.
valveNo
}}
</div>
<div>
DI_TIME=
{{
currentData
.
diTime
}}
</div>
</div>
</div>
<div
class=
"data-item"
>
<div
class=
"data-item"
>
<!--
<div>
峰值R:
{{
currentData
.
peakValueR
}}
</div>
<div>
峰值H:
{{
currentData
.
peakValueH
}}
</div>
-->
<div>
peak=
{{
currentData
.
peak
}}
</div>
<div>
peak=
{{
currentData
.
peak
}}
</div>
</div>
</div>
</div>
</div>
<!--
<div
class=
"data-box second-box"
>
<!--
<div
class=
"data-box second-box"
>
<div>
时间:
{{
secondaryData
.
time
}}
, 仓室:
{{
secondaryData
.
chamber
}}
, 反吹:
{{
secondaryData
.
backwash
}}
, 谷值:
{{
secondaryData
.
valleyValue
}}
, 仓室状态阀门
{{
secondaryData
.
status
}}
False
{{
secondaryData
.
falseVal
}}
</div>
<div>
时间:
{{
secondaryData
.
time
}}
, 仓室:
{{
secondaryData
.
chamber
}}
, 反吹:
{{
secondaryData
.
backwash
}}
, 谷值:
{{
secondaryData
.
valleyValue
}}
, 仓室状态阀门
{{
secondaryData
.
status
}}
False
{{
secondaryData
.
falseVal
}}
</div>
</div>
-->
</div>
-->
</div>
</div>
</div>
<div
class=
"data-table"
>
<div
class=
"data-table"
>
<div
class=
"time-controls"
>
<div
class=
"time-controls"
>
<el-button
@
click=
"navigateBackward"
>
<el-button
@
click=
"navigateBackward"
>
<el-icon><ArrowLeftBold
/>
向前
</el-icon>
<el-icon><ArrowLeftBold
/>
向前
</el-icon>
...
@@ -65,415 +85,451 @@
...
@@ -65,415 +85,451 @@
<thead>
<thead>
<tr>
<tr>
<th>
名称
</th>
<th>
名称
</th>
<th
v-for=
"(value, index) in tableData"
:key=
"index"
>
{{
value
.
compartName
}}
</th>
<th
v-for=
"(value, index) in tableData"
:key=
"index"
>
{{
value
.
compartName
}}
</th>
</tr>
</tr>
</thead>
</thead>
<tbody>
<tbody>
<tr>
<tr>
<td>
峰值_R
</td>
<td>
峰值_R
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'r'+index"
>
{{
value
.
peakValueR
||
'-'
}}
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'r' + index"
>
{{
value
.
peakValueR
||
"-"
}}
</td>
</tr>
</tr>
<tr>
<tr>
<td>
峰值_H
</td>
<td>
峰值_H
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'h'+index"
>
{{
value
.
peakValueH
||
'-'
}}
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'h' + index"
>
{{
value
.
peakValueH
||
"-"
}}
</td>
</tr>
</tr>
<tr>
<tr>
<td>
状态
</td>
<td>
状态
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'s'+index"
:class=
"
{ 'error': value.status === 1 }">
{{
value
.
status
===
1
?
'故障'
:
'正常'
}}
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'s' + index"
:class=
"
{ error: value.status === 1 }"
>
{{
value
.
status
===
1
?
"故障"
:
"正常"
}}
</td>
</tr>
</tr>
<tr>
<tr>
<td>
反吹中
</td>
<td>
反吹中
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'b'+index"
>
{{
value
.
blowBack
||
'-'
}}
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'b' + index"
>
{{
value
.
blowBack
||
"-"
}}
</td>
</tr>
</tr>
<tr>
<tr>
<td>
谷值
</td>
<td>
谷值
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'v'+index"
>
{{
value
.
valleyValue
||
'-'
}}
</td>
<td
v-for=
"(value, index) in tableData"
:key=
"'v' + index"
>
{{
value
.
valleyValue
||
"-"
}}
</td>
</tr>
</tr>
</tbody>
</tbody>
</table>
</table>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
,
onBeforeUnmount
,
watch
}
from
'vue'
import
{
ref
,
reactive
,
onMounted
,
onBeforeUnmount
,
watch
}
from
"vue"
;
import
*
as
echarts
from
'echarts'
import
*
as
echarts
from
"echarts"
;
import
moment
from
'moment'
import
moment
from
"moment"
;
import
{
ArrowRightBold
,
ArrowLeftBold
}
from
'@element-plus/icons-vue'
import
{
ArrowRightBold
,
ArrowLeftBold
}
from
"@element-plus/icons-vue"
;
import
{
getBagMonitoringChartOption
}
from
'@/utils/chart.js'
import
{
getBagMonitoringChartOption
}
from
"@/utils/chart.js"
;
import
{
getMonitorToday
,
getMonitorList
,
getMonitorRealtime
}
from
'@/request/api/bagMonitor'
import
{
import
{
useRoute
}
from
'vue-router'
getMonitorToday
,
getMonitorList
,
getMonitorRealtime
,
}
from
"@/request/api/bagMonitor"
;
import
{
useRoute
}
from
"vue-router"
;
// 获取路由参数
// 获取路由参数
const
route
=
useRoute
()
const
route
=
useRoute
()
;
// 设备选择
// 设备选择
const
selectedDevice
=
ref
(
null
)
const
selectedDevice
=
ref
(
null
)
;
const
isPanelOpen
=
ref
(
true
)
const
isPanelOpen
=
ref
(
true
)
;
// 图表相关
// 图表相关
const
chartRef
=
ref
(
null
)
const
chartRef
=
ref
(
null
)
;
let
chartInstance
=
null
let
chartInstance
=
null
;
let
updateTimer
=
null
// 定时器引用
let
updateTimer
=
null
;
// 定时器引用
let
lastTimePoint
=
null
let
lastTimePoint
=
null
;
// 控制是否获取实时设备状态数据
// 控制是否获取实时设备状态数据
let
showRealtimeDeviceStatus
=
true
let
showRealtimeDeviceStatus
=
true
;
// 从路由参数获取dusterNo
// 从路由参数获取dusterNo
const
dusterNo
=
ref
(
route
.
params
.
dusterNo
||
route
.
query
.
dusterNo
||
'ZH-ZL-1GL-001'
)
// 默认值作为fallback
const
dusterNo
=
ref
(
route
.
params
.
dusterNo
||
route
.
query
.
dusterNo
||
"ZH-ZL-1GL-001"
);
// 默认值作为fallback
// 图表数据
// 图表数据
const
chartData
=
reactive
({
const
chartData
=
reactive
({
xData
:
[],
xData
:
[],
seriesData
:
[]
seriesData
:
[]
,
})
})
;
const
deviceList
=
ref
([]);
const
deviceList
=
ref
([]);
const
currentTime
=
ref
(
null
);
const
currentTime
=
ref
(
null
);
// 当前数据面板
// 当前数据面板
const
currentData
=
ref
({
const
currentData
=
ref
({
"date"
:
""
,
realtime
:
""
,
"realData"
:
""
,
time
:
""
,
"valveNo"
:
""
,
compartNo
:
""
,
"baseline"
:
""
,
blowBack
:
""
,
"peak"
:
""
,
di3
:
""
,
"time"
:
""
,
row
:
""
,
"compartName"
:
""
,
realData
:
""
,
"blowBack"
:
""
,
baseline
:
""
,
"row"
:
""
delay
:
""
,
})
totalTime
:
""
,
next
:
""
,
valveNo
:
""
,
diTime
:
""
,
peak
:
""
,
});
// 表格数据
// 表格数据
const
tableData
=
ref
([{
const
tableData
=
ref
([
compartName
:
'默认'
,
{
peakValueR
:
0
,
compartName
:
"默认"
,
peakValueH
:
0
,
peakValueR
:
0
,
status
:
0
,
peakValueH
:
0
,
blowBack
:
0
,
status
:
0
,
valleyValue
:
0
blowBack
:
0
,
}]);
valleyValue
:
0
,
},
]);
// 时间控制
// 时间控制
const
timeInterval
=
ref
(
'10'
)
const
timeInterval
=
ref
(
"10"
);
const
togglePanel
=
()
=>
{
const
togglePanel
=
()
=>
{
isPanelOpen
.
value
=
!
isPanelOpen
.
value
isPanelOpen
.
value
=
!
isPanelOpen
.
value
;
}
}
;
// 初始化图表
// 初始化图表
const
initChart
=
()
=>
{
const
initChart
=
()
=>
{
if
(
chartInstance
)
{
if
(
chartInstance
)
{
chartInstance
.
dispose
()
chartInstance
.
dispose
()
;
}
}
// 初始化图表数据
// 初始化图表数据
initChartData
()
initChartData
()
;
}
}
;
// 初始化图表数据
// 初始化图表数据
const
initChartData
=
()
=>
{
const
initChartData
=
()
=>
{
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
{
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
{
console
.
warn
(
'缺少dusterNo或deviceNo,无法获取数据'
)
console
.
warn
(
"缺少dusterNo或deviceNo,无法获取数据"
);
return
return
;
}
}
// 获取昨天这个之前的数据
// 获取昨天这个之前的数据
const
startTime
=
moment
().
subtract
(
1
,
'days'
).
subtract
(
5
,
'minutes'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
const
startTime
=
moment
()
const
endTime
=
moment
().
subtract
(
1
,
'days'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
.
subtract
(
5
,
"minutes"
)
chartData
.
xData
=
[]
.
format
(
"YYYY-MM-DD HH:mm:ss"
);
chartData
.
seriesData
=
[]
const
endTime
=
moment
().
format
(
"YYYY-MM-DD HH:mm:ss"
);
chartData
.
xData
=
[];
chartData
.
seriesData
=
[];
getMonitorToday
({
getMonitorToday
({
dusterNo
:
dusterNo
.
value
,
dusterNo
:
dusterNo
.
value
,
deviceNo
:
selectedDevice
.
value
,
deviceNo
:
selectedDevice
.
value
,
startTime
:
startTime
,
startTime
:
startTime
,
endTime
:
endTime
endTime
:
endTime
,
}).
then
(
res
=>
{
// 将data中的date和realData数据添加到chartData中,要求大数据量下速度快
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
res
.
data
.
forEach
((
item
)
=>
{
chartData
.
xData
.
push
(
item
.
date
)
chartData
.
seriesData
.
push
(
item
.
realData
)
})
// 当前时间
currentTime
.
value
=
res
.
data
[
res
.
data
.
length
-
1
].
date
chartInstance
=
echarts
.
init
(
chartRef
.
value
)
// 启动定时更新
startRealTimeUpdates
()
}
else
{
console
.
warn
(
'未获取到初始数据'
)
}
}).
catch
(
err
=>
{
console
.
error
(
'获取初始数据失败:'
,
err
)
})
})
}
.
then
((
res
)
=>
{
// 将data中的date和realData数据添加到chartData中,要求大数据量下速度快
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
res
.
data
.
forEach
((
item
)
=>
{
chartData
.
xData
.
push
(
item
.
date
);
chartData
.
seriesData
.
push
(
item
.
realData
);
});
// 当前时间
currentTime
.
value
=
res
.
data
[
res
.
data
.
length
-
1
].
date
;
chartInstance
=
echarts
.
init
(
chartRef
.
value
);
// 启动定时更新
startRealTimeUpdates
();
}
else
{
console
.
warn
(
"未获取到初始数据"
);
}
})
.
catch
((
err
)
=>
{
console
.
error
(
"获取初始数据失败:"
,
err
);
});
};
// 更新图表
// 更新图表
const
updateChart
=
()
=>
{
const
updateChart
=
()
=>
{
if
(
chartInstance
)
{
if
(
chartInstance
)
{
chartInstance
.
setOption
(
getBagMonitoringChartOption
(
chartData
.
xData
,
chartData
.
seriesData
))
chartInstance
.
setOption
(
getBagMonitoringChartOption
(
chartData
.
xData
,
chartData
.
seriesData
)
);
}
}
}
}
;
// 启动实时更新
// 启动实时更新
const
startRealTimeUpdates
=
()
=>
{
const
startRealTimeUpdates
=
()
=>
{
if
(
updateTimer
)
{
if
(
updateTimer
)
{
clearInterval
(
updateTimer
)
clearInterval
(
updateTimer
)
;
}
}
updateTimer
=
setInterval
(()
=>
{
updateTimer
=
setInterval
(()
=>
{
updateFunction
()
updateFunction
();
},
1000
)
},
1000
);
isRealTimeMode
=
true
showRealtimeDeviceStatus
=
true
;
showRealtimeDeviceStatus
=
true
};
}
// 更新函数
// 更新函数
const
updateFunction
=
()
=>
{
const
updateFunction
=
()
=>
{
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
return
;
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
return
;
// 从API获取实时数据
// 从API获取实时数据
if
(
showRealtimeDeviceStatus
)
{
if
(
showRealtimeDeviceStatus
)
{
getMonitorRealtime
({
getMonitorRealtime
({
dusterNo
:
dusterNo
.
value
,
dusterNo
:
dusterNo
.
value
,
deviceNo
:
selectedDevice
.
value
deviceNo
:
selectedDevice
.
value
,
}).
then
(
res
=>
{
if
(
res
.
data
)
{
// 更新数据面板
if
(
res
.
data
.
realtimeCompart
)
{
tableData
.
value
=
res
.
data
.
realtimeCompart
}
if
(
res
.
data
.
realtimeCurve
)
{
currentData
.
value
=
res
.
data
.
realtimeCurve
}
}
}).
catch
(
err
=>
{
console
.
error
(
'获取实时数据失败:'
,
err
)
})
})
.
then
((
res
)
=>
{
if
(
res
.
data
)
{
// 更新数据面板
if
(
res
.
data
.
realtimeCompart
)
{
tableData
.
value
=
res
.
data
.
realtimeCompart
;
}
if
(
res
.
data
.
realtimePanel
)
{
currentData
.
value
=
res
.
data
.
realtimePanel
;
}
}
})
.
catch
((
err
)
=>
{
console
.
error
(
"获取实时数据失败:"
,
err
);
});
}
}
// 结束时间往后推一秒
// 结束时间往后推一秒
let
endTime
=
moment
(
new
Date
(
currentTime
.
value
)).
add
(
1
,
'seconds'
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
let
endTime
=
moment
(
new
Date
(
currentTime
.
value
))
.
add
(
1
,
"seconds"
)
.
format
(
"YYYY-MM-DD HH:mm:ss"
);
getMonitorToday
({
getMonitorToday
({
dusterNo
:
dusterNo
.
value
,
dusterNo
:
dusterNo
.
value
,
deviceNo
:
selectedDevice
.
value
,
deviceNo
:
selectedDevice
.
value
,
startTime
:
currentTime
.
value
,
startTime
:
currentTime
.
value
,
endTime
:
endTime
endTime
:
endTime
,
}).
then
(
res
=>
{
}).
then
(
(
res
)
=>
{
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
const
item
=
res
.
data
[
res
.
data
.
length
-
1
]
const
item
=
res
.
data
[
res
.
data
.
length
-
1
];
chartData
.
xData
.
push
(
item
.
date
)
chartData
.
xData
.
push
(
item
.
date
);
chartData
.
seriesData
.
push
(
item
.
realData
||
0
)
chartData
.
seriesData
.
push
(
item
.
realData
||
0
);
// 移除最旧的数据点以保持固定长度
// 移除最旧的数据点以保持固定长度
if
(
chartData
.
xData
.
length
>
301
)
{
// 保持300秒的数据
if
(
chartData
.
xData
.
length
>
301
)
{
chartData
.
xData
.
shift
()
// 保持300秒的数据
chartData
.
seriesData
.
shift
()
chartData
.
xData
.
shift
();
}
chartData
.
seriesData
.
shift
();
currentTime
.
value
=
endTime
;
}
// 更新图表
currentTime
.
value
=
endTime
;
updateChart
()
// 更新图表
updateChart
();
}
}
})
})
;
}
}
;
// 停止实时更新
// 停止实时更新
const
stopRealTimeUpdates
=
()
=>
{
const
stopRealTimeUpdates
=
()
=>
{
if
(
updateTimer
)
{
if
(
updateTimer
)
{
clearInterval
(
updateTimer
)
clearInterval
(
updateTimer
)
;
updateTimer
=
null
updateTimer
=
null
;
}
}
isRealTimeMode
=
false
showRealtimeDeviceStatus
=
false
;
showRealtimeDeviceStatus
=
false
};
}
// 向前导航(查看更早的数据)
// 向前导航(查看更早的数据)
const
navigateBackward
=
()
=>
{
const
navigateBackward
=
()
=>
{
// 不完全关闭轮询,只禁用实时设备状态获取
// 不完全关闭轮询,只禁用实时设备状态获取
showRealtimeDeviceStatus
=
false
showRealtimeDeviceStatus
=
false
;
// 获取时间间隔(分钟)
// 获取时间间隔(分钟)
const
interval
=
parseInt
(
timeInterval
.
value
)
||
10
const
interval
=
parseInt
(
timeInterval
.
value
)
||
10
;
const
intervalMs
=
interval
*
60
*
1000
const
intervalMs
=
interval
*
60
*
1000
;
// 如果是第一次点击,以当前最后一条数据的时间为参考
// 如果是第一次点击,以当前最后一条数据的时间为参考
if
(
lastTimePoint
===
null
&&
chartData
.
xData
.
length
>
0
)
{
if
(
lastTimePoint
===
null
&&
chartData
.
xData
.
length
>
0
)
{
const
lastTimeString
=
chartData
.
xData
[
chartData
.
xData
.
length
-
1
]
const
lastTimeString
=
chartData
.
xData
[
chartData
.
xData
.
length
-
1
]
;
lastTimePoint
=
new
Date
(
lastTimeString
)
lastTimePoint
=
new
Date
(
lastTimeString
)
;
}
else
if
(
lastTimePoint
===
null
)
{
}
else
if
(
lastTimePoint
===
null
)
{
// 如果没有数据,使用当前时间
// 如果没有数据,使用当前时间
lastTimePoint
=
new
Date
()
lastTimePoint
=
new
Date
()
;
}
}
// 计算新的时间范围
// 计算新的时间范围
const
endTime
=
new
Date
(
lastTimePoint
.
getTime
()
-
intervalMs
)
const
endTime
=
new
Date
(
lastTimePoint
.
getTime
()
-
intervalMs
)
;
lastTimePoint
=
endTime
lastTimePoint
=
endTime
;
// 重新生成数据
// 重新生成数据
generateHistoricalData
(
endTime
,
interval
)
generateHistoricalData
(
endTime
,
interval
)
;
}
}
;
// 向后导航(查看更近的数据)
// 向后导航(查看更近的数据)
const
navigateForward
=
()
=>
{
const
navigateForward
=
()
=>
{
// 不完全关闭轮询,只禁用实时设备状态获取
// 不完全关闭轮询,只禁用实时设备状态获取
showRealtimeDeviceStatus
=
false
showRealtimeDeviceStatus
=
false
;
// 获取时间间隔(分钟)
// 获取时间间隔(分钟)
const
interval
=
parseInt
(
timeInterval
.
value
)
||
10
const
interval
=
parseInt
(
timeInterval
.
value
)
||
10
;
const
intervalMs
=
interval
*
60
*
1000
const
intervalMs
=
interval
*
60
*
1000
;
// 如果是第一次点击,以当前最后一条数据的时间为参考
// 如果是第一次点击,以当前最后一条数据的时间为参考
if
(
lastTimePoint
===
null
&&
chartData
.
xData
.
length
>
0
)
{
if
(
lastTimePoint
===
null
&&
chartData
.
xData
.
length
>
0
)
{
const
lastTimeString
=
chartData
.
xData
[
chartData
.
xData
.
length
-
1
]
const
lastTimeString
=
chartData
.
xData
[
chartData
.
xData
.
length
-
1
]
;
lastTimePoint
=
new
Date
(
lastTimeString
)
lastTimePoint
=
new
Date
(
lastTimeString
)
;
}
else
if
(
lastTimePoint
===
null
)
{
}
else
if
(
lastTimePoint
===
null
)
{
// 如果没有数据,使用当前时间
// 如果没有数据,使用当前时间
lastTimePoint
=
new
Date
()
lastTimePoint
=
new
Date
()
;
}
}
// 计算新的时间范围
// 计算新的时间范围
const
endTime
=
new
Date
(
lastTimePoint
.
getTime
()
+
intervalMs
)
const
endTime
=
new
Date
(
lastTimePoint
.
getTime
()
+
intervalMs
)
;
// 如果新的结束时间超过当前时间,则切换回实时模式
// 如果新的结束时间超过当前时间,则切换回实时模式
const
now
=
moment
()
const
now
=
moment
()
;
if
(
endTime
>
now
)
{
if
(
endTime
>
now
)
{
lastTimePoint
=
null
lastTimePoint
=
null
;
showRealtimeDeviceStatus
=
true
showRealtimeDeviceStatus
=
true
;
return
return
;
}
}
lastTimePoint
=
endTime
lastTimePoint
=
endTime
;
// 重新生成数据
// 重新生成数据
generateHistoricalData
(
endTime
,
interval
)
generateHistoricalData
(
endTime
,
interval
)
;
}
}
;
const
reset
=
()
=>
{
const
reset
=
()
=>
{
// 清空现有数据
// 清空现有数据
chartData
.
xData
=
[]
chartData
.
xData
=
[]
;
chartData
.
seriesData
=
[]
chartData
.
seriesData
=
[]
;
lastTimePoint
=
null
lastTimePoint
=
null
;
// 恢复实时设备状态获取
// 恢复实时设备状态获取
showRealtimeDeviceStatus
=
true
showRealtimeDeviceStatus
=
true
;
// 重新生成当前时间往前300秒的数据
// 重新生成当前时间往前300秒的数据
const
now
=
new
Date
()
const
now
=
new
Date
();
generateHistoricalData
(
now
,
5
);
generateHistoricalData
(
now
,
5
)
// 开启实时更新
// 开启实时更新
startRealTimeUpdate
()
startRealTimeUpdate
()
;
}
}
;
// 开启实时更新(重置用)
// 开启实时更新(重置用)
const
startRealTimeUpdate
=
()
=>
{
const
startRealTimeUpdate
=
()
=>
{
// 确保之前的定时器已清除
// 确保之前的定时器已清除
stopRealTimeUpdates
()
stopRealTimeUpdates
();
// 初始化实时模式标志
isRealTimeMode
=
true
// 启动定时更新
// 启动定时更新
updateTimer
=
setInterval
(()
=>
{
updateTimer
=
setInterval
(()
=>
{
updateFunction
()
updateFunction
()
;
},
1000
)
},
1000
)
;
}
}
;
// 生成历史数据
// 生成历史数据
const
generateHistoricalData
=
(
endTime
,
intervalMinutes
)
=>
{
const
generateHistoricalData
=
(
endTime
,
intervalMinutes
)
=>
{
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
return
;
if
(
!
dusterNo
.
value
||
!
selectedDevice
.
value
)
return
;
// 清空现有数据
// 清空现有数据
chartData
.
xData
=
[]
chartData
.
xData
=
[]
;
chartData
.
seriesData
=
[]
chartData
.
seriesData
=
[]
;
const
startTime
=
new
Date
(
endTime
.
getTime
()
-
intervalMinutes
*
60
*
1000
)
const
startTime
=
new
Date
(
endTime
.
getTime
()
-
intervalMinutes
*
60
*
1000
)
;
const
startTimeStr
=
moment
(
startTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
const
startTimeStr
=
moment
(
startTime
).
format
(
"YYYY-MM-DD HH:mm:ss"
);
const
endTimeStr
=
moment
(
endTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
const
endTimeStr
=
moment
(
endTime
).
format
(
"YYYY-MM-DD HH:mm:ss"
);
// 从API获取历史数据
// 从API获取历史数据
getMonitorToday
({
getMonitorToday
({
dusterNo
:
dusterNo
.
value
,
dusterNo
:
dusterNo
.
value
,
deviceNo
:
selectedDevice
.
value
,
deviceNo
:
selectedDevice
.
value
,
startTime
:
startTimeStr
,
startTime
:
startTimeStr
,
endTime
:
endTimeStr
endTime
:
endTimeStr
,
}).
then
(
res
=>
{
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
res
.
data
.
forEach
(
item
=>
{
chartData
.
xData
.
push
(
item
.
date
)
chartData
.
seriesData
.
push
(
item
.
realData
)
})
// 更新图表
updateChart
()
}
}).
catch
(
err
=>
{
console
.
error
(
'获取历史数据失败:'
,
err
)
})
})
}
.
then
((
res
)
=>
{
if
(
res
.
data
&&
res
.
data
.
length
>
0
)
{
res
.
data
.
forEach
((
item
)
=>
{
chartData
.
xData
.
push
(
item
.
date
);
chartData
.
seriesData
.
push
(
item
.
realData
);
});
// 更新图表
updateChart
();
}
})
.
catch
((
err
)
=>
{
console
.
error
(
"获取历史数据失败:"
,
err
);
});
};
// 监听窗口大小变化,调整图表大小
// 监听窗口大小变化,调整图表大小
const
handleResize
=
()
=>
{
const
handleResize
=
()
=>
{
if
(
chartInstance
)
{
if
(
chartInstance
)
{
chartInstance
.
resize
()
chartInstance
.
resize
()
;
}
}
}
}
;
const
getDeviceList
=
()
=>
{
const
getDeviceList
=
()
=>
{
if
(
!
dusterNo
.
value
)
return
;
if
(
!
dusterNo
.
value
)
return
;
getMonitorList
({
getMonitorList
({
dusterNo
:
dusterNo
.
value
dusterNo
:
dusterNo
.
value
,
}).
then
(
res
=>
{
}).
then
(
(
res
)
=>
{
deviceList
.
value
=
res
.
data
.
devices
||
[];
deviceList
.
value
=
res
.
data
.
devices
||
[];
if
(
deviceList
.
value
.
length
>
0
)
{
if
(
deviceList
.
value
.
length
>
0
)
{
selectedDevice
.
value
=
deviceList
.
value
[
0
].
deviceNo
selectedDevice
.
value
=
deviceList
.
value
[
0
].
deviceNo
;
tableData
.
value
=
Array
.
from
({
length
:
res
.
data
.
compartCount
},
(
item
,
index
)
=>
({
tableData
.
value
=
Array
.
from
(
compartName
:
`
${
index
+
1
}
仓`
,
{
length
:
res
.
data
.
compartCount
},
peakValueR
:
0
,
(
item
,
index
)
=>
({
peakValueH
:
0
,
compartName
:
`
${
index
+
1
}
仓`
,
status
:
0
,
peakValueR
:
0
,
blowBack
:
0
,
peakValueH
:
0
,
}))
status
:
0
,
blowBack
:
0
,
})
);
}
}
initChart
()
initChart
()
;
})
})
;
}
}
;
// 监听dusterNo变化
// 监听dusterNo变化
watch
(
dusterNo
,
(
newVal
)
=>
{
watch
(
dusterNo
,
(
newVal
)
=>
{
if
(
newVal
)
{
if
(
newVal
)
{
// 重新获取设备列表
// 重新获取设备列表
getDeviceList
()
getDeviceList
()
;
}
}
})
})
;
onMounted
(()
=>
{
onMounted
(()
=>
{
console
.
log
(
"dusterNo"
,
route
);
console
.
log
(
"dusterNo"
,
route
);
if
(
dusterNo
.
value
)
{
if
(
dusterNo
.
value
)
{
getDeviceList
()
getDeviceList
()
;
}
}
window
.
addEventListener
(
'resize'
,
handleResize
)
window
.
addEventListener
(
"resize"
,
handleResize
);
})
})
;
onBeforeUnmount
(()
=>
{
onBeforeUnmount
(()
=>
{
window
.
removeEventListener
(
'resize'
,
handleResize
)
window
.
removeEventListener
(
"resize"
,
handleResize
);
// 清除定时器
// 清除定时器
if
(
updateTimer
)
{
if
(
updateTimer
)
{
clearInterval
(
updateTimer
)
clearInterval
(
updateTimer
)
;
updateTimer
=
null
updateTimer
=
null
;
}
}
// 销毁图表实例
// 销毁图表实例
if
(
chartInstance
)
{
if
(
chartInstance
)
{
chartInstance
.
dispose
()
chartInstance
.
dispose
()
;
chartInstance
=
null
chartInstance
=
null
;
}
}
})
})
;
</
script
>
</
script
>
<
style
scoped
lang=
"scss"
>
<
style
scoped
lang=
"scss"
>
...
@@ -481,15 +537,16 @@ onBeforeUnmount(() => {
...
@@ -481,15 +537,16 @@ onBeforeUnmount(() => {
width
:
100%
;
width
:
100%
;
height
:
calc
(
100%
-
14px
);
height
:
calc
(
100%
-
14px
);
box-sizing
:
border-box
;
box-sizing
:
border-box
;
overflow-x
:
hidden
;
// overflow-x: hidden;
position
:
relative
;
.header
{
.header
{
position
:
relative
;
position
:
relative
;
display
:
flex
;
display
:
flex
;
justify-content
:
center
;
justify-content
:
center
;
align-items
:
center
;
align-items
:
center
;
margin-bottom
:
16px
;
margin-bottom
:
16px
;
.select-container
{
.select-container
{
position
:
absolute
;
position
:
absolute
;
left
:
0
;
left
:
0
;
...
@@ -498,13 +555,13 @@ onBeforeUnmount(() => {
...
@@ -498,13 +555,13 @@ onBeforeUnmount(() => {
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
z-index
:
99
;
z-index
:
99
;
span
{
span
{
display
:
block
;
display
:
block
;
width
:
110px
;
width
:
110px
;
margin-right
:
10px
;
margin-right
:
10px
;
}
}
.device-number
{
.device-number
{
background
:
#fcf0c2
;
background
:
#fcf0c2
;
padding
:
2px
8px
;
padding
:
2px
8px
;
...
@@ -512,14 +569,14 @@ onBeforeUnmount(() => {
...
@@ -512,14 +569,14 @@ onBeforeUnmount(() => {
border-radius
:
6px
;
border-radius
:
6px
;
}
}
}
}
.title
{
.title
{
font-size
:
18px
;
font-size
:
18px
;
font-weight
:
bold
;
font-weight
:
bold
;
color
:
#409
EFF
;
color
:
#409
eff
;
}
}
}
}
.chart-container
{
.chart-container
{
width
:
100%
;
width
:
100%
;
height
:
calc
(
100%
-
350px
);
height
:
calc
(
100%
-
350px
);
...
@@ -527,7 +584,8 @@ onBeforeUnmount(() => {
...
@@ -527,7 +584,8 @@ onBeforeUnmount(() => {
border-radius
:
4px
;
border-radius
:
4px
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
position
:
relative
;
.chart-wrapper
{
.chart-wrapper
{
flex
:
1
;
flex
:
1
;
width
:
100%
;
width
:
100%
;
...
@@ -543,101 +601,110 @@ onBeforeUnmount(() => {
...
@@ -543,101 +601,110 @@ onBeforeUnmount(() => {
border-radius
:
4px
;
border-radius
:
4px
;
}
}
}
}
.no-data
{
.data-panel
{
position
:
absolute
;
position
:
absolute
;
top
:
110px
;
top
:
0
;
right
:
25px
;
left
:
0
;
width
:
320px
;
width
:
100%
;
height
:
100%
;
z-index
:
10
;
z-index
:
10
;
transition
:
transform
0
.3s
ease-in-out
;
}
}
&
.collapsed
{
transform
:
translateX
(
345px
);
.data-panel
{
}
position
:
absolute
;
top
:
0px
;
.panel-toggle
{
right
:
0px
;
position
:
absolute
;
width
:
320px
;
width
:
25px
;
z-index
:
100
;
height
:
30px
;
transition
:
transform
0
.3s
ease-in-out
;
background
:
#fff
;
top
:
1px
;
&
.collapsed
{
transform
:
translateX
(
345px
);
}
.panel-toggle
{
position
:
absolute
;
width
:
25px
;
height
:
30px
;
background
:
#fff
;
top
:
1px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
border-radius
:
4px
;
}
.collapsed-icon
{
left
:
-23px
;
}
.expanded-icon
{
right
:
-23px
;
}
.data-box
{
padding
:
10px
;
background-color
:
rgba
(
255
,
255
,
255
,
0
.9
);
border-radius
:
4px
;
border
:
1px
solid
#ebeef5
;
box-shadow
:
0
2px
12px
0
rgba
(
0
,
0
,
0
,
0
.1
);
margin-bottom
:
10px
;
.data-item
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
justify-content
:
center
;
margin-bottom
:
5px
;
cursor
:
pointer
;
font-size
:
14px
;
border-radius
:
4px
;
}
.collapsed-icon
{
div
{
left
:
-23px
;
flex
:
1
;
}
.expanded-icon
{
right
:
-23px
;
}
.data-box
{
padding
:
10px
;
background-color
:
rgba
(
255
,
255
,
255
,
0
.9
);
border-radius
:
4px
;
border
:
1px
solid
#ebeef5
;
box-shadow
:
0
2px
12px
0
rgba
(
0
,
0
,
0
,
0
.1
);
margin-bottom
:
10px
;
.data-item
{
display
:
flex
;
justify-content
:
space-between
;
margin-bottom
:
5px
;
font-size
:
14px
;
div
{
flex
:
1
;
}
}
}
}
}
}
.second-box
{
font-size
:
12px
;
.second-box
{
}
font-size
:
12px
;
}
}
}
}
.data-table
{
.data-table
{
background-color
:
#fff
;
background-color
:
#fff
;
border-radius
:
4px
;
border-radius
:
4px
;
padding
:
10px
0
;
padding
:
10px
0
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
table
{
table
{
width
:
100%
;
width
:
100%
;
border-collapse
:
collapse
;
border-collapse
:
collapse
;
th
,
td
{
th
,
border
:
1px
solid
#EBEEF5
;
td
{
border
:
1px
solid
#ebeef5
;
text-align
:
center
;
text-align
:
center
;
padding
:
8px
;
padding
:
8px
;
font-size
:
14px
;
font-size
:
14px
;
}
}
th
{
th
{
background-color
:
#
F5F7FA
;
background-color
:
#
f5f7fa
;
color
:
#606266
;
color
:
#606266
;
}
}
.error
{
.error
{
color
:
#
F56C6C
;
color
:
#
f56c6c
;
}
}
.highlight
{
.highlight
{
background-color
:
#
FCF8E
3
;
background-color
:
#
fcf8e
3
;
position
:
relative
;
position
:
relative
;
&
:
:
after
{
&
:
:
after
{
content
:
""
;
content
:
""
;
position
:
absolute
;
position
:
absolute
;
width
:
16px
;
width
:
16px
;
height
:
16px
;
height
:
16px
;
background-color
:
#
E6A23C
;
background-color
:
#
e6a23c
;
border-radius
:
50%
;
border-radius
:
50%
;
top
:
50%
;
top
:
50%
;
left
:
50%
;
left
:
50%
;
...
@@ -646,17 +713,18 @@ onBeforeUnmount(() => {
...
@@ -646,17 +713,18 @@ onBeforeUnmount(() => {
}
}
}
}
}
}
.time-controls
{
.time-controls
{
margin-bottom
:
10px
;
margin-bottom
:
10px
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.time-label
,
.time-unit
{
.time-label
,
.time-unit
{
margin
:
0
5px
;
margin
:
0
5px
;
}
}
.time-input
{
.time-input
{
width
:
60px
;
width
:
60px
;
}
}
...
@@ -664,4 +732,3 @@ onBeforeUnmount(() => {
...
@@ -664,4 +732,3 @@ onBeforeUnmount(() => {
}
}
}
}
</
style
>
</
style
>
\ No newline at end of file
src/views/dustMonitoring/index.vue
View file @
c3807a12
...
@@ -74,6 +74,7 @@
...
@@ -74,6 +74,7 @@
class=
"point warn"
class=
"point warn"
v-for=
"item in detailObj.compartHealthList[0]"
v-for=
"item in detailObj.compartHealthList[0]"
:key=
"item"
:key=
"item"
@
click=
"handleStatusDotClick()"
></div>
></div>
</div>
</div>
<div
class=
"part"
>
<div
class=
"part"
>
...
@@ -117,6 +118,7 @@
...
@@ -117,6 +118,7 @@
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
,
onUnmounted
,
watch
,
computed
}
from
"vue"
;
import
{
ref
,
reactive
,
onMounted
,
onUnmounted
,
watch
,
computed
}
from
"vue"
;
import
{
useRouter
}
from
"vue-router"
;
import
*
as
echarts
from
"echarts"
;
import
*
as
echarts
from
"echarts"
;
import
{
getDataFun
}
from
"@/request/method.js"
;
import
{
getDataFun
}
from
"@/request/method.js"
;
import
{
useUsersStore
}
from
"@/pinia/user.js"
;
import
{
useUsersStore
}
from
"@/pinia/user.js"
;
...
@@ -148,6 +150,7 @@ const option = {
...
@@ -148,6 +150,7 @@ const option = {
},
},
],
],
};
};
const
router
=
useRouter
();
const
chartInstance
=
reactive
({});
const
chartInstance
=
reactive
({});
const
chartData
=
reactive
([{},
{},
{}]);
const
chartData
=
reactive
([{},
{},
{}]);
const
initChart
=
(
instance
,
option
,
domEl
)
=>
{
const
initChart
=
(
instance
,
option
,
domEl
)
=>
{
...
@@ -546,6 +549,14 @@ const dusterName = computed(() => {
...
@@ -546,6 +549,14 @@ const dusterName = computed(() => {
return
dusterList
.
value
.
find
((
item
)
=>
item
.
dusterNo
==
form
.
dusterNo
)
return
dusterList
.
value
.
find
((
item
)
=>
item
.
dusterNo
==
form
.
dusterNo
)
?.
dusterName
;
?.
dusterName
;
});
});
const
handleStatusDotClick
=
()
=>
{
router
.
push
({
path
:
"/bag-monitor"
,
query
:
{
dusterNo
:
form
.
dusterNo
,
}
});
};
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
$borderColor
:
#bbbdc3
91
;
$borderColor
:
#bbbdc3
91
;
...
...
src/views/dustOverview/index.vue
View file @
c3807a12
...
@@ -362,7 +362,6 @@ const handleValveNumClick = (row) => {
...
@@ -362,7 +362,6 @@ const handleValveNumClick = (row) => {
};
};
const
handleStatusDotClick
=
(
row
,
colIndex
)
=>
{
const
handleStatusDotClick
=
(
row
,
colIndex
)
=>
{
console
.
log
(
"row"
,
row
);
router
.
push
({
router
.
push
({
path
:
"/bag-monitor"
,
path
:
"/bag-monitor"
,
query
:
{
query
:
{
...
...
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