diff --git a/.cursor/rules/react-frontend.mdc b/.cursor/rules/react-frontend.mdc index af5eff6..a52a9b1 100644 --- a/.cursor/rules/react-frontend.mdc +++ b/.cursor/rules/react-frontend.mdc @@ -9,14 +9,17 @@ alwaysApply: false ## Stack - React 18 + TypeScript strict + Vite + TailwindCSS v4 - shadcn/ui + Radix primitives for components -- Framer Motion for animations +- Framer Motion for chat animations (PlaygroundPage only) - react-i18next for i18n (zh/en) -- TanStack Query for data fetching, Zustand for client state +- TanStack Query for data fetching - lucide-react for icons, axios for HTTP +- D3.js (submodule imports) for citation graph ## Conventions - Import alias `@/` maps to `frontend/src/` - API client at `@/lib/api.ts`, typed services at `@/services/api.ts` +- API URLs: use `apiUrl()` / `wsUrl()` from `@/lib/api-config.ts` — never hardcode `/api/v1/` +- Query keys: use typed factory at `@/lib/query-keys.ts` for all TanStack Query keys - Types at `@/types/index.ts` must mirror backend Pydantic schemas - Use `cn()` from `@/lib/utils` for conditional class merging - Functional components only, no class components @@ -24,7 +27,14 @@ alwaysApply: false - i18n keys in `@/i18n/locales/{en,zh}.json` - UI components from shadcn/ui at `@/components/ui/` +## Layout & Components +- Use `PageLayout` (not PageHeader) for page structure +- Use `DataTable` for tabular data with sorting/pagination/selection +- Use `DualSidebar` for navigation — context-aware (chat history on chat routes) +- Use shadcn `Select`, `Tabs`, `Badge` instead of native HTML elements +- Prefer CSS transitions over Framer Motion for non-chat pages + ## CI Build - Type check: `npx tsc -b` (stricter than `--noEmit`, matches CI) - Build: `cd frontend && npm run build` -- Dev server: port 3000 on `0.0.0.0`, proxies `/api` → backend `:8000` +- Dev server: port 3001 on `0.0.0.0`, proxies `/api` → backend `:8000` diff --git a/.cursor/skills/frontend-design/SKILL.md b/.cursor/skills/frontend-design/SKILL.md index 20198e4..f9fd1d7 100644 --- a/.cursor/skills/frontend-design/SKILL.md +++ b/.cursor/skills/frontend-design/SKILL.md @@ -6,16 +6,18 @@ description: Create distinctive, production-grade frontend interfaces with high # Frontend Design for Omelette ## Stack -React 18 + TypeScript + TailwindCSS v4 + shadcn/ui + Radix + Framer Motion + lucide-react +React 18 + TypeScript + TailwindCSS v4 + shadcn/ui + Radix + lucide-react + D3.js ## Design Direction: Scientific Editorial Omelette is a scientific literature assistant. The UI should feel like a **modern research tool** — clean, information-dense but not cluttered, with editorial precision. - **Tone**: Refined academic + modern SaaS. Think Notion meets Google Scholar. -- **Color**: Neutral base (slate/zinc) with warm accent (amber/orange — the "omelette" brand). Dark mode support. +- **Color**: Purple/blue primary (`#6C5CE7` style, OKLCH tokens), neutral base (slate). Dark mode with sidebar-specific tokens. - **Typography**: `Inter` for body (legibility), monospace for metadata. Use font-weight variation for hierarchy, not color. - **Spacing**: Generous whitespace between sections, tight within cards. 4px grid system. -- **Motion**: Subtle — `framer-motion` for page transitions and list staggering. No gratuitous bouncing. +- **Motion**: CSS transitions preferred. Framer Motion only in PlaygroundPage chat animations. +- **Layout**: `PageLayout` for page structure, `DualSidebar` for navigation (context-aware panels), `DataTable` for tabular data. +- **API URLs**: Always use `apiUrl()` / `wsUrl()` from `@/lib/api-config.ts`. ## Component Patterns diff --git a/docs/brainstorms/2026-03-19-frontend-redesign-brainstorm.md b/docs/brainstorms/2026-03-19-frontend-redesign-brainstorm.md new file mode 100644 index 0000000..5f3d0e5 --- /dev/null +++ b/docs/brainstorms/2026-03-19-frontend-redesign-brainstorm.md @@ -0,0 +1,172 @@ +--- +date: 2026-03-19 +topic: frontend-redesign +status: approved +tags: [frontend, design, ui, api, figma] +--- + +# 前端全面重设计 — Brainstorm + +## What We're Building + +基于 Figma 设计规范(`omelette-ui`),对 Omelette 前端进行全面视觉重设计,同时对齐后端 48 项 API 改进。采用**主题层改造**策略:先改 CSS 变量/主题 + 基础组件,再逐页面适配。 + +核心变化: +- 从 shadcn neutral 灰色调 → **紫/蓝紫色调**主色系 +- 从单层图标侧边栏 → **双层侧边栏**(图标栏 + 可展开文本栏) +- 聊天页增加 **Figma 风格欢迎界面**(Logo + 问候语 + 功能卡片入口) +- 表格增加**看板视图**(列表 + 看板双视图切换) +- 移除 @a2ui-sdk/react 依赖,用**自定义组件替换** +- 前端 API 调用层全面对齐后端新接口(参数格式、响应结构、新增端点) +- **移动端重新设计**,对齐 Figma 移动端规范 + +## Why This Approach + +### 考虑的方案 + +| 方案 | 描述 | 优缺点 | +|------|------|--------| +| A. 主题层改造 ✅ | 先改主题变量+基础组件,再逐页面适配 | 渐进式、每步可验证、风险低 | +| B. 页面级重写 | 按优先级逐页面完全重写 | 过渡期风格混搭 | +| C. 设计系统先行 | 先建完整组件库再替换 | 前期投入大、见效慢 | + +**选择方案 C**:先构建完整设计系统(Design Tokens + 组件库),确保每个组件都完美匹配 Figma 紫色调规范后,再一次性替换所有页面。虽然前期投入大,但最终一致性最高,且组件可复用,长期维护成本低。 + +## Figma 设计规范参考 + +**Figma 文件**: `S0EBb8yirqyBEUUwkVsFOz` (omelette-ui) + +### 关键页面映射 + +| Figma 页面 | Node ID | Omelette 页面 | +|-----------|---------|--------------| +| ai-聊天机器人(空状态) | 12327:142158 | PlaygroundPage(空聊天) | +| ai聊天机器人/类型(输入状态) | 12327:146598 | PlaygroundPage(输入中) | +| ai聊天机器人/我的工具 | 12327:151038 | 工具模式选择 | +| ai聊天机器人/我的工具/写作 | 12327:151425 | WritingPage | +| 项目管理/项目 | 12327:116150 | KnowledgeBasesPage | +| 项目管理/任务(列表) | 12327:116272 | TasksPage(列表视图) | +| 项目管理/任务(看板) | 12327:121306 | TasksPage(看板视图) | +| 目标 | 12327:128438 | Papers 列表 / Discovery | +| 活动/屏幕截图 | 12327:114747 | 项目仪表盘(统计概览) | +| 设置/我的个人资料 | 12327:152210 | SettingsPage | + +### 设计语言要素 + +- **主色**: 紫/蓝紫色 (#6C5CE7 风格),用于按钮、激活态、强调 +- **布局**: 双层侧边栏(左侧紧凑图标 + 可展开文本导航) +- **Top Bar**: 欢迎语 + 通知/帮助图标 + 用户信息 +- **卡片**: 柔和渐变色背景(粉、黄、蓝、绿)+ 圆角 +- **表格**: 带进度条、徽章、分页的数据表格 +- **移动端**: 375px 宽,底部导航栏,紧凑卡片布局 + +## Key Decisions + +| 决策 | 选择 | 理由 | +|------|------|------| +| 色彩方案 | 完全采用 Figma 紫色调 | 统一视觉 identity | +| 侧边栏 | 双层:图标栏 + 可展开文本栏 | Figma 规范,提升导航效率 | +| 聊天欢迎页 | Figma 风格(Logo + 问候 + 功能卡片) | 丰富空状态体验 | +| 表格视图 | 列表 + 看板双视图 | 列表满足基本需求,看板提升 Tasks 体验 | +| A2UI SDK | 替换为自定义组件 | 完全控制样式,减少外部依赖 | +| 移动端 | 重新设计 | 对齐 Figma 移动端规范 | +| API 对齐 | 全面适配 48 项后端修复 | 后端已完成,前端需跟进 | +| 实施策略 | 方案 C:设计系统先行 | 一致性最高,组件可复用 | + +## 实施层次(方案 C:设计系统先行) + +### 阶段 1:Design Tokens + 主题基础 + +1. **Design Tokens 定义** — 从 Figma 提取完整 tokens: + - 颜色系统(primary: 紫色梯度、neutral、semantic 颜色) + - 间距系统(4px 基础网格) + - 圆角(sm/md/lg/xl) + - 阴影(sm/md/lg) + - 排版系统(字体大小、行高、字重) +2. **CSS 变量重定义** — `index.css` 中 light/dark 主题全部改为紫色系 +3. **Tailwind 配置更新** — 扩展 theme 匹配 design tokens + +### 阶段 2:基础组件库重建 + +在 `components/ui/` 中重建/升级所有基础组件: + +| 组件类别 | 组件列表 | 改造重点 | +|---------|---------|---------| +| 输入 | Button, Input, Textarea, Select, Checkbox, Switch | 紫色主题、新变体 | +| 展示 | Card, Badge, Avatar, Tooltip, Skeleton | 渐变卡片、新徽章色 | +| 反馈 | Dialog, Sheet, AlertDialog, Toast | 紫色调、圆角更新 | +| 导航 | Tabs, DropdownMenu, Popover | 激活态紫色 | +| 数据 | Table, Pagination, DataGrid | 表格行高、斑马纹 | +| 新增 | KanbanBoard, StatsCard, ProgressBar, DualSidebar | 按 Figma 新建 | + +### 阶段 3:布局系统重建 + +1. **DualSidebar** — 双层侧边栏组件(图标栏 + 可展开文本栏) +2. **TopBar** — 欢迎语 + 通知 + 用户头像 +3. **AppShell** — 基于新 DualSidebar + TopBar 重构 +4. **MobileLayout** — 底部导航 + 紧凑头部 +5. **PageLayout** — 统一页面容器(标题 + 操作栏 + 内容区) + +### 阶段 4:API 服务层对齐 + +1. **services/api.ts** — 对齐分页参数标准化(PaginationParams)、Literal 类型 +2. **services/chat-api.ts** — SSE 错误格式统一处理 +3. **services/kb-api.ts** — 对齐新的 dedup auto-resolve、batch 操作 +4. **services/subscription-api.ts** — 对齐 feed 查询新参数 +5. **types/** — 更新 TypeScript 类型定义匹配后端 schema 变化 +6. **新增 Pipeline WebSocket** — 连接 `/api/v1/pipelines/{thread_id}/ws` + +### 阶段 5:自定义组件替换 A2UI + +| A2UI 组件 | 替换方案 | +|-----------|----------| +| A2UICitationCard | 自定义 CitationCard(紫色调、卡片样式) | +| A2UIRewriteDiff | 自定义 DiffViewer(保留 react-diff-viewer-continued) | +| A2UIStatsDashboard | 自定义 StatsGrid(参考 Figma 统计卡片) | +| react-force-graph-2d | D3.js 自定义引用图谱 | + +### 阶段 6:全面页面替换 + +一次性替换所有页面,使用新组件库: + +| 优先级 | 页面 | 改造内容 | +|--------|------|----------| +| P0 | AppShell(布局) | 使用新 DualSidebar + TopBar | +| P0 | PlaygroundPage(聊天) | 欢迎页、功能卡片、消息气泡样式 | +| P1 | KnowledgeBasesPage | 项目卡片/列表、搜索、CRUD 对话框 | +| P1 | PapersPage | 新 DataGrid、状态 Badge、批量操作 | +| P1 | SettingsPage | 侧边导航 + 多面板(LLM、Embedding、系统) | +| P2 | DiscoveryPage | Keywords/Search/Subscriptions 三面板 | +| P2 | TasksPage | 列表 + KanbanBoard 视图切换 | +| P2 | WritingPage | 工具卡片入口、结果展示 | +| P3 | PDFReaderPage | 全新布局设计(参考 Semantic Reader) | +| P3 | ChatHistoryPage | 历史列表样式统一 | + +## 已解决问题 + +1. ~~范围确认~~ → 全部页面(Chat、Sidebar、KB、Papers、Discovery、Settings、Tasks、Writing、PDF Reader) +2. ~~色彩方案~~ → 完全采用 Figma 紫色调 +3. ~~实施策略~~ → 方案 C:设计系统先行(一致性最高) +4. ~~A2UI 处理~~ → 自定义组件替换,移除 @a2ui-sdk/react 依赖 +5. ~~移动端~~ → 重新设计,对齐 Figma 移动端规范 +6. ~~暗色模式~~ → 保留 dark mode,配合紫色调重新设计暗色变量 +7. ~~PDF 阅读器~~ → 重新设计布局(参考主流论文阅读器),无 Figma 参考 +8. ~~i18n~~ → 专注英文,中文后续再补 +9. ~~引用图谱~~ → 替换为 D3.js 自定义图谱(更灵活控制样式和交互) + +## Open Questions + +(无——已全部解决) + +## 补充决策 + +| 决策 | 选择 | 理由 | +|------|------|------| +| 暗色模式 | 保留,紫色调重新设计暗色变量 | 用户已习惯 dark mode,紫色暗色版可以很优雅 | +| PDF 阅读器 | 重新设计布局 | 参考主流论文阅读器(Semantic Reader/ReadPaper),提升阅读体验 | +| i18n | 先英文,中文后补 | 集中精力先完成一套完整的设计语言 | +| 引用图谱 | D3.js 替换 force-graph | 完全控制配色和交互,更好融入紫色设计系统 | + +## Next Steps + +→ `/ce:plan` 制定详细实施计划(分阶段任务、文件变更清单、测试策略) diff --git a/docs/brainstorms/2026-03-19-frontend-systematic-cleanup-brainstorm.md b/docs/brainstorms/2026-03-19-frontend-systematic-cleanup-brainstorm.md new file mode 100644 index 0000000..06829e0 --- /dev/null +++ b/docs/brainstorms/2026-03-19-frontend-systematic-cleanup-brainstorm.md @@ -0,0 +1,111 @@ +# Frontend 系统化清理与优化 + +**日期:** 2026-03-19 +**状态:** 已确认 +**关联:** 前端重设计完成后的质量收尾 + +--- + +## 我们要做什么 + +对前端重设计之后遗留的所有问题进行系统化修复,按优先级从高到低逐步处理: + +1. **修复严重 Bug** — API 类型不匹配导致功能失效 +2. **清理死代码与废弃依赖** — 减少维护负担和 bundle 体积 +3. **统一 API 层** — 提取 API_BASE_URL 常量,消除硬编码路径 +4. **补全缺失的 API service 方法** — 确保前端可调用所有后端端点 +5. **代码质量提升** — i18n 覆盖、类型安全改进 + +--- + +## 为什么选择这个方案 + +- 全部系统化处理:不留技术债 +- 按优先级排序:先修 Bug 确保功能正确,再做清理和改进 +- framer-motion 保持现状:不是优先项,聊天体验动画可接受 +- API 硬编码地址:提取 `API_BASE_URL` 常量统一管理 + +--- + +## 关键决策 + +### 决策 1:Bug 修复(P0) + +| Bug | 问题 | 修复方案 | +|-----|------|----------| +| 去重冲突操作 | 前端发 `keep_existing`,后端期望 `keep_old` | 将 `DedupConflictPanel.tsx` 中的 `keep_existing` 改为 `keep_old` | +| Pipeline 上传字段 | 前端用 `file_paths`,后端期望 `pdf_paths` | 修改 `pipeline-api.ts` 的 `UploadPipelineRequest` | +| Pipeline 冲突类型 | `ResolvedConflict` 前后端结构完全不同 | 与后端 schema 对齐:`conflict_id: str`, `action: 'keep_old' \| 'keep_new' \| 'merge' \| 'skip'` | + +### 决策 2:死代码清理(P1) + +删除以下不再被引用的文件: +- `frontend/src/components/playground/sidebar-utils.ts` +- `frontend/src/components/playground/SidebarToggleButton.tsx` +- `frontend/src/components/layout/PageHeader.tsx` +- `frontend/src/components/layout/PageTransition.tsx` + +从 `package.json` 移除未使用的依赖: +- `@a2ui-sdk/react` +- `@a2ui-sdk/types`(如果存在) +- `react-force-graph-2d` + +### 决策 3:API 层统一(P1) + +提取 `API_BASE_URL` 常量到 `frontend/src/lib/api-config.ts`,替换以下 7 处硬编码: + +| 文件 | 硬编码路径 | +|------|-----------| +| `services/api.ts` | RAG index stream | +| `pages/project/WritingPage.tsx` | Writing review draft stream | +| `hooks/use-pipeline-ws.ts` | Pipeline WebSocket | +| `pages/project/PDFReaderPage.tsx` | PDF URL | +| `components/pdf-reader/SelectionQA.tsx` | Chat stream | +| `lib/chat-transport.ts` | Chat stream | +| `services/rewrite-api.ts` | Rewrite stream | + +### 决策 4:补全 API Service 方法(P2) + +新增以下前端 service 方法对齐后端端点: + +| 后端端点 | 前端 service | +|---------|-------------| +| `POST /projects/{id}/pipeline/run` | `pipelineApi.runAll(projectId)` | +| `POST /projects/{id}/pipeline/paper/{paperId}` | `pipelineApi.runPaper(projectId, paperId)` | +| `POST /projects/{id}/subscriptions/check-updates` | `subscriptionApi.checkUpdates(projectId)` | +| `POST /projects/{id}/dedup/verify` | `dedupApi.verify(projectId, ...)` | +| `POST /projects/{id}/writing/assist` | `writingApi.assist(projectId, task, ...)` | + +### 决策 5:i18n 补全(P2) + +补充以下硬编码字符串的 i18n key: +- DualSidebar: "Omelette" 标题、aria-labels +- DataTable / Pagination: aria-labels +- KeywordsPage: 数据库名称 +- SearchPage: 数据源名称 + +### 决策 6:类型安全(P3) + +逐步减少 `as any` / `as unknown` 使用: +- `MessageBubbleV2.tsx` 的 markdown components +- `PapersPage.tsx` 的 `GraphData` 转换 +- `DedupConflictPanel.tsx` 的多处不安全转换 + +### 决策 7:保持现状 + +- **framer-motion**: 保留在 PlaygroundPage 和 playground 子组件中 +- **DiscoveryPage 布局**: 当前可用,后续优化 + +--- + +## 已解决的问题 + +- Q: 侧边栏重复? → 已修复,ChatHistorySidebar 集成到 DualSidebar +- Q: framer-motion 如何处理? → 保持现状 +- Q: 硬编码 URL 如何处理? → 提取 API_BASE_URL 常量 + +--- + +## 开放问题 + +无 diff --git a/docs/brainstorms/2026-03-19-sidebar-simplification-brainstorm.md b/docs/brainstorms/2026-03-19-sidebar-simplification-brainstorm.md new file mode 100644 index 0000000..479fd8f --- /dev/null +++ b/docs/brainstorms/2026-03-19-sidebar-simplification-brainstorm.md @@ -0,0 +1,42 @@ +# Brainstorm: DualSidebar 简化 & 项目页侧边栏重复修复 + +日期: 2026-03-19 + +## 我们要解决什么 + +### 问题 +项目页面(`/projects/:id/*`)存在侧边栏重复: +- `DualSidebar`(全局):icon rail + 展开面板(NavPanel / ChatHistoryPanel) +- `ProjectDetail.tsx`(项目路由):独立 `