feat: websocket展示资源利用率
This commit is contained in:
parent
8e725d3f78
commit
29c6e368ae
@ -1 +1,2 @@
|
|||||||
VITE_BASE_URL = /api
|
VITE_BASE_URL = /api
|
||||||
|
VITE_WEBSOCKET = /socket
|
||||||
|
@ -1 +1,2 @@
|
|||||||
VITE_BASE_URL = http://127.0.0.1:8000/api/
|
VITE_BASE_URL = http://127.0.0.1:8000/api
|
||||||
|
VITE_WEBSOCKET = ws://localhost:8000/ws
|
||||||
|
45
frontend/package-lock.json
generated
45
frontend/package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^3.2.12",
|
"ant-design-vue": "^3.2.12",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"echarts": "^5.3.3",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.21",
|
"pinia": "^2.0.21",
|
||||||
@ -807,6 +808,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
|
||||||
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
|
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/echarts": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "2.3.0",
|
||||||
|
"zrender": "5.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.15.7",
|
"version": "0.15.7",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
||||||
@ -2628,6 +2638,11 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -2928,6 +2943,14 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zrender": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "2.3.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3536,6 +3559,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
|
||||||
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
|
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
|
||||||
},
|
},
|
||||||
|
"echarts": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "2.3.0",
|
||||||
|
"zrender": "5.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"esbuild": {
|
"esbuild": {
|
||||||
"version": "0.15.7",
|
"version": "0.15.7",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
||||||
@ -4726,6 +4758,11 @@
|
|||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||||
|
},
|
||||||
"type-check": {
|
"type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -4911,6 +4948,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"zrender": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "2.3.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^3.2.12",
|
"ant-design-vue": "^3.2.12",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"echarts": "^5.3.3",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.21",
|
"pinia": "^2.0.21",
|
||||||
|
107
frontend/src/components/echart/echart-system-info.vue
Normal file
107
frontend/src/components/echart/echart-system-info.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<script setup>
|
||||||
|
import Echart from './echart.vue'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
cpuValue: {
|
||||||
|
type: String,
|
||||||
|
require: true
|
||||||
|
},
|
||||||
|
memoryValue: {
|
||||||
|
type: String,
|
||||||
|
require: true
|
||||||
|
},
|
||||||
|
diskValue: {
|
||||||
|
type: String,
|
||||||
|
require: true
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = computed(() => {
|
||||||
|
const gaugeData = [
|
||||||
|
{
|
||||||
|
value: props.cpuValue,
|
||||||
|
name: 'CPU',
|
||||||
|
title: {
|
||||||
|
offsetCenter: ['-60%', '80%']
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
offsetCenter: ['-60%', '95%']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: props.memoryValue,
|
||||||
|
name: 'MEMORY',
|
||||||
|
title: {
|
||||||
|
offsetCenter: ['0%', '80%']
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
offsetCenter: ['0%', '95%']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: props.diskValue,
|
||||||
|
name: 'DISK',
|
||||||
|
title: {
|
||||||
|
offsetCenter: ['60%', '80%']
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
offsetCenter: ['60%', '95%']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
anchor: {
|
||||||
|
show: true,
|
||||||
|
showAbove: true,
|
||||||
|
size: 18,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#FAC858'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z',
|
||||||
|
width: 8,
|
||||||
|
length: '80%',
|
||||||
|
offsetCenter: [0, '8%']
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
overlap: true,
|
||||||
|
roundCap: true
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
roundCap: true
|
||||||
|
},
|
||||||
|
data: gaugeData,
|
||||||
|
title: {
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
width: 40,
|
||||||
|
height: 14,
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#fff',
|
||||||
|
backgroundColor: 'auto',
|
||||||
|
borderRadius: 3,
|
||||||
|
formatter: '{value}%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="system-info">
|
||||||
|
<Echart :options="options" :style="style" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
38
frontend/src/components/echart/echart.vue
Normal file
38
frontend/src/components/echart/echart.vue
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, watchEffect } from 'vue'
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
require: true
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
width: '100%',
|
||||||
|
height: '360px'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const echartRef = ref()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const instance = echarts.init(echartRef.value)
|
||||||
|
|
||||||
|
// props 变化就重新设置值
|
||||||
|
watchEffect(() => {
|
||||||
|
console.log('eachart 基础组件')
|
||||||
|
instance.setOption(props.options)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="echart">
|
||||||
|
<div ref="echartRef" :style="style"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -1,7 +1,46 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
import { onUnmounted, ref } from 'vue'
|
||||||
|
|
||||||
|
import EchartSystemInfo from '@/components/echart/echart-system-info.vue'
|
||||||
|
|
||||||
|
/** websocket */
|
||||||
|
let ws = new WebSocket('ws://localhost:8000/ws')
|
||||||
|
|
||||||
|
const wsData = ref()
|
||||||
|
ws.onmessage = (e) => {
|
||||||
|
// 接收消息
|
||||||
|
wsData.value = JSON.parse(e.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
ws.close()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>about</div>
|
<div class="about">
|
||||||
|
<a-card class="system">
|
||||||
|
<template #title> 资源使用率(虚拟数据) </template>
|
||||||
|
<EchartSystemInfo
|
||||||
|
:cpu-value="wsData?.usage.cpu"
|
||||||
|
:disk-value="wsData?.usage.disk"
|
||||||
|
:memory-value="wsData?.usage.memory"
|
||||||
|
:style="{ width: '100%', height: '300px' }"
|
||||||
|
/>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.about {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.system {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .ant-card {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -6,7 +6,6 @@ import { PlusOutlined } from '@ant-design/icons-vue'
|
|||||||
import { getRoles, queryRole, delRole, putRole, addRole } from '@/service/role'
|
import { getRoles, queryRole, delRole, putRole, addRole } from '@/service/role'
|
||||||
import { getMenus } from '@/service/menu'
|
import { getMenus } from '@/service/menu'
|
||||||
import { columns, rules, treeFieldNames } from './conf'
|
import { columns, rules, treeFieldNames } from './conf'
|
||||||
import { formatTime } from '@/utils/format'
|
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { getMenus as getRoleMenu } from '@/service/user'
|
import { getMenus as getRoleMenu } from '@/service/user'
|
||||||
|
|
||||||
@ -239,10 +238,10 @@ watch(
|
|||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'created'">
|
<template v-else-if="column.key === 'created'">
|
||||||
{{ formatTime(record.created) }}
|
{{ $$formatTime(record.created) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'modified'">
|
<template v-else-if="column.key === 'modified'">
|
||||||
{{ formatTime(record.modified) }}
|
{{ $$formatTime(record.modified) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'action'">
|
<template v-else-if="column.key === 'action'">
|
||||||
<span>
|
<span>
|
||||||
|
@ -26,8 +26,8 @@ export default defineConfig({
|
|||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, '')
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
},
|
},
|
||||||
'/socket.io': {
|
'/socket': {
|
||||||
target: 'ws://localhost:5000',
|
target: 'ws://localhost:8000/ws',
|
||||||
ws: true
|
ws: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user