diff --git a/CHANGELOG.md b/CHANGELOG.md index b133992..c1df0ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ + [新增] 配置与用户偏好支持通过配置文件导入和导出。 + [新增] 模型渠道新增火山方舟协议。 ++ [优化] 画布左侧元素列表新增图片放大预览操作。 + [优化] 图片遮罩、切图与裁剪编辑支持常用快捷操作并修复高分辨率图片预览闪烁。 + [优化] 提示词详情弹窗改为上下布局并限制显示尺寸。 diff --git a/docs/content/docs/progress/pending-test.mdx b/docs/content/docs/progress/pending-test.mdx index 8583948..dad36df 100644 --- a/docs/content/docs/progress/pending-test.mdx +++ b/docs/content/docs/progress/pending-test.mdx @@ -5,6 +5,7 @@ description: 当前版本已实现但仍需人工验证的变更项 # 待测试 +- 画布左侧元素列表:点击元素整行应平滑定位并选中对应节点;有内容的图片元素应显示预览按钮,点击后打开大图弹窗且不触发画布定位。 - 配置与用户偏好:导出 JSON 后应包含渠道、默认模型、生成偏好、提示词来源和 WebDAV 配置;在修改当前配置后重新导入该文件,应恢复导出时的设置,错误 JSON 文件应提示格式不正确。配置文件包含 API Key 和 WebDAV 凭据,不应公开分享。 - 模型渠道协议:渠道编辑可选择「火山方舟」并自动填入方舟接口地址;任意名称的生图模型应按方舟 JSON 格式提交参考图,任意名称的视频模型应按方舟任务格式提交和查询,不再依赖模型名包含 `doubao`、`seedream` 或 `seedance`;1080p 不应再因模型名包含 `fast` 被禁用,参考视频应允许最大 200MB、总像素 409600-8295044,并继续校验官方宽高、比例和时长限制。 - 图片编辑弹窗:遮罩、切图和裁剪连续滚轮缩放时,图片与遮罩应保持同步且不再闪烁、短暂消失或跳动;遮罩画笔圆心应始终固定在鼠标位置,仅直径随缩放变化,缩放后仍可准确涂抹、拖动切分线和调整裁剪框。 diff --git a/web/src/components/canvas/canvas-side-panel.tsx b/web/src/components/canvas/canvas-side-panel.tsx index 7ce0857..93d0052 100644 --- a/web/src/components/canvas/canvas-side-panel.tsx +++ b/web/src/components/canvas/canvas-side-panel.tsx @@ -29,6 +29,7 @@ type Props = { nodes: CanvasNodeData[]; selectedNodeIds: Set; onFocusNode: (nodeId: string) => void; + onPreviewNode: (nodeId: string) => void; onInsertAsset: (payload: InsertAssetPayload) => void; }; @@ -48,7 +49,7 @@ const STATUS_COLOR: Record = { idle: "transparent", }; -export function CanvasSidePanel({ nodes, selectedNodeIds, onFocusNode, onInsertAsset }: Props) { +export function CanvasSidePanel({ nodes, selectedNodeIds, onFocusNode, onPreviewNode, onInsertAsset }: Props) { const theme = canvasThemes[useThemeStore((state) => state.theme)]; const [tab, setTab] = useState("canvas"); const width = useCanvasSidePanelStore((state) => state.width); @@ -103,7 +104,7 @@ export function CanvasSidePanel({ nodes, selectedNodeIds, onFocusNode, onInsertA
{tab === "canvas" ? ( - + ) : tab === "assets" ? ( ) : ( @@ -144,7 +145,7 @@ function nodePreviewText(node: CanvasNodeData) { return getNodeDefinition(node.type)?.title || node.type; } -function CanvasNodesTab({ nodes, selectedNodeIds, onFocusNode, theme }: { nodes: CanvasNodeData[]; selectedNodeIds: Set; onFocusNode: (nodeId: string) => void; theme: CanvasTheme }) { +function CanvasNodesTab({ nodes, selectedNodeIds, onFocusNode, onPreviewNode, theme }: { nodes: CanvasNodeData[]; selectedNodeIds: Set; onFocusNode: (nodeId: string) => void; onPreviewNode: (nodeId: string) => void; theme: CanvasTheme }) { const { message } = App.useApp(); const [keyword, setKeyword] = useState(""); const [typeFilter, setTypeFilter] = useState("all"); @@ -216,23 +217,26 @@ function CanvasNodesTab({ nodes, selectedNodeIds, onFocusNode, theme }: { nodes: const isChecked = checked.has(node.id); const active = selectMode ? isChecked : selectedNodeIds.has(node.id); return ( - +
+ + {selectMode || !isImage ? null : ( +
+ +
+ )} +
); })}
diff --git a/web/src/pages/canvas/project.tsx b/web/src/pages/canvas/project.tsx index 8f2f31d..524741f 100644 --- a/web/src/pages/canvas/project.tsx +++ b/web/src/pages/canvas/project.tsx @@ -2756,7 +2756,7 @@ function InfiniteCanvasPage() { return (
- +