From: CodeBuddy Date: Wed, 30 Sep 2026 05:15:33 +0000 (+0800) Subject: feat: 拆分 AIDC 轻量版为独立开关(aidc-lite),与完整版门禁互不干扰 X-Git-Url: http://acesimba.cloud/gitweb/?a=commitdiff_plain;p=StationAIDemo.git feat: 拆分 AIDC 轻量版为独立开关(aidc-lite),与完整版门禁互不干扰 --- diff --git a/backend/main.py b/backend/main.py index 5150a3a..c59fb54 100644 --- a/backend/main.py +++ b/backend/main.py @@ -3,6 +3,7 @@ import re import json import base64 import asyncio +import subprocess from datetime import datetime, timedelta from typing import Any, Optional from urllib.parse import unquote, urlparse, urlunparse @@ -36,6 +37,51 @@ TASK_INDEX_HTML = os.path.join( os.path.dirname(os.path.dirname(__file__)), "frontend", "dist", "index.html" ) +# 每个任务关联的 systemd 单元:开启即启动,关闭即停止以释放资源。 +# aidemo 为控制面(承载 /list 与门禁),其后端 :8000 不可停止,故为空列表。 +TASK_SERVICES = { + "aidemo": [], + "stationbuilder": [ + "stationbuilder-prod.service", + "stationbuilder-db.service", + "stationbuilder-sidecar.service", + ], + "stationbuilder-vue": [ + "stationbuilder-vue.service", + "stationbuilder-vue-db.service", + "stationbuilder-vue-sidecar.service", + ], + # AIDC 为纯前端静态站点(无后端进程),由其专属 nginx 路由(静态托管 /home/AIDC/dist) + # 配合门禁(auth_request)控制访问;关闭即门禁拦截、不提供服务,无需 systemd 进程启停。 + # aidc-lite 为轻量版,独立开关,同样无后端进程。 + "aidc": [], + "aidc-lite": [], +} + + +def control_services(task_id: str, action: str) -> dict: + """对任务关联的 systemd 单元执行 start/stop。返回 {unit: 状态}。 + + action 为 'start' 或 'stop'。单元不存在或操作失败会在结果中以 err: 前缀标注, + 不会抛出,避免影响任务开关本身的持久化。 + """ + units = TASK_SERVICES.get(task_id, []) + result = {} + for unit in units: + try: + proc = subprocess.run( + ["systemctl", action, unit], + capture_output=True, + text=True, + timeout=30, + ) + result[unit] = ( + "ok" if proc.returncode == 0 else f"err:{proc.stderr.strip()[:200]}" + ) + except Exception as e: + result[unit] = f"err:{str(e)[:200]}" + return result + def load_tasks() -> list[dict]: if not os.path.exists(TASKS_FILE): @@ -1043,7 +1089,8 @@ async def open_task(task_id: str, request: Request): return JSONResponse(status_code=404, content={"ok": False, "message": "任务不存在"}) task["open"] = True save_tasks(tasks) - return {"ok": True, "task": task} + services = control_services(task_id, "start") + return {"ok": True, "task": task, "services": services} @app.post("/api/tasks/{task_id}/close") @@ -1056,7 +1103,8 @@ async def close_task(task_id: str, request: Request): return JSONResponse(status_code=404, content={"ok": False, "message": "任务不存在"}) task["open"] = False save_tasks(tasks) - return {"ok": True, "task": task} + services = control_services(task_id, "stop") + return {"ok": True, "task": task, "services": services} @app.get("/t/{task_id}") diff --git a/backend/tasks.json b/backend/tasks.json index b7d660a..8b5337a 100644 --- a/backend/tasks.json +++ b/backend/tasks.json @@ -2,11 +2,26 @@ { "id": "aidemo", "name": "AIDemo", - "open": true + "open": false }, { "id": "stationbuilder", "name": "StationBuilder", + "open": false + }, + { + "id": "stationbuilder-vue", + "name": "StationBuilder (Vue 移植版)", + "open": false + }, + { + "id": "aidc", + "name": "AIDC 智慧运维系统", + "open": true + }, + { + "id": "aidc-lite", + "name": "AIDC 智慧运维系统(轻量版)", "open": true } ] \ No newline at end of file diff --git a/frontend/src/List.tsx b/frontend/src/List.tsx index 4fa25b9..013225b 100644 --- a/frontend/src/List.tsx +++ b/frontend/src/List.tsx @@ -144,7 +144,10 @@ export default function TaskList() {