feat: restart button in settings via atexit+execv

This commit is contained in:
2026-07-26 18:32:16 +08:00
parent 2daa4d48f1
commit b44241c666
2 changed files with 24 additions and 4 deletions
+9 -3
View File
@@ -389,9 +389,6 @@ async def api_import_backup(file: UploadFile = File(...)):
from config.settings import reload_config
reload_config()
from models.dashboard import dashboard_manager
import importlib
importlib.reload(__import__('models.dashboard', fromlist=['dashboard_manager']))
from server.game_manager import game_plugin_manager
game_plugin_manager.reload()
@@ -400,6 +397,15 @@ async def api_import_backup(file: UploadFile = File(...)):
return {"ok": False, "message": str(e)}
# ---- Restart ----
@router.post("/restart")
async def api_restart():
import os, sys, atexit
logger.info("Restart requested via API")
atexit.register(lambda: os.execv(sys.executable, [sys.executable] + sys.argv))
sys.exit(0)
# ---- Data Forwarding ----
@router.get("/forward")
async def api_list_forward_targets():
+15 -1
View File
@@ -111,6 +111,18 @@ const PageSettings = {
}; input.click();
});
document.getElementById('btn-restart-server')?.addEventListener('click', async () => {
if (!confirm('确定重启 TurboSu 服务?')) return;
try {
await fetch('/api/restart', { method: 'POST' });
Toast.show('服务正在重启,3秒后自动刷新...', 'info');
setTimeout(() => location.reload(), 3000);
} catch (e) {
Toast.show('重启请求已发送,请手动刷新', 'info');
setTimeout(() => location.reload(), 3000);
}
});
document.getElementById('settings-test-mode')?.addEventListener('change', async (e) => {
const on = e.target.checked;
await API.updateConfig({ ui_test_mode: on });
@@ -184,7 +196,9 @@ const PageSettings = {
'<div class="settings-section"><h3>游戏插件管理</h3><div style="display:flex;gap:8px;margin-bottom:16px"><button id="btn-import-plugin" class="btn btn-secondary btn-sm">导入 .tsp</button><button id="btn-reload-plugins" class="btn btn-secondary btn-sm">重新加载</button></div><div id="settings-game-list">' + this._gamePluginListHtml(games) + '</div></div>' +
'<div class="settings-section"><h3>数据备份</h3><div class="settings-row"><div><div class="settings-label">导出全量备份</div><div class="settings-desc">打包仪表盘+场景+配置为 .tsb</div></div><div class="settings-control"><button id="btn-export-backup" class="btn btn-secondary btn-sm">下载 .tsb</button></div></div><div class="settings-row"><div><div class="settings-label">恢复备份</div><div class="settings-desc">从 .tsb 文件恢复,需重启</div></div><div class="settings-control"><button id="btn-import-backup" class="btn btn-secondary btn-sm">导入 .tsb</button></div></div></div>' +
'<div class="settings-section"><h3>数据备份</h3><div class="settings-row"><div><div class="settings-label">导出全量备份</div><div class="settings-desc">打包仪表盘+场景+配置为 .tsb</div></div><div class="settings-control"><button id="btn-export-backup" class="btn btn-secondary btn-sm">下载 .tsb</button></div></div><div class="settings-row"><div><div class="settings-label">恢复备份</div><div class="settings-desc">从 .tsb 文件恢复</div></div><div class="settings-control"><button id="btn-import-backup" class="btn btn-secondary btn-sm">导入 .tsb</button></div></div></div>' +
'<div class="settings-section"><h3>系统</h3><div class="settings-row"><div><div class="settings-label">重启 TurboSu</div><div class="settings-desc">重新加载所有代码和配置</div></div><div class="settings-control"><button id="btn-restart-server" class="btn btn-danger btn-sm">重启服务</button></div></div></div>' +
'<div class="settings-section"><h3>开发工具</h3><div class="settings-row"><div><div class="settings-label">UI 测试模式</div><div class="settings-desc">本地随机模拟遥测数据</div></div><div class="settings-control"><label class="switch-label"><input type="checkbox" id="settings-test-mode" ' + (cfg.ui_test_mode?'checked':'') + '><span class="switch-track"></span></label></div></div></div>' +