console: 一页式控制台排版 + 数据卡片
保持 Muse 风格(白底、细线、灰/浅蓝气泡),不再四栏切视图: 顶栏(连接/健康/配额/刷新 + 锚点导航)+ 6 张数据卡片 (健康、配额、任务、Workers、项目、项目数据,均取自已有 store 数据,未加载不以 0 充数)+ 所有模块按顺序铺在一页 (派发、任务列表、对话+详情、项目、环境、Workers、技能、 自动化、分诊、管理区、API Key)。图标栏与右侧栏删除, 内容分别移到顶栏与各自模块下;今天列表与任务列表重复, 不再单独保留;对话为空时不再重复渲染派发表单。 含自动选第一个项目修复(主要聊天不再空)与继续消息 历史,console 标记单测本地 53 项通过。
This commit is contained in:
1 parent
a13762cfbe
commit
8b455c6554
9 files changed
+263
-272
No files matched your search
+108
-50
@@ -1,72 +1,130 @@
|
||||
import { useState } from "react";
|
||||
import { ConsoleContext } from "./context";
|
||||
import { ConsoleContext, useConsole } from "./context";
|
||||
import { useConsoleStore } from "./hooks/useConsoleStore";
|
||||
import { useAutoRefresh, useIntervalMs } from "./hooks/useAutoRefresh";
|
||||
import IconRail, { type View } from "./components/IconRail";
|
||||
import DataCards from "./sections/DataCards";
|
||||
import DispatchSection from "./sections/DispatchSection";
|
||||
import TaskListSection from "./sections/TaskListSection";
|
||||
import ConversationSection from "./sections/ConversationSection";
|
||||
import TaskDetailPanel from "./sections/TaskDetailPanel";
|
||||
import ApiKeySection from "./sections/ApiKeySection";
|
||||
import AdminSection from "./sections/AdminSection";
|
||||
import ProjectsSection from "./sections/ProjectsSection";
|
||||
import MembersPanel from "./sections/MembersPanel";
|
||||
import EnvSection from "./sections/EnvSection";
|
||||
import EnvContextPanel from "./sections/EnvContextPanel";
|
||||
import WorkersSection from "./sections/WorkersSection";
|
||||
import HealthPanel from "./sections/HealthPanel";
|
||||
import SkillsSection from "./sections/SkillsSection";
|
||||
import SkillsToolsPanel from "./sections/SkillsToolsPanel";
|
||||
import AutomationsSection from "./sections/AutomationsSection";
|
||||
import TriageSection from "./sections/TriageSection";
|
||||
import TaskListSection from "./sections/TaskListSection";
|
||||
import ConversationSection from "./sections/ConversationSection";
|
||||
import RightPanel from "./sections/RightPanel";
|
||||
|
||||
// Layout only, Muse web/desktop style: no big header bar.
|
||||
// Icon rail (56px) + left list (260px) + centre conversation (elastic,
|
||||
// content centred) + right panel (300px, profile/today/detail). The
|
||||
// centre top bar is minimal: a back arrow (back to the task view) on
|
||||
// the left, and, only when the right panel is closed, a button to
|
||||
// reopen it — the right panel's own X closes it. Selecting a task in
|
||||
// the left list switches the centre conversation and the right detail
|
||||
// to that task together; selecting a module switches the centre to
|
||||
// that module and the right detail to its context.
|
||||
// Layout only: ONE scrollable console page, Muse web/desktop tokens
|
||||
// (white, hairlines, grey/blue bubbles) but console ordering — no
|
||||
// icon-rail column, no left list column, no right panel column, no
|
||||
// view switching. Everything is on the page: a slim sticky top bar
|
||||
// (name + real connection status + health + quota + refresh stamp +
|
||||
// anchor nav), a data-cards row, then every module as a section in
|
||||
// order. The old right panel's content moved here: its profile/status
|
||||
// line is the top bar, its 今天 list is redundant with the full task
|
||||
// list section, and its detail/context panels sit under their own
|
||||
// sections below (detail under 对话, members under 项目, and so on).
|
||||
// The old icon rail's module switching is the anchor nav.
|
||||
const NAV: Array<[string, string]> = [
|
||||
["#sec-dispatch", "派发"], ["#sec-tasks", "任务"], ["#sec-conv", "对话"],
|
||||
["#sec-projects", "项目"], ["#sec-env", "环境"], ["#sec-workers", "Workers"],
|
||||
["#sec-skills", "技能"], ["#sec-automations", "自动化"], ["#sec-triage", "分诊"],
|
||||
["#sec-admin", "管理区"], ["#sec-key", "API Key"],
|
||||
];
|
||||
|
||||
function TopBar() {
|
||||
return (
|
||||
<header className="dash-topbar">
|
||||
<div className="dash-topbar-row">
|
||||
<span className="dash-brand">Codex 命令台</span>
|
||||
<TopStatus />
|
||||
<span className="muted dash-hide-sm"><TopHealth /></span>
|
||||
<span className="muted dash-hide-sm"><TopQuota /></span>
|
||||
<span className="muted dash-stamp"><TopStamp /></span>
|
||||
</div>
|
||||
<nav className="dash-nav" aria-label="页面导航">
|
||||
{NAV.map(([href, label]) => <a key={href} href={href}>{label}</a>)}
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
// Tiny readers so the top bar re-renders from the store.
|
||||
function TopStatus() {
|
||||
const ctx = useConsole();
|
||||
return <span className={ctx.keySaved ? "dash-status ok" : "dash-status off"}>{ctx.keySaved ? "● 已连接" : "○ 未连接"}</span>;
|
||||
}
|
||||
function TopHealth() {
|
||||
return <>{useConsole().healthText}</>;
|
||||
}
|
||||
function TopQuota() {
|
||||
return <>{useConsole().quotaText}</>;
|
||||
}
|
||||
function TopStamp() {
|
||||
return <>自动刷新 · 每 10 秒 · 已刷新 {useConsole().refreshStamp}</>;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const store = useConsoleStore();
|
||||
const [view, setView] = useState<View>("task");
|
||||
const [rightOpen, setRightOpen] = useState(true);
|
||||
useAutoRefresh((selectFocused) => store.refreshAll(selectFocused), 10000);
|
||||
useIntervalMs(() => store.refreshSlow(), 60000);
|
||||
|
||||
const centre = (() => {
|
||||
switch (view) {
|
||||
case "projects": return <ProjectsSection />;
|
||||
case "env": return <EnvSection />;
|
||||
case "workers": return <WorkersSection />;
|
||||
case "skills": return <SkillsSection />;
|
||||
case "automations": return <AutomationsSection />;
|
||||
case "triage": return <TriageSection />;
|
||||
case "admin": return <AdminSection />;
|
||||
case "key": return <ApiKeySection />;
|
||||
default: return <ConversationSection />;
|
||||
}
|
||||
})();
|
||||
const scrollToDispatch = () => {
|
||||
document.getElementById("sec-dispatch")?.scrollIntoView({ behavior: "smooth" });
|
||||
};
|
||||
|
||||
return (
|
||||
<ConsoleContext.Provider value={store}>
|
||||
<div className={"muse-app" + (rightOpen ? "" : " no-right")}>
|
||||
<IconRail view={view} onSelect={setView} />
|
||||
<aside className="list-col">
|
||||
<TaskListSection onNew={() => setView("task")} />
|
||||
</aside>
|
||||
<main className="center-col">
|
||||
<div className="center-topbar">
|
||||
<button type="button" className="icon-btn" aria-label="返回任务" title="返回任务" onClick={() => setView("task")}>←</button>
|
||||
{rightOpen ? <span className="muted">Codex 命令台</span> : (
|
||||
<button type="button" onClick={() => setRightOpen(true)}>显示右侧栏</button>
|
||||
)}
|
||||
<TopBar />
|
||||
<main className="dash-page">
|
||||
<DataCards />
|
||||
<section id="sec-dispatch" className="dash-section">
|
||||
<DispatchSection />
|
||||
</section>
|
||||
<section id="sec-tasks" className="dash-section card">
|
||||
<h2>任务列表</h2>
|
||||
<TaskListSection onNew={scrollToDispatch} />
|
||||
</section>
|
||||
<section id="sec-conv" className="dash-section">
|
||||
<div className="card">
|
||||
<h2>对话</h2>
|
||||
<ConversationSection />
|
||||
</div>
|
||||
<div className="center-inner">{centre}</div>
|
||||
</main>
|
||||
{rightOpen ? (
|
||||
<aside className="right-col">
|
||||
<RightPanel view={view} onSelect={setView} onClose={() => setRightOpen(false)} />
|
||||
</aside>
|
||||
) : null}
|
||||
</div>
|
||||
<TaskDetailPanel />
|
||||
</section>
|
||||
<section id="sec-projects" className="dash-section">
|
||||
<ProjectsSection />
|
||||
<MembersPanel />
|
||||
</section>
|
||||
<section id="sec-env" className="dash-section">
|
||||
<EnvSection />
|
||||
<EnvContextPanel />
|
||||
</section>
|
||||
<section id="sec-workers" className="dash-section">
|
||||
<WorkersSection />
|
||||
<HealthPanel />
|
||||
</section>
|
||||
<section id="sec-skills" className="dash-section">
|
||||
<SkillsSection />
|
||||
<SkillsToolsPanel />
|
||||
</section>
|
||||
<section id="sec-automations" className="dash-section">
|
||||
<AutomationsSection />
|
||||
</section>
|
||||
<section id="sec-triage" className="dash-section">
|
||||
<TriageSection />
|
||||
</section>
|
||||
<section id="sec-admin" className="dash-section">
|
||||
<AdminSection />
|
||||
</section>
|
||||
<section id="sec-key" className="dash-section">
|
||||
<ApiKeySection />
|
||||
</section>
|
||||
</main>
|
||||
</ConsoleContext.Provider>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user