+
+
+
+ {{ data.cpuCore }} CPU
Memory Usage: {{ data.memoryUsage.toFixed(1) }}GB{{ memoryTotal.toFixed(1) }} GB
-
-
-
网络流量
+
+
+
+
+ CPU
+ {{ cpuPercentage.toFixed(1) }}%
+
+
+
+
+
+ 内存
+ {{ memoryUsage.toFixed(1) }} GB
+
+
+
+
+
+
+
+
网络上传
+
{{ fitByUnit(data.networkUpload, 'KB') }}/s
+
-
-
{{ ` ${fitByUnit(data.networkUpload, 'KB')} /s ` }}
-
-
-
{{ ` ${fitByUnit(data.networkDownload, 'KB')} /s ` }}
+
网络下载
+
{{ fitByUnit(data.networkDownload, 'KB') }}/s
-
+
diff --git a/monitor-web/src/component/TabItem.vue b/monitor-web/src/component/TabItem.vue
index 6a21429..848ed7f 100644
--- a/monitor-web/src/component/TabItem.vue
+++ b/monitor-web/src/component/TabItem.vue
@@ -1,33 +1,73 @@
-
- {{ name }}
-
+
diff --git a/monitor-web/src/component/__tests__/PreviewCard.test.js b/monitor-web/src/component/__tests__/PreviewCard.test.js
new file mode 100644
index 0000000..cfdf79e
--- /dev/null
+++ b/monitor-web/src/component/__tests__/PreviewCard.test.js
@@ -0,0 +1,103 @@
+// @vitest-environment jsdom
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { mount } from '@vue/test-utils'
+
+const toolMocks = vi.hoisted(() => ({
+ copyIp: vi.fn(),
+ rename: vi.fn()
+}))
+
+vi.mock('@/tools', () => ({
+ copyIp: toolMocks.copyIp,
+ fitByUnit: (value, unit) => `${value} ${unit}`,
+ osNameToIcon: () => ({ color: '#0b6bee', icon: 'fa-linux' }),
+ percentageToStatus: (value) => (value >= 80 ? 'exception' : 'success'),
+ rename: toolMocks.rename
+}))
+
+const stubs = {
+ 'el-icon': { template: '
' },
+ 'el-progress': {
+ name: 'ElProgress',
+ props: ['percentage', 'status', 'strokeWidth', 'showText'],
+ template: '
'
+ }
+}
+
+import PreviewCard from '@/component/PreviewCard.vue'
+
+/**
+ * 构造主机预览卡片最小完整数据。
+ *
+ * @returns {object} 主机预览数据
+ */
+function createHost() {
+ return {
+ id: 1,
+ location: 'cn',
+ name: '生产节点 · 上海',
+ online: true,
+ ip: '10.20.0.12',
+ osName: 'Ubuntu',
+ osVersion: '24.04',
+ cpuName: 'AMD EPYC 7763',
+ cpuCore: 32,
+ memory: 64,
+ cpuUsage: 0.34,
+ memoryUsage: 27.8,
+ networkUpload: 832,
+ networkDownload: 1620
+ }
+}
+
+describe('PreviewCard.vue', () => {
+ beforeEach(() => {
+ toolMocks.copyIp.mockReset()
+ toolMocks.rename.mockReset()
+ })
+
+ it('opens host details with Enter and Space', async () => {
+ const wrapper = mount(PreviewCard, {
+ props: { data: createHost(), update: vi.fn() },
+ global: { stubs }
+ })
+
+ await wrapper.trigger('keydown', { key: 'Enter' })
+ await wrapper.trigger('keydown', { key: ' ' })
+
+ expect(wrapper.emitted('open')).toHaveLength(2)
+ })
+
+ it('keeps rename and copy actions independent from opening the card', async () => {
+ const update = vi.fn()
+ const host = createHost()
+ const wrapper = mount(PreviewCard, {
+ props: { data: host, update },
+ global: { stubs }
+ })
+
+ await wrapper.get(`[aria-label="重命名主机 ${host.name}"]`).trigger('click')
+ await wrapper.get(`[aria-label="复制 IP ${host.ip}"]`).trigger('click')
+
+ expect(toolMocks.rename).toHaveBeenCalledWith(host.id, host.name, update)
+ expect(toolMocks.copyIp).toHaveBeenCalledWith(host.ip)
+ expect(wrapper.emitted('open')).toBeUndefined()
+ })
+
+ it('clamps invalid utilization values to safe progress percentages', () => {
+ const host = {
+ ...createHost(),
+ cpuUsage: 2,
+ memory: 0,
+ memoryUsage: Number.NaN
+ }
+ const wrapper = mount(PreviewCard, {
+ props: { data: host, update: vi.fn() },
+ global: { stubs }
+ })
+
+ const progress = wrapper.findAllComponents({ name: 'ElProgress' })
+ expect(progress[0].props('percentage')).toBe(100)
+ expect(progress[1].props('percentage')).toBe(0)
+ })
+})
diff --git a/monitor-web/src/views/IndexView.vue b/monitor-web/src/views/IndexView.vue
index 16139f3..ba34802 100755
--- a/monitor-web/src/views/IndexView.vue
+++ b/monitor-web/src/views/IndexView.vue
@@ -1,65 +1,19 @@
-
-
-
-
-
-
-
-
-
-
- 管理员
- 子账户
- {{ store.user.username }}
-
-
{{ store.user.email }}
-
-
-
-
-
-
-
-
- 退出登录
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
flying monitor
+
+ 基础设施控制台
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 退出登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/monitor-web/src/views/WelcomeView.vue b/monitor-web/src/views/WelcomeView.vue
index 2068dde..8088e69 100755
--- a/monitor-web/src/views/WelcomeView.vue
+++ b/monitor-web/src/views/WelcomeView.vue
@@ -1,40 +1,290 @@
+
+
-
-
-
-
-
-
欢迎来到flying监控
-
你可以在这里看到你的各个服务器运行状况
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+

+
flying monitor
+
+
+
欢迎来到 flying monitor
+
清晰掌握每台服务器的运行状态
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/monitor-web/src/views/tabs/AlertView.vue b/monitor-web/src/views/tabs/AlertView.vue
index 4fcd018..ff692f4 100644
--- a/monitor-web/src/views/tabs/AlertView.vue
+++ b/monitor-web/src/views/tabs/AlertView.vue
@@ -46,16 +46,24 @@ const activeTab = computed({
diff --git a/monitor-web/src/views/tabs/Probes.vue b/monitor-web/src/views/tabs/Probes.vue
index 924321e..cccd59b 100644
--- a/monitor-web/src/views/tabs/Probes.vue
+++ b/monitor-web/src/views/tabs/Probes.vue
@@ -664,18 +664,27 @@ onMounted(() => {
diff --git a/monitor-web/src/views/tabs/Security.vue b/monitor-web/src/views/tabs/Security.vue
index 8cd9f09..deac1f5 100644
--- a/monitor-web/src/views/tabs/Security.vue
+++ b/monitor-web/src/views/tabs/Security.vue
@@ -232,11 +232,9 @@ onBeforeUnmount(() => {
-
+
+ {{ (item.username || 'U').charAt(0).toUpperCase() }}
+
{{ item.username }}
@@ -274,35 +272,43 @@ onBeforeUnmount(() => {
diff --git a/monitor-web/src/views/tabs/StatusPageConfig.vue b/monitor-web/src/views/tabs/StatusPageConfig.vue
index 2843a63..2e9c9b0 100644
--- a/monitor-web/src/views/tabs/StatusPageConfig.vue
+++ b/monitor-web/src/views/tabs/StatusPageConfig.vue
@@ -115,7 +115,7 @@ onMounted(() => {
公开状态页可在
-
+
{{ previewHref }}
访问;任何访客(包括未登录用户)均可查看勾选的客户端在线状态与最近 24 小时可用率。响应严格不暴露
@@ -208,16 +208,18 @@ onMounted(() => {
}
.info-card {
- border-radius: 7px;
- padding: 15px 20px;
- background-color: var(--el-bg-color);
width: 100%;
- max-width: 880px;
+ max-width: 960px;
+ padding: 24px;
+ border: 1px solid var(--app-border);
+ border-radius: var(--app-radius-md);
+ background: var(--app-surface);
+ box-shadow: var(--app-shadow-sm);
.title {
font-size: 18px;
- font-weight: bold;
- color: dodgerblue;
+ font-weight: 750;
+ color: var(--app-text);
}
}
@@ -226,4 +228,18 @@ onMounted(() => {
gap: 10px;
align-items: center;
}
+
+@media (max-width: 600px) {
+ .info-card {
+ padding: 18px 14px;
+ }
+
+ .action-bar {
+ flex-wrap: wrap;
+ }
+
+ .action-bar .el-button {
+ flex: 1;
+ }
+}
diff --git a/monitor-web/src/views/welcome/ForgetPage.vue b/monitor-web/src/views/welcome/ForgetPage.vue
index e926f8d..6e00233 100755
--- a/monitor-web/src/views/welcome/ForgetPage.vue
+++ b/monitor-web/src/views/welcome/ForgetPage.vue
@@ -1,102 +1,115 @@
-
-
+
+
-
-
-
重置密码
-
请输入需要重置密码的电子邮件地址
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ coldTime > 0 ? '请稍后 ' + coldTime + ' 秒' : '获取验证码' }}
-
-
-
-
-
-
-
- 开始重置密码
-
+
+
+ 重置密码
+ 验证账户邮箱后即可设置新密码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ coldTime > 0 ? '请稍后 ' + coldTime + ' 秒' : '获取验证码' }}
+
+
+
+
+
+
+ 开始重置密码
+
+
+ 返回登录
+
-
-
-
-
-
重置密码
-
请填写您的新密码,务必牢记,防止丢失
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 立即重置密码
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即重置密码
+
-
+
-
+
diff --git a/monitor-web/src/views/welcome/LoginPage.vue b/monitor-web/src/views/welcome/LoginPage.vue
index 7800aff..912ab4e 100755
--- a/monitor-web/src/views/welcome/LoginPage.vue
+++ b/monitor-web/src/views/welcome/LoginPage.vue
@@ -1,58 +1,57 @@
-
-
-
登录
-
在进入系统之前请先输入用户名和密码进行登录
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- 忘记密码?
-
-
-
-
-
- 立即登录
-
+
+ 忘记密码?
+
+
+
+
+ 立即登录
+
-
+
From 16bda8bcf404ef6d6ad0f425fcbf5a4e799b9f34 Mon Sep 17 00:00:00 2001
From: flyingcoding <54491871+flyingcoding@users.noreply.github.com>
Date: Sat, 11 Jul 2026 13:07:18 +0800
Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=9D=E6=8C=81=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E9=A1=B5=20E2E=20=E4=BA=A4=E4=BA=92=E5=90=88=E5=90=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
monitor-web/src/views/tabs/Manage.vue | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/monitor-web/src/views/tabs/Manage.vue b/monitor-web/src/views/tabs/Manage.vue
index 3ab6c8c..ab8fc91 100644
--- a/monitor-web/src/views/tabs/Manage.vue
+++ b/monitor-web/src/views/tabs/Manage.vue
@@ -151,7 +151,7 @@ function openTerminal(id) {
管理主机列表
-
管理服务器并快速查看 CPU、内存与网络状态
+
在这里你可以管理你的各个服务器,并快速查看 CPU、内存与网络状态
-
-
- 添加新主机
-
-
+
清除筛选