-
5public/static/config.js
-
34src/api/ai/ai.js
-
BINsrc/assets/images/serve1-1.png
-
BINsrc/assets/images/serve1-2.png
-
BINsrc/assets/images/serve1-3.png
-
BINsrc/assets/images/serve1.png
-
BINsrc/assets/images/ter1-1.png
-
BINsrc/assets/images/ter1.png
-
BINsrc/assets/images/ter2-1.png
-
BINsrc/assets/images/ter2.png
-
BINsrc/assets/images/ter3-1.png
-
BINsrc/assets/images/ter3.png
-
BINsrc/assets/images/ter4-1.png
-
BINsrc/assets/images/ter4.png
-
BINsrc/assets/images/ter5-1.png
-
BINsrc/assets/images/ter5.png
-
31src/assets/styles/archives-manage.scss
-
1src/assets/styles/index.scss
-
4src/assets/styles/sidebar.scss
-
11src/layout/components/Navbar.vue
-
2src/views/archivesManage/managementLibrary/anjuan/index.vue
-
14src/views/archivesManage/managementLibrary/anjuan/tableList.vue
-
3src/views/archivesManage/managementLibrary/file/index.vue
-
43src/views/archivesManage/managementLibrary/index.vue
-
25src/views/archivesManage/managementLibrary/juannei/index.vue
-
6src/views/archivesManage/managementLibrary/mixins/index.js
-
42src/views/archivesManage/managementLibrary/module/collectHeader.vue
-
4src/views/archivesStatistics/customDefinedStatistics/index.vue
-
6src/views/collectReorganizi/batchConnection/index.vue
-
6src/views/collectReorganizi/collectionLibrary/anjuan/index.vue
-
59src/views/collectReorganizi/collectionLibrary/file/index.vue
-
4src/views/collectReorganizi/collectionLibrary/index.vue
-
12src/views/collectReorganizi/collectionLibrary/juannei/index.vue
-
2src/views/components/category/PreviewForm.vue
-
52src/views/components/categoryTree.vue
-
220src/views/components/echarts/serverGpu.vue
-
237src/views/components/echarts/serverGpuOther.vue
-
219src/views/components/echarts/serverGpuUse.vue
-
8src/views/components/echarts/serverProgress.vue
-
275src/views/components/echarts/serverProgress2.vue
-
314src/views/components/serveTerminal.vue
-
107src/views/home.vue
-
12src/views/login.vue
-
492src/views/system/paramSetting/index.vue
@ -1,7 +1,8 @@ |
|||||
window.g = { |
window.g = { |
||||
AXIOS_TIMEOUT: 10000, |
AXIOS_TIMEOUT: 10000, |
||||
// ApiUrl: 'http://27.16.212.58:11100', // 配置服务器地址,
|
|
||||
ApiUrl: 'http://192.168.99.71:11110', |
|
||||
|
ApiUrl: 'http://27.19.50.212:11100', |
||||
|
// ApiUrl: 'http://27.16.212.58:11100',
|
||||
|
// ApiUrl: 'http://192.168.99.71:11110',
|
||||
// ApiUrl: 'http://192.168.99.107:11100',
|
// ApiUrl: 'http://192.168.99.107:11100',
|
||||
AIDeepSeekUrl:'http://192.168.99.86:12123', |
AIDeepSeekUrl:'http://192.168.99.86:12123', |
||||
ProcessModelUrl:'http://192.168.99.72:11200', |
ProcessModelUrl:'http://192.168.99.72:11200', |
||||
|
After Width: 200 | Height: 200 | Size: 3.5 KiB |
|
After Width: 200 | Height: 200 | Size: 3.1 KiB |
|
After Width: 200 | Height: 200 | Size: 4.8 KiB |
|
After Width: 200 | Height: 200 | Size: 3.5 KiB |
|
After Width: 200 | Height: 200 | Size: 4.7 KiB |
|
After Width: 200 | Height: 200 | Size: 4.7 KiB |
|
After Width: 222 | Height: 200 | Size: 3.8 KiB |
|
After Width: 222 | Height: 200 | Size: 3.8 KiB |
|
After Width: 200 | Height: 200 | Size: 1.8 KiB |
|
After Width: 200 | Height: 200 | Size: 1.8 KiB |
|
After Width: 200 | Height: 200 | Size: 4.0 KiB |
|
After Width: 200 | Height: 200 | Size: 4.0 KiB |
|
After Width: 200 | Height: 200 | Size: 2.8 KiB |
|
After Width: 200 | Height: 200 | Size: 2.8 KiB |
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
|
||||
@ -0,0 +1,314 @@ |
|||||
|
<template> |
||||
|
<div class="service-all"> |
||||
|
<div v-if="serviceTop" class="service-top-text" :class="!serviceTop ? 'false-active' : 'true-active'">AI处理终端 |
||||
|
<div class="service-left" /> |
||||
|
<div class="service-right" /> |
||||
|
</div> |
||||
|
<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> |
||||
|
</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 crudAiTask, { FetchAITerminalStatusQuery } from '@/api/ai/ai' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
export default { |
||||
|
name: 'ServeTerminal', |
||||
|
components: { }, |
||||
|
props: { |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
service: { |
||||
|
'service_FileParsing_v1': { 'last_heartbeat': 1736496962.2368362, 'status': '' }, |
||||
|
'service_fileParsing': { 'last_heartbeat': 1736496961.953832, 'status': '' }, |
||||
|
'service_imgOCR': { 'last_heartbeat': 1736496961.6238313, 'status': '' }, |
||||
|
'service_aiResult': { 'last_heartbeat': 1736496960.8598323, '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() { |
||||
|
crudAiTask.FetchInitSetting().then(res => { |
||||
|
if (res) { |
||||
|
this.handleService(res.ip) |
||||
|
} |
||||
|
}).catch(() => { |
||||
|
}) |
||||
|
}, |
||||
|
handleService(ip) { |
||||
|
this.servicesDisplayed = false |
||||
|
FetchAITerminalStatusQuery({ 'ip': ip }).then(res => { |
||||
|
// { |
||||
|
// "service_FileParsing_v1":{"last_heartbeat":1736496962.2368362,"status":"running"}, |
||||
|
// "service_fileParsing":{"last_heartbeat":1736496961.953832,"status":"running"} |
||||
|
// "service_imgOCR":{"last_heartbeat":1736496961.6238313,"status":"running"}, |
||||
|
// "service_aiResult":{"last_heartbeat":1736496960.8598323,"status":"running"}, |
||||
|
// } |
||||
|
if (res) { |
||||
|
this.serviceTop = true |
||||
|
this.service = JSON.parse(res) |
||||
|
this.serviceItems = [] |
||||
|
const keysOrder = ['service_FileParsing_v1', 'service_fileParsing', 'service_imgOCR', 'service_aiResult'] |
||||
|
keysOrder.forEach(key => { |
||||
|
let serviceName = '' |
||||
|
switch (key) { |
||||
|
case 'service_FileParsing_v1': |
||||
|
serviceName = '文件解析V1' |
||||
|
break |
||||
|
case 'service_fileParsing': |
||||
|
serviceName = '文件解析' |
||||
|
break |
||||
|
case 'service_imgOCR': |
||||
|
serviceName = '文字识别' |
||||
|
break |
||||
|
case 'service_aiResult': |
||||
|
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 77px; |
||||
|
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{ |
||||
|
&::after{ |
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
bottom: -10px; |
||||
|
width: 67%; |
||||
|
height: 1px; |
||||
|
background-color: #9098a4; |
||||
|
margin-left: -1px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.service-left{ |
||||
|
position: relative; |
||||
|
position: absolute; |
||||
|
left: -1px; |
||||
|
top: 40px; |
||||
|
width: 45%; |
||||
|
height: 82%; |
||||
|
border-top: 1px solid #9098a4; |
||||
|
border-left: 1px solid #9098a4; |
||||
|
} |
||||
|
.service-right{ |
||||
|
position: relative; |
||||
|
position: absolute; |
||||
|
right: 33%; |
||||
|
top: 40px; |
||||
|
width: 13%; |
||||
|
height: 74%; |
||||
|
border-top: 1px solid #9098a4; |
||||
|
border-right: 1px solid #9098a4; |
||||
|
} |
||||
|
.service-list{ |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
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: 74px; |
||||
|
height: 70px; |
||||
|
font-size: 12px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
&:nth-child(1){ |
||||
|
&::before{ |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
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/ter1-1.png') no-repeat center center; |
||||
|
background-size: 32px auto; |
||||
|
} |
||||
|
&.true-active{ |
||||
|
background: url('~@/assets/images/ter1.png') no-repeat center center; |
||||
|
background-size: 32px auto; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
&:nth-child(3){ |
||||
|
&::before{ |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
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> |
||||
@ -0,0 +1,492 @@ |
|||||
|
<template> |
||||
|
<div class="app-container row-container"> |
||||
|
<div class="container-wrap" style="height: calc(100vh - 200px);"> |
||||
|
<span class="right-top-line" /> |
||||
|
<span class="left-bottom-line" /> |
||||
|
<el-form ref="form" :rules="rules" :model="form" size="small" label-width="120px"> |
||||
|
<el-row style="display: flex; justify-content: flex-start;"> |
||||
|
<el-form-item label="AI处理终端IP" prop="ip"> |
||||
|
<el-input v-model="form.ip" placeholder="请输入IP地址,如:192.168.1.1" style="width: 300px;" /> |
||||
|
</el-form-item> |
||||
|
<div v-if="form.ip" style="margin-left: 20px; margin-top: 6px; cursor: pointer;" @click="handleService"><i class="iconfont icon-bendiguajie" /></div> |
||||
|
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后,方可执行视觉盘点任务</p> |
||||
|
<div style="margin-left: 20px;"> |
||||
|
<el-button :loading="resetLoading" @click="toVerify('reset')">重启服务</el-button> |
||||
|
<!-- <el-button>关闭</el-button> --> |
||||
|
</div> |
||||
|
</el-row> |
||||
|
<!-- <el-row style="display: flex; justify-content: flex-start;"> |
||||
|
<el-form-item label="层位占用上限" prop="maxNum"> |
||||
|
<el-input v-model="form.maxNum" type="number" placeholder="请输入" style="width: 300px;" /> |
||||
|
</el-form-item> |
||||
|
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后,方可在倒架建议中给出正确的数据(通常情况下,上限为 50 册)</p> |
||||
|
</el-row> --> |
||||
|
</el-form> |
||||
|
<div> |
||||
|
<el-button style="margin-left: 30px;" :loading="crud.status.cu === 2" type="primary" @click="toVerify('add')">保存</el-button> |
||||
|
<span style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置需要超级管理员权限授权!</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<el-dialog class="tip-dialog tip-middle-dialog" title="操作提示" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="verifyDialogVisible" :before-close="handleClose"> |
||||
|
<div class="setting-dialog"> |
||||
|
<div class="tip-content"> |
||||
|
<p class="tipMsg">这里为技术人员维护系统时使用,普通用户无需设置</p> |
||||
|
<p class="delt-tip"><span>注意:强行修改会导致系统数据异常或丢失!如因用户强行修改,本系统不负责因此导致的相关后果!</span></p> |
||||
|
</div> |
||||
|
<el-form ref="verfiyForm" :model="verfiyForm" style="margin-top:30px;" @submit.native.prevent> |
||||
|
<el-form-item label="维护验证码" label-width="110px"> |
||||
|
<el-input v-model="verfiyForm.verifyCode" show-password style="width: 480px;" /> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
<div slot="footer" class="dialog-footer"> |
||||
|
<el-button @click="handleClose">取消 </el-button> |
||||
|
<el-button type="primary" @click.native="handleConfirm">确定</el-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
|
||||
|
<el-dialog class="tip-dialog tip-middle-dialog" title="AI处理终端连接测试" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="serviceDialogVisible" :before-close="handleClose"> |
||||
|
<div class="setting-dialog tip-service"> |
||||
|
<i class="iconfont icon-lianjieduankai" /> |
||||
|
<div class="tip-service-content"> |
||||
|
<p>终端连接超时,请检查配置是否正确或终端是否运行成功!</p> |
||||
|
<p>请尽快联系系统维护人员进行恢复</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
|
||||
|
<el-dialog class="tip-dialog tip-middle-dialog" title="AI处理终端连接测试" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="serviceContentDialogVisible" :before-close="handleClose"> |
||||
|
<div class="setting-dialog service-all"> |
||||
|
<div class="service-top-text"><i class="iconfont icon-zhongduanjiankong" />终端连接正常</div> |
||||
|
<!-- <ul> |
||||
|
<li v-for="(item, index) in serviceItems" :key="index" :style="{animationDelay: index * 300 + 'ms'}"> |
||||
|
<p :class="item.status === 'running'? 'true-active' : 'false-active' ">{{ item.serviceName }}</p> |
||||
|
<i v-if="item.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
</ul> --> |
||||
|
<ul> |
||||
|
<li v-for="(item, index) in serviceItems" :key="index"> |
||||
|
<p :class="index <= currentIndex && item.status === 'running'? 'true-active' : 'false-active' ">{{ item.serviceName }}</p> |
||||
|
<i v-if="index <= currentIndex && item.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else-if="index <= currentIndex" class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<!-- <ul> |
||||
|
<li> |
||||
|
<p :class="service.service_imgCamera.status === 'running' ? 'true-active' : 'false-active' ">图像采集</p> |
||||
|
<i v-if="service.service_imgCamera.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<p :class="service.service_imgProcess.status === 'running' ? 'true-active' : 'false-active' ">图像处理</p> |
||||
|
<i v-if="service.service_imgProcess.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<p :class="service.service_imgYolo.status === 'running' ? 'true-active' : 'false-active' ">图像识别</p> |
||||
|
<i v-if="service.service_imgYolo.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<p :class="service.service_imgOcr.status === 'running' ? 'true-active' : 'false-active' ">文字识别</p> |
||||
|
<i v-if="service.service_imgOcr.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else class="iconfont icon-cuowu1" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<p :class="service.service_imgResult.status === 'running' ? 'true-active' : 'false-active' ">同步服务</p> |
||||
|
<i v-if="service.service_imgResult.status === 'running'" class="iconfont icon-shi" /> |
||||
|
<i v-else 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> |
||||
|
</el-dialog> |
||||
|
|
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import crudAiTask, { FetchAITerminalStatusQuery, FetchStartStopBookAIService } from '@/api/ai/ai' |
||||
|
import { encrypt } from '@/utils/rsaEncrypt' |
||||
|
import { verifyMaintenance } from '@/api/system/field' |
||||
|
import CRUD, { presenter, header, form, crud } from '@crud/crud' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
|
||||
|
const defaultForm = { ip: '', maxNum: null } |
||||
|
|
||||
|
export default { |
||||
|
name: 'ParamSetting', |
||||
|
components: { }, |
||||
|
cruds() { |
||||
|
return CRUD({ |
||||
|
title: '参数设置', |
||||
|
url: 'api/ai/initSetting', |
||||
|
crudMethod: { ...crudAiTask }, |
||||
|
sort: [], |
||||
|
query: { |
||||
|
size: null, |
||||
|
page: null |
||||
|
}, |
||||
|
optShow: { |
||||
|
add: true, |
||||
|
edit: false, |
||||
|
del: false, |
||||
|
download: false, |
||||
|
group: false, |
||||
|
reset: false |
||||
|
}, |
||||
|
queryOnPresenterCreated: false |
||||
|
}) |
||||
|
}, |
||||
|
mixins: [presenter(), header(), form(defaultForm), crud()], |
||||
|
data() { |
||||
|
return { |
||||
|
permission: { |
||||
|
add: ['admin', 'paramSetting:add'], |
||||
|
edit: ['admin', 'paramSetting:edit'], |
||||
|
del: ['admin', 'paramSetting:del'] |
||||
|
}, |
||||
|
verifyDialogVisible: false, |
||||
|
verfiyForm: { |
||||
|
verifyCode: '' |
||||
|
}, |
||||
|
verifyStatus: '', |
||||
|
showVerifyDialog: true, |
||||
|
resetLoading: false, |
||||
|
rules: { |
||||
|
ip: [ |
||||
|
{ required: true, message: 'AI处理终端IP不可为空', trigger: 'blur' } |
||||
|
], |
||||
|
maxNum: [ |
||||
|
{ required: true, message: '层位占用上限不可为空', trigger: 'blur' } |
||||
|
] |
||||
|
}, |
||||
|
serviceDialogVisible: false, |
||||
|
serviceContentDialogVisible: false, |
||||
|
service: { |
||||
|
'service_FileParsing_v1': { 'last_heartbeat': 1736496962.2368362, 'status': '' }, |
||||
|
'service_fileParsing': { 'last_heartbeat': 1736496961.953832, 'status': '' }, |
||||
|
'service_imgOCR': { 'last_heartbeat': 1736496961.6238313, 'status': '' }, |
||||
|
'service_aiResult': { 'last_heartbeat': 1736496960.8598323, 'status': '' } |
||||
|
}, |
||||
|
serviceItems: [], |
||||
|
currentIndex: -1, |
||||
|
timer: null, |
||||
|
servicesDisplayed: false, |
||||
|
|
||||
|
formValidate: { |
||||
|
mainImage: '' |
||||
|
}, |
||||
|
ruleValidate: { |
||||
|
mainImage: [ |
||||
|
{ required: true, message: '请上传照片', trigger: 'blur' } |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'baseApi' |
||||
|
]), |
||||
|
isAllServicesRunning() { |
||||
|
return Object.values(this.service).every(service => service.status === 'running') |
||||
|
} |
||||
|
}, |
||||
|
created() { |
||||
|
this.initData() |
||||
|
}, |
||||
|
beforeDestroy() { |
||||
|
if (this.timer) { |
||||
|
clearInterval(this.timer) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
initData() { |
||||
|
crudAiTask.FetchInitSetting().then(res => { |
||||
|
this.crud.form.ip = res.ip |
||||
|
this.maxNum = res.maxNum |
||||
|
this.crud.form.maxNum = res.maxNum |
||||
|
}).catch(() => { |
||||
|
}) |
||||
|
}, |
||||
|
handleService() { |
||||
|
this.servicesDisplayed = false |
||||
|
FetchAITerminalStatusQuery({ 'ip': this.crud.form.ip }).then(res => { |
||||
|
// { |
||||
|
// "service_FileParsing_v1":{"last_heartbeat":1736496962.2368362,"status":"running"}, |
||||
|
// "service_fileParsing":{"last_heartbeat":1736496961.953832,"status":"running"} |
||||
|
// "service_imgOCR":{"last_heartbeat":1736496961.6238313,"status":"running"}, |
||||
|
// "service_aiResult":{"last_heartbeat":1736496960.8598323,"status":"running"}, |
||||
|
// } |
||||
|
if (res) { |
||||
|
this.serviceContentDialogVisible = true |
||||
|
this.service = JSON.parse(res) |
||||
|
this.serviceItems = [] |
||||
|
const keysOrder = ['service_FileParsing_v1', 'service_fileParsing', 'service_imgOCR', 'service_aiResult'] |
||||
|
keysOrder.forEach(key => { |
||||
|
let serviceName = '' |
||||
|
switch (key) { |
||||
|
case 'service_FileParsing_v1': |
||||
|
serviceName = '文件解析V1' |
||||
|
break |
||||
|
case 'service_fileParsing': |
||||
|
serviceName = '文件解析' |
||||
|
break |
||||
|
case 'service_imgOCR': |
||||
|
serviceName = '文字识别' |
||||
|
break |
||||
|
case 'service_aiResult': |
||||
|
serviceName = '数据同步' |
||||
|
break |
||||
|
} |
||||
|
this.serviceItems.push({ |
||||
|
serviceName: serviceName, |
||||
|
status: this.service[key].status |
||||
|
}) |
||||
|
}) |
||||
|
this.showServicesSequentially() |
||||
|
} else { |
||||
|
this.serviceDialogVisible = true |
||||
|
} |
||||
|
}).catch(() => { |
||||
|
}) |
||||
|
}, |
||||
|
showServicesSequentially() { |
||||
|
// let delay = 0 |
||||
|
// this.serviceItems.forEach((item, index) => { |
||||
|
// setTimeout(() => { |
||||
|
// this.$set(this.serviceItems, index, { |
||||
|
// ...item, |
||||
|
// opacity: 1 |
||||
|
// }) |
||||
|
// }, delay) |
||||
|
// delay += 300 |
||||
|
// }) |
||||
|
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) |
||||
|
}, |
||||
|
[CRUD.HOOK.beforeToCU](crud, form, btn) { |
||||
|
if (this.showVerifyDialog) { |
||||
|
// 打开输入验证码对话框 |
||||
|
this.verifyDialogVisible = true |
||||
|
return false |
||||
|
} |
||||
|
}, |
||||
|
[CRUD.HOOK.beforeRefresh]() { |
||||
|
|
||||
|
}, |
||||
|
// 提交前的验证 |
||||
|
[CRUD.HOOK.afterValidateCU](crud) { |
||||
|
console.log(crud.form) |
||||
|
return false |
||||
|
}, |
||||
|
toVerify(btn) { |
||||
|
this.verifyStatus = btn |
||||
|
if (btn === 'reset') { |
||||
|
this.verifyDialogVisible = true |
||||
|
} else { |
||||
|
if (this.form.ip) { |
||||
|
if (this.showVerifyDialog) { |
||||
|
this.verifyDialogVisible = true |
||||
|
return false |
||||
|
} |
||||
|
} else { |
||||
|
this.$refs.form.validateField(['ip'], err => { |
||||
|
console.log('err', err) |
||||
|
if (err) { |
||||
|
return |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
handleConfirm() { |
||||
|
verifyMaintenance(encrypt(this.verfiyForm.verifyCode)).then((res) => { |
||||
|
if (res) { |
||||
|
this.verifyDialogVisible = false |
||||
|
this.verfiyForm.verifyCode = '' |
||||
|
this.showVerifyDialog = false |
||||
|
if (this.verifyStatus === 'add') { |
||||
|
crudAiTask.FetchEditSetting(this.crud.form).then(res => { |
||||
|
this.$message({ message: '修改成功', type: 'success', offset: 8 }) |
||||
|
this.initData() |
||||
|
}).catch(() => { |
||||
|
}) |
||||
|
} else { |
||||
|
this.resetLoading = true |
||||
|
// 重启服务 |
||||
|
this.handleConnectAIService() |
||||
|
} |
||||
|
} else { |
||||
|
this.$message({ message: '验证码错误!', type: 'error', offset: 8 }) |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
async handleConnectAIService() { |
||||
|
try { |
||||
|
// // 第一次先关闭 |
||||
|
// const firstRes = await FetchStartStopBookAIService({ runType: 0 }) |
||||
|
// console.log('先关闭', firstRes) |
||||
|
// this.$message({ message: '关闭服务成功', type: 'success', offset: 8 }) |
||||
|
// 第二次重新开启 |
||||
|
// 1开启(先关后开) 2关闭 (彻底关闭) |
||||
|
const secondRes = await FetchStartStopBookAIService({ runType: 1 }) |
||||
|
console.log('后开启', secondRes) |
||||
|
this.$message({ message: '重启服务成功', type: 'success', offset: 8 }) |
||||
|
this.resetLoading = false |
||||
|
} catch (error) { |
||||
|
this.$message({ message: '请求失败', type: 'error', offset: 8 }) |
||||
|
this.resetLoading = false |
||||
|
} |
||||
|
}, |
||||
|
handleClose() { |
||||
|
if (this.$refs.verfiyForm) { |
||||
|
this.verfiyForm.verifyCode = '' |
||||
|
this.$refs.verfiyForm.resetFields() |
||||
|
this.verifyDialogVisible = false |
||||
|
} |
||||
|
|
||||
|
this.serviceContentDialogVisible = false |
||||
|
this.serviceDialogVisible = false |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
::v-deep div.el-dialog__footer { |
||||
|
text-align: center; |
||||
|
} |
||||
|
.tip-service{ |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
color: #0C0E1E; |
||||
|
font-size: 16px; |
||||
|
line-height: 40px; |
||||
|
padding: 40px !important; |
||||
|
.iconfont{ |
||||
|
font-size: 30px; |
||||
|
margin-right: 10px; |
||||
|
color: #ED4A41; |
||||
|
} |
||||
|
p{ |
||||
|
&:first-child{ |
||||
|
color: #ED4A41; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.service-all{ |
||||
|
text-align: center; |
||||
|
padding: 30px 0 30px 0 !important; |
||||
|
color: #0C0E1E; |
||||
|
ul{ |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
padding: 60px 0 40px 0; |
||||
|
li{ |
||||
|
position: relative; |
||||
|
&::before{ |
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
top: -30px; |
||||
|
width: 1px; |
||||
|
height: 20px; |
||||
|
background-color: #9098a4; |
||||
|
margin-left: -1px; |
||||
|
} |
||||
|
p{ |
||||
|
padding: 5px; |
||||
|
border: 1px solid #9098a4; |
||||
|
margin-bottom: 10px; |
||||
|
border-radius: 4px; |
||||
|
&.false-active{ |
||||
|
border-color: #ED4A41; |
||||
|
color: #ED4A41; |
||||
|
} |
||||
|
&.true-active{ |
||||
|
border-color: rgb(18, 196, 122); |
||||
|
color: rgb(18, 196, 122); |
||||
|
} |
||||
|
} |
||||
|
.iconfont::before{ |
||||
|
margin-right: 0 !important; |
||||
|
} |
||||
|
.icon-cuowu1{ |
||||
|
color: #ED4A41; |
||||
|
} |
||||
|
.icon-shi{ |
||||
|
color: rgb(18, 196, 122); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.service-top-text{ |
||||
|
position: relative; |
||||
|
font-size: 18px; |
||||
|
margin: 0 33px 0 43px; |
||||
|
color: rgb(18, 196, 122); |
||||
|
i.iconfont{ |
||||
|
font-size: 18px; |
||||
|
margin-right: 6px; |
||||
|
} |
||||
|
&::before{ |
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
bottom: -30px; |
||||
|
width: 1px; |
||||
|
height: 20px; |
||||
|
background-color:#9098a4; |
||||
|
margin-left: -1px; |
||||
|
} |
||||
|
&::after{ |
||||
|
content: ""; |
||||
|
position: absolute; |
||||
|
left: 0; |
||||
|
bottom: -30px; |
||||
|
width: 100%; |
||||
|
height: 1px; |
||||
|
background-color: #9098a4; |
||||
|
margin-left: -1px; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.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> |
||||