大量优化修改扣积分规则
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { ChevronDown, SlidersHorizontal, Sparkles } from "lucide-react";
|
||||
import { CustomSelect } from "./custom-select";
|
||||
import { modelDurations, modelResolutions } from "./free-create/constants";
|
||||
import type { ModelConfig } from "../types";
|
||||
|
||||
/** 无目录时的回落清单(展示名,与会话 params.model 历史值兼容)。 */
|
||||
export const OMNI_VIDEO_MODELS = ["Seedance 2.5", "Seedance 2.0", "Seedance 2.0 Fast", "Seedance 2.0 Mini"];
|
||||
export const OMNI_IMAGE_MODELS = ["Seedream5.0", "YQ image2"];
|
||||
export const OMNI_RESOLUTIONS = ["1080p", "720p", "480p"];
|
||||
export const OMNI_RATIOS = ["9:16", "16:9", "1:1", "4:3", "3:4"];
|
||||
export const OMNI_VIDEO_DURATIONS = [
|
||||
"4 秒", "5 秒", "6 秒", "7 秒", "8 秒", "9 秒", "10 秒",
|
||||
"智能时长", "4 秒", "5 秒", "6 秒", "7 秒", "8 秒", "9 秒", "10 秒",
|
||||
"11 秒", "12 秒", "13 秒", "14 秒", "15 秒", "30 秒",
|
||||
];
|
||||
export const OMNI_IMAGE_COUNTS = ["1 张", "2 张", "4 张", "8 张"];
|
||||
@@ -20,6 +23,59 @@ function withCurrent(values: string[], current: string) {
|
||||
return current && !values.includes(current) ? [current, ...values] : values;
|
||||
}
|
||||
|
||||
function modelOptionLabel(config: ModelConfig): string {
|
||||
return (config.display_name || config.name || "").trim();
|
||||
}
|
||||
|
||||
/** 忽略空格/横杠/大小写,兼容旧会话「Seedance 2.0 Mini」对上后台「Seedance-2.0-Mini」。 */
|
||||
function normalizeModelKey(value: string): string {
|
||||
return String(value || "").toLowerCase().replace(/[\s_\-·.]+/g, "");
|
||||
}
|
||||
|
||||
/** 会话里存的是展示名;用 display_name / name 都能对上目录项。 */
|
||||
export function findCatalogModel(
|
||||
configs: ModelConfig[] | undefined,
|
||||
label: string,
|
||||
capability: "video" | "image",
|
||||
): ModelConfig | undefined {
|
||||
const list = (configs || []).filter((c) => c.capability === capability && c.status !== "disabled");
|
||||
const key = (label || "").trim();
|
||||
if (!key) return list[0];
|
||||
const norm = normalizeModelKey(key);
|
||||
return (
|
||||
list.find((c) => modelOptionLabel(c) === key)
|
||||
|| list.find((c) => c.name === key)
|
||||
|| list.find((c) => normalizeModelKey(modelOptionLabel(c)) === norm)
|
||||
|| list.find((c) => normalizeModelKey(c.name) === norm)
|
||||
|| list.find((c) => {
|
||||
const dn = normalizeModelKey(c.display_name || "");
|
||||
const nm = normalizeModelKey(c.name || "");
|
||||
return (dn && (dn.includes(norm) || norm.includes(dn))) || (nm && (nm.includes(norm) || norm.includes(nm)));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function catalogModelLabels(
|
||||
configs: ModelConfig[] | undefined,
|
||||
capability: "video" | "image",
|
||||
fallback: string[],
|
||||
): string[] {
|
||||
const labels = (configs || [])
|
||||
.filter((c) => c.capability === capability)
|
||||
.map(modelOptionLabel)
|
||||
.filter(Boolean);
|
||||
const seen = new Set<string>();
|
||||
const unique = labels.filter((x) => (seen.has(x) ? false : (seen.add(x), true)));
|
||||
return unique.length ? unique : fallback;
|
||||
}
|
||||
|
||||
function durationLabelsForModel(config: ModelConfig | undefined, isVideo: boolean): string[] {
|
||||
if (!isVideo) return [...OMNI_IMAGE_COUNTS];
|
||||
const seconds = modelDurations(config);
|
||||
if (!seconds.length) return [...OMNI_VIDEO_DURATIONS];
|
||||
return ["智能时长", ...seconds.map((n) => `${n} 秒`)];
|
||||
}
|
||||
|
||||
export function OmniParamBar({
|
||||
isVideo,
|
||||
disabled,
|
||||
@@ -27,6 +83,7 @@ export function OmniParamBar({
|
||||
resolution,
|
||||
ratio,
|
||||
duration,
|
||||
catalogModels,
|
||||
onModel,
|
||||
onResolution,
|
||||
onRatio,
|
||||
@@ -38,6 +95,7 @@ export function OmniParamBar({
|
||||
resolution: string;
|
||||
ratio: string;
|
||||
duration: string;
|
||||
catalogModels?: ModelConfig[];
|
||||
onModel: (value: string) => void;
|
||||
onResolution: (value: string) => void;
|
||||
onRatio: (value: string) => void;
|
||||
@@ -47,6 +105,20 @@ export function OmniParamBar({
|
||||
const [customOn, setCustomOn] = useState(isVideo ? duration !== "智能时长" : true);
|
||||
const wrapRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const capability = isVideo ? "video" as const : "image" as const;
|
||||
const selected = useMemo(
|
||||
() => findCatalogModel(catalogModels, model, capability),
|
||||
[catalogModels, model, capability],
|
||||
);
|
||||
|
||||
const models = withCurrent(
|
||||
catalogModelLabels(catalogModels, capability, isVideo ? OMNI_VIDEO_MODELS : OMNI_IMAGE_MODELS),
|
||||
model,
|
||||
);
|
||||
const allowedRes = isVideo ? modelResolutions(selected) : [];
|
||||
const resolutions = withCurrent(allowedRes.length ? allowedRes : OMNI_RESOLUTIONS, resolution);
|
||||
const durations = withCurrent(durationLabelsForModel(selected, isVideo), duration);
|
||||
|
||||
useEffect(() => {
|
||||
setCustomOn(isVideo ? duration !== "智能时长" : true);
|
||||
}, [isVideo, duration]);
|
||||
@@ -60,8 +132,18 @@ export function OmniParamBar({
|
||||
return () => document.removeEventListener("mousedown", onDown);
|
||||
}, [menuOpen]);
|
||||
|
||||
const models = withCurrent(isVideo ? OMNI_VIDEO_MODELS : OMNI_IMAGE_MODELS, model);
|
||||
const durations = isVideo ? OMNI_VIDEO_DURATIONS : OMNI_IMAGE_COUNTS;
|
||||
useEffect(() => {
|
||||
if (!selected || !isVideo) return;
|
||||
const nextRes = modelResolutions(selected);
|
||||
if (nextRes.length && resolution && !nextRes.includes(resolution)) {
|
||||
onResolution(nextRes.includes("720p") ? "720p" : nextRes[0]);
|
||||
}
|
||||
const nextDur = durationLabelsForModel(selected, true);
|
||||
if (duration && duration !== "智能时长" && !nextDur.includes(duration)) {
|
||||
onDuration(nextDur.includes("8 秒") ? "8 秒" : (nextDur.find((x) => x !== "智能时长") || "智能时长"));
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selected?.id, isVideo]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -84,7 +166,7 @@ export function OmniParamBar({
|
||||
disabled={disabled}
|
||||
value={resolution}
|
||||
onChange={onResolution}
|
||||
options={toOptions(withCurrent(OMNI_RESOLUTIONS, resolution))}
|
||||
options={toOptions(resolutions)}
|
||||
/>
|
||||
</label>
|
||||
<label className="omni-parameter">
|
||||
@@ -136,7 +218,7 @@ export function OmniParamBar({
|
||||
</div>
|
||||
) : null}
|
||||
<div className="omni-duration-values" hidden={isVideo && !customOn}>
|
||||
{durations.map((value) => (
|
||||
{(isVideo ? durations.filter((value) => value !== "智能时长") : durations).map((value) => (
|
||||
<button
|
||||
type="button"
|
||||
key={value}
|
||||
|
||||
Reference in New Issue
Block a user