fix(web): 模型分组 - 画布图片参数对齐创作页规则,宽高比直接取模型组并集 values,质量等能力取路由模型配置

This commit is contained in:
✨await
2026-08-17 11:34:02 +08:00
parent ad0923a892
commit cbd598e8c1
2 changed files with 34 additions and 3 deletions

View File

@@ -68,7 +68,7 @@ export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle =
? []
: usesResolutionPicker && activeResolution
? resolutionOptions.filter((item) => item.tier === activeResolution.tier).map((item) => ({ value: item.ratio, label: item.ratio, size: item.size, width: item.width, height: item.height, icon: item.width === item.height ? "square" : item.width > item.height ? "landscape" : "portrait" }))
: aspectOptions.filter((item) => imageOptionAllowed(profile, item));
: imageAspectOptions(profile);
const selectedAspect = availableAspects.find((item) => imageOptionValue(profile, item) === activeSize || item.value === activeSize) || availableAspects.find((item) => item.label === activeRatio);
const dimensions = readSizeDimensions(activeSize, selectedAspect || aspectOptions[0]);
const activeQualityOptions = profile.quality.values.map((value) => qualityOptions.find((item) => item.value === value) || { value, label: value });
@@ -199,6 +199,34 @@ function imageOptionAllowed(profile: ImageCapabilityConfig, option: AspectOption
return [option.value, option.size, option.width && option.height ? `${option.width}x${option.height}` : ""].filter(Boolean).some((value) => profile.size.values.includes(String(value)));
}
// 宽高比选项直接取模型配置 values(与创作页面一致),不在白名单里的比例(如 8:1)也能显示。
function imageAspectOptions(profile: ImageCapabilityConfig): AspectOption[] {
if (profile.size.parameter === "none") return [];
const values = profile.size.values.filter((value) => value.trim().toLowerCase() !== "auto");
if (!values.length) return profile.size.allowCustom ? aspectOptions.filter((item) => item.value !== "auto") : [];
return values.map((value) => {
const known = aspectOptions.find((item) => (item.size || item.value) === value || item.value === value);
if (known) return known;
const parts = ratioParts(value);
return { value, label: value, size: value, width: parts?.width || 0, height: parts?.height || 0, icon: "custom" };
});
}
function ratioParts(value: string) {
const pixel = value.trim().match(/^(\d+)x(\d+)$/i);
if (pixel) {
const divisor = gcd(Number(pixel[1]), Number(pixel[2]));
return { width: Number(pixel[1]) / divisor, height: Number(pixel[2]) / divisor };
}
const ratio = value.trim().match(/^(\d+):(\d+)$/);
if (!ratio) return undefined;
return { width: Number(ratio[1]), height: Number(ratio[2]) };
}
function gcd(a: number, b: number): number {
return b ? gcd(b, a % b) : a;
}
function imageOptionValue(profile: ImageCapabilityConfig, option: AspectOption) {
const candidates = [option.size, option.value, option.width && option.height ? `${option.width}x${option.height}` : ""].filter(Boolean).map(String);
return candidates.find((value) => profile.size.values.includes(value)) || option.size || option.value || "auto";

View File

@@ -110,14 +110,17 @@ export function resolveCompatibleModel(config: AiConfig, selected: string, requi
// 同显示名分组的模型族:尺寸/比例/分辨率选项取组内全部模型配置的并集,
// 让用户能看到并选择任意成员支持的能力,选中后由兼容路由落到具体模型。
// 质量、透明背景等其余能力取当前选中(路由后)模型的配置,与创作页面一致。
export function mergedImageCapabilityConfig(config: AiConfig, selected: string): ImageCapabilityConfig {
const options = selectableModelsByCapability(config, "image");
const group = options.length ? groupModelsByDisplayName(config, options).find((item) => item.models.includes(selected)) : undefined;
const models = group?.models.length ? group.models : [selected];
const selectedProfile = modelCapabilityConfigFor(config, selected).image;
const profiles = models.map((model) => modelCapabilityConfigFor(config, model).image).filter((profile): profile is ImageCapabilityConfig => Boolean(profile));
if (profiles.length <= 1) return profiles[0] || defaultImageCapabilityConfig();
if (profiles.length <= 1) return selectedProfile || defaultImageCapabilityConfig();
const values = Array.from(new Set(profiles.flatMap((profile) => profile.size.values)));
return { ...profiles[0], size: { ...profiles[0].size, values } };
const base = selectedProfile || profiles[0];
return { ...base, size: { ...base.size, values } };
}
// 切换模型后初始化图片参数为该模型能力默认值,避免旧参数在目标模型族不兼容导致无法切换。