保持一页式控制台排版与全部功能、API 不变,只换视觉: 深色顶栏 #24292f、Primer 浅色配色(边框 #d0d7de、链接蓝 #0969da、绿主按钮 #2da44e)、6px 圆角方框、系统字体与 等宽 ID/trace;任务列表改 issues 式(状态圆点 + 标题 + 灰色元信息);对话改评论时间线(白框 + 头部 + 正文, 竖线连接),灰/蓝气泡已移除;自动选项目与继续消息历史 不受影响。console 标记单测本地 53 项通过。
127 lines
4.9 KiB
TypeScript
127 lines
4.9 KiB
TypeScript
import { ConsoleContext, useConsole } from "./context";
|
|
import { useConsoleStore } from "./hooks/useConsoleStore";
|
|
import { useAutoRefresh, useIntervalMs } from "./hooks/useAutoRefresh";
|
|
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";
|
|
|
|
// Layout only: ONE scrollable console page in GitHub Primer style —
|
|
// a dark header bar (name + real connection status + health + quota
|
|
// + refresh stamp + anchor nav as header links), a data-cards row,
|
|
// then every module as a bordered section in order. No icon-rail
|
|
// column, no left list column, no right panel column, no view
|
|
// switching. Detail/context panels sit under their own sections
|
|
// below (detail under 对话, members under 项目, and so on).
|
|
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();
|
|
useAutoRefresh((selectFocused) => store.refreshAll(selectFocused), 10000);
|
|
useIntervalMs(() => store.refreshSlow(), 60000);
|
|
const scrollToDispatch = () => {
|
|
document.getElementById("sec-dispatch")?.scrollIntoView({ behavior: "smooth" });
|
|
};
|
|
|
|
return (
|
|
<ConsoleContext.Provider value={store}>
|
|
<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>
|
|
<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>
|
|
);
|
|
}
|