Browse Source

页面优化

master
xuhuajiao 5 months ago
parent
commit
54c3f18e87
  1. 11
      src/api/deviceVI/index.js
  2. BIN
      src/assets/images/serve1-1.png
  3. BIN
      src/assets/images/serve1-2.png
  4. BIN
      src/assets/images/serve1-3.png
  5. BIN
      src/assets/images/serve1.png
  6. BIN
      src/assets/images/ter1-1.png
  7. BIN
      src/assets/images/ter1.png
  8. BIN
      src/assets/images/ter2-1.png
  9. BIN
      src/assets/images/ter2.png
  10. BIN
      src/assets/images/ter3-1.png
  11. BIN
      src/assets/images/ter3.png
  12. BIN
      src/assets/images/ter4-1.png
  13. BIN
      src/assets/images/ter4.png
  14. BIN
      src/assets/images/ter5-1.png
  15. BIN
      src/assets/images/ter5.png
  16. 220
      src/views/components/echarts/serverGpu.vue
  17. 237
      src/views/components/echarts/serverGpuOther.vue
  18. 219
      src/views/components/echarts/serverGpuUse.vue
  19. 8
      src/views/components/echarts/serverProgress.vue
  20. 275
      src/views/components/echarts/serverProgress2.vue
  21. 15
      src/views/components/hkVideo.vue
  22. 302
      src/views/components/serveTerminal.vue
  23. 108
      src/views/home.vue
  24. 5
      src/views/visualCheck/venueDevice/bookshelfPosition/index.vue
  25. 15
      src/views/visualCheck/venueDevice/device/index.vue

11
src/api/deviceVI/index.js

@ -78,4 +78,13 @@ export function FetchUnboundGrid(params) {
})
}
export default { add, edit, del, FetchRegionTree, FetchinitDeviceInfoList, FetchDeviceById, FetchDeviceShelfGridBinding, FetchBoundGridByDevice, FetchUnboundGrid }
// 根据摄像头信息获取摄像头状态2export function FetchBoundGridByDevice(params) {
export function FetchPingIP(params) {
return request({
url: 'api/queryDeviceAPI/pingIP',
method: 'get',
params
})
}
export default { add, edit, del, FetchRegionTree, FetchinitDeviceInfoList, FetchDeviceById, FetchDeviceShelfGridBinding, FetchBoundGridByDevice, FetchUnboundGrid, FetchPingIP }

BIN
src/assets/images/serve1-1.png

After

Width: 200  |  Height: 200  |  Size: 3.5 KiB

BIN
src/assets/images/serve1-2.png

After

Width: 200  |  Height: 200  |  Size: 3.1 KiB

BIN
src/assets/images/serve1-3.png

After

Width: 200  |  Height: 200  |  Size: 4.8 KiB

BIN
src/assets/images/serve1.png

After

Width: 200  |  Height: 200  |  Size: 3.5 KiB

BIN
src/assets/images/ter1-1.png

After

Width: 200  |  Height: 200  |  Size: 3.3 KiB

BIN
src/assets/images/ter1.png

After

Width: 200  |  Height: 200  |  Size: 3.3 KiB

BIN
src/assets/images/ter2-1.png

After

Width: 222  |  Height: 200  |  Size: 3.8 KiB

BIN
src/assets/images/ter2.png

After

Width: 222  |  Height: 200  |  Size: 3.8 KiB

BIN
src/assets/images/ter3-1.png

After

Width: 200  |  Height: 200  |  Size: 5.0 KiB

BIN
src/assets/images/ter3.png

After

Width: 200  |  Height: 200  |  Size: 4.9 KiB

BIN
src/assets/images/ter4-1.png

After

Width: 203  |  Height: 200  |  Size: 3.2 KiB

BIN
src/assets/images/ter4.png

After

Width: 203  |  Height: 200  |  Size: 3.2 KiB

BIN
src/assets/images/ter5-1.png

After

Width: 200  |  Height: 200  |  Size: 2.8 KiB

BIN
src/assets/images/ter5.png

After

Width: 200  |  Height: 200  |  Size: 2.8 KiB

220
src/views/components/echarts/serverGpu.vue

@ -0,0 +1,220 @@
<template>
<div id="main" :style="{height:height,width:width}" style="margin-top: -20px;" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
temperature: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'temperature': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('main')
const myChart = echarts.init(chartDom)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 60,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(this.temperature)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 14,
color: axisLineHandler(this.temperature)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '50%'],
fontSize: 14,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 26,
fontWeight: 'bolder',
formatter: '{value} °C',
color: 'auto'
},
data: [
{
value: this.temperature,
// name: dataNameHandler(dataValue)
name: '温度'
}
]
},
//
{
type: 'gauge',
radius: 66, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 2,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 7,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

237
src/views/components/echarts/serverGpuOther.vue

@ -0,0 +1,237 @@
<template>
<div id="mainOther" :style="{height:height,width:width}" style="margin-top: -20px;" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
memoryTotal: {
type: Number,
require: true,
default: function() {
return 0
}
},
memoryFree: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'memoryTotal': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
},
'memoryFree': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
// window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('mainOther')
const myChart = echarts.init(chartDom)
const dataValue = this.memoryTotal === 0 ? 0 : ((this.memoryTotal - this.memoryFree) / this.memoryTotal * 100).toFixed(0)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 60,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(dataValue)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 14,
color: axisLineHandler(dataValue)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '50%'],
fontSize: 14,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 26,
fontWeight: 'bolder',
formatter: '{value} %',
color: 'auto'
},
data: [
{
value: dataValue,
name: ((this.memoryTotal - this.memoryFree) / 1024).toFixed(2) + 'G' + ' / ' + (this.memoryTotal / 1024).toFixed(0) + 'G'
}
]
},
//
{
type: 'gauge',
radius: 66, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 1,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 8,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

219
src/views/components/echarts/serverGpuUse.vue

@ -0,0 +1,219 @@
<template>
<div id="mainUse" :style="{height:height,width:width}" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
utilization: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'utilization': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
// window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('mainUse')
const myChart = echarts.init(chartDom)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 120,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(this.utilization)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 26,
color: axisLineHandler(this.utilization)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '40%'],
fontSize: 18,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 40,
fontWeight: 'bolder',
formatter: '{value} %',
color: 'auto'
},
data: [
{
value: this.utilization,
name: '占用率'
}
]
},
//
{
type: 'gauge',
radius: 130, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 1,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 8,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

8
src/views/components/echarts/serverProgress.vue

@ -1,5 +1,5 @@
<template>
<div class="chart-wrapper" style="display: flex; justify-content: space-between; align-items: center; overflow: hidden; margin-top: -20px;">
<div class="chart-wrapper" style="display: flex; justify-content: space-between; align-items: center; overflow: hidden;">
<div class="progress-class">
<el-progress class="differ" type="circle" stroke-linecap="butt" :percentage="systemData.cpuPercentage" :stroke-width="30" :width="200" :format="formatterSame" />
<svg width="100%" height="100%">
@ -22,7 +22,7 @@
<div class="progress-right" style="display: flex; flex-wrap: wrap; align-items: center; flex: 1; height: 100%;">
<div class="progress-right-item">
<div class="progress-right-txt right-txt1">
<p>内存占</p>
<p>内存占用率</p>
<span>{{ systemData.memPercentage }}<i>%</i></span>
</div>
<div class="progress-class2">
@ -48,7 +48,7 @@
</div>
<div class="progress-right-item">
<div class="progress-right-txt right-txt2">
<p>磁盘占</p>
<p>磁盘占用率</p>
<span>{{ systemData.sysFilesPercentage }}<i>%</i></span>
</div>
<div class="progress-class3">
@ -221,7 +221,7 @@ export default {
font-size: 30px !important;
color: #0C0E1E;
&::before {
content: 'CPU占';
content: 'CPU占用率';
width: 100%;
position: absolute;
top: -85%;

275
src/views/components/echarts/serverProgress2.vue

@ -1,275 +0,0 @@
<template>
<div id="main4" :style="{height:height}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons')
import resize from '@/views/dashboard/mixins/resize'
// const gaugeData = [
// {
// value: 20,
// name: 'Perfect',
// title: {
// offsetCenter: ['0%', '-30%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '-20%']
// }
// },
// {
// value: 40,
// name: 'Good',
// title: {
// offsetCenter: ['0%', '0%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '10%']
// }
// },
// {
// value: 60,
// name: 'Commonly',
// title: {
// offsetCenter: ['0%', '30%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '40%']
// }
// }
// ]
// var ROOT_PATH = 'https://echarts.apache.org/examples/data/asset/img/custom-gauge-panel.png'
// var _panelImageURL = ROOT_PATH + '/data/asset/img/custom-gauge-panel.png'
// var _animationDuration = 1000
// var _animationDurationUpdate = 1000
// var _animationEasingUpdate = 'quarticInOut'
// var _valOnRadianMax = 80
// var _outerRadius = 80
// var _innerRadius = 50
// var _pointerInnerRadius = 50
// var _insidePanelRadius = 30
// var _currentDataIndex = 0
export default {
name: 'AcrossEcharts',
mixins: [resize],
props: {
addArcivesData: {
type: Object,
require: true,
default: function() {
return {}
}
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null,
panelImageURL: 'https://echarts.apache.org/examples/data/asset/img/custom-gauge-panel.png',
animationDuration: 1000,
animationDurationUpdate: 1000,
animationEasingUpdate: 'quarticInOut',
valOnRadianMax: 200,
outerRadius: 200,
innerRadius: 170,
pointerInnerRadius: 40,
insidePanelRadius: 140
}
},
watch: {
// 'addArcivesData': {
// handler(val) {
// setTimeout(() => {
// this.drawChart()
// }, 100)
// },
// immediate: true,
// deep: true
// }
},
mounted() {
this.drawChart()
window.addEventListener('resize', this.__resizeHandler)
},
methods: {
renderItem(params, api) {
var valOnRadian = api.value(1)
var coords = api.coord([api.value(0), valOnRadian])
var polarEndRadian = coords[3]
var imageStyle = {
image: this.panelImageURL,
x: params.coordSys.cx - this.outerRadius,
y: params.coordSys.cy - this.outerRadius,
width: this.outerRadius * 2,
height: this.outerRadius * 2
}
return {
type: 'group',
children: [
{
type: 'image',
style: imageStyle,
clipPath: {
type: 'sector',
shape: {
cx: params.coordSys.cx,
cy: params.coordSys.cy,
r: this.uterRadius,
r0: this.innerRadius,
startAngle: 0,
endAngle: -polarEndRadian,
transition: 'endAngle',
enterFrom: { endAngle: 0 }
}
}
},
{
type: 'image',
style: imageStyle,
clipPath: {
type: 'polygon',
shape: {
points: this.makePionterPoints(params, polarEndRadian)
},
extra: {
polarEndRadian: polarEndRadian,
transition: 'polarEndRadian',
enterFrom: { polarEndRadian: 0 }
},
during: function(apiDuring) {
apiDuring.setShape(
'points',
this.makePionterPoints(params, apiDuring.getExtra('polarEndRadian'))
)
}
}
},
{
type: 'circle',
shape: {
cx: params.coordSys.cx,
cy: params.coordSys.cy,
r: this.insidePanelRadius
},
style: {
fill: '#fff',
shadowBlur: 25,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(76,107,167,0.4)'
}
},
{
type: 'text',
extra: {
valOnRadian: valOnRadian,
transition: 'valOnRadian',
enterFrom: { valOnRadian: 0 }
},
style: {
text: this.makeText(valOnRadian),
fontSize: 30,
fontWeight: 700,
x: params.coordSys.cx,
y: params.coordSys.cy,
fill: 'rgb(0,50,190)',
align: 'center',
verticalAlign: 'middle',
enterFrom: { opacity: 0 }
},
during: function(apiDuring) {
apiDuring.setStyle(
'text',
this.makeText(apiDuring.getExtra('valOnRadian'))
)
}
}
]
}
},
makeText(valOnRadian) {
// Validate additive animation calc.
if (valOnRadian < -10) {
alert('illegal during val: ' + valOnRadian)
}
return ((valOnRadian / this.valOnRadianMax) * 100).toFixed(0) + '%'
},
convertToPolarPoint(renderItemParams, radius, radian) {
return [
Math.cos(radian) * radius + renderItemParams.coordSys.cx,
-Math.sin(radian) * radius + renderItemParams.coordSys.cy
]
},
makePionterPoints(renderItemParams, polarEndRadian) {
return [
this.convertToPolarPoint(renderItemParams, this.outerRadius, polarEndRadian),
this.convertToPolarPoint(
renderItemParams,
this.outerRadius,
polarEndRadian + Math.PI * 0.03
),
this.convertToPolarPoint(renderItemParams, this.pointerInnerRadius, polarEndRadian)
]
},
drawChart() {
const chartDom = document.getElementById('main4')
this.chart = echarts.init(chartDom)
let option = null
option = {
animationEasing: this.animationEasingUpdate,
animationDuration: this.animationDuration,
animationDurationUpdate: this.animationDurationUpdate,
animationEasingUpdate: this.animationEasingUpdate,
dataset: {
source: [[1, 156]]
},
tooltip: {},
angleAxis: {
type: 'value',
startAngle: 0,
show: false,
min: 0,
max: this.valOnRadianMax
},
radiusAxis: {
type: 'value',
show: false
},
polar: {},
series: [
{
type: 'custom',
coordinateSystem: 'polar',
renderItem: this.renderItem
}
]
}
var _this = this
setInterval(function() {
var nextSource = [[1, Math.round(Math.random() * this.valOnRadianMax)]]
_this.chart.setOption({
dataset: {
source: nextSource
}
})
}, 3000)
option && this.chart.setOption(option)
}
}
}
</script>
<style lang="scss" scoped>
</style>

15
src/views/components/hkVideo.vue

@ -35,12 +35,7 @@ export default {
// this.controlVolume()
},
mounted() {
// videovideoID
// 127.0.0.1:8000webrtc-streamerIP8000
// eslint-disable-next-line no-undef
this.webRtcServer = new WebRtcStreamer('video', location.protocol + '//' + this.camera_ip)
// rtsp,rtspH264
this.webRtcServer.connect('rtsp://' + this.hkConfig.username + ':' + this.hkConfig.password + '@' + this.hkConfig.ip + ':' + this.hkConfig.port + '/h264/ch1/main/av_stream')
},
//
beforeDestroy() {
@ -53,6 +48,14 @@ export default {
this.$refs.video1.volume = 0
this.$refs.video2.volume = 0
})
},
initVideo() {
// videovideoID
// 127.0.0.1:8000webrtc-streamerIP8000
// eslint-disable-next-line no-undef
this.webRtcServer = new WebRtcStreamer('video', location.protocol + '//' + this.camera_ip)
// rtsp,rtspH264
this.webRtcServer.connect('rtsp://' + this.hkConfig.username + ':' + this.hkConfig.password + '@' + this.hkConfig.ip + ':' + this.hkConfig.port + '/h264/ch1/main/av_stream')
}
}
}

302
src/views/components/serveTerminal.vue

@ -0,0 +1,302 @@
<template>
<div class="service-all">
<div v-if="serviceTop" class="service-top-text" :class="!serviceTop ? 'false-active' : 'true-active'">AI处理终端</div>
<!-- <i class="iconfont icon-zhongduanjiankong" />终端连接正常 -->
<ul v-if="serviceTop" class="service-list">
<li v-for="(item, index) in serviceItems" :key="index">
<p :class="index <= currentIndex && item.status === 'running'? 'true-active' : 'false-active' ">
{{ item.serviceName }}
</p>
<!-- {{ item.serviceName }} -->
<!-- <i v-if="index <= currentIndex && item.status === 'running'" class="iconfont icon-shi" />
<i v-else-if="index <= currentIndex" class="iconfont icon-cuowu1" /> -->
</li>
</ul>
<div v-if="servicesDisplayed && isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed && isAllServicesRunning }" style="color: rgb(18, 196, 122);">所有服务均正常运行请放心使用</div>
<div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div>
<div v-if="!serviceTop" class="tip-service" :class="{ 'fade-in': !serviceTop }">
<i class="iconfont icon-lianjieduankai" />
<div class="tip-service-content">
<p>AI处理终端连接超时请检查配置是否正确或终端是否运行成功!</p>
<p>请尽快联系系统维护人员进行恢复</p>
</div>
</div>
</div></template>
<script>
import crudStockTask, { FetchAITerminalStatusQuery } from '@/api/stockTask/index'
import { mapGetters } from 'vuex'
export default {
name: 'ServeTerminal',
components: { },
props: {
},
data() {
return {
service: {
'service_imgCamera': { 'last_heartbeat': 1736496962.2368362, 'status': '' },
'service_imgProcess': { 'last_heartbeat': 1736496960.8598323, 'status': '' },
'service_imgYolo': { 'last_heartbeat': 1736496961.953832, 'status': '' },
'service_imgOcr': { 'last_heartbeat': 1736496961.6238313, 'status': '' },
'service_imgResult': { 'last_heartbeat': 1736496963.4378026, 'status': '' }
},
serviceItems: [],
currentIndex: -1,
timer: null,
servicesDisplayed: false,
serviceTop: false
}
},
computed: {
...mapGetters([
'baseApi'
]),
isAllServicesRunning() {
return Object.values(this.service).every(service => service.status === 'running')
}
},
mounted() {
},
methods: {
initData() {
crudStockTask.FetchInitSetting().then(res => {
if (res) {
this.handleService(res.ip)
}
}).catch(() => {
})
},
handleService(ip) {
this.servicesDisplayed = false
FetchAITerminalStatusQuery({ 'ip': ip }).then(res => {
// {
// "service_imgCamera":{"last_heartbeat":1736496962.2368362,"status":"running"},
// "service_imgProcess":{"last_heartbeat":1736496960.8598323,"status":"running"},
// "service_imgYolo":{"last_heartbeat":1736496961.953832,"status":"running"}
// "service_imgOcr":{"last_heartbeat":1736496961.6238313,"status":"running"},
// "service_imgResult":{"last_heartbeat":1736496963.4378026,"status":"running"},
// }
if (res) {
this.serviceTop = true
this.service = JSON.parse(res)
this.serviceItems = []
const keysOrder = ['service_imgCamera', 'service_imgProcess', 'service_imgYolo', 'service_imgOcr', 'service_imgResult']
keysOrder.forEach(key => {
let serviceName = ''
switch (key) {
case 'service_imgCamera':
serviceName = '图像采集'
break
case 'service_imgProcess':
serviceName = '图像处理'
break
case 'service_imgYolo':
serviceName = '图像识别'
break
case 'service_imgOcr':
serviceName = '文字识别'
break
case 'service_imgResult':
serviceName = '同步服务'
break
}
this.serviceItems.push({
serviceName: serviceName,
status: this.service[key].status
})
})
this.showServicesSequentially()
} else {
this.serviceTop = false
}
}).catch(() => {
})
},
showServicesSequentially() {
let index = 0
const interval = 300
this.timer = setInterval(() => {
this.currentIndex = index
index++
if (index >= this.serviceItems.length) {
clearInterval(this.timer)
setTimeout(() => {
this.servicesDisplayed = true
}, 500)
}
}, interval)
}
}
}
</script>
<style lang="scss" scoped>
.tip-service{
display: flex;
justify-content: center;
color: #0C0E1E;
font-size: 16px;
line-height: 40px;
padding: 40px 0;
.iconfont{
font-size: 30px;
margin-right: 10px;
color: #ED4A41;
}
p{
&:first-child{
color: #ED4A41;
}
}
}
.service-all{
position: relative;
height: 230px;
color: #0C0E1E;
}
.service-top-text{
position: relative;
font-size: 12px;
margin: 0 65px;
height: 72px;
text-align: center;
background: url('~@/assets/images/serve1.png') no-repeat center center;
background-size: 40px auto;
&.false-active{
background: url('~@/assets/images/serve1-1.png') no-repeat center center;
background-size: 40px auto;
}
&.true-active{
&::before{
content: "";
position: absolute;
left: 50%;
bottom: -10px;
width: 1px;
height: 16px;
background-color:#9098a4;
margin-left: -1px;
}
&::after{
content: "";
position: absolute;
left: 0;
bottom: -10px;
width: 100%;
height: 1px;
background-color: #9098a4;
margin-left: -1px;
}
}
}
.service-list{
display: flex;
justify-content: space-between;
padding: 30px 40px 10px 40px;
li{
position: relative;
&::before{
content: "";
position: absolute;
left: 50%;
top: -20px;
width: 1px;
height: 10px;
background-color: #9098a4;
margin-left: -1px;
}
p{
width: 50px;
height: 70px;
font-size: 12px;
}
&:nth-child(1){
p{
&.false-active{
background: url('~@/assets/images/ter1-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter1.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(2){
p{
&.false-active{
background: url('~@/assets/images/ter2-1.png') no-repeat center center;
background-size: 32px auto;
}
&.true-active{
background: url('~@/assets/images/ter2.png') no-repeat center center;
background-size: 32px auto;
}
}
}
&:nth-child(3){
p{
&.false-active{
background: url('~@/assets/images/ter3-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter3.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(4){
p{
&.false-active{
background: url('~@/assets/images/ter4-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter4.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(5){
p{
&.false-active{
background: url('~@/assets/images/ter5-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter5.png') no-repeat center center;
background-size: 36px auto;
}
}
}
}
}
.service-bottom-text{
font-size: 12px;
text-align: center;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.5s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
.fade-in {
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

108
src/views/home.vue

@ -60,8 +60,33 @@
<div style="position: absolute; right: 20px; top: 20px; color: #999; cursor: pointer;" class="el-icon-refresh" @click="refreshSystemData" />
</h3>
<!-- <div class="chart-wrapper"> -->
<serverProgress :system-data="systemData" />
<!-- <serverProgress :system-data="systemData" /> -->
<!-- </div> -->
<swiper
ref="swiperServer"
class="swiper-server"
:options="swiperOptionServer"
:auto-update="true"
:auto-destroy="true"
:delete-instance-on-destroy="true"
:cleanup-styles-on-destroy="true"
>
<swiper-slide class="swiper-slide-server">
<serverProgress :system-data="systemData" />
</swiper-slide>
<swiper-slide class="swiper-slide-server cpu-echarts">
<serverGpuUse :utilization="utilization" />
<div class="cpu-right">
<serverGpu :temperature="temperature" />
<serverGpuOther :memory-total="memoryTotal" :memory-free="memoryFree" />
</div>
<div style="position: absolute; bottom: 136px; right: 70px; font-weight: bold;">{{ GPUName }}</div>
</swiper-slide>
<swiper-slide class="swiper-slide-server">
<serveTerminal ref="serveTerminalRefs" />
</swiper-slide>
<div slot="pagination" class="swiper-pagination" />
</swiper>
</div>
</el-col>
</el-row>
@ -128,10 +153,16 @@ import taskStockLogEcharts from '@/views/components/echarts/taskStockLog.vue'
import bookSwiper from '@/views/components/bookSwiper.vue'
import checkSwiper from '@/views/components/checkSwiper.vue'
import serverProgress from '@/views/components/echarts/serverProgress.vue'
import serverGpu from '@/views/components/echarts/serverGpu.vue'
import serverGpuUse from '@/views/components/echarts/serverGpuUse.vue'
import serverGpuOther from '@/views/components/echarts/serverGpuOther.vue'
import serveTerminal from '@/views/components/serveTerminal.vue'
import { FetchInitHomeInfo, FetchInitStockInfo } from '@/api/stockTask/index'
import { FetchInitStockLogList } from '@/api/stockTaskLog/index'
import { FetchSystemInfo } from '@/api/home/cpu/index'
import { mapGetters } from 'vuex'
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
export default {
name: 'Dashboard',
@ -143,7 +174,13 @@ export default {
bookSwiper,
checkSwiper,
// typePie,
serverProgress
serverProgress,
serverGpu,
serverGpuUse,
serverGpuOther,
serveTerminal,
swiper,
swiperSlide
},
data() {
return {
@ -179,13 +216,33 @@ export default {
addArcivesMonth: [],
addArcivesNum: [],
addArcivesNumFile: []
}
},
swiperActiveIndex: 0,
swiperOptionServer: {
autoplay: {
delay: 8000,
disableOnInteraction: false
},
slidesPerView: 'auto',
pagination: {
el: '.swiper-pagination',
clickable: true
}
},
memoryFree: 0,
memoryTotal: 0,
GPUName: '',
temperature: 0,
utilization: 0
}
},
computed: {
...mapGetters([
'user'
])
]),
swiperServer() {
return this.$refs.swiperServer.$el.swiper
}
},
created() {
this.handleMainData()
@ -200,6 +257,8 @@ export default {
} else {
this.$refs.bookSwiperRefs.getInitHotShelfList()
}
this.$refs.serveTerminalRefs.initData()
})
},
mounted() {
@ -240,6 +299,12 @@ export default {
// 使memUsed/memTotal
this.systemData.memPercentage = Math.round(res.memUsed / res.memTotal * 100)
this.memoryFree = res.memoryFree
this.memoryTotal = res.memoryTotal
this.GPUName = res.GPUName
this.temperature = res.temperature
this.utilization = res.utilization
// 使sysFiles[i].used/sysFiles[i].total
let sysFilesTotalUsed = 0
let sysFilesTotal = 0
@ -256,7 +321,14 @@ export default {
memPercentage: 0,
sysFilesPercentage: 0
}
this.memoryFree = 0
this.memoryTotal = 0
this.GPUName = ''
this.temperature = 0
this.utilization = 0
this.getSystemInfo()
this.$refs.serveTerminalRefs.initData()
},
getStockLog() {
FetchInitStockLogList().then(res => {
@ -294,7 +366,7 @@ export default {
position: relative;
.chart-wrapper {
height: calc(100% - 55px);
height: calc(100% - 120px);
}
}
@media (max-width: 1024px) {
@ -374,4 +446,30 @@ export default {
font-size: 12px;
line-height: 30px;
}
.swiper-server{
position: relative;
height: 300px;
::v-deep .swiper-wrapper{
height: 344px;
}
.swiper-pagination{
bottom: 80px;
}
}
.cpu-echarts{
position: relative;
display: flex;
justify-content: flex-start;
align-items: center;
// background-color: #000;
.cpu-right{
flex: 1;
height: 100%;
display: flex;
justify-content: flex-start;
// flex-direction: column;
// flex-wrap: wrap;
}
}
</style>

5
src/views/visualCheck/venueDevice/bookshelfPosition/index.vue

@ -155,7 +155,7 @@
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<hkVideo :hk-config="hkConfig" />
<hkVideo ref="hkVideoRef" :hk-config="hkConfig" />
</div>
</el-dialog>
@ -474,6 +474,9 @@ export default {
'port': res.rtsp
}
this.hkVideoVisible = true
this.$nextTick(() => {
this.$refs.hkVideoRef.initVideo()
})
}
})
},

15
src/views/visualCheck/venueDevice/device/index.vue

@ -97,7 +97,8 @@
</el-table-column>
<el-table-column label="状态" prop="deviceState" align="center">
<template slot-scope="scope">
<span :class="{ 'spk-a': scope.row.deviceState === 1, 'off-line': scope.row.deviceState !== 1 }" />
<span v-if="scope.row.deviceState === null" class="el-icon-loading" />
<span v-else :class="{ 'spk-a': scope.row.deviceState === 1, 'off-line': scope.row.deviceState !== 1 }" />
</template>
</el-table-column>
<el-table-column prop="shelfCount" label="已绑架位" />
@ -426,6 +427,17 @@ export default {
this.crud.query.deviceType = this.optionVal
},
[CRUD.HOOK.afterRefresh](crud) {
crud.data.forEach(element => {
element.deviceState = null
this.getDeviceState(element)
})
},
getDeviceState(element) {
crudDevice.FetchPingIP({ ip: element.ipv4 }).then((data) => {
element.deviceState = data === true ? 1 : 0
}).catch((error) => {
console.error(error)
})
},
handleNodeClick(data) {
this.$nextTick(() => {
@ -450,6 +462,7 @@ export default {
}
this.crud.toQuery()
const params = {
'floorId': this.crud.query.floorId,
'regionId': this.crud.query.regionId

Loading…
Cancel
Save