10 KiB
啡跃 Endoleap
本地 Next.js App Router + TypeScript + Tailwind CSS + shadcn/ui 项目。首页和账户页参考 qyof 的 PROMPT 文件,工作台使用合并后的单侧栏,参考 Notion 的留白与账户菜单组织方式。Other Designs 用于首页叙事与版式参考。
项目目录:/Users/zzyang/endoleap。
启动
npm ci
npm run dev
默认仅监听本机 localhost:17321。生产模式:npm run build && npm start。
- 首页:/
- 登录、注册:/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 导入及操作帮助。
- 图谱名称、ID 和 workspace 仍来自 Foundry。当前节点、连线与视图属于当前浏览器的本地草稿,按 workspace/board 分开保存,尚未同步到 Foundry 或其他设备。可导出 JSON 备份,导入操作可撤销。
- 分享、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 添加纯文本,便签按钮添加文本卡片。纯文本没有卡片外框、连接点或四向加号。
- 底部图形按钮打开左侧图标浮层,可搜索并插入 45 个 Lucide 图标;图标支持移动、缩放、旋转和颜色设置,无需额外图标目录服务。
- 大小、角度、样式、字号和图标标识保存在本地草稿及 JSON;支持撤销和重做。目前尚未存入数据库,Core 的 board.content 不接受这些字段。后端需求及验收契约见 CORE_CANVAS_API.md。
- 业务类继承为
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。