Просмотр исходного кода

fix(cfc-web): 系统状态卡片增加变更日志入口与服务器运行监控

在系统状态卡片中: 版本号旁增加「查看变更日志」链接, 点击弹出 dialog 显示 CHANGELOG.md 解析内容

新增服务器运行状态: 运行时长、CPU 使用率、JVM 内存占用, 数据来自后端 /api/system/health 接口

已在 mounted 中调用 loadServerHealth() 自动加载

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
iwt 2 месяцев назад
Родитель
Сommit
53fa2c902f
1 измененных файлов с 151 добавлено и 6 удалено
  1. 151 6
      cfc-web/src/views/Dashboard.vue

+ 151 - 6
cfc-web/src/views/Dashboard.vue

@@ -187,7 +187,10 @@
     </div>
     <div class="health-info">
       <div class="health-label">系统版本</div>
-      <div class="health-value">{{ version }}</div>
+      <div class="health-value">
+        {{ version }}
+        <el-link type="primary" :underline="false" style="font-size:12px;margin-left:6px" @click="showChangelog">查看变更日志</el-link>
+      </div>
     </div>
   </div>
   <div class="health-item">
@@ -208,6 +211,33 @@
       <div class="health-value">~45 个</div>
     </div>
   </div>
+  <div class="health-item">
+    <div class="health-icon health-icon--uptime">
+      <i class="el-icon-time"></i>
+    </div>
+    <div class="health-info">
+      <div class="health-label">服务器运行时长</div>
+      <div class="health-value">{{ serverHealth.uptime }}</div>
+    </div>
+  </div>
+  <div class="health-item">
+    <div class="health-icon health-icon--cpu">
+      <i class="el-icon-cpu"></i>
+    </div>
+    <div class="health-info">
+      <div class="health-label">CPU 使用率</div>
+      <div class="health-value">{{ serverHealth.cpuUsagePercent }}% ({{ serverHealth.cpuCores }}核)</div>
+    </div>
+  </div>
+  <div class="health-item">
+    <div class="health-icon health-icon--memory">
+      <i class="el-icon-coffee"></i>
+    </div>
+    <div class="health-info">
+      <div class="health-label">JVM 内存</div>
+      <div class="health-value">{{ serverHealth.memUsed }} / {{ serverHealth.memMax }} ({{ serverHealth.memUsagePercent }}%)</div>
+    </div>
+  </div>
 </div>
 <div class="health-links">
   <el-button size="mini" icon="el-icon-s-order" @click="$router.push('/tasks')">任务管理</el-button>
@@ -275,16 +305,27 @@
           <div class="action-label">系统设置</div>
         </div>
       </div>
-    </div>
-  </el-col>
+     </div>
+   </el-col>
 </el-row>
-    </div>
-  </div>
+     </div>
+   </div>
+
+<!-- 变更日志弹窗 -->
+<el-dialog
+  title="变更日志"
+  :visible.sync="changelogVisible"
+  width="700px"
+  custom-class="changelog-dialog"
+  append-to-body
+>
+  <div v-loading="changelogLoading" class="changelog-body" v-html="changelogContent"></div>
+</el-dialog>
 </template>
 
 <script>
 import * as echarts from 'echarts'
-import { getDashboardStats, getMembershipStats, getTrendStats, getDashboardOverview } from '@/api/admin'
+import { getDashboardStats, getMembershipStats, getTrendStats, getDashboardOverview, getSystemHealth } from '@/api/admin'
 
 export default {
   name: 'Dashboard',
@@ -337,6 +378,7 @@ mounted() {
   this.loadDashboardData()
   this.loadTrend()
   this.loadMembership()
+  this.loadServerHealth()
   this.resizeHandler = () => {
     this.trendChart && this.trendChart.resize()
     this.memberChart && this.memberChart.resize()
@@ -373,6 +415,25 @@ beforeDestroy() {
       console.error('加载仪表盘数据失败:', error)
     }
   },
+    async loadServerHealth() {
+      try {
+        const res = await getSystemHealth()
+        if (res.code === 200 && res.data) {
+          const d = res.data
+          this.serverHealth = {
+            uptime: d.uptime || '--',
+            memUsed: d.memUsed || '--',
+            memMax: d.memMax || '--',
+            memUsagePercent: d.memUsagePercent || '--',
+            cpuCores: d.cpuCores || '--',
+            cpuLoad: d.cpuLoad || '--',
+            cpuUsagePercent: d.cpuUsagePercent || '--'
+          }
+        }
+      } catch (error) {
+        console.error('加载服务器状态失败:', error)
+      }
+    },
     showChangelog() {
       this.changelogVisible = true
       if (this.changelogContent) return
@@ -720,6 +781,18 @@ initMemberPieChart() {
   background: linear-gradient(135deg, #0EA5E9, #0284C7);
 }
 
+.health-icon--uptime {
+  background: linear-gradient(135deg, #8B5CF6, #7C3AED);
+}
+
+.health-icon--cpu {
+  background: linear-gradient(135deg, #EF4444, #F87171);
+}
+
+.health-icon--memory {
+  background: linear-gradient(135deg, #10B981, #059669);
+}
+
 .health-info {
   flex: 1;
 }
@@ -884,3 +957,75 @@ initMemberPieChart() {
   width: 100%;
 }
 </style>
+
+<style>
+.changelog-dialog .el-dialog__body {
+  max-height: 500px;
+  overflow-y: auto;
+}
+.changelog-body {
+  padding: 8px 4px;
+  line-height: 1.8;
+  font-size: 14px;
+  color: #374151;
+}
+.changelog-body h1 {
+  font-size: 20px;
+  font-weight: 700;
+  margin: 16px 0 8px;
+  color: #1E293B;
+}
+.changelog-body h2 {
+  font-size: 17px;
+  font-weight: 600;
+  margin: 14px 0 6px;
+  color: #1E293B;
+  border-left: 3px solid #6366F1;
+  padding-left: 8px;
+}
+.changelog-body h3 {
+  font-size: 15px;
+  font-weight: 600;
+  margin: 10px 0 4px;
+  color: #374151;
+}
+.changelog-body ul {
+  margin: 4px 0 8px;
+  padding-left: 20px;
+}
+.changelog-body li {
+  margin: 2px 0;
+}
+.changelog-body .cl-item {
+  margin: 4px 0;
+}
+.changelog-body .cl-empty {
+  text-align: center;
+  color: #94A3B8;
+  padding: 32px 0;
+}
+.changelog-body code {
+  background: #F1F5F9;
+  padding: 2px 6px;
+  border-radius: 3px;
+  font-size: 13px;
+}
+.changelog-body pre {
+  background: #F8FAFC;
+  border: 1px solid #E2E8F0;
+  border-radius: 8px;
+  padding: 12px;
+  overflow-x: auto;
+}
+.changelog-body pre code {
+  background: none;
+  padding: 0;
+}
+.changelog-body a {
+  color: #6366F1;
+  text-decoration: none;
+}
+.changelog-body a:hover {
+  text-decoration: underline;
+}
+</style>