Files
Endoleap/README.md
T

145 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 啡跃 Endoleap
本地 Next.js App Router + TypeScript + Tailwind CSS + shadcn/ui 项目。首页采用留白、黑色主按钮、衬线标题与线稿画布预览;账户页保留原有布局。工作台使用合并后的单侧栏。
项目目录:`/Users/zzyang/endoleap`。
## 启动
```sh
npm ci
npm run dev
```
默认仅监听本机 localhost:17321。生产模式:`npm run build && npm start`。
- 首页:/(未登录显示 landing page;有效登录会话跳转 /dashboard)
- 登录、注册:/login
- 登录回调:/auth/callback
- 真实工作台:/dashboard
- 本地演示:/dashboard?demo=1
- 无限图谱:/dashboard/{workspace}/{board}
## 路由结构
- `src/app/layout.tsx`:根布局、中文语言标记、全局样式与页面元信息。
- `src/app/page.tsx`:首页。
- `src/app/login/page.tsx`、`src/app/auth/callback/page.tsx`:账户页与登录回调。
- `src/app/dashboard/layout.tsx`:共享单侧栏;`page.tsx` 保留空白工作区。
- `src/app/dashboard/dashboard.tsx`:侧栏收起/展开、页面搜索、新建图谱与底部账户弹出框。
- `src/app/dashboard/[workspace]/[board]/page.tsx`:按 workspace 和图谱 ID 打开页面,重新读取后端资料。
- `src/components/ui/icon-button.tsx`:Lucide 图标按钮,图标为 16×16px,上下 4px、左右 6px 内边距,总尺寸为 28×24px。
- `src/app/api/**/route.ts`:Foundry 代理与 OAuth 跳转,使用 App Router Route Handlers。
## 配置
复制 .env.example 为 .env.local,按实际部署填写:
- FOUNDRY_API_ORIGIN:仅供 Next 服务端请求后端,默认 https://api.foundry.entroia.com。
- NEXT_PUBLIC_FOUNDRY_PROJECT:项目标识,默认 endoleap。
Slack Client Secret、Signing Secret、Verification Token、用户令牌与 app token 均不需要放入此前端。浏览器调用同源 Next API,由服务端转发到 Foundry。Foundry 会话保存在 HttpOnly / SameSite=Lax Cookie,生产 HTTPS 反向代理需传 X-Forwarded-Proto=https。不要将原始会话写入客户端存储。
Google / Slack 的提供方回调仍是 Foundry 后端地址;后端的项目回调映射必须指向本前端 /auth/callback。协议、主机名、端口必须与启动第三方登录时一致,否则 sessionStorage 中的 verifier 无法恢复。正式账号授权、邮件验证与 OAuth 全流程尚未完成真人验收;HTTP 302 跳转成功不能代表登录成功。
## 当前功能与范围
- 响应式首页、锚点导航与 FAQ。
- 邮箱注册 / 登录 / 邮件验证兑换,Google 和 Slack 的 PKCE 登录入口及回调处理。
- 真实用户资料、空间列表与创建、画布列表与创建。资料和空间并行读取;首次创建画布时自动建立个人空间。
- 单侧栏第一行提供完全收起/恢复与新建页面,第二行为当前空间页面列表搜索。侧栏使用 Motion for React 14.9.1 实现 240ms 开关动画,尊重系统减少动态效果偏好,收起后保留左上角快捷浮框。
- 账户菜单分为工作空间概览、账户设置、用户资料与空间切换、新建工作空间、退出登录;账户设置和新建空间均接入 Foundry。菜单文字和行距参考 Notion 收紧,工作空间分组标题保留浅灰色。
- 底部按钮、账户菜单和设置面板使用 Foundry `profile.avatar_url` 提供的 Google 头像;无头像或图片加载失败时显示姓名首字。
- 新建页面使用 Foundry Core 的 `POST /workspaces/{workspace}/materials`,提交 `kind: board`、默认名称“未命名图谱”和内容版本;由后端生成 ID。没有空间时先创建“个人空间”,成功后跳转到图谱的独立地址。
- 本地演示提供示例图谱、搜索、新建和浏览器保存,支持图谱独立地址与刷新。
- 图谱页面使用 React Flow 12.12.1,支持空白处平移、节点拖动、连线、多选、缩放和文本编辑。文字、脚本、图片节点和创作模板可从底部悬浮工具栏插入。
- 右上角悬浮框提供撤销、重做、缩放、恢复 100%、适应画布和 JSON 导出;底部支持 JSON 导入及操作帮助。
- 真实图谱先读取 Core Canvas 快照,再开放编辑;节点、样式、连线与视图以独立版本串行自动保存。旧本地草稿需用户明确选择恢复;版本冲突停止覆盖并保留恢复记录。演示模式仅本地保存。分区框及成员归属已匹配 Core 022086b 的保存契约,详见 docs/CORE_FRAME_EXTENSION.md。
- 分享、Agent、收藏、自由绘图及多人协同尚未接入。画布覆盖整个视口,侧栏和快捷浮框覆盖其上;演示数据不写入线上。
- 收起侧栏后,左上角浮框显示 Logo 和用户头像;头像与展开侧栏底部的账户按钮打开同一个菜单。
- 本地演示仅用于查看界面,不提供后端认证与权限。
Figma 原始 Logo、人物插画与图标已下载到 public/assets,不依赖临时 Figma URL。品牌保持啡跃 Endoleap;shadcn Button / Dialog 使用官方 registry 源码。依赖版本固定,package-lock.json 可用于 npm ci。
## 验证
```sh
npm run build
node tests/api-smoke.mjs
```
API 测试使用本机临时后端和独立前端进程,检查会话 Cookie、令牌不泄漏、同源校验和路径白名单,不访问线上账号。构建需先完成。冒烟测试还覆盖所有页面地址、元信息、OAuth 跳转、请求体限制及退出会话。此前的浏览器验收覆盖登录/注册切换、演示画布创建、搜索空状态、笔记保存、桌面与 390px 手机布局;本次迁移的验证结果见 VALIDATION.md。
若执行环境限制 Turbopack 的 CSS 工作进程绑定本地端口,可使用官方 Webpack 模式:`npm run build -- --webpack`。
项目已同步至 `ssh://git@gitea.entroia.com:22222/Zayden-Jung/endoleap.git`;尚未部署。
性能分析、实测耗时和修复说明见 [PERFORMANCE.md](PERFORMANCE.md)。
流程回归可在支持 TypeScript 类型擦除的 Node 版本执行:`node --experimental-strip-types --test tests/workspace.test.mjs`。
## 品牌资源
`public/brand/` 原样复用旧 PROMPT 仓库 `Zayden-Jung/probably-rendering-one-more-pixel-tonight` 的 `packages/brand/assets/`,来源提交 `47467874841ea7f7b4b362d4ec0e66f236c6a7d6`。
共 88 个原始资源:6 套 PNG(logo/icon/mono 的 light 与 dark 版本,每套 16、24、32、48、64、128、180、192、256、512、1024、2048px),8 个 SVG,以及 8 个应用图标文件(含 3 种 ICO、Apple Touch 和 PWA PNG)。所有文件与来源 Git blob 哈希一致。
收起侧栏后的浮框使用 Logo 返回 `/`;展开侧栏后仍保留新建页面按钮。首页与账户页品牌组件使用原始 SVG,根布局声明 ICO、深浅色 PNG favicon 和 Apple Touch 图标。
## 画布操作
- 拖动空白处平移;拖动节点标题或边框移动节点。抓手模式下也可从节点内容处平移。
- V 选择、H 抓手,按住空格临时平移,Shift 框选;拖动节点两侧的圆点创建连线。
- 触控板滚动平移,Ctrl / ⌘ 加滚动或双指捏合缩放。右上角提供缩放和适应画布。
- 底部可添加文字、图片、脚本或三节点创作模板。图片支持 PNG/JPEG/WebP/GIF,单张上限 2 MB。
- Ctrl / ⌘ + Z 撤销,Shift + Ctrl / ⌘ + Z 重做;支持 JSON 导入导出和 40 步撤销历史。
- 状态与导入回归:`node --experimental-strip-types --test tests/canvas.test.mjs tests/workspace.test.mjs`。
## 悬浮栏尺寸
左上角显示当前图谱标题,复用页面已读取的资料,不额外请求后端;长标题省略并可悬停查看。左上、右上、底部与帮助按钮共用 `toolbar.module.css`:图标/Logo/浮框头像 20px,图标按钮含 padding 的总尺寸为 32×32px,主文字 14px,容器内边距 4px,间隙 4px,圆角 8px。悬浮栏距屏幕边缘统一为 12px;右上角窄屏时下移避免与标题重叠。
## 图谱改名
左上角标题第一次点击选中,选中后再次点击进入编辑;回车或失焦保存,Esc 取消,F2 也可直接编辑。真实图谱改名先读取最新资料和版本,再携带 If-Match 更新名称,保留描述与内容;版本冲突时提示重试。演示模式保存到本地。保存后标题、侧栏列表及导出文件名同步更新。
左上和底部工具栏按右上视图控件的分组节奏增加横向留白(间隙 6px、横向内边距 6px),按钮仍为 32×32px,竖向内边距仍为 4px。三处分隔线统一;左侧标题不再额外叠加外边距,右上现有样式保持不变。
卡片选中时,四边正中心淡入固定尺寸的小连接点;取消选中后淡出隐藏,不再显示大加号。拖动连接点建立贝塞尔连线,曲线直接连接两端卡片边缘中心,缩放及旋转后同步更新;选中后点击连接点打开菜单,选择文本、上传图片或脚本后再创建节点并连线。选中卡片拖线到空白处,也会在释放位置打开类型菜单。新增节点与连线组成一步撤销。
## 元素变换、样式与继承
- 右下角缩放符号始终显示,拖动会选中并调整大小,已移除八向缩放控件。样式浮栏中的旋转按钮开启旋转模式,拖动元素旋转,Shift 吸附 15°;点击外部或按 Esc 退出。纯文本宽、高独立调整,文字随宽度换行,字号由样式栏控制;图标保持等比缩放。
- 卡片标题位于框外,整个框内是文本编辑区域;卡片与纯文本均取消独立的聚焦内框。
- 样式浮栏提供文字颜色、字体、字号、加粗、斜体、下划线、对齐、行距、背景及旋转;样式作用于整个文本节点。选中与取消选中、菜单均有动画,尊重系统减少动态效果偏好。
- 底部 T 添加纯文本,便签按钮添加文本卡片。纯文本没有卡片外框、连接点或四向加号。
- 底部图形按钮打开左侧图标浮层,可搜索并分批加载 2313 个 Lucide 图标;图标支持移动、缩放、旋转和颜色设置,无需额外图标目录服务。
- 大小、角度、样式、字号和图标标识通过独立 Canvas 快照接口存入数据库,并保留本地恢复记录及 JSON 导出。保存使用独立版本及 If-Match,串行提交并合并等待中的更新,冲突后停止自动写入。分区框、名称模式和成员归属已随 Core 022086b 部署支持,使用同一个快照接口保存。
- 业务类继承为 `CanvasElement → CardElement → TextCardElement / ImageCardElement / ScriptCardElement`;`PlainTextElement` 和 `IconElement` 直接继承 `CanvasElement`。基础元素拥有缩放和旋转能力,卡片层追加连线和分支能力。React 组件通过组合共享 `TransformableNode`。
- `/dashboard/{workspace}/{board}` 的两个 ID 分别标识工作空间和图谱。
- 回归:`node --experimental-strip-types --test tests/canvas-style.test.mjs tests/canvas-geometry.test.mjs tests/canvas.test.mjs tests/workspace.test.mjs`。
## 框选区
底部「添加框选区」插入可调整大小的分区;选中框可改名,名称提供隐藏、固定屏幕字号、随画布缩放三种模式。拖动边框或名称移动分区,右下角调整大小。框在内容下方,内部空白仍可平移画布。
只有实际拖入的内容才建立归属,以内容中心进入分区为准;拖出后退出,重叠区域优先较小分区。移动分区只带动已有成员,不会自动收纳覆盖到的其他内容;删除分区会保留成员位置与内容。单次拖动及归属变化可以一步撤销,分区设置和归属进入草稿与 JSON。
## 服务端快照与 slug 路由
Core 57aab71 提供基础快照,022086b 已补齐分区框并部署。前端允许 `/workspaces/{workspace}/materials/{board}/canvas`,保留 ETag / If-Match,只为 Canvas 路由放宽至 5 MiB。打开画布并行读取材料信息和快照;读取失败时不开放空白编辑器,避免覆盖远程数据。800ms 防抖提交,更新串行化;失败停止自动写入并提供重试、导出和重新读取。旧草稿和未同步恢复记录都需明确选择,默认使用服务端快照。
URL 的 workspace 与 board 可分别使用 ID 或 slug,支持全部四种组合。以接口返回的 canonical ID 做身份校验、本地恢复隔离与保存路径,侧栏高亮、标题及改名支持 slug;新侧栏链接优先使用可用 slug。改名不自动更改 slug。
分区字段契约:[CORE_FRAME_EXTENSION.md](docs/CORE_FRAME_EXTENSION.md)。前端已按该契约保存分区,无需额外数据库结构或接口。
首页现提供可点击的画布预览、三段创作说明、FAQ 和本地演示入口;已登录访问 `/` 仍跳转无画布的 `/dashboard`。
## 最新编辑交互
文本卡片、脚本和纯文本统一为单击选中、双击进入编辑(采用系统双击窗口);选中后隔很久再单击不会误进编辑。非编辑状态可直接拖动整个文本区域,不再使用纯文本左上角拖动按钮;Esc 或失焦退出编辑。卡片外部标题可双击改名。
底部同时提供图片卡片与纯图片入口;纯图片按原图比例插入,没有卡片标题/连接点,支持整图拖动、等比缩放及旋转。分区工具栏显式提高层级,修复可见但无法操作的问题。完整继承关系见 [CANVAS_ELEMENTS.md](docs/CANVAS_ELEMENTS.md)。
会话策略已按确认方案准备前后端实现:30 天闲置续期、90 天绝对期限,Core PR #10 已随主线 7847167 的部署 #889 成功上线;既有过期会话不会复活,有效会话可在下一次鉴权时续期。详见 [SESSION_LIFETIME.md](docs/SESSION_LIFETIME.md)。纯图片快照配套 Core PR #11(codex/plain-images)已随部署 #889 上线;其余已部署节点保存保持兼容。