fix(image): 修复图片生成和编辑请求中尺寸参数传递问题

- 添加 resolveRequestSize 函数处理尺寸参数解析逻辑
- 将 pixelSize 变量重命名为 requestSize 以提高代码可读性
- 修复当尺寸为 auto 时不发送 size 参数的功能
- 确保所有非 auto 尺寸值都会正确传递到请求中
- 更新图片生成和编辑函数中的尺寸参数处理逻辑
This commit is contained in:
HouYunFei
2026-05-26 11:26:27 +08:00
parent 778fd065ec
commit 9754af3bf9
8 changed files with 427 additions and 392 deletions
+15 -22
View File
@@ -2,19 +2,22 @@
import { BookOpen, CheckSquare, ClipboardPaste, Download, FolderPlus, History, LoaderCircle, Plus, SlidersHorizontal, Sparkles, Trash2, Upload, VideoIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { App, AutoComplete, Button, Checkbox, Drawer, Empty, Input, Modal, Tag, Typography } from "antd";
import { App, Button, Checkbox, Drawer, Empty, Input, Modal, Tag, Typography } from "antd";
import localforage from "localforage";
import { nanoid } from "nanoid";
import { AssetPickerModal, type InsertAssetPayload } from "@/app/(user)/canvas/components/asset-picker-modal";
import { ModelPicker } from "@/components/model-picker";
import { PromptSelectDialog } from "@/components/prompts/prompt-select-dialog";
import { VideoSettingsPanel, normalizeVideoResolutionValue, normalizeVideoSizeValue, videoSizeLabel } from "@/components/video-settings-panel";
import { canvasThemes } from "@/lib/canvas-theme";
import { formatBytes, formatDuration } from "@/lib/image-utils";
import { resolveMediaUrl, uploadMediaFile } from "@/services/file-storage";
import { uploadImage } from "@/services/image-storage";
import { requestVideoGeneration } from "@/services/api/video";
import { useAssetStore } from "@/stores/use-asset-store";
import { useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
import { useThemeStore } from "@/stores/use-theme-store";
import type { ReferenceImage } from "@/types/image";
type GeneratedVideo = {
@@ -52,9 +55,6 @@ type GenerationLog = {
type UpdateAiConfig = <K extends keyof AiConfig>(key: K, value: AiConfig[K]) => void;
const sizeOptions = ["1280x720", "720x1280", "1024x1024", "1792x1024", "1024x1792"].map((value) => ({ label: value, value }));
const resolutionOptions = ["720", "480"].map((value) => ({ label: `${value}p`, value }));
const secondOptions = ["6", "10", "12", "16", "20"].map((value) => ({ label: `${value}s`, value }));
const LOG_STORE_KEY = "infinite-canvas:video_generation_logs";
const logStore = localforage.createInstance({ name: "infinite-canvas", storeName: "video_generation_logs" });
@@ -306,7 +306,7 @@ export default function VideoPage() {
<div className="flex items-center justify-between rounded-lg border border-stone-200 bg-stone-50 px-3 py-2 text-sm dark:border-stone-800 dark:bg-stone-900 sm:hidden">
<span className="truncate text-stone-500 dark:text-stone-400">
{model} · {normalizeResolution(effectiveConfig.vquality)}p · {normalizeVideoSize(effectiveConfig.size)} · {normalizeVideoSeconds(effectiveConfig.videoSeconds)}s
{model} · {normalizeResolution(effectiveConfig.vquality)}p · {videoSizeLabel(effectiveConfig.size)} · {normalizeVideoSeconds(effectiveConfig.videoSeconds)}s
</span>
<Button size="small" type="text" icon={<SlidersHorizontal className="size-4" />} onClick={() => setSettingsOpen(true)}>
@@ -357,8 +357,8 @@ export default function VideoPage() {
<Drawer title="生成记录" placement="bottom" size="large" open={logsOpen} onClose={() => setLogsOpen(false)}>
<LogPanel logs={logs} selectedLogIds={selectedLogIds} activeLogId={previewLog?.id} onSelectedLogIdsChange={setSelectedLogIds} onCreateSession={createSession} onDeleteSelected={() => setDeleteConfirmOpen(true)} onPreviewLog={previewGenerationLog} />
</Drawer>
<Drawer title="参数" placement="bottom" size="default" open={settingsOpen} onClose={() => setSettingsOpen(false)}>
<div className="grid grid-cols-2 gap-3">
<Drawer title="参数" placement="bottom" height="82vh" open={settingsOpen} onClose={() => setSettingsOpen(false)}>
<div className="grid grid-cols-2 gap-3 pb-4">
<GenerationSettings config={effectiveConfig} model={model} updateConfig={updateConfig} openConfigDialog={openConfigDialog} />
</div>
</Drawer>
@@ -372,24 +372,17 @@ export default function VideoPage() {
}
function GenerationSettings({ config, model, updateConfig, openConfigDialog }: { config: AiConfig; model: string; updateConfig: UpdateAiConfig; openConfigDialog: (shouldPromptContinue?: boolean) => void }) {
const theme = canvasThemes[useThemeStore((state) => state.theme)];
return (
<>
<label className="col-span-2 block min-w-0 sm:col-span-1">
<span className="mb-1.5 block text-sm font-semibold sm:mb-2 sm:text-base"></span>
<ModelPicker config={config} value={model} onChange={(value) => updateConfig("videoModel", value)} fullWidth onMissingConfig={() => openConfigDialog(false)} />
</label>
<label className="block">
<span className="mb-1.5 block text-sm font-semibold sm:mb-2 sm:text-base"></span>
<AutoComplete className="canvas-control-select w-full" value={config.videoSeconds} options={secondOptions} onChange={(value) => updateConfig("videoSeconds", value)} />
</label>
<label className="block">
<span className="mb-1.5 block text-sm font-semibold sm:mb-2 sm:text-base"></span>
<AutoComplete className="canvas-control-select w-full" value={config.size} options={sizeOptions} placeholder="例如 1280x720" onChange={(value) => updateConfig("size", value)} />
</label>
<label className="block">
<span className="mb-1.5 block text-sm font-semibold sm:mb-2 sm:text-base"></span>
<AutoComplete className="canvas-control-select w-full" value={normalizeResolution(config.vquality)} options={resolutionOptions} placeholder="例如 720" onChange={(value) => updateConfig("vquality", value)} />
</label>
<div className="col-span-2">
<VideoSettingsPanel config={config} onConfigChange={(key, value) => updateConfig(key, value)} theme={theme} showTitle={false} className="space-y-4" />
</div>
</>
);
}
@@ -582,13 +575,13 @@ function buildVideoConfig(config: AiConfig, model: string): AiConfig {
function normalizeVideoSeconds(value: string) {
const seconds = Math.floor(Number(value) || 6);
return String([6, 10, 12, 16, 20].includes(seconds) ? seconds : 6);
return String(Math.max(1, Math.min(20, seconds)));
}
function normalizeVideoSize(value: string) {
return /^\d+x\d+$/.test(value || "") ? value : "1280x720";
return normalizeVideoSizeValue(value);
}
function normalizeResolution(value: string) {
return value.replace(/p$/i, "") || "720";
return normalizeVideoResolutionValue(value);
}