完成主机添加和删除功能,修复BUG
This commit is contained in:
parent
c95323d5d3
commit
84d875e248
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -41,7 +41,7 @@ spring:
|
||||
mail-limit: 60
|
||||
flow:
|
||||
period: 3
|
||||
limit: 10
|
||||
limit: 20
|
||||
block: 30
|
||||
cors:
|
||||
origin: '*'
|
||||
|
@ -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">
|
||||
|
46
itbaima-monitor-web/src/component/RegisterCard.vue
Normal file
46
itbaima-monitor-web/src/component/RegisterCard.vue
Normal 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>
|
@ -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, [
|
||||
|
@ -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>
|
||||
|
@ -3,7 +3,9 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
Loading…
x
Reference in New Issue
Block a user