console: 项目导航移到左侧栏,工作台不再承担项目模块
左侧栏 ProjectNav:项目完整列表(名 + 短 id + 我的角色, 选中高亮,点击切换)+ 创建项目(名/GitHub 仓库/repo_url) + 选中项目成员(邀请/改角色/新增移除);工作台删除 sec-projects 一节与任务列表里的项目下拉框,侧栏为唯一 项目选择器,自动选第一个项目逻辑不变。 薄模块补齐(均为已核实后端路由):成员移除 DELETE、 自动化详情(GET 单条 + 产出)与编辑 PATCH、分诊条目点进 任务/自动化详情、Workers 搜索与在线筛选、管理区设置配额 POST。主线新功能(Todos、Browser、taskMeta 等)原样保留, 未做任何回退。console 标记单测本地 53 项通过。
This commit is contained in:
1 parent
d6369154c2
commit
08484302ac
16 files changed
+293
-100
No files matched your search
@@ -1,13 +1,15 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { api } from "../api/client";
|
||||
import { paths } from "../api/paths";
|
||||
import type { Automation, Triage } from "../api/types";
|
||||
import type { Automation, AutomationDetail, Triage } from "../api/types";
|
||||
|
||||
// Project-scoped tools shown in the centre for their own views:
|
||||
// automations (create/list/cancel) and the triage inbox (4 groups).
|
||||
export function useProjectTools(getProjectId: () => string) {
|
||||
const [automations, setAutomations] = useState<Automation[]>([]);
|
||||
const [autoMsg, setAutoMsg] = useState("");
|
||||
const [autoDetail, setAutoDetail] = useState<AutomationDetail | null>(null);
|
||||
const [autoDetailMsg, setAutoDetailMsg] = useState("");
|
||||
const [triage, setTriage] = useState<Triage | null>(null);
|
||||
const [triageError, setTriageError] = useState("");
|
||||
|
||||
@@ -66,10 +68,26 @@ export function useProjectTools(getProjectId: () => string) {
|
||||
const pid = getProjectId();
|
||||
if (!pid) return;
|
||||
void api(paths.projectAutomationCancel(pid, id), "POST", {})
|
||||
.then(() => { setAutoMsg("自动化已取消"); void refreshAutomations(pid); })
|
||||
.then(() => { setAutoMsg("自动化已取消"); setAutoDetail((prev) => (prev && prev.id === id ? null : prev)); void refreshAutomations(pid); })
|
||||
.catch((e: any) => setAutoMsg("取消失败:" + e.message));
|
||||
}, [getProjectId, refreshAutomations]);
|
||||
|
||||
// GET /projects/{pid}/automations/{aid}: full definition + recent
|
||||
// runs (+ runs_note, heartbeat_binding). Verified against origin/main
|
||||
// cloud/server.py _automation_get / cloud/automations.py get_automation.
|
||||
const loadAutomationDetail = useCallback(async (id: string) => {
|
||||
const pid = getProjectId();
|
||||
if (!pid) { setAutoDetailMsg("先选项目"); return; }
|
||||
try {
|
||||
const d = await api<AutomationDetail>(paths.projectAutomation(pid, id));
|
||||
setAutoDetail(d);
|
||||
setAutoDetailMsg("");
|
||||
} catch (e: any) { setAutoDetailMsg("详情加载失败:" + e.message); }
|
||||
}, [getProjectId]);
|
||||
|
||||
const closeAutomationDetail = useCallback(() => { setAutoDetail(null); setAutoDetailMsg(""); }, []);
|
||||
|
||||
|
||||
const refreshTriage = useCallback(async (pid?: string) => {
|
||||
const id = pid !== undefined ? pid : getProjectId();
|
||||
if (!id) { setTriage(null); return; }
|
||||
@@ -80,5 +98,5 @@ export function useProjectTools(getProjectId: () => string) {
|
||||
} catch (e: any) { setTriageError("分诊加载失败:" + e.message); }
|
||||
}, [getProjectId]);
|
||||
|
||||
return { automations, autoMsg, triage, triageError, refreshAutomations, createAutomation, updateAutomation, cancelAutomation, refreshTriage };
|
||||
return { automations, autoMsg, autoDetail, autoDetailMsg, triage, triageError, refreshAutomations, createAutomation, updateAutomation, cancelAutomation, loadAutomationDetail, closeAutomationDetail, refreshTriage };
|
||||
}
|
||||
Reference in new issue
Block a user