完成主机添加和删除功能,修复BUG

This commit is contained in:
柏码の讲师 2023-12-03 18:04:08 +08:00
parent c95323d5d3
commit 84d875e248
11 changed files with 128 additions and 16 deletions

View File

@ -11,8 +11,7 @@
<groupId>com.example</groupId>
<artifactId>itbaima-monitor-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>my-project-backend</name>
<description>my-project-backend</description>
<name>itbaima-monitor-server</name>
<properties>
<java.version>17</java.version>
</properties>

View File

@ -52,4 +52,15 @@ public class MonitorController {
public RestBean<RuntimeDetailVO> runtimeDetailsNow(int clientId) {
return RestBean.success(service.clientRuntimeDetailsNow(clientId));
}
@GetMapping("/register")
public RestBean<String> registerToken() {
return RestBean.success(service.registerToken());
}
@GetMapping("/delete")
public RestBean<String> deleteClient(int clientId) {
service.deleteClient(clientId);
return RestBean.success();
}
}

View File

@ -25,4 +25,5 @@ public interface ClientService extends IService<Client> {
ClientDetailsVO clientDetails(int clientId);
RuntimeDetailsVO clientRuntimeDetailsHistory(int clientId);
RuntimeDetailVO clientRuntimeDetailsNow(int clientId);
void deleteClient(int clientId);
}

View File

@ -41,6 +41,8 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
@PostConstruct
public void initClientCache() {
clientIdCache.clear();
clientTokenCache.clear();
this.list().forEach(this::addClientCache);
}
@ -132,7 +134,7 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
@Override
public RuntimeDetailsVO clientRuntimeDetailsHistory(int clientId) {
RuntimeDetailsVO vo = influx.readRuntimeData();
RuntimeDetailsVO vo = influx.readRuntimeData(clientId);
ClientDetail client = detailMapper.selectById(clientId);
BeanUtils.copyProperties(client, vo);
return vo;
@ -143,6 +145,14 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
return lastRuntime.get(clientId);
}
@Override
public void deleteClient(int clientId) {
baseMapper.deleteById(clientId);
detailMapper.deleteById(clientId);
this.initClientCache();
lastRuntime.remove(clientId);
}
private boolean isOnline(RuntimeDetailVO runtime) {
return runtime != null && System.currentTimeMillis() - runtime.getTimestamp() < 60 * 1000;
}

View File

@ -47,14 +47,15 @@ public class InfluxDbUtils {
writeApi.writeMeasurement(BUCKET, ORG, WritePrecision.NS, data);
}
public RuntimeDetailsVO readRuntimeData() {
public RuntimeDetailsVO readRuntimeData(int clientId) {
RuntimeDetailsVO vo = new RuntimeDetailsVO();
String query = """
from(bucket: "%s")
|> range(start: %s)
|> filter(fn: (r) => r["_measurement"] == "runtime")
|> filter(fn: (r) => r["clientId"] == "%s")
""";
String format = String.format(query, BUCKET, "-1h");
String format = String.format(query, BUCKET, "-1h", clientId);
List<FluxTable> tables = client.getQueryApi().query(format, ORG);
int size = tables.size();
if (size == 0) return vo;
@ -63,7 +64,10 @@ public class InfluxDbUtils {
JSONObject object = new JSONObject();
object.put("timestamp", records.get(i).getTime());
for (int j = 0; j < size; j++) {
FluxRecord record = tables.get(j).getRecords().get(i);
FluxRecord record = tables
.get(j)
.getRecords()
.get(i);
object.put(record.getField(), record.getValue());
}
vo.getList().add(object);

View File

@ -41,7 +41,7 @@ spring:
mail-limit: 60
flow:
period: 3
limit: 10
limit: 20
block: 30
cors:
origin: '*'

View File

@ -2,9 +2,10 @@
import {computed, reactive, watch} from "vue";
import {get, post} from "@/net";
import {useClipboard} from "@vueuse/core";
import {ElMessage} from "element-plus";
import {ElMessage, ElMessageBox} from "element-plus";
import {cpuNameToImage, fitToRightByteUnit, osNameToIcon, percentageToStatus, rename} from "@/tools";
import RuntimeHistroy from "@/component/RuntimeHistroy.vue";
import {Delete} from "@element-plus/icons-vue";
const locations = [
{name: 'cn', desc: '中国大陆'},
@ -21,6 +22,7 @@ const props = defineProps({
update: Function,
show: Boolean
})
const emits = defineEmits(['delete'])
const details = reactive({
base: {},
@ -61,6 +63,20 @@ function updateDetails() {
init(props.id)
}
function deleteClient() {
ElMessageBox.confirm('删除此主机后所有统计数据都将丢失,您确定要这样做吗?', '删除主机', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
get(`/api/monitor/delete?clientId=${props.id}`, () => {
emits('delete')
props.update()
ElMessage.success('主机已成功移除')
})
}).catch(() => {})
}
setInterval(() => {
if(props.show && details.runtime) {
get(`/api/monitor/runtime-now?clientId=${props.id}`, data => {
@ -88,9 +104,13 @@ watch(() => props.id, init, { immediate: true })
<div class="client-details"
v-loading="Object.keys(details.base).length === 0">
<div v-if="Object.keys(details.base).length">
<div class="title">
<i class="fa-solid fa-server"></i>
服务器信息
<div style="display: flex;justify-content: space-between">
<div class="title">
<i class="fa-solid fa-server"></i>
服务器信息
</div>
<el-button :icon="Delete" type="danger"
@click="deleteClient" plain text>删除此主机</el-button>
</div>
<el-divider style="margin: 10px 0"/>
<div class="details-list">

View File

@ -0,0 +1,46 @@
<script setup>
import axios from "axios";
defineProps({
token: String
})
</script>
<template>
<div class="register-card">
<div class="title"><i class="fa-regular fa-square-plus"></i> 添加新的主机</div>
<div class="desc">请按照以下步骤完成新主机的添加添加后即可实时管理服务器以及检测运行状态</div>
<el-divider style="margin: 10px 0"/>
<div class="sub-title">1.部署客户端</div>
<div class="desc">在需要监控的服务器上运行监控客户端程序客户端程序依赖于Java17运行环境请提前安装好启动完成后即可进行下一步</div>
<div class="sub-title" style="margin-top: 10px">2.输入监控服务器地址</div>
<div class="desc">此地址用于客户端实时上报运行时状态数据请务必保证正确填写</div>
<el-input v-model="axios.defaults.baseURL" readonly/>
<div class="sub-title" style="margin-top: 10px">3.输入授权码</div>
<div class="desc">客户端所有请求必须携带授权码才能被服务端正确识别</div>
<el-input :model-value="token" readonly/>
</div>
</template>
<style scoped>
.register-card {
margin: 15px 20px;
.title {
font-size: 18px;
font-weight: bold;
}
.sub-title {
font-size: 16px;
font-weight: bold;
color: dodgerblue;
}
.desc {
font-size: 13px;
color: grey;
line-height: 16px;
}
}
</style>

View File

@ -31,8 +31,8 @@ function updateMemoryUsage(list) {
function updateNetworkUsage(list) {
const chart = charts[2]
let data = [
list.map(item => item.networkUpload),
list.map(item => item.networkDownload)
list.map(item => item.networkUpload.toFixed(1)),
list.map(item => item.networkDownload.toFixed(1))
]
const option = defaultOption('网络(KB/s)', localTimeLine(list))
doubleSeries(option, ['上传(KB/s)', '下载(KB/s)'], data, [

View File

@ -3,6 +3,8 @@ import PreviewCard from "@/component/PreviewCard.vue";
import {get} from "@/net";
import {reactive, ref} from "vue";
import ClientDetails from "@/component/ClientDetails.vue";
import {Plus} from "@element-plus/icons-vue";
import RegisterCard from "@/component/RegisterCard.vue";
const list = ref([])
@ -14,6 +16,11 @@ const displayClientDetails = id => {
detail.id = id
detail.show = true
}
const register = reactive({
show: false,
token: ''
})
const refreshToken = () => get('/api/monitor/register', code => register.token = code)
const updateList = () => get('/api/monitor/list', data => list.value = data)
setInterval(updateList, 10000)
@ -22,8 +29,15 @@ updateList()
<template>
<div class="manage-main">
<div class="title"><i class="fa-solid fa-server"></i> 管理主机列表</div>
<div class="description">在这里管理所有已经注册的主机实例实时监控主机运行状态快速进行管理和操作</div>
<div style="display: flex;justify-content: space-between;align-items: end">
<div>
<div class="title"><i class="fa-solid fa-server"></i> 管理主机列表</div>
<div class="description">在这里管理所有已经注册的主机实例实时监控主机运行状态快速进行管理和操作</div>
</div>
<div>
<el-button :icon="Plus" type="primary" @click="register.show = true" plain>添加新主机</el-button>
</div>
</div>
<el-divider style="margin: 10px 0"/>
<div class="card-list">
<preview-card :update="updateList" :data="item" v-for="item in list"
@ -31,7 +45,12 @@ updateList()
</div>
<el-drawer size="520" :show-close="false" v-model="detail.show"
:with-header="false" v-if="list.length" @close="detail.id = -1">
<client-details :id="detail.id" :update="updateList" :show="detail.show"/>
<client-details :id="detail.id" :update="updateList" :show="detail.show" @delete="detail.show = false"/>
</el-drawer>
<el-drawer style="width: 600px;margin: 10px auto" v-model="register.show"
direction="btt" :show-close="false" :with-header="false"
:size="320" @open="refreshToken">
<register-card :token="register.token"/>
</el-drawer>
</div>
</template>

View File

@ -3,7 +3,9 @@
</script>
<template>
<div>
</div>
</template>
<style scoped>