fix: improve agent workflow settings loading
This commit is contained in:
parent
03cdefca34
commit
040a1f514f
@ -184,6 +184,9 @@ const WORKFLOW_STEP_DRAG_DATA_TYPE = "application/x-agent-workflow-step";
|
||||
const WORKFLOW_SETTINGS_DRAFT_STORAGE_KEY = "agent-workflow-settings-draft:v1";
|
||||
const WORKFLOW_SETTINGS_STALE_DRAFT_STORAGE_KEY = "agent-workflow-settings-stale-draft:v1";
|
||||
const WORKFLOW_SETTINGS_DRAFT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
const AGENT_WORKFLOW_SETTINGS_ENDPOINT =
|
||||
"/api/site-settings?scope=agent-workflow-admin";
|
||||
const AGENT_WORKFLOW_SAVE_TIMEOUT_MS = 30_000;
|
||||
const DELETE_WORKFLOW_STEP_PASSWORD = "123456";
|
||||
const BUSINESS_MODE_DEFAULT_MODEL_EMPTY_VALUE = "__agent_workflow_mode_default_model_empty__";
|
||||
|
||||
@ -282,6 +285,24 @@ function scheduleWorkflowIdleTask(callback: () => void, timeoutMs = 2000) {
|
||||
return () => globalThis.clearTimeout(timer);
|
||||
}
|
||||
|
||||
async function fetchAgentWorkflowSettingsWithTimeout(
|
||||
input: RequestInfo | URL,
|
||||
init: RequestInit = {},
|
||||
timeoutMs = AGENT_WORKFLOW_SAVE_TIMEOUT_MS
|
||||
) {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = globalThis.setTimeout(() => controller.abort(), timeoutMs);
|
||||
|
||||
try {
|
||||
return await fetch(input, {
|
||||
...init,
|
||||
signal: controller.signal,
|
||||
});
|
||||
} finally {
|
||||
globalThis.clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
|
||||
function BufferedInput({
|
||||
commitDelayMs = 450,
|
||||
onBlur,
|
||||
@ -1881,7 +1902,7 @@ export function AgentWorkflowSettingsClient({
|
||||
backLabel = "返回设置",
|
||||
}: AgentWorkflowSettingsClientProps = {}) {
|
||||
const { data, isLoading, mutate } = useSWR<AgentWorkflowSettingsPayload>(
|
||||
"/api/site-settings",
|
||||
AGENT_WORKFLOW_SETTINGS_ENDPOINT,
|
||||
fetcher,
|
||||
{ refreshInterval: 60_000 }
|
||||
);
|
||||
@ -3817,9 +3838,12 @@ export function AgentWorkflowSettingsClient({
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setIsSaving(true);
|
||||
const latestSettingsResponse = await fetch("/api/site-settings", {
|
||||
cache: "no-store",
|
||||
});
|
||||
const latestSettingsResponse = await fetchAgentWorkflowSettingsWithTimeout(
|
||||
AGENT_WORKFLOW_SETTINGS_ENDPOINT,
|
||||
{
|
||||
cache: "no-store",
|
||||
}
|
||||
);
|
||||
|
||||
if (!latestSettingsResponse.ok) {
|
||||
throw new Error("保存前校验服务器配置失败,请刷新页面后重试");
|
||||
@ -3871,11 +3895,14 @@ export function AgentWorkflowSettingsClient({
|
||||
changedPayload.agentWorkflowSettingsBaseSignatures[field] = baseSignatures[field];
|
||||
}
|
||||
|
||||
const response = await fetch("/api/site-settings", {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(changedPayload),
|
||||
});
|
||||
const response = await fetchAgentWorkflowSettingsWithTimeout(
|
||||
"/api/site-settings",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(changedPayload),
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
let message = "保存失败";
|
||||
@ -3939,7 +3966,11 @@ export function AgentWorkflowSettingsClient({
|
||||
.join("、")}`
|
||||
);
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : "保存失败");
|
||||
if (error instanceof DOMException && error.name === "AbortError") {
|
||||
toast.error("保存请求超时,请检查网络或稍后重试");
|
||||
} else {
|
||||
toast.error(error instanceof Error ? error.message : "保存失败");
|
||||
}
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
||||
@ -38,7 +38,6 @@ import {
|
||||
normalizeAgentWorkflowStepOrdering,
|
||||
normalizeAgentWorkflowUiConfig,
|
||||
} from "@/lib/agents/workflow-ui-config";
|
||||
import { optimizeAgentWorkflowUiConfigPreviewImages } from "@/lib/agents/workflow-preview-images";
|
||||
import {
|
||||
AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||||
defaultAgentWorkflowBrandModelConfig,
|
||||
@ -505,16 +504,17 @@ const PUBLIC_SITE_SETTINGS_SCOPES = new Set<string>([
|
||||
|
||||
const SCOPED_SITE_SETTINGS_SERVER_CACHE_TTL_MS = 30_000;
|
||||
const scopedSiteSettingsServerCache = new Map<
|
||||
PublicSiteSettingsScope,
|
||||
string,
|
||||
{ data: Record<string, unknown>; expiresAt: number }
|
||||
>();
|
||||
|
||||
function createScopedSiteSettingsResponse(
|
||||
scope: PublicSiteSettingsScope,
|
||||
data: Record<string, unknown>,
|
||||
cacheStatus: "HIT" | "MISS" = "MISS"
|
||||
cacheStatus: "HIT" | "MISS" = "MISS",
|
||||
cacheKey: string = scope
|
||||
) {
|
||||
scopedSiteSettingsServerCache.set(scope, {
|
||||
scopedSiteSettingsServerCache.set(cacheKey, {
|
||||
data,
|
||||
expiresAt: Date.now() + SCOPED_SITE_SETTINGS_SERVER_CACHE_TTL_MS,
|
||||
});
|
||||
@ -561,7 +561,13 @@ function createBrandingSettings(settings: Record<string, unknown> | undefined) {
|
||||
};
|
||||
}
|
||||
|
||||
async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
async function getScopedPublicSiteSettings(
|
||||
scope: PublicSiteSettingsScope,
|
||||
options: {
|
||||
brandName?: string;
|
||||
cacheKey?: string;
|
||||
} = {}
|
||||
) {
|
||||
if (scope === "auth") {
|
||||
const { settings, valueByKey } = await readScopedSiteSettings([
|
||||
"login_notification",
|
||||
@ -580,11 +586,30 @@ async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
const { valueByKey } = await readScopedSiteSettings([
|
||||
AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||||
]);
|
||||
return createScopedSiteSettingsResponse(scope, {
|
||||
agentWorkflowBrandModelConfig: normalizeAgentWorkflowBrandModelConfig(
|
||||
valueByKey.get(AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY)
|
||||
),
|
||||
});
|
||||
const brandModelConfig = normalizeAgentWorkflowBrandModelConfig(
|
||||
valueByKey.get(AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY)
|
||||
);
|
||||
const normalizedBrandName = String(options.brandName || "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const scopedBrandModelConfig = normalizedBrandName
|
||||
? {
|
||||
...brandModelConfig,
|
||||
entries: brandModelConfig.entries.filter(
|
||||
(entry) =>
|
||||
entry.brandName.trim().toLowerCase() === normalizedBrandName
|
||||
),
|
||||
}
|
||||
: brandModelConfig;
|
||||
|
||||
return createScopedSiteSettingsResponse(
|
||||
scope,
|
||||
{
|
||||
agentWorkflowBrandModelConfig: scopedBrandModelConfig,
|
||||
},
|
||||
"MISS",
|
||||
options.cacheKey
|
||||
);
|
||||
}
|
||||
|
||||
if (scope === "agent-presets") {
|
||||
@ -603,24 +628,19 @@ async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
}
|
||||
|
||||
if (scope === "agent-canvas") {
|
||||
const [{ settings, valueByKey }, agentPsdTemplates] = await Promise.all([
|
||||
readScopedSiteSettings([
|
||||
REALTIME_CANVAS_CONFIG_KEY,
|
||||
REALTIME_CANVAS_MODE_ICON_CONFIG_KEY,
|
||||
CANVAS_TOOLBAR_CONFIG_SETTING_KEY,
|
||||
LAYER_SPLIT_CONFIG_KEY,
|
||||
ANGLE_EDIT_CONFIG_KEY,
|
||||
CANVAS_AGENT_MODE_ENABLED_KEY,
|
||||
VIDEO_CANVAS_ENABLED_KEY,
|
||||
VIDEO_CANVAS_SIDEBAR_ENABLED_KEY,
|
||||
ENHANCE_PRO_KREA_SETTING_KEY,
|
||||
STYLE_PRO_CONFIG_KEY,
|
||||
AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||||
AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||||
AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY,
|
||||
AGENT_PSD_TEMPLATE_CATEGORY_TAG_CONFIG_KEY,
|
||||
]),
|
||||
readAgentPsdTemplates().catch(() => []),
|
||||
const { settings, valueByKey } = await readScopedSiteSettings([
|
||||
REALTIME_CANVAS_CONFIG_KEY,
|
||||
REALTIME_CANVAS_MODE_ICON_CONFIG_KEY,
|
||||
CANVAS_TOOLBAR_CONFIG_SETTING_KEY,
|
||||
LAYER_SPLIT_CONFIG_KEY,
|
||||
ANGLE_EDIT_CONFIG_KEY,
|
||||
CANVAS_AGENT_MODE_ENABLED_KEY,
|
||||
VIDEO_CANVAS_ENABLED_KEY,
|
||||
VIDEO_CANVAS_SIDEBAR_ENABLED_KEY,
|
||||
ENHANCE_PRO_KREA_SETTING_KEY,
|
||||
STYLE_PRO_CONFIG_KEY,
|
||||
AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||||
AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY,
|
||||
]);
|
||||
const canvasFeatureAvailability = await readCanvasFeatureAvailability(
|
||||
valueByKey
|
||||
@ -629,11 +649,6 @@ async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
const videoCanvasSidebarEnabled = normalizeVideoCanvasSidebarEnabled(
|
||||
valueByKey.get(VIDEO_CANVAS_SIDEBAR_ENABLED_KEY)
|
||||
);
|
||||
const agentPsdTemplateCategoryTagConfig =
|
||||
normalizeAgentPsdTemplateCategoryTagConfig(
|
||||
valueByKey.get(AGENT_PSD_TEMPLATE_CATEGORY_TAG_CONFIG_KEY)
|
||||
);
|
||||
|
||||
return createScopedSiteSettingsResponse(scope, {
|
||||
...createBrandingSettings(typedSettings),
|
||||
agentEnabled: typedSettings?.agentEnabled ?? true,
|
||||
@ -667,16 +682,9 @@ async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
agentWorkflowUiConfig: normalizeAgentWorkflowUiConfig(
|
||||
valueByKey.get(AGENT_WORKFLOW_UI_CONFIG_KEY)
|
||||
),
|
||||
agentWorkflowBrandModelConfig: normalizeAgentWorkflowBrandModelConfig(
|
||||
valueByKey.get(AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY)
|
||||
),
|
||||
agentWorkflowShowcaseConfig: normalizeAgentWorkflowShowcaseConfig(
|
||||
valueByKey.get(AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY)
|
||||
),
|
||||
agentPsdTemplateCategoryTagIndex: buildAgentPsdTemplateCategoryTagIndex({
|
||||
templates: agentPsdTemplates,
|
||||
config: agentPsdTemplateCategoryTagConfig,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -842,23 +850,71 @@ async function getScopedPublicSiteSettings(scope: PublicSiteSettingsScope) {
|
||||
});
|
||||
}
|
||||
|
||||
async function getAgentWorkflowAdminSettingsResponse() {
|
||||
const { settings, valueByKey } = await readScopedSiteSettings([
|
||||
...AGENT_WORKFLOW_SETTINGS_CONFLICT_KEYS,
|
||||
]);
|
||||
const workflowSettings =
|
||||
createAgentWorkflowSettingsStateFromValues(valueByKey);
|
||||
const response = NextResponse.json({
|
||||
...workflowSettings,
|
||||
agentWorkflowDefaultModelId:
|
||||
String(
|
||||
(settings as { agentWorkflowDefaultModelId?: string | null } | undefined)
|
||||
?.agentWorkflowDefaultModelId || ""
|
||||
).trim() || null,
|
||||
});
|
||||
|
||||
response.headers.set("Cache-Control", "no-store");
|
||||
response.headers.set("X-Site-Settings-Scope", "agent-workflow-admin");
|
||||
return response;
|
||||
}
|
||||
|
||||
// GET /api/site-settings - 获取网站设置 (公开)
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const scope = request.nextUrl.searchParams.get("scope") || "";
|
||||
if (PUBLIC_SITE_SETTINGS_SCOPES.has(scope)) {
|
||||
const scopedScope = scope as PublicSiteSettingsScope;
|
||||
const cached = scopedSiteSettingsServerCache.get(scopedScope);
|
||||
const brandName =
|
||||
scopedScope === "agent-brand-model"
|
||||
? request.nextUrl.searchParams.get("brand") || ""
|
||||
: "";
|
||||
const cacheKey = brandName.trim()
|
||||
? `${scopedScope}:${brandName.trim().toLowerCase()}`
|
||||
: scopedScope;
|
||||
const cached = scopedSiteSettingsServerCache.get(cacheKey);
|
||||
if (cached && cached.expiresAt > Date.now()) {
|
||||
return createScopedSiteSettingsResponse(scopedScope, cached.data, "HIT");
|
||||
return createScopedSiteSettingsResponse(
|
||||
scopedScope,
|
||||
cached.data,
|
||||
"HIT",
|
||||
cacheKey
|
||||
);
|
||||
}
|
||||
|
||||
return getScopedPublicSiteSettings(scopedScope);
|
||||
return getScopedPublicSiteSettings(scopedScope, {
|
||||
brandName,
|
||||
cacheKey,
|
||||
});
|
||||
}
|
||||
|
||||
const session = await auth().catch(() => null);
|
||||
const isAdmin = isSiteAdminType(session?.user?.type);
|
||||
const canManageAgentWorkflow = isAgentWorkflowAdminType(session?.user?.type);
|
||||
|
||||
if (scope === "agent-workflow-admin") {
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
if (!canManageAgentWorkflow) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
}
|
||||
|
||||
return getAgentWorkflowAdminSettingsResponse();
|
||||
}
|
||||
|
||||
const [
|
||||
settings,
|
||||
notificationSetting,
|
||||
@ -2316,14 +2372,9 @@ export async function PUT(request: NextRequest) {
|
||||
|
||||
if (agentWorkflowUiConfig !== undefined) {
|
||||
const normalized = normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig);
|
||||
const { config: optimized, summary } =
|
||||
await optimizeAgentWorkflowUiConfigPreviewImages(normalized);
|
||||
if (summary.optimized > 0 || summary.failed > 0) {
|
||||
console.log("[Site Settings API] Agent workflow preview optimization:", summary);
|
||||
}
|
||||
await persistSystemSettingWithHistory(
|
||||
AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||||
optimized,
|
||||
normalized,
|
||||
"agent-workflow"
|
||||
);
|
||||
}
|
||||
@ -2574,6 +2625,7 @@ export async function PUT(request: NextRequest) {
|
||||
}
|
||||
|
||||
await persistHomeAnimationConfig();
|
||||
scopedSiteSettingsServerCache.clear();
|
||||
|
||||
return NextResponse.json({
|
||||
...updated,
|
||||
@ -2973,14 +3025,9 @@ export async function PUT(request: NextRequest) {
|
||||
|
||||
if (agentWorkflowUiConfig !== undefined) {
|
||||
const normalized = normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig);
|
||||
const { config: optimized, summary } =
|
||||
await optimizeAgentWorkflowUiConfigPreviewImages(normalized);
|
||||
if (summary.optimized > 0 || summary.failed > 0) {
|
||||
console.log("[Site Settings API] Agent workflow preview optimization:", summary);
|
||||
}
|
||||
await persistSystemSettingWithHistory(
|
||||
AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||||
optimized,
|
||||
normalized,
|
||||
"agent-workflow"
|
||||
);
|
||||
}
|
||||
@ -3227,6 +3274,7 @@ export async function PUT(request: NextRequest) {
|
||||
},
|
||||
});
|
||||
}
|
||||
scopedSiteSettingsServerCache.clear();
|
||||
|
||||
return NextResponse.json({
|
||||
...created,
|
||||
|
||||
@ -133,7 +133,6 @@ import {
|
||||
normalizeAgentModeWorkspaceState,
|
||||
} from "@/lib/agents/mode-workspace-state";
|
||||
import { normalizeAgentPresetModeConfig } from "@/lib/agents/preset-mode-config";
|
||||
import type { AgentPsdTemplateCategoryTagIndex } from "@/lib/agents/psd-template-category-tag-config";
|
||||
import { normalizeAgentWorkflowBrandModelConfig } from "@/lib/agents/workflow-brand-model-config";
|
||||
import {
|
||||
compactVideoCanvasMarkers,
|
||||
@ -171,7 +170,6 @@ import {
|
||||
getEnabledAgentWorkflowStepTree,
|
||||
getAgentWorkflowBusinessModeSettings,
|
||||
getAgentWorkflowPageFeatureSettings,
|
||||
normalizeAgentWorkflowUiConfig,
|
||||
sanitizeAgentWorkflowSelections,
|
||||
} from "@/lib/agents/workflow-ui-config";
|
||||
import { cn, fetcher } from "@/lib/utils";
|
||||
@ -222,6 +220,7 @@ import type {
|
||||
AgentWorkflowSelectedBrandModel,
|
||||
AgentWorkflowShowcaseConfig,
|
||||
AgentWorkflowStepKey,
|
||||
AgentWorkflowUiConfig,
|
||||
} from "@/types/agent";
|
||||
import type {
|
||||
CanvasEdge,
|
||||
@ -234,11 +233,20 @@ import type {
|
||||
} from "@/types/canvas";
|
||||
|
||||
const CANVAS_SITE_SETTINGS_REFRESH_INTERVAL_MS = 15000;
|
||||
const CANVAS_SITE_SETTINGS_TIMEOUT_MS = 10000;
|
||||
|
||||
const fetchCanvasSiteSettings = async (url: string) => {
|
||||
const separator = url.includes("?") ? "&" : "?";
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, CANVAS_SITE_SETTINGS_TIMEOUT_MS);
|
||||
|
||||
const response = await fetch(`${url}${separator}t=${Date.now()}`, {
|
||||
cache: "no-store",
|
||||
signal: controller.signal,
|
||||
}).finally(() => {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@ -1869,37 +1877,18 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) {
|
||||
realtimeCanvasModeIconConfig?: Partial<RealtimeCanvasModeIconConfig>;
|
||||
canvasToolbarConfig?: CanvasToolbarConfig;
|
||||
agentWorkflowShowcaseConfig?: AgentWorkflowShowcaseConfig;
|
||||
agentWorkflowBrandModelConfig?: unknown;
|
||||
agentPsdTemplateCategoryTagIndex?: AgentPsdTemplateCategoryTagIndex;
|
||||
agentWorkflowUiConfig?: {
|
||||
pageFeatureSettings?: {
|
||||
presetStepEnabled?: boolean;
|
||||
materialStepEnabled?: boolean;
|
||||
psdTemplateEnabled?: boolean;
|
||||
batchProcessingEnabled?: boolean;
|
||||
};
|
||||
steps?: Array<{
|
||||
key: AgentWorkflowStepKey;
|
||||
title: string;
|
||||
description?: string | null;
|
||||
enabled?: boolean;
|
||||
sortOrder?: number;
|
||||
options?: Array<{
|
||||
key: string;
|
||||
buttonName: string;
|
||||
description?: string | null;
|
||||
previewImageUrl?: string | null;
|
||||
enabled?: boolean;
|
||||
sortOrder?: number;
|
||||
promptFragment?: string | null;
|
||||
}>;
|
||||
}>;
|
||||
};
|
||||
agentWorkflowUiConfig?: AgentWorkflowUiConfig;
|
||||
}>(canvasSiteSettingsKey, fetchCanvasSiteSettings, {
|
||||
onSuccess: () => {
|
||||
setHasResolvedCanvasSiteSettings(true);
|
||||
},
|
||||
refreshInterval: CANVAS_SITE_SETTINGS_REFRESH_INTERVAL_MS,
|
||||
onError: () => {
|
||||
setHasResolvedCanvasSiteSettings(true);
|
||||
},
|
||||
refreshInterval: requestedAgentMode
|
||||
? 0
|
||||
: CANVAS_SITE_SETTINGS_REFRESH_INTERVAL_MS,
|
||||
errorRetryCount: 1,
|
||||
revalidateOnFocus: true,
|
||||
revalidateOnReconnect: true,
|
||||
});
|
||||
@ -1955,8 +1944,7 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) {
|
||||
!agentProjectId ||
|
||||
loadedAgentProjectId === agentProjectId;
|
||||
const resolvedWorkflowUiConfig = useMemo(
|
||||
() =>
|
||||
normalizeAgentWorkflowUiConfig(siteSettingsData?.agentWorkflowUiConfig),
|
||||
() => siteSettingsData?.agentWorkflowUiConfig || defaultAgentWorkflowUiConfig,
|
||||
[siteSettingsData?.agentWorkflowUiConfig]
|
||||
);
|
||||
const workflowPageFeatureSettings = useMemo(
|
||||
@ -1989,6 +1977,19 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) {
|
||||
(isAgentWorkspaceEnabled || shouldUseStyleModeButtonForStylePro);
|
||||
const shouldShowStandaloneStyleProToolbarButton =
|
||||
isStyleProToolbarEnabled && !shouldUseStyleModeButtonForStylePro;
|
||||
const normalizedBrandModelName = workflowInputs.brand.trim();
|
||||
const brandModelSettingsKey =
|
||||
requestedAgentMode && normalizedBrandModelName
|
||||
? `/api/site-settings?scope=agent-brand-model&brand=${encodeURIComponent(
|
||||
normalizedBrandModelName
|
||||
)}`
|
||||
: null;
|
||||
const { data: brandModelSettingsData } = useSWR<{
|
||||
agentWorkflowBrandModelConfig?: unknown;
|
||||
}>(brandModelSettingsKey, fetchCanvasSiteSettings, {
|
||||
errorRetryCount: 1,
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
const sanitizedWorkflowSelections = useMemo(
|
||||
() =>
|
||||
sanitizeAgentWorkflowSelections({
|
||||
@ -2003,9 +2004,9 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) {
|
||||
const resolvedBrandModelConfig = useMemo(
|
||||
() =>
|
||||
normalizeAgentWorkflowBrandModelConfig(
|
||||
siteSettingsData?.agentWorkflowBrandModelConfig
|
||||
brandModelSettingsData?.agentWorkflowBrandModelConfig
|
||||
),
|
||||
[siteSettingsData?.agentWorkflowBrandModelConfig]
|
||||
[brandModelSettingsData?.agentWorkflowBrandModelConfig]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -24,12 +24,18 @@ export function AgentWorkflowBrandModelPicker({
|
||||
onSelectBrandModel,
|
||||
theme = "light",
|
||||
}: AgentWorkflowBrandModelPickerProps) {
|
||||
const { data } = useSWR<{ agentWorkflowBrandModelConfig?: AgentWorkflowBrandModelConfig }>(
|
||||
"/api/site-settings?scope=agent-brand-model",
|
||||
fetcher
|
||||
);
|
||||
|
||||
const normalizedBrand = brand.trim();
|
||||
const brandModelSettingsKey = normalizedBrand
|
||||
? `/api/site-settings?scope=agent-brand-model&brand=${encodeURIComponent(
|
||||
normalizedBrand
|
||||
)}`
|
||||
: null;
|
||||
const { data, error } = useSWR<{
|
||||
agentWorkflowBrandModelConfig?: AgentWorkflowBrandModelConfig;
|
||||
}>(brandModelSettingsKey, fetcher, {
|
||||
errorRetryCount: 1,
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
const config = useMemo(
|
||||
() => normalizeAgentWorkflowBrandModelConfig(data?.agentWorkflowBrandModelConfig),
|
||||
[data?.agentWorkflowBrandModelConfig]
|
||||
@ -43,7 +49,7 @@ export function AgentWorkflowBrandModelPicker({
|
||||
);
|
||||
const images = matchedEntry?.images || [];
|
||||
const isDark = theme === "dark";
|
||||
const isLoading = !data;
|
||||
const isLoading = Boolean(normalizedBrand) && !data && !error;
|
||||
|
||||
const renderPlaceholderGrid = (message: string, iconMode: "loading" | "empty" = "empty") => (
|
||||
<div className="space-y-3">
|
||||
@ -127,6 +133,8 @@ export function AgentWorkflowBrandModelPicker({
|
||||
|
||||
{isLoading ? (
|
||||
renderPlaceholderGrid("正在加载品牌模特图库,请稍候...", "loading")
|
||||
) : error ? (
|
||||
renderPlaceholderGrid("品牌模特图库暂时加载失败,不影响继续生成;稍后可刷新重试。")
|
||||
) : !normalizedBrand ? (
|
||||
renderPlaceholderGrid("先回到第一步选择品牌,第二步才会按品牌展示可选模特图。")
|
||||
) : images.length > 0 ? (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user