console: GitHub 风格(Primer)

保持一页式控制台排版与全部功能、API 不变,只换视觉:
深色顶栏 #24292f、Primer 浅色配色(边框 #d0d7de、链接蓝
#0969da、绿主按钮 #2da44e)、6px 圆角方框、系统字体与
等宽 ID/trace;任务列表改 issues 式(状态圆点 + 标题 +
灰色元信息);对话改评论时间线(白框 + 头部 + 正文,
竖线连接),灰/蓝气泡已移除;自动选项目与继续消息历史
不受影响。console 标记单测本地 53 项通过。
This commit is contained in:
host committed 2026-10-29 10:13:30 +08:00
1 parent bbe02efc14
commit e90c885290
6 files changed
+171 -158

No files matched your search

@@ -1,14 +1,13 @@
import { useConsole } from "../context";
import { shortId } from "../api/client";
// Left list panel, Muse screenshot style: rounded search on top, a
// 主要聊天 section header with a + button, then the task list. The
// search input IS the existing task search (id/prompt); the status and
// executor filters are kept as a compact row below it — the screenshot
// has no filters, but dropping them would cut functionality, so they
// stay, just compact. List rows show the prompt truncated on one line
// with a status dot, short id, status and executor below it; the
// selected row is highlighted grey, as in the screenshot.
// GitHub issues-style task list: search on top, the project selector
// (the auto-project fix — do not remove it), a 主要聊天 header with a
// + button, then hairline rows with a Primer status dot at the left,
// a 14px title and a 12px muted meta line. The search input IS the
// existing task search (id/prompt); status and executor filters stay
// as a compact row below it. The selected row gets the light
// blue-grey background (#ddf4ff), not a bubble.
export default function TaskListSection({ onNew }: { onNew: () => void }) {
const ctx = useConsole();
return (
@@ -46,18 +45,18 @@ export default function TaskListSection({ onNew }: { onNew: () => void }) {
: !ctx.projectId ? <div className="muted">先选项目</div>
: ctx.filteredTasks.length === 0 ? <div className="muted">{ctx.tasks.length ? "没有符合筛选条件的任务" : "该项目暂无任务"}</div>
: (
<ul className="muse-list">
<ul className="issue-list">
{ctx.filteredTasks.slice().reverse().map((t) => (
<li key={t.id} className={"muse-item" + (ctx.currentTask?.id === t.id ? " selected" : "")} onClick={() => ctx.showDetail(t.id)}>
<div className="muse-item-title">
{t.plan ? "[计划] " : ""}{t.forked_from ? "[分支] " : ""}{t.coordinator_parts ? "[协调] " : ""}{t.parent_task_id ? "[协调子任务] " : ""}{String(t.prompt || shortId(t.id)).slice(0, 60)}
</div>
<div className="muse-item-sub">
<span className={"task-dot st-" + t.status} />
<span>{shortId(t.id)}</span>
<span className={"st-" + t.status}>{t.status}</span>
<span>{t.executor || ""}</span>
</div>
<li key={t.id} className={"issue-item" + (ctx.currentTask?.id === t.id ? " selected" : "")} onClick={() => ctx.showDetail(t.id)}>
<span className={"issue-state st-" + t.status} aria-hidden="true" />
<span>
<div className="issue-title">
{t.plan ? "[计划] " : ""}{t.forked_from ? "[分支] " : ""}{t.coordinator_parts ? "[协调] " : ""}{t.parent_task_id ? "[协调子任务] " : ""}{String(t.prompt || shortId(t.id)).slice(0, 60)}
</div>
<div className="issue-meta">
{shortId(t.id)} · <span className={"st-" + t.status}>{t.status}</span> · {t.executor || ""}{t.updated_at ? " · " + new Date(t.updated_at * 1000).toLocaleString() : ""}
</div>
</span>
</li>
))}
</ul>
@@ -31,7 +31,7 @@ export default function TracePanel() {
<div className="chat-column">
<ChatList messages={messages} empty="(暂无链路条目)" />
</div>
<div className="muted">对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具气泡,计划/思考/子代理开始结束是居中状态提示。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。</div>
<div className="muted">对话时间线:首条是本任务 prompt(用户);助手回复来自 message 条目,命令/文件/工具/调用是工具评论框,计划/思考/子代理开始结束是时间线上的状态文字。流式进行中时新条目实时追加;你在底部时自动跟随,往上翻时暂停跟随,点“回到最新”恢复。</div>
</>
);
}