266 lines
6.6 KiB
Vue
266 lines
6.6 KiB
Vue
<template>
|
||
<div class="page">
|
||
<section class="card">
|
||
<div class="head">
|
||
<p class="tag">服务器</p>
|
||
<h2 class="header">数据刷新与采集</h2>
|
||
<p class="desc">用于配置服务器仪表板的请求频率和 metrics 参数。</p>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<p class="label">当前状态刷新频率(秒)</p>
|
||
<t-input v-model="snapshotRefreshText" type="number" clearable placeholder="默认 3 秒" />
|
||
</div>
|
||
|
||
<div class="group">
|
||
<p class="label">历史采样刷新频率(秒)</p>
|
||
<t-input v-model="historyRefreshText" type="number" clearable placeholder="默认 10 秒" />
|
||
</div>
|
||
|
||
<div class="group">
|
||
<p class="label">当前状态采集指标</p>
|
||
<div class="metrics">
|
||
<t-button
|
||
v-for="metric in snapshotMetricOptions"
|
||
:key="metric.value"
|
||
size="small"
|
||
theme="primary"
|
||
:variant="isSnapshotMetricChecked(metric.value) ? 'base' : 'outline'"
|
||
@click="toggleSnapshotMetric(metric.value)"
|
||
>
|
||
<span v-text="metric.label" />
|
||
</t-button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="group">
|
||
<p class="label">历史采样采集指标</p>
|
||
<div class="metrics">
|
||
<t-button
|
||
v-for="metric in historyMetricOptions"
|
||
:key="metric.value"
|
||
size="small"
|
||
theme="primary"
|
||
:variant="isHistoryMetricChecked(metric.value) ? 'base' : 'outline'"
|
||
@click="toggleHistoryMetric(metric.value)"
|
||
>
|
||
<span v-text="metric.label" />
|
||
</t-button>
|
||
</div>
|
||
</div>
|
||
|
||
<t-button block theme="primary" @click="saveServerDashboardSetting">
|
||
保存服务器配置
|
||
</t-button>
|
||
<t-button block variant="outline" @click="resetServerDashboardSetting">
|
||
恢复默认
|
||
</t-button>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<div class="head">
|
||
<p class="tag">Docker</p>
|
||
<h2 class="header">配置待定</h2>
|
||
<p class="desc">后续将支持 Docker 仪表板采集项和展示策略配置。</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<div class="head">
|
||
<p class="tag">UPS</p>
|
||
<h2 class="header">配置待定</h2>
|
||
<p class="desc">后续将支持 UPS 仪表板采集项和告警策略配置。</p>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { Toast } from "tdesign-mobile-vue";
|
||
import {
|
||
useSettingStore,
|
||
type DashboardHistoryMetric,
|
||
type DashboardSnapshotMetric,
|
||
type ServerDashboardSetting
|
||
} from "@/store/settingStore";
|
||
|
||
defineOptions({
|
||
name: "DashboardSetting"
|
||
});
|
||
|
||
const settingStore = useSettingStore();
|
||
|
||
const snapshotMetricOptions: Array<{ label: string; value: DashboardSnapshotMetric }> = [
|
||
{ label: "系统", value: "os" },
|
||
{ label: "CPU", value: "cpu" },
|
||
{ label: "内存", value: "memory" },
|
||
{ label: "JVM", value: "jvm" },
|
||
{ label: "网络", value: "network" },
|
||
{ label: "硬件", value: "hardware" },
|
||
{ label: "磁盘", value: "storage" }
|
||
];
|
||
|
||
const historyMetricOptions: Array<{ label: string; value: DashboardHistoryMetric }> = [
|
||
{ label: "CPU", value: "cpu" },
|
||
{ label: "内存", value: "memory" },
|
||
{ label: "JVM", value: "jvm" },
|
||
{ label: "网络", value: "network" }
|
||
];
|
||
|
||
const snapshotRefreshText = ref("");
|
||
const historyRefreshText = ref("");
|
||
const selectedSnapshotMetrics = ref<DashboardSnapshotMetric[]>([]);
|
||
const selectedHistoryMetrics = ref<DashboardHistoryMetric[]>([]);
|
||
|
||
watch(
|
||
() => settingStore.dashboard.server,
|
||
(setting) => {
|
||
snapshotRefreshText.value = String(setting.snapshotRefreshSeconds);
|
||
historyRefreshText.value = String(setting.historyRefreshSeconds);
|
||
selectedSnapshotMetrics.value = [...setting.snapshotMetrics];
|
||
selectedHistoryMetrics.value = [...setting.historyMetrics];
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
function isSnapshotMetricChecked(metric: DashboardSnapshotMetric): boolean {
|
||
return selectedSnapshotMetrics.value.includes(metric);
|
||
}
|
||
|
||
function isHistoryMetricChecked(metric: DashboardHistoryMetric): boolean {
|
||
return selectedHistoryMetrics.value.includes(metric);
|
||
}
|
||
|
||
function toggleSnapshotMetric(metric: DashboardSnapshotMetric): void {
|
||
if (isSnapshotMetricChecked(metric)) {
|
||
if (selectedSnapshotMetrics.value.length <= 1) {
|
||
Toast({
|
||
theme: "warning",
|
||
message: "当前状态至少保留一个采集指标"
|
||
});
|
||
return;
|
||
}
|
||
|
||
selectedSnapshotMetrics.value = selectedSnapshotMetrics.value.filter((item) => item !== metric);
|
||
return;
|
||
}
|
||
|
||
selectedSnapshotMetrics.value = [...selectedSnapshotMetrics.value, metric];
|
||
}
|
||
|
||
function toggleHistoryMetric(metric: DashboardHistoryMetric): void {
|
||
if (isHistoryMetricChecked(metric)) {
|
||
if (selectedHistoryMetrics.value.length <= 1) {
|
||
Toast({
|
||
theme: "warning",
|
||
message: "历史采样至少保留一个采集指标"
|
||
});
|
||
return;
|
||
}
|
||
|
||
selectedHistoryMetrics.value = selectedHistoryMetrics.value.filter((item) => item !== metric);
|
||
return;
|
||
}
|
||
|
||
selectedHistoryMetrics.value = [...selectedHistoryMetrics.value, metric];
|
||
}
|
||
|
||
function saveServerDashboardSetting(): void {
|
||
const nextSetting: Partial<ServerDashboardSetting> = {
|
||
snapshotRefreshSeconds: normalizeSecondValue(snapshotRefreshText.value, 3),
|
||
historyRefreshSeconds: normalizeSecondValue(historyRefreshText.value, 10),
|
||
snapshotMetrics: selectedSnapshotMetrics.value,
|
||
historyMetrics: selectedHistoryMetrics.value
|
||
};
|
||
|
||
settingStore.setServerDashboard(nextSetting);
|
||
Toast({
|
||
theme: "success",
|
||
message: "服务器仪表板配置已保存"
|
||
});
|
||
}
|
||
|
||
function resetServerDashboardSetting(): void {
|
||
settingStore.setServerDashboard({
|
||
snapshotRefreshSeconds: 3,
|
||
historyRefreshSeconds: 10,
|
||
snapshotMetrics: ["os", "cpu", "memory", "jvm", "network", "hardware", "storage"],
|
||
historyMetrics: ["cpu", "memory", "jvm", "network"]
|
||
});
|
||
|
||
Toast({
|
||
theme: "success",
|
||
message: "已恢复默认配置"
|
||
});
|
||
}
|
||
|
||
function normalizeSecondValue(value: string, fallback: number): number {
|
||
const numberValue = Number(value);
|
||
if (Number.isNaN(numberValue)) {
|
||
return fallback;
|
||
}
|
||
|
||
return Math.min(Math.max(Math.floor(numberValue), 1), 120);
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.page {
|
||
gap: 1rem;
|
||
display: flex;
|
||
padding: 1rem;
|
||
flex-direction: column;
|
||
|
||
.card {
|
||
gap: 1rem;
|
||
display: flex;
|
||
padding: 1rem;
|
||
border-radius: 1rem;
|
||
flex-direction: column;
|
||
border: 1px solid var(--app-line);
|
||
background: var(--app-card);
|
||
box-shadow: 0 .35rem 1rem rgba(17, 32, 56, .05);
|
||
}
|
||
|
||
.head,
|
||
.group {
|
||
gap: .5rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.tag,
|
||
.label,
|
||
.desc {
|
||
margin: 0;
|
||
color: var(--app-sub);
|
||
}
|
||
|
||
.tag,
|
||
.label {
|
||
font-size: .875rem;
|
||
}
|
||
|
||
.header {
|
||
margin: 0;
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
.desc {
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.metrics {
|
||
gap: .75rem;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
}
|
||
}
|
||
|
||
:global(.theme-dark) .page {
|
||
.card {
|
||
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
|
||
}
|
||
}
|
||
</style>
|