Skip to content

feat(frontend): 画布图标语言与原版统一到 DSH 插件版那套内联图标 - #71

Merged
zlZayn merged 4 commits into
mainfrom
feat/dock-and-node-icons
Nov 7, 2026
Merged

zlZayn merged 4 commits into
mainfrom
feat/dock-and-node-icons

Conversation

@zlZayn

@zlZayn zlZayn commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

改了什么

维护者要求两个项目(原版 Imagora / DSH 插件版 dsh-imagora-desk)的图标语言收敛成一套。本 PR 按已定决策,以插件版那套内联图标为准(24 viewBox、strokeWidth 1.7、round cap/join、currentColor),把原版这两处换掉:

  1. 新增 frontend/src/components/Icon.tsx — 画布图标语言的唯一出处。PATHS(图标名 → path d)是插件版 src/client/icons.tsx 的逐字拷贝,刻意保留完整清单,为的是两边能直接 diff(只留用得到的几条,下次同步就只能人肉比对)。名字拼错时退回 help(问号)而不是渲染空白,跟插件版同行为。
  2. 画布左下角控制坞(CanvasPage.tsx 的 <DockRow icon={…}>,9 行)。
  3. 节点右侧 hover 操作栏(CanvasNodes.tsx 的 ActionButton:图片节点 7 个按钮,加图片组 / 提示词卡的删除按钮)。
  4. 操作栏描边顺手统一:border-white/40 → .node-actions(rgba(32,43,51,.13),与 .studio-canvas .node-pop 的节点卡描边同值)。白色 40% 只在深色底上读得出来,浅底画布上等于没有边,浮层边界全靠阴影硬撑;统一后「表面细线」在画布上只有一种读法,且只有一个改动点。
  5. 文档:frontend/README.md 组件索引新增 Icon.tsx、样式体系新增 .node-actions 与「画布图标」两行;docs/ARCHITECTURE.md 8.4 新增一条图标语言约定(含「改形状 = 两个仓库同时改」与老坑说明)。

没动的:按钮的 label / title / aria-label 一个没改,只换图形;布局尺寸、圆角、间距、颜色 token、交互、文案一律未动;提示词卡的 StatusLight 等非图标部分未动。

为什么

维护者原话:「画布左下角的竖状工具栏则是我们插件做得更好……让它去那个项目提 PR」,以及后续一条「图片节点右侧工具栏,两个项目的统一一下,也包括图标啥的」。两个项目的画布是同一套交互,图标却是两种笔触(lucide 2px vs 插件版 1.7px),来回切项目就觉得整块界面不像一个产品。

两个项目是什么关系

这次改动横跨两个仓库,先把关系说清(不然「以插件版为准」读起来像空降结论):

  • 本仓库(原版 Imagora):独立的本地 Web 应用 —— Python 后端 + frontend/ React/Vite 前端,uv run python -m main ui 起 7860,浏览器里开画布工作台。
  • 插件版 cslkkl/dsh-imagora-desk:把同一张自由画布搬进 DeepSeek Harness,作为插件渲染在宿主页面里(src/client/ 组件 + src/host/ 接口)。节点类型、操作栏职责、连线语义与这里一一对应,是同一个产品的另一次实现,UI 上打磨得更细。

所以两边不是两个不相干的软件,而是同一套画布的两处实现,同一个人维护:交互一致、视觉却各走各的,来回切就会露出「像两个产品」。这次统一的是图标语言,以插件版的内联图标为准;形状源是插件版 src/client/icons.tsx,本 PR 在 frontend/src/components/Icon.tsx 里逐字拷了一份,并把「改形状 = 两个仓库一起改」写进文件头与 ARCHITECTURE,免得下次又分叉。

本轮只动原版这一侧:插件版本来就是这套图标,它的源码与 dist/client.js 零改动。

真机截图

五张本机实拍(隔离实例 + 真实 Chromium,加载的就是本 PR 构建出的 dist/)见评论:控件坞九行、图片节点右侧七个按钮、空的图片组卡、悬停「新建提示词卡片」、尺寸下拉展开态。

图标映射表(只换图形,语义与无障碍名字不变)

控件坞(CanvasPage.tsx,尺寸都是 14):

原 lucide 现在
ZoomIn zoomIn
ZoomOut zoomOut
Maximize maximize
Crosshair focus
Magnet magnet
Map as MapIcon map
Lock lock
LockOpen unlock
CircleHelp help

节点右侧操作栏(CanvasNodes.tsx,尺寸都是 14):

原 lucide 按钮(label 未变) 现在
Eye 预览大图 eye
Crop 裁剪图片 crop
Maximize2 放大图片 expand
Scissors 切分图片 grid
Brush 蒙版重绘 wand
RefreshCw 替换图片 image
Trash2 删除图片 / 删除图片组 / 删除 trash

顺带绕掉一条老坑:控件坞原来写 Map as MapIcon,因为名叫 Map 的组件会遮蔽全局 Map 类型、把 React Flow 的泛型推断搞崩(报一串与 UI 无关的类型错误)。现在名字走字符串键,不会再撞名;这条坑写进了 Icon.tsx 与 ARCHITECTURE 注释,免得下一个人重踩。

lucide-react 依赖保留(grep 全仓确认过)

这两处之外仍有 4 个文件在引 lucide,所以只改 import、不动 package.json:

  • App.tsx — Palette / Plug
  • useCanvasDrop.tsx — Layers / Plus / Type / X
  • ResultPanel.tsx — AlertTriangle / Ban / Sparkles
  • CanvasPage.tsx — GripVertical(可拖出按钮的拖拽把手,不在本次统一范围)

验证(本机 Windows,node 24 / npm 12 / Python 3.12)

命令 结果
cd frontend; npm run build 通过:tsc --noEmit 无错 + vite 2040 modules(dist/assets/index-*.js 598.73 kB、index-*.css 92.70 kB)
cd frontend; npm test 1069 passed(65 个测试文件全通过)
cd frontend; npm run lint 零告警(exit 0)
uv run python scripts/check_docs.py ✔ 链接 545 处可解析;后端 485 / 前端 1069 计数与文档一致

新增断言都挂在既有用例里,用例总数不变(仍是 1069),所以仪表盘数字不用动:

  • CanvasNodes.test.tsx:操作栏必须挂 .node-actions、不得再出现 border-white;裁剪按钮里那颗 svg 的 viewBox=0 0 24 24 / stroke-width=1.7 / stroke=currentColor / aria-hidden=true。
  • CanvasPage.baseline.test.tsx:控件坞「放大画布」那颗图标同样锁这套笔画。

E2E(frontend/e2e/verify_canvas.py,105 断言)本机未跑,由 CI 的 e2e job 兜(它自建 dist/ 并用真实浏览器点这些按钮,断言名用的是 aria-label,本次没动 aria-label)。

副作用(已知,接受)

  • 图标线条比原 lucide 细一档(1.7 vs 2):这是插件版的既定观感,不是笔误;两个项目统一到同一档才有意义。
  • 操作栏描边从白 40% 变成中性 rgba(32,43,51,.13):浅底上边界更清楚;深色壁纸下会比原来薄一档(同值已在节点卡上用着,视觉上是「同一套细线」)。

提交拆分(一个提交只做一件事)

  1. feat(frontend): 新增内联图标模块 Icon.tsx(形状源与 DSH 插件版同源)
  2. feat(frontend): 画布左下角控制坞九行图标换成内联 Icon
  3. feat(frontend): 节点右侧操作栏七按钮换内联图标 + 描边归 .node-actions
  4. docs(frontend): 登记 Icon.tsx 与 .node-actions,写清画布图标语言约定

@zlZayn zlZayn added the enhancement New feature or request label Nov 7, 2026
@zlZayn zlZayn self-assigned this Nov 7, 2026
@zlZayn

zlZayn commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator Author

真机截图

隔离实例 + 真实 Chromium,加载的是本次构建的 dist/:

imagora-icons-all

两个项目的关系

  • 本仓库(原版 Imagora):独立的本地 Web 应用 —— Python 后端 + frontend/ React/Vite 前端。
  • DSH 插件版 cslkkl/dsh-imagora-desk:把同一张自由画布搬进 DeepSeek,作为插件渲染在宿主页面里。

同一套画布的两处实现、同一个人维护。这次把图标语言统一到插件版那套内联图标(形状源 src/client/icons.tsx,本 PR 逐字拷进 frontend/src/components/Icon.tsx)。本轮只动原版,插件版源码与 dist/client.js 零改动。

@zlZayn
zlZayn merged commit 650d43b into main Nov 7, 2026
4 checks passed
@zlZayn
zlZayn deleted the feat/dock-and-node-icons branch November 7, 2026 12:52
zlZayn added a commit that referenced this pull request Nov 7, 2026
* fix(frontend): 控件坞图标压掉 React Flow 内置 svg 的 fill/12px,恢复描边线条

* test(frontend): 锁住控件坞图标是描边线条(fill none + 14px)

* docs(frontend): 记下 React Flow 会填实控件坞图标这条坑,同步仪表盘 1071
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant