feat(ux): T4-a 全局 AI 工具条 — 项目页顶部常驻写本章/审稿/大纲/设定库/工具箱
新 lib/nav/ai-tools.ts (aiToolItems) + components/AiToolbar.tsx 服务端组件;AppShell 顶栏下渲染(仅项目页),用 --chrome CSS 变量统一 chrome 高度,6 个固定高度页改用 calc(100vh-var(--chrome,4rem)) 适配。TDD: ai-tools 测。前端门禁绿: lint/tsc/vitest/build。
This commit is contained in:
28
apps/web/lib/nav/ai-tools.test.ts
Normal file
28
apps/web/lib/nav/ai-tools.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { aiToolItems } from "./ai-tools";
|
||||
|
||||
describe("aiToolItems", () => {
|
||||
it("returns 5 items", () => {
|
||||
expect(aiToolItems("p1")).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("leads with 写本章 (primary, key write)", () => {
|
||||
const [first] = aiToolItems("p1");
|
||||
expect(first.label).toBe("写本章");
|
||||
expect(first.primary).toBe(true);
|
||||
expect(first.key).toBe("write");
|
||||
});
|
||||
|
||||
it("scopes every href under the project path", () => {
|
||||
for (const item of aiToolItems("abc")) {
|
||||
expect(item.href.startsWith("/projects/abc/")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("maps 审稿 to the review page and key", () => {
|
||||
const review = aiToolItems("p1").find((item) => item.label === "审稿");
|
||||
expect(review?.href).toBe("/projects/p1/review");
|
||||
expect(review?.key).toBe("review");
|
||||
});
|
||||
});
|
||||
29
apps/web/lib/nav/ai-tools.ts
Normal file
29
apps/web/lib/nav/ai-tools.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// T4-a · 顶部 AI 工具条数据(纯逻辑,UX §3/§5)。
|
||||
// 把高频 AI 动作(写本章/审稿/大纲/设定库/工具箱)做成常驻一排,根治「命令面板太隐蔽」。
|
||||
// 只露已实现能力;新生成器(创作工具箱 B 组)落地后并入工具箱入口。
|
||||
// 组件只渲染;条目与激活键集中在此,复用 ActiveNav 高亮规则。
|
||||
|
||||
import type { ActiveNav } from "./items";
|
||||
|
||||
export interface AiToolItem {
|
||||
href: string;
|
||||
label: string;
|
||||
// 行首字形(纸感,非语义;aria-hidden 渲染)。
|
||||
glyph: string;
|
||||
// 高亮键(与 AppShell activeNav 比对)。
|
||||
key: ActiveNav;
|
||||
// 主动作(写本章)朱砂强调,其余次级。
|
||||
primary?: boolean;
|
||||
}
|
||||
|
||||
// 项目内页 AI 工具条条目(按已实现能力露出)。
|
||||
export function aiToolItems(projectId: string): AiToolItem[] {
|
||||
const base = `/projects/${projectId}`;
|
||||
return [
|
||||
{ href: `${base}/write`, label: "写本章", glyph: "✍", key: "write", primary: true },
|
||||
{ href: `${base}/review`, label: "审稿", glyph: "✦", key: "review" },
|
||||
{ href: `${base}/outline`, label: "大纲", glyph: "❡", key: "outline" },
|
||||
{ href: `${base}/codex`, label: "设定库", glyph: "❖", key: "codex" },
|
||||
{ href: `${base}/skills`, label: "工具箱", glyph: "✧", key: "skills" },
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user