啡跃 Endoleap

本地 Next.js App Router + TypeScript + Tailwind CSS + shadcn/ui 项目。首页采用留白、黑色主按钮、衬线标题与线稿画布预览;账户页保留原有布局。工作台使用合并后的单侧栏。

项目目录:/Users/zzyang/endoleap。

启动

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。

验证

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。 流程回归可在支持 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。前端已按该契约保存分区,无需额外数据库结构或接口。

首页现提供可点击的画布预览、三段创作说明、FAQ 和本地演示入口;已登录访问 / 仍跳转无画布的 /dashboard。

最新编辑交互

文本卡片、脚本和纯文本统一为单击选中、双击进入编辑(采用系统双击窗口);选中后隔很久再单击不会误进编辑。非编辑状态可直接拖动整个文本区域,不再使用纯文本左上角拖动按钮;Esc 或失焦退出编辑。卡片外部标题可双击改名。

底部同时提供图片卡片与纯图片入口;纯图片按原图比例插入,没有卡片标题/连接点,支持整图拖动、等比缩放及旋转。分区工具栏显式提高层级,修复可见但无法操作的问题。完整继承关系见 CANVAS_ELEMENTS.md。

会话策略已按确认方案准备前后端实现:30 天闲置续期、90 天绝对期限,Core PR #10 已随主线 7847167 的部署 #889 成功上线;既有过期会话不会复活,有效会话可在下一次鉴权时续期。详见 SESSION_LIFETIME.md。纯图片快照配套 Core PR #11(codex/plain-images)已随部署 #889 上线;其余已部署节点保存保持兼容。

S
Description
No description provided
Readme 14 MiB
Languages
TypeScript 51%
JavaScript 46.2%
CSS 2.8%