Merge branch 'dev'

This commit is contained in:
qinglong
2026-06-14 19:52:16 +08:00
7 changed files with 35 additions and 9 deletions
+14
View File
@@ -4,9 +4,23 @@
import logging import logging
import asyncio import asyncio
import sys import sys
import os as _os
import signal import signal
import time import time
import argparse import argparse
# 确保项目根目录在 sys.path 中 (嵌入式 CPython / PyPy 需要)
_sys_path_root = _os.path.dirname(_os.path.abspath(__file__))
if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
# Windows 控制台强制 UTF-8 (避免 GBK 编解码 emoji 报错)
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except Exception:
pass
from services.project_engine import ProjectEngine from services.project_engine import ProjectEngine
from services.pyenv_manager import PyEnvManager from services.pyenv_manager import PyEnvManager
from services.proxy_service import ProxyService from services.proxy_service import ProxyService
+1 -1
View File
@@ -295,12 +295,12 @@
'<div class="node-url">'+esc(n.url||'')+'</div>'+ '<div class="node-url">'+esc(n.url||'')+'</div>'+
(n.notes ? '<div class="node-notes">📝 '+esc(n.notes)+'</div>' : '')+ (n.notes ? '<div class="node-notes">📝 '+esc(n.notes)+'</div>' : '')+
'<div class="node-latency" style="font-size:.7rem;color:var(--text-dim);margin-top:4px">⏱ —</div>'+ '<div class="node-latency" style="font-size:.7rem;color:var(--text-dim);margin-top:4px">⏱ —</div>'+
'<div class="col-info" style="font-size:.65rem;color:var(--text-dim);margin-top:2px"></div>'+
'</div>'+ '</div>'+
'<div class="col-right-stack">'+ '<div class="col-right-stack">'+
'<div class="mtr" id="mtr-'+id+'-cpu"><div class="mtr-data"><span class="rlabel">CPU</span> <span class="rval cpu-val">0%</span></div><canvas id="'+id+'-cpu" height="60"></canvas></div>'+ '<div class="mtr" id="mtr-'+id+'-cpu"><div class="mtr-data"><span class="rlabel">CPU</span> <span class="rval cpu-val">0%</span></div><canvas id="'+id+'-cpu" height="60"></canvas></div>'+
'<div class="mtr" id="mtr-'+id+'-mem"><div class="mtr-data"><span class="rlabel">MEM</span> <span class="rval mem-val">0%</span> <span class="mem-row-detail" style="font-size:.65rem;color:var(--text-dim)"></span></div><canvas id="'+id+'-mem" height="60"></canvas></div>'+ '<div class="mtr" id="mtr-'+id+'-mem"><div class="mtr-data"><span class="rlabel">MEM</span> <span class="rval mem-val">0%</span> <span class="mem-row-detail" style="font-size:.65rem;color:var(--text-dim)"></span></div><canvas id="'+id+'-mem" height="60"></canvas></div>'+
'<div class="mtr" id="mtr-'+id+'-net"><div class="mtr-data"><span class="rlabel">NET</span> <span class="rval net-down" style="font-size:.85rem">0</span> <span class="rval net-up" style="font-size:.85rem">0</span></div><canvas id="'+id+'-net" height="60"></canvas></div>'+ '<div class="mtr" id="mtr-'+id+'-net"><div class="mtr-data"><span class="rlabel">NET</span> <span class="rval net-down" style="font-size:.85rem">0</span> <span class="rval net-up" style="font-size:.85rem">0</span></div><canvas id="'+id+'-net" height="60"></canvas></div>'+
'<div class="col-info" style="text-align:right;font-size:.7rem;color:var(--text-dim);margin-top:4px"></div>'+
'</div>'+ '</div>'+
'<div class="col-disk"><div class="disk-list"></div></div>'+ '<div class="col-disk"><div class="disk-list"></div></div>'+
'<div class="col-extra">'+ '<div class="col-extra">'+
+4 -2
View File
@@ -89,7 +89,8 @@ class LogService:
runtime_handler = logging.handlers.RotatingFileHandler( runtime_handler = logging.handlers.RotatingFileHandler(
self.log_dir / "runtime" / runtime_log_file, self.log_dir / "runtime" / runtime_log_file,
maxBytes=self._parse_size(self.config['logging'].get('max_file_size', '10MB')), maxBytes=self._parse_size(self.config['logging'].get('max_file_size', '10MB')),
backupCount=self.config['logging'].get('max_log_files', 3) backupCount=self.config['logging'].get('max_log_files', 3),
encoding='utf-8'
) )
runtime_handler.setLevel(getattr(logging, self.config['logging']['level'], logging.INFO)) runtime_handler.setLevel(getattr(logging, self.config['logging']['level'], logging.INFO))
runtime_handler.setFormatter(file_formatter) runtime_handler.setFormatter(file_formatter)
@@ -101,7 +102,8 @@ class LogService:
debug_handler = logging.handlers.RotatingFileHandler( debug_handler = logging.handlers.RotatingFileHandler(
self.log_dir / "debug" / debug_log_file, self.log_dir / "debug" / debug_log_file,
maxBytes=self._parse_size(self.config['logging'].get('max_file_size', '10MB')), maxBytes=self._parse_size(self.config['logging'].get('max_file_size', '10MB')),
backupCount=self.config['logging'].get('max_log_files', 3) backupCount=self.config['logging'].get('max_log_files', 3),
encoding='utf-8'
) )
debug_handler.setLevel(logging.DEBUG) debug_handler.setLevel(logging.DEBUG)
debug_handler.setFormatter(file_formatter) debug_handler.setFormatter(file_formatter)
+3 -2
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""SenSu PyEnvManager — Python 版本管理 + venv + 依赖安装""" """SenSu PyEnvManager — Python 版本管理 + venv + 依赖安装"""
import os, sys, subprocess, logging, venv, shutil import os, sys, subprocess, logging, shutil
from pathlib import Path from pathlib import Path
from typing import Optional, List from typing import Optional, List
@@ -76,7 +76,8 @@ class PyEnvManager:
logger.info(f"创建 venv: {venv_path} (Python {python_version or 'default'})") logger.info(f"创建 venv: {venv_path} (Python {python_version or 'default'})")
try: try:
venv.create(str(venv_path), with_pip=True, clear=True) import venv as _venv
_venv.create(str(venv_path), with_pip=True, clear=True)
# Install/upgrade pip # Install/upgrade pip
pip = str(venv_path / "bin" / "pip") pip = str(venv_path / "bin" / "pip")
subprocess.run([pip, "install", "--upgrade", "pip"], capture_output=True, timeout=60) subprocess.run([pip, "install", "--upgrade", "pip"], capture_output=True, timeout=60)
+9 -2
View File
@@ -71,9 +71,13 @@ if exist "config\framework\base_config.yaml" (
echo. echo.
if %FAIL% gtr 0 ( if %FAIL% gtr 0 (
echo [WARN] %FAIL% 项缺失,自动安装... echo [WARN] %FAIL% 项缺失,自动安装...
"%PYTHON%" -m pip install -r requirements.txt "%PYTHON%" -m pip install -r requirements.txt --no-warn-script-location --root-user-action=ignore 2>&1
if %errorlevel% neq 0 ( if %errorlevel% neq 0 (
echo [FAIL] 安装失败,请手动执行: .venv\Scripts\pip install -r requirements.txt if %NO_VENV% equ 1 (
echo [FAIL] 安装失败,请手动执行: pip install -r requirements.txt
) else (
echo [FAIL] 安装失败,请手动执行: .venv\Scripts\pip install -r requirements.txt
)
pause pause
exit /b 1 exit /b 1
) )
@@ -86,6 +90,9 @@ echo 🚀 启动 SenSu (无头模式)...
echo Web 面板: http://0.0.0.0:4200/SenSu echo Web 面板: http://0.0.0.0:4200/SenSu
echo. echo.
:: 确保项目根目录在 Python 搜索路径中 (嵌入式 CPython 需要)
set PYTHONPATH=%~dp0;%PYTHONPATH%
"%PYTHON%" main.py --headless "%PYTHON%" main.py --headless
pause pause
+2 -1
View File
@@ -50,7 +50,8 @@ window.DashboardModule = {
} }
var base = window.location.pathname.split("/").slice(0, 2).join("/"); var base = window.location.pathname.split("/").slice(0, 2).join("/");
var ws = new WebSocket("ws://" + location.host + base + "/api/system/ws"); var proto = location.protocol === 'https:' ? 'wss://' : 'ws://';
var ws = new WebSocket(proto + location.host + base + "/api/system/ws");
self.ws = ws; self.ws = ws;
ws.onopen = function() { ws.onopen = function() {
+2 -1
View File
@@ -25,7 +25,8 @@ window.LogsModule = {
} }
var base = window.location.pathname.split("/").slice(0, 2).join("/"); var base = window.location.pathname.split("/").slice(0, 2).join("/");
var ws = new WebSocket("ws://" + location.host + base + "/api/logs/ws"); var proto = location.protocol === 'https:' ? 'wss://' : 'ws://';
var ws = new WebSocket(proto + location.host + base + "/api/logs/ws");
self.ws = ws; self.ws = ws;
ws.onopen = function() { ws.onopen = function() {