moki 2 viikkoa sitten
vanhempi
sitoutus
25f652907a
5 muutettua tiedostoa jossa 79 lisäystä ja 126 poistoa
  1. 3 0
      .gitignore
  2. 22 8
      internal/web/embed.go
  3. 0 118
      internal/web/index.html
  4. 38 0
      logs
  5. 16 0
      scripts/build.sh

+ 3 - 0
.gitignore

@@ -35,3 +35,6 @@ data/
 
 # Logs
 *.log
+
+# Frontend build artifact
+internal/web/html/

+ 22 - 8
internal/web/embed.go

@@ -1,20 +1,34 @@
 package web
 
 import (
-	_ "embed"
+	"embed"
+	"io/fs"
 	"net/http"
+	"strings"
 )
 
-//go:embed index.html
-var indexHTML string
+//go:embed all:html
+var htmlFS embed.FS
 
 func Handler() http.HandlerFunc {
+	fsys, err := fs.Sub(htmlFS, "html")
+	if err != nil {
+		panic("failed to create sub filesystem: " + err.Error())
+	}
+	fileServer := http.FileServer(http.FS(fsys))
+
 	return func(w http.ResponseWriter, r *http.Request) {
-		if r.URL.Path != "/" {
-			http.NotFound(w, r)
-			return
+		path := r.URL.Path
+
+		if path != "/" {
+			cleanPath := strings.TrimPrefix(path, "/")
+			if _, err := fs.Stat(fsys, cleanPath); err == nil {
+				fileServer.ServeHTTP(w, r)
+				return
+			}
 		}
-		w.Header().Set("Content-Type", "text/html; charset=utf-8")
-		w.Write([]byte(indexHTML))
+
+		r.URL.Path = "/"
+		fileServer.ServeHTTP(w, r)
 	}
 }

+ 0 - 118
internal/web/index.html

@@ -1,118 +0,0 @@
-<!DOCTYPE html>
-<html lang="zh-CN">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>OpenCode Monitor</title>
-    <style>
-        * { margin: 0; padding: 0; box-sizing: border-box; }
-        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 20px; }
-        .container { max-width: 1200px; margin: 0 auto; }
-        h1 { color: #333; margin-bottom: 20px; }
-        .status-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
-        .status-card { padding: 16px 0; }
-        .status-card h2 { color: #666; font-size: 14px; margin-bottom: 8px; }
-        .status-value { font-size: 32px; font-weight: bold; margin-bottom: 8px; }
-        .status-time { color: #999; font-size: 12px; }
-        .status-空闲 { color: #52c41a; }
-        .status-工作中 { color: #ff4d4f; }
-        .status-思考中 { color: #faad14; }
-        .status-运行中 { color: #1890ff; }
-        .status-完成 { color: #52c41a; }
-        .status-错误 { color: #ff4d4f; }
-        .status-重试中 { color: #faad14; }
-        .status-修改中 { color: #722ed1; }
-        .log { margin-top: 20px; }
-        .log h2 { color: #666; font-size: 14px; margin-bottom: 12px; }
-        .log-list { max-height: 300px; overflow-y: auto; }
-        .log-item { padding: 8px 0; border-bottom: 1px solid #f0f0f0; font-size: 14px; }
-        .log-item:last-child { border-bottom: none; }
-        .log-time { color: #999; margin-right: 8px; }
-        .log-port { color: #1890ff; margin-right: 8px; }
-        .connected { color: #52c41a; font-size: 12px; margin-left: 10px; }
-        .disconnected { color: #ff4d4f; font-size: 12px; margin-left: 10px; }
-    </style>
-</head>
-<body>
-    <div class="container">
-        <h1>OpenCode Monitor <span id="connectionStatus" class="disconnected">● 未连接</span></h1>
-        <div class="status-grid" id="statusGrid">
-            <div class="status-card">
-                <h2>当前状态</h2>
-                <div class="status-value" id="currentStatus">等待中...</div>
-                <div class="status-time" id="statusTime"></div>
-            </div>
-        </div>
-        <div class="log">
-            <h2>状态日志</h2>
-            <div class="log-list" id="logList"></div>
-        </div>
-    </div>
-
-    <script>
-        const statusGrid = document.getElementById('statusGrid');
-        const logList = document.getElementById('logList');
-        const currentStatus = document.getElementById('currentStatus');
-        const statusTime = document.getElementById('statusTime');
-        const connectionStatus = document.getElementById('connectionStatus');
-        
-        let ws = null;
-        let reconnectTimer = null;
-
-        function connect() {
-            const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
-            ws = new WebSocket(protocol + '//' + window.location.host + '/ws');
-
-            ws.onopen = function() {
-                connectionStatus.textContent = '● 已连接';
-                connectionStatus.className = 'connected';
-                if (reconnectTimer) {
-                    clearTimeout(reconnectTimer);
-                    reconnectTimer = null;
-                }
-            };
-
-            ws.onmessage = function(event) {
-                try {
-                    const data = JSON.parse(event.data);
-                    updateStatus(data);
-                    addLog(data);
-                } catch (e) {
-                    console.error('解析消息失败:', e);
-                }
-            };
-
-            ws.onclose = function() {
-                connectionStatus.textContent = '● 未连接';
-                connectionStatus.className = 'disconnected';
-                reconnectTimer = setTimeout(connect, 3000);
-            };
-
-            ws.onerror = function() {
-                ws.close();
-            };
-        }
-
-        function updateStatus(data) {
-            currentStatus.textContent = data.status;
-            currentStatus.className = 'status-value status-' + data.status;
-            statusTime.textContent = '端口: ' + data.port + ' | 更新时间: ' + new Date().toLocaleTimeString();
-        }
-
-        function addLog(data) {
-            const item = document.createElement('div');
-            item.className = 'log-item';
-            item.innerHTML = '<span class="log-time">' + new Date().toLocaleTimeString() + '</span>' +
-                           '<span class="log-port">[:' + data.port + ']</span>' +
-                           '<span class="status-' + data.status + '">' + data.status + '</span>';
-            logList.insertBefore(item, logList.firstChild);
-            
-            while (logList.children.length > 50) {
-                logList.removeChild(logList.lastChild);
-            }
-        }
-
-        connect();
-    </script>
-</body>
-</html>

+ 38 - 0
logs

@@ -147,3 +147,41 @@
 [INFO] 2026/06/04 16:41:21 WebSocket 客户端已连接,当前连接数: 1
 [INFO] 2026/06/04 16:41:39 端口 44101 监控已停止,等待重新连接
 [INFO] 2026/06/04 16:41:39 发现新实例端口: 44101,开始监控
+[INFO] 2026/06/04 16:42:48 收到停止信号,正在退出
+[INFO] 2026/06/04 16:57:12 数据库已连接: ./data/config.db
+[INFO] 2026/06/04 16:57:12 MQTT 已连接: tcp://47.92.50.210:9883 (主题: opencode/status)
+[INFO] 2026/06/04 16:57:12 MQTT 已连接: tcp://47.92.50.210:9883
+[INFO] 2026/06/04 16:57:12 API 服务已启动: :8045
+[INFO] 2026/06/04 16:57:12 API 服务器开始监听: :8045
+[INFO] 2026/06/04 16:57:12 WebSocket 客户端已连接,当前连接数: 1
+[INFO] 2026/06/04 16:57:13 WebSocket 客户端已连接,当前连接数: 2
+[INFO] 2026/06/04 16:57:13 开始监控端口: 42597
+[INFO] 2026/06/04 16:57:13 找到 5 个实例: [4096 37081 42597 44101 46077]
+[INFO] 2026/06/04 16:57:13 动态模式启动,每 1 秒扫描新实例
+[INFO] 2026/06/04 16:57:13 开始监控端口: 37081
+[INFO] 2026/06/04 16:57:13 开始监控端口: 4096
+[INFO] 2026/06/04 16:57:13 开始监控端口: 46077
+[INFO] 2026/06/04 16:57:13 开始监控端口: 44101
+[INFO] 2026/06/04 16:57:13 端口 44101 已连接到事件流: http://127.0.0.1:44101/event
+[INFO] 2026/06/04 16:57:13 端口 37081 已连接到事件流: http://127.0.0.1:37081/event
+[INFO] 2026/06/04 16:57:13 端口 46077 已连接到事件流: http://127.0.0.1:46077/event
+[INFO] 2026/06/04 16:57:13 端口 42597 已连接到事件流: http://127.0.0.1:42597/event
+[INFO] 2026/06/04 16:57:13 端口 4096 已连接到事件流: http://127.0.0.1:4096/event
+[INFO] 2026/06/04 16:57:16 WebSocket 客户端已连接,当前连接数: 3
+[INFO] 2026/06/04 16:57:16 WebSocket 客户端已连接,当前连接数: 4
+[INFO] 2026/06/04 16:57:16 WebSocket 客户端已连接,当前连接数: 5
+[INFO] 2026/06/04 16:57:16 WebSocket 客户端已连接,当前连接数: 6
+[INFO] 2026/06/04 16:57:16 WebSocket 客户端已连接,当前连接数: 7
+[INFO] 2026/06/04 16:57:24 WebSocket 客户端已连接,当前连接数: 8
+[WARN] 2026/06/04 16:57:35 端口 44101 连接断开: bufio.Scanner: token too long, 3秒后重连
+[INFO] 2026/06/04 16:57:38 端口 44101 已连接到事件流: http://127.0.0.1:44101/event
+[WARN] 2026/06/04 16:57:42 端口 44101 连接断开: bufio.Scanner: token too long, 3秒后重连
+[INFO] 2026/06/04 16:57:45 端口 44101 已连接到事件流: http://127.0.0.1:44101/event
+[WARN] 2026/06/04 16:58:25 端口 44101 连接断开: bufio.Scanner: token too long, 3秒后重连
+[INFO] 2026/06/04 16:58:28 端口 44101 已连接到事件流: http://127.0.0.1:44101/event
+[WARN] 2026/06/04 16:58:32 端口 44101 连接断开: bufio.Scanner: token too long, 3秒后重连
+[INFO] 2026/06/04 16:58:35 端口 44101 已连接到事件流: http://127.0.0.1:44101/event
+[INFO] 2026/06/04 16:58:45 收到停止信号,正在退出
+[INFO] 2026/06/04 16:58:45 端口 42597 监控已停止,等待重新连接
+[INFO] 2026/06/04 16:58:45 端口 44101 监控已停止,等待重新连接
+[INFO] 2026/06/04 16:58:45 端口 4096 监控已停止,等待重新连接

+ 16 - 0
scripts/build.sh

@@ -1,5 +1,21 @@
 #!/bin/bash
 
+set -e
+
+# 构建前端
+WEB_DIR="/home/moki/Project/ai-status-light-web"
+HTML_DIR="/home/moki/GolandProjects/AI-Status-Light/internal/web/html"
+
+if [ -d "$WEB_DIR" ]; then
+    echo "Building frontend..."
+    cd "$WEB_DIR" && npm run build
+    rm -rf "$HTML_DIR"
+    cp -r dist "$HTML_DIR"
+    echo "Frontend built and copied."
+fi
+
+cd /home/moki/GolandProjects/AI-Status-Light
+
 BINARY_NAME="opencode-monitor"
 VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")