From 624c1923a0a1fe7f20e5ebc06b748ae229a7f162 Mon Sep 17 00:00:00 2001 From: ddCat Date: Thu, 23 Jul 2026 19:28:07 +0800 Subject: [PATCH] =?UTF-8?q?fix(canvas):=20=E5=9B=BE=E5=83=8F=E5=8F=82?= =?UTF-8?q?=E6=95=B0=20-=20=E7=A7=BB=E9=99=A4=E9=80=8F=E6=98=8E=E8=83=8C?= =?UTF-8?q?=E6=99=AF=E8=AF=AF=E6=8B=A6=E6=88=AA=E5=B9=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=2021:9=20=E5=B0=BA=E5=AF=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/service/provider.go | 9 --------- web/src/components/image-settings-panel.tsx | 11 +++++------ web/src/services/api/image.ts | 11 +---------- web/src/stores/use-config-store.ts | 7 ------- 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/backend/internal/service/provider.go b/backend/internal/service/provider.go index 39de9f75e..a611e10fe 100644 --- a/backend/internal/service/provider.go +++ b/backend/internal/service/provider.go @@ -327,9 +327,6 @@ func systemChannelIDFromBaseURL(baseURL string) string { } func runImageTask(ctx context.Context, input canvasGenerationInput) (map[string]interface{}, error) { - if input.Config.TransparentBackground == "true" && !supportsTransparentImageBackground(input.Config) { - return nil, errors.New("当前模型不支持透明背景,请关闭透明背景或切换至 GPT Image 1 系列模型") - } var payload imageResponse if len(input.ReferenceImages) > 0 || input.Mask != nil { body := &bytes.Buffer{} @@ -1781,12 +1778,6 @@ func isArkPlanVideoConfig(config providerConfig) bool { return strings.Contains(strings.ToLower(config.BaseURL), "/api/plan/v3") } -// 透明背景必须按模型能力显式开放,避免上游静默忽略参数后返回不透明图片。 -func supportsTransparentImageBackground(config providerConfig) bool { - model := strings.ToLower(strings.TrimSpace(config.Model)) - return strings.EqualFold(strings.TrimSpace(config.APIFormat), "openai") && (model == "gpt-image-1" || strings.HasPrefix(model, "gpt-image-1-") || strings.HasPrefix(model, "gpt-image-1.")) -} - func normalizeImageQuality(value string) string { switch strings.ToLower(strings.TrimSpace(value)) { case "1k": diff --git a/web/src/components/image-settings-panel.tsx b/web/src/components/image-settings-panel.tsx index 12f17d14e..d87ebde2a 100644 --- a/web/src/components/image-settings-panel.tsx +++ b/web/src/components/image-settings-panel.tsx @@ -2,7 +2,7 @@ import { type ReactNode, useState } from "react"; import { ConfigProvider, Switch } from "antd"; import { type CanvasTheme } from "@/lib/canvas-theme"; -import { supportsTransparentImageBackground, type AiConfig } from "@/stores/use-config-store"; +import { type AiConfig } from "@/stores/use-config-store"; const qualityOptions = [ { value: "auto", label: "自动" }, @@ -19,6 +19,7 @@ const aspectOptions = [ { value: "4:3", label: "4:3", width: 1360, height: 1024, icon: "landscape" }, { value: "3:4", label: "3:4", width: 1024, height: 1360, icon: "portrait" }, { value: "16:9", label: "16:9", width: 1824, height: 1024, icon: "landscape" }, + { value: "21:9", label: "21:9", size: "2352x1008", width: 2352, height: 1008, icon: "landscape" }, { value: "9:16", label: "9:16", width: 1024, height: 1824, icon: "portrait" }, { value: "1:1-2k", label: "1:1(2k)", size: "2048x2048", width: 2048, height: 2048, icon: "square" }, { value: "16:9-2k", label: "16:9(2k)", size: "2048x1152", width: 2048, height: 1152, icon: "landscape" }, @@ -43,7 +44,6 @@ export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle = const [snapDimensionToStep, setSnapDimensionToStep] = useState(true); const quality = config.quality || "auto"; const transparentBackground = config.transparentBackground === "true"; - const transparentBackgroundSupported = supportsTransparentImageBackground(config, config.model || config.imageModel); const count = Math.max(1, Math.min(maxCount, Math.floor(Math.abs(Number(config.count)) || 1))); const activeSize = config.size || "auto"; const selectedAspect = aspectOptions.find((item) => (item.size || item.value) === activeSize || item.value === activeSize); @@ -84,15 +84,14 @@ export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle =
透明背景 -
- {transparentBackgroundSupported ? "输出保留 Alpha 通道的 PNG" : transparentBackground ? "当前模型不支持,生成会被阻止" : "当前模型不支持透明背景"} +
+ 请求模型输出保留 Alpha 通道的 PNG
- event.stopPropagation()}> + event.stopPropagation()}> onConfigChange("transparentBackground", checked ? "true" : "false")} /> diff --git a/web/src/services/api/image.ts b/web/src/services/api/image.ts index 1e408edfc..c9a9a0d61 100644 --- a/web/src/services/api/image.ts +++ b/web/src/services/api/image.ts @@ -1,6 +1,6 @@ import axios from "axios"; -import { buildApiUrl, isSystemProxyBaseUrl, resolveBackendApiUrl, resolveModelRequestConfig, supportsTransparentImageBackground, type AiConfig, type ModelChannel } from "@/stores/use-config-store"; +import { buildApiUrl, isSystemProxyBaseUrl, resolveBackendApiUrl, resolveModelRequestConfig, type AiConfig, type ModelChannel } from "@/stores/use-config-store"; import { nanoid } from "nanoid"; import { dataUrlToFile } from "@/lib/image-utils"; import { buildImageReferencePromptText } from "@/lib/image-reference-prompt"; @@ -233,13 +233,6 @@ function readStatusError(status: number | undefined, fallback: string) { return status ? `${fallback}:${status}` : fallback; } -function assertTransparentBackgroundSupported(config: AiConfig, model: string) { - if (config.transparentBackground !== "true") return; - if (!supportsTransparentImageBackground(config, model)) { - throw new Error("当前模型不支持透明背景,请关闭“透明背景”或切换至 GPT Image 1 系列模型"); - } -} - function withSystemPrompt(config: AiConfig, prompt: string) { const systemPrompt = config.systemPrompt.trim(); return systemPrompt ? `${systemPrompt}\n\n${prompt}` : prompt; @@ -764,7 +757,6 @@ function parseGeminiImagePayload(payload: GeminiPayload) { export async function requestGeneration(config: AiConfig, prompt: string, options?: RequestOptions) { const selectedModel = config.model || config.imageModel; - assertTransparentBackgroundSupported(config, selectedModel); const requestConfig = resolveModelRequestConfig(config, selectedModel); const n = Math.max(1, Math.min(15, Math.floor(Math.abs(Number(config.count)) || 1))); if (requestConfig.apiFormat === "gemini") { @@ -803,7 +795,6 @@ export async function requestGeneration(config: AiConfig, prompt: string, option export async function requestEdit(config: AiConfig, prompt: string, references: ReferenceImage[], mask?: ReferenceImage, options?: RequestOptions) { const selectedModel = config.model || config.imageModel; - assertTransparentBackgroundSupported(config, selectedModel); const requestConfig = resolveModelRequestConfig(config, selectedModel); const n = Math.max(1, Math.min(15, Math.floor(Math.abs(Number(config.count)) || 1))); const requestPrompt = buildImageReferencePromptText(prompt, references); diff --git a/web/src/stores/use-config-store.ts b/web/src/stores/use-config-store.ts index 5c51d4c4b..4fd17cced 100644 --- a/web/src/stores/use-config-store.ts +++ b/web/src/stores/use-config-store.ts @@ -383,13 +383,6 @@ export function resolveModelChannel(config: AiConfig, value: string) { return matched || config.channels[0] || createModelChannel({ id: "default", name: "默认渠道", baseUrl: config.baseUrl, apiKey: config.apiKey, apiFormat: config.apiFormat, models: config.models.map(modelOptionName) }); } -// 透明背景必须按模型能力显式开放,避免代理接口静默忽略参数后返回不透明图片。 -export function supportsTransparentImageBackground(config: AiConfig, value: string) { - const channel = resolveModelChannel(config, value); - const model = modelOptionName(value).trim().toLowerCase(); - return channel.apiFormat === "openai" && (model === "gpt-image-1" || model.startsWith("gpt-image-1-") || model.startsWith("gpt-image-1.")); -} - export function resolveModelRequestConfig(config: AiConfig, value: string) { const channel = resolveModelChannel(config, value); return {