修复画布自动模式误用预览尺寸为分辨率

This commit is contained in:
Your Name 2026-02-08 23:06:53 +08:00
parent 1092db2b88
commit 75993d98af
3 changed files with 51 additions and 14 deletions

View File

@ -58,15 +58,22 @@ interface CanvasChatPanelProps {
// 建议卡片数据 - 已移除 // 建议卡片数据 - 已移除
const SUGGESTIONS: { title: string; desc: string; image: string }[] = []; const SUGGESTIONS: { title: string; desc: string; image: string }[] = [];
// 获取图片的原始尺寸 // 获取图片尺寸(保留原图分辨率 + 画布显示尺寸)
function getImageDimensions(url: string): Promise<{ width: number; height: number }> { function getImageDimensions(url: string): Promise<{
width: number;
height: number;
originalWidth: number;
originalHeight: number;
}> {
return new Promise((resolve) => { return new Promise((resolve) => {
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
// 限制最大尺寸,避免节点过大 // 限制最大尺寸,避免节点过大
const maxSize = 500; const maxSize = 500;
let width = img.naturalWidth; const originalWidth = img.naturalWidth;
let height = img.naturalHeight; const originalHeight = img.naturalHeight;
let width = originalWidth;
let height = originalHeight;
// 如果图片太大,按比例缩小 // 如果图片太大,按比例缩小
if (width > maxSize || height > maxSize) { if (width > maxSize || height > maxSize) {
@ -83,11 +90,11 @@ function getImageDimensions(url: string): Promise<{ width: number; height: numbe
height = Math.round(height * scale); height = Math.round(height * scale);
} }
resolve({ width, height }); resolve({ width, height, originalWidth, originalHeight });
}; };
img.onerror = () => { img.onerror = () => {
// 加载失败时使用默认尺寸 // 加载失败时使用默认尺寸
resolve({ width: 300, height: 300 }); resolve({ width: 300, height: 300, originalWidth: 0, originalHeight: 0 });
}; };
img.src = url; img.src = url;
}); });
@ -682,6 +689,10 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
src: url, src: url,
status: 'completed', status: 'completed',
prompt: '对话生成', prompt: '对话生成',
metadata: {
originalWidth: dimensions.originalWidth,
originalHeight: dimensions.originalHeight,
},
}, },
connections: [], connections: [],
}); });
@ -812,9 +823,15 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
: `用户未选中图片,默认使用最近 ${contextNodes.length} 张`, : `用户未选中图片,默认使用最近 ${contextNodes.length} 张`,
...contextNodes.map((node, index) => { ...contextNodes.map((node, index) => {
const label = positionLabel(node); const label = positionLabel(node);
const size = node.size ? `${Math.round(node.size.width)}x${Math.round(node.size.height)}` : "未知尺寸"; const metadata = (node.data as any)?.metadata;
const originalWidth = Number(metadata?.originalWidth || 0);
const originalHeight = Number(metadata?.originalHeight || 0);
const originalSize =
originalWidth > 0 && originalHeight > 0
? `,原图分辨率 ${Math.round(originalWidth)}x${Math.round(originalHeight)}`
: "";
const prompt = (node.data as any)?.prompt; const prompt = (node.data as any)?.prompt;
return `图片${index + 1}: ${label},尺寸 ${size}${prompt ? `,描述:${String(prompt).slice(0, 60)}` : ""}`; return `图片${index + 1}: ${label}${originalSize}${prompt ? `,描述:${String(prompt).slice(0, 60)}` : ""}`;
}), }),
"若用户提到左/右/上/下/中等方位,请匹配对应位置的图片。", "若用户提到左/右/上/下/中等方位,请匹配对应位置的图片。",
]; ];
@ -1001,6 +1018,10 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
status: 'completed', status: 'completed',
title: file.name.replace(/\.[^.]+$/, ""), title: file.name.replace(/\.[^.]+$/, ""),
prompt: file.name.replace(/\.[^.]+$/, ""), prompt: file.name.replace(/\.[^.]+$/, ""),
metadata: {
originalWidth: dimensions.originalWidth,
originalHeight: dimensions.originalHeight,
},
}, },
connections: [], connections: [],
}); });

View File

@ -295,14 +295,21 @@ export function CanvasWorkspace() {
setViewport({ x: newX, y: newY, zoom: newZoom }); setViewport({ x: newX, y: newY, zoom: newZoom });
}, [isMacPlatform, setViewport, viewport.x, viewport.y, viewport.zoom]); }, [isMacPlatform, setViewport, viewport.x, viewport.y, viewport.zoom]);
const getImageDimensionsFromFile = useCallback((file: File): Promise<{ width: number; height: number }> => { const getImageDimensionsFromFile = useCallback((file: File): Promise<{
width: number;
height: number;
originalWidth: number;
originalHeight: number;
}> => {
return new Promise((resolve) => { return new Promise((resolve) => {
const url = URL.createObjectURL(file); const url = URL.createObjectURL(file);
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
const maxSize = 500; const maxSize = 500;
let width = img.naturalWidth; const originalWidth = img.naturalWidth;
let height = img.naturalHeight; const originalHeight = img.naturalHeight;
let width = originalWidth;
let height = originalHeight;
if (width > maxSize || height > maxSize) { if (width > maxSize || height > maxSize) {
const scale = Math.min(maxSize / width, maxSize / height); const scale = Math.min(maxSize / width, maxSize / height);
width = Math.round(width * scale); width = Math.round(width * scale);
@ -315,11 +322,11 @@ export function CanvasWorkspace() {
height = Math.round(height * scale); height = Math.round(height * scale);
} }
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
resolve({ width, height }); resolve({ width, height, originalWidth, originalHeight });
}; };
img.onerror = () => { img.onerror = () => {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
resolve({ width: 300, height: 300 }); resolve({ width: 300, height: 300, originalWidth: 0, originalHeight: 0 });
}; };
img.src = url; img.src = url;
}); });
@ -352,6 +359,10 @@ export function CanvasWorkspace() {
status: "generating", status: "generating",
prompt: cleanName || "拖拽上传", prompt: cleanName || "拖拽上传",
title: cleanName || "拖拽上传", title: cleanName || "拖拽上传",
metadata: {
originalWidth: dimensions.originalWidth,
originalHeight: dimensions.originalHeight,
},
}, },
connections: [], connections: [],
}); });
@ -365,6 +376,10 @@ export function CanvasWorkspace() {
status: "completed", status: "completed",
prompt: cleanName || "拖拽上传", prompt: cleanName || "拖拽上传",
title: cleanName || "拖拽上传", title: cleanName || "拖拽上传",
metadata: {
originalWidth: dimensions.originalWidth,
originalHeight: dimensions.originalHeight,
},
}, },
}); });
toast.success("图片已添加到画布"); toast.success("图片已添加到画布");

View File

@ -139,7 +139,8 @@ async function generateAgentConversation(
- ### 图片分析 - ### 图片分析
- ### 执行计划 - ### 执行计划
- ### 输出设置 - ### 输出设置
6) “图片分析”要结合每张参考图差异,给出风格/构图/材质/光影等具体观察。`; 6) “图片分析”要结合每张参考图差异,给出风格/构图/材质/光影等具体观察。
7) 只有明确拿到“原图分辨率”时,才能写具体像素尺寸;否则只写宽高比/清晰度目标,不要编造 335x500 这类预览尺寸。`;
const prompt = [ const prompt = [
`【用户原始需求】${state.text || "(无文本)"}`, `【用户原始需求】${state.text || "(无文本)"}`,