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

编写webui系统信息(首页)代码

niujiuru 1 неделя назад
Родитель
Сommit
3616886b3b

+ 83 - 0
web-ui.service/page1_handler.go

@@ -6,6 +6,7 @@ import (
 	"net/http"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"runtime"
 	"strconv"
 	"strings"
@@ -210,3 +211,85 @@ func formatSize(size uint64) string {
 		return fmt.Sprintf("%dB", size)
 	}
 }
+
+func systemLoadAverageHandler(w http.ResponseWriter, r *http.Request) {
+	data, err := os.ReadFile("/proc/loadavg")
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	fields := strings.Fields(string(data))
+
+	if len(fields) < 3 {
+		http.Error(w, "invalid /proc/loadavg", http.StatusInternalServerError)
+		return
+	}
+
+	resp := struct {
+		Load1m  string `json:"load1m"`
+		Load5m  string `json:"load5m"`
+		Load15m string `json:"load15m"`
+	}{
+		Load1m:  formatLoad(fields[0]),
+		Load5m:  formatLoad(fields[1]),
+		Load15m: formatLoad(fields[2]),
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(resp)
+}
+
+func formatLoad(v string) string {
+	f, err := strconv.ParseFloat(v, 64)
+	if err != nil {
+		return noValue
+	}
+
+	return strconv.FormatFloat(f, 'f', 2, 64)
+}
+
+func serviceStatusHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != http.MethodGet {
+		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+
+	services := []struct {
+		name string
+		dir  string
+	}{
+		{"yfkj-networkd.service", "/opt/yfkj/networkd.service"},
+		{"yfkj-timesyncd.service", "/opt/yfkj/timesyncd.service"},
+		{"yfkj-gnss.service", "/opt/yfkj/gnss.service"},
+		{"yfkj-sshd-mqtt-bridge.service", "/opt/yfkj/sshd-mqtt-bridge.service"},
+		{"yfkj-camera-capture.service", "/opt/yfkj/camera-capture.service"},
+		{"yfkj-app-install.service", "/opt/yfkj/app-install.service"},
+		{"yfkj-web-ui.service", "/opt/yfkj/web-ui.service"},
+		{"yfkj-upgrade.service", "/opt/yfkj/upgrade.service"},
+	}
+
+	data := make(map[string]string, len(services)*2)
+
+	for i, s := range services {
+		n := i + 1
+
+		status := noValue
+		if out, err := exec.Command("systemctl", "is-active", s.name).Output(); err == nil {
+			if strings.TrimSpace(string(out)) == "active" {
+				status = "🟢运行中..."
+			}
+		}
+
+		data[fmt.Sprintf("var%d", n)] = status
+
+		if v, err := os.ReadFile(filepath.Join(s.dir, "version.txt")); err == nil {
+			data[fmt.Sprintf("var%d%d", n, n)] = "v" + strings.TrimSpace(string(v))
+		} else {
+			data[fmt.Sprintf("var%d%d", n, n)] = noValue
+		}
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(data)
+}

+ 0 - 3
web-ui.service/web/app.html

@@ -24,9 +24,6 @@
       </div>
     </div>
     <div class="actions">
-      <span id="sshd-status" class="status">
-         --
-      </span>
       <button class="btn btn-red" onclick="logout()">退出</button>
     </div>
   </header>

+ 19 - 11
web-ui.service/web/pages/page1.html

@@ -33,17 +33,17 @@
       <div class="info-list">
         <div class="info-item">
           <span class="info-name">系统01分钟负载</span>
-          <span class="info-value" id="load-1m">--</span>
+          <span class="info-value" id="load1m">--</span>
         </div>
 
         <div class="info-item">
           <span class="info-name">系统05分钟负载</span>
-          <span class="info-value" id="load-1m">--</span>
+          <span class="info-value" id="load5m">--</span>
         </div>
 
         <div class="info-item">
           <span class="info-name">系统15分钟负载</span>
-          <span class="info-value" id="load-1m">--</span>
+          <span class="info-value" id="load15m">--</span>
         </div>
       </div>
     </div>
@@ -56,7 +56,8 @@
             <div class="info-name">networkd.service</div>
             <div class="info-desc">网络管理服务</div>
           </div>
-          <span class="info-version" id="var1">--</span>
+          <span class="info-value" id="var1">--</span>
+          <span class="info-value" id="var11">--</span>
         </div>
 
         <div class="info-item">
@@ -64,7 +65,8 @@
             <div class="info-name">timesyncd.service</div>
             <div class="info-desc">系统时间同步</div>
           </div>
-          <span class="info-version" id="var2">--</span>
+          <span class="info-value" id="var2">--</span>
+          <span class="info-value" id="var22">--</span>
         </div>
 
         <div class="info-item">
@@ -72,7 +74,8 @@
             <div class="info-name">gnss.service</div>
             <div class="info-desc">位置信息获取</div>
           </div>
-          <span class="info-version" id="var3">--</span>
+          <span class="info-value" id="var3">--</span>
+          <span class="info-value" id="var33">--</span>
         </div>
 
         <div class="info-item">
@@ -80,7 +83,8 @@
             <div class="info-name">sshd-mqtt-bridge.service</div>
             <div class="info-desc">远程运维通道</div>
           </div>
-          <span class="info-version" id="var4">--</span>
+          <span class="info-value" id="var4">--</span>
+          <span class="info-value" id="var44">--</span>
         </div>
 
         <div class="info-item">
@@ -88,7 +92,8 @@
             <div class="info-name">camera-capture.service</div>
             <div class="info-desc">相机图像采集</div>
           </div>
-          <span class="info-version" id="var5">--</span>
+          <span class="info-value" id="var5">--</span>
+          <span class="info-value" id="var55">--</span>
         </div>
 
         <div class="info-item">
@@ -96,7 +101,8 @@
             <div class="info-name">app-install.service</div>
             <div class="info-desc">应用安装卸载</div>
           </div>
-          <span class="info-version" id="var6">--</span>
+          <span class="info-value" id="var6">--</span>
+          <span class="info-value" id="var66">--</span>
         </div>
 
         <div class="info-item">
@@ -104,7 +110,8 @@
             <div class="info-name">web-ui.service</div>
             <div class="info-desc">统一配置管理</div>
           </div>
-          <span class="info-version" id="var7">--</span>
+          <span class="info-value" id="var7">--</span>
+          <span class="info-value" id="var77">--</span>
         </div>
 
         <div class="info-item">
@@ -112,7 +119,8 @@
             <div class="info-name">upgrade.service</div>
             <div class="info-desc">自动服务升级</div>
           </div>
-          <span class="info-version", id="var8">--</span>
+          <span class="info-value" id="var8">--</span>
+          <span class="info-value" id="var88">--</span>
         </div>
       </div>
     </div>

+ 7 - 6
web-ui.service/web/static/css/page1.css

@@ -52,12 +52,13 @@
     border-bottom:1px solid #1f2937;
 }
 
-.info-item:last-child {
-    border-bottom:none;
+.info-info {
+    display:flex;
+    flex-direction:column;
 }
 
 .info-name {
-    width:200px;
+    width:160px;
     flex-shrink:0;
     color:#cbd5e1;
     font-size:14px;
@@ -70,9 +71,9 @@
 }
 
 .info-value {
-    width:80px;
-    margin-left:20px;
-    text-align:right;
+    width:100px;
+    margin-left:8px;
+    text-align:center;
     color:#94a3b8;
     font-size:14px;
     font-family:ui-monospace,Consolas,monospace;

+ 0 - 40
web-ui.service/web/static/js/app.js

@@ -56,48 +56,8 @@ async function fetchIMEI() {
   }
 }
 
-let sshdStatusTimer = null;
-function getSshdStatus() {
-  fetch("/api/sshd/status")
-    .then(r => {
-      if (!r.ok) {
-        throw new Error("HTTP " + r.status);
-      }
-
-      return r.json();
-    })
-    .then(data => {
-      document.getElementById("sshd-status").textContent = data.status || "--";
-    })
-    .catch(e => {
-      console.error("sshd status failed:", e);
-      document.getElementById("sshd-status").textContent = "--";
-    });
-}
-
-function startSshdStatusRefresh() {
-  if (sshdStatusTimer) {
-    return;
-  }
-
-  getSshdStatus();
-
-  sshdStatusTimer = setInterval(() => {
-    getSshdStatus();
-  }, 5000);
-}
-
-function stopSshdStatusRefresh() {
-  if (sshdStatusTimer) {
-    clearInterval(sshdStatusTimer);
-    sshdStatusTimer = null;
-  }
-}
-
 function loadIMEI() {
     fetchIMEI();
 }
 
 loadIMEI();
-
-startSshdStatusRefresh();

+ 100 - 4
web-ui.service/web/static/js/page1.js

@@ -2,6 +2,7 @@ let cpuChart       = null;
 let memChart       = null;
 let diskChart      = null;
 let sysStatusTimer = null;
+let resizeHandler  = null;
 
 function getSystemInfo(){
   fetch("/api/system/info")
@@ -98,13 +99,89 @@ function gaugeOption(){
   };
 }
 
+function getLoadInfo(){
+  fetch("/api/system/loadAverage")
+    .then(async r => {
+      if (!r.ok) {
+        throw new Error("HTTP " + r.status);
+      }
+
+      return r.json();
+    })
+    .then(data => {
+      document.getElementById("load1m").textContent = data.load1m || "--";
+      document.getElementById("load5m").textContent = data.load5m || "--";
+      document.getElementById("load15m").textContent = data.load15m || "--";
+    })
+    .catch(e => {
+      console.error("network status failed:", e);
+
+      document.getElementById("load1m").textContent = "--";
+      document.getElementById("load5m").textContent = "--";
+      document.getElementById("load15m").textContent = "--";
+    });
+}
+
+function getServiceInfo(){
+  fetch("/api/system/serviceStatus")
+    .then(r => {
+      if (!r.ok) {
+        throw new Error("HTTP " + r.status);
+      }
+
+      return r.json();
+    })
+    .then(data => {
+      document.getElementById("var1").textContent = data.var1 || "--";
+      document.getElementById("var2").textContent = data.var2 || "--";
+      document.getElementById("var3").textContent = data.var3 || "--";
+      document.getElementById("var4").textContent = data.var4 || "--";
+      document.getElementById("var5").textContent = data.var5 || "--";
+      document.getElementById("var6").textContent = data.var6 || "--";
+      document.getElementById("var7").textContent = data.var7 || "--";
+      document.getElementById("var8").textContent = data.var8 || "--";
+      document.getElementById("var11").textContent = data.var11 || "--";
+      document.getElementById("var22").textContent = data.var22 || "--";
+      document.getElementById("var33").textContent = data.var33 || "--";
+      document.getElementById("var44").textContent = data.var44 || "--";
+      document.getElementById("var55").textContent = data.var55 || "--";
+      document.getElementById("var66").textContent = data.var66 || "--";
+      document.getElementById("var77").textContent = data.var77 || "--";
+      document.getElementById("var88").textContent = data.var88 || "--";
+    })
+    .catch(e => {
+      console.error("getAllServiceStatus status failed:", e);
+
+      document.getElementById("var1").textContent = "--";
+      document.getElementById("var2").textContent = "--";
+      document.getElementById("var3").textContent = "--";
+      document.getElementById("var4").textContent = "--";
+      document.getElementById("var5").textContent = "--";
+      document.getElementById("var6").textContent = "--";
+      document.getElementById("var7").textContent = "--";
+      document.getElementById("var8").textContent = "--";
+      document.getElementById("var11").textContent = "--";
+      document.getElementById("var22").textContent = "--";
+      document.getElementById("var33").textContent = "--";
+      document.getElementById("var44").textContent = "--";
+      document.getElementById("var55").textContent = "--";
+      document.getElementById("var66").textContent = "--";
+      document.getElementById("var77").textContent = "--";
+      document.getElementById("var88").textContent = "--";
+    });
+}
+
 function startSysStatusRefresh(){
   if(sysStatusTimer) return;
 
   getSystemInfo();
+  getLoadInfo();
+  getServiceInfo();
 
   sysStatusTimer = setInterval(() => {
     getSystemInfo();
+    getLoadInfo();
+    getServiceInfo();
   }, 3000);
 }
 
@@ -115,6 +192,12 @@ function stopSysStatusRefresh(){
   }
 }
 
+function resizeSysCharts(){
+  cpuChart?.resize();
+  memChart?.resize();
+  diskChart?.resize();
+}
+
 function initPage1(){
   cpuChart=echarts.init(document.getElementById("cpu-chart"));
   memChart=echarts.init(document.getElementById("mem-chart"));
@@ -150,16 +233,29 @@ function initPage1(){
 
   startSysStatusRefresh();
 
+  resizeHandler = resizeSysCharts;
+
+  window.addEventListener(
+    "resize",
+    resizeHandler
+  );
+
   setTimeout(()=>{
-    cpuChart.resize();
-    memChart.resize();
-    diskChart.resize();
-  },500);
+    resizeSysCharts();
+  },100);
 }
 
 function exitPage1(){
   stopSysStatusRefresh();
 
+  if(resizeHandler){
+    window.removeEventListener(
+      "resize",
+      resizeHandler
+    );
+    resizeHandler=null;
+  }
+
   cpuChart?.dispose();
   memChart?.dispose();
   diskChart?.dispose();

+ 0 - 18
web-ui.service/web_handler.go

@@ -83,24 +83,6 @@ func getIMEIHandler(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-func sshdStatusHandler(w http.ResponseWriter, r *http.Request) {
-	if r.Method != http.MethodGet {
-		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
-		return
-	}
-
-	status := noValue
-	cmd := exec.Command("systemctl", "is-active", "yfkj-sshd-mqtt-bridge.service")
-	if out, err := cmd.Output(); err == nil {
-		if strings.TrimSpace(string(out)) == "active" {
-			status = "🟢 YFKJ-SSHD"
-		}
-	}
-
-	w.Header().Set("Content-Type", "application/json")
-	json.NewEncoder(w).Encode(map[string]string{"status": status})
-}
-
 func (ui *WebUI) rootHandler(w http.ResponseWriter, r *http.Request) {
 	path := r.URL.Path
 

+ 10 - 5
web-ui.service/web_route.go

@@ -24,11 +24,6 @@ var routes = []Route{
 	},
 
 	{
-		"/api/sshd/status",
-		sshdStatusHandler,
-	},
-
-	{
 		"/api/service/log",
 		serviceLogHandler,
 	},
@@ -39,6 +34,16 @@ var routes = []Route{
 	},
 
 	{
+		"/api/system/loadAverage",
+		systemLoadAverageHandler,
+	},
+
+	{
+		"/api/system/serviceStatus",
+		serviceStatusHandler,
+	},
+
+	{
 		"/api/network/interfaces",
 		netInterfaces,
 	},