config?.inputOptions?.brands || defaultAgentWorkflowUiConfig.inputOptions?.brands || [],
+ () =>
+ config?.inputOptions?.brands ||
+ defaultAgentWorkflowUiConfig.inputOptions?.brands ||
+ [],
[config?.inputOptions?.brands]
);
const brandStoreEntries = useMemo(
@@ -557,8 +581,13 @@ export function AgentWorkflowBrandStorePanel({
(thirdEntry.fourthCategories || []).length > 0
)
)
- ) || Boolean(config?.inputOptions?.fourthCategories?.length)),
- [brandStoreEntries, config?.inputOptions?.fourthCategories, hasThirdCategoryLevel]
+ ) ||
+ Boolean(config?.inputOptions?.fourthCategories?.length)),
+ [
+ brandStoreEntries,
+ config?.inputOptions?.fourthCategories,
+ hasThirdCategoryLevel,
+ ]
);
const isDark = theme === "dark";
@@ -589,7 +618,8 @@ export function AgentWorkflowBrandStorePanel({
nextInputs.officialSecondCategory &&
!officialSecondCategoryOptions.some(
(option) =>
- option.trim().toLowerCase() === nextInputs.officialSecondCategory.trim().toLowerCase()
+ option.trim().toLowerCase() ===
+ nextInputs.officialSecondCategory.trim().toLowerCase()
)
) {
nextInputs = {
@@ -605,7 +635,8 @@ export function AgentWorkflowBrandStorePanel({
nextInputs.officialThirdCategory &&
!officialThirdCategoryOptions.some(
(option) =>
- option.trim().toLowerCase() === nextInputs.officialThirdCategory.trim().toLowerCase()
+ option.trim().toLowerCase() ===
+ nextInputs.officialThirdCategory.trim().toLowerCase()
)
) {
nextInputs = {
@@ -645,10 +676,20 @@ export function AgentWorkflowBrandStorePanel({
)}
>
-
+
{resolvedTitle}
-
@@ -688,7 +729,10 @@ export function AgentWorkflowBrandStorePanel({
: `请先选择${firstCategoryLabel}`
}
theme={theme}
- disabled={!inputs.brand || (brandStoreEntries.length > 0 && storeOptions.length === 0)}
+ disabled={
+ !inputs.brand ||
+ (brandStoreEntries.length > 0 && storeOptions.length === 0)
+ }
onValueChange={(value) =>
onInputsChange({
...inputs,
@@ -719,7 +763,8 @@ export function AgentWorkflowBrandStorePanel({
...inputs,
thirdCategory: value,
fourthCategory:
- value.trim().toLowerCase() === inputs.thirdCategory.trim().toLowerCase()
+ value.trim().toLowerCase() ===
+ inputs.thirdCategory.trim().toLowerCase()
? inputs.fourthCategory
: "",
})
@@ -738,7 +783,9 @@ export function AgentWorkflowBrandStorePanel({
: `请先选择${thirdCategoryLabel}`
}
theme={theme}
- disabled={!inputs.thirdCategory || fourthCategoryOptions.length === 0}
+ disabled={
+ !inputs.thirdCategory || fourthCategoryOptions.length === 0
+ }
onValueChange={(value) =>
onInputsChange({
...inputs,
@@ -775,7 +822,10 @@ export function AgentWorkflowBrandStorePanel({
: "请先选择二级品类"
}
theme={theme}
- disabled={!inputs.officialSecondCategory || officialThirdCategoryOptions.length === 0}
+ disabled={
+ !inputs.officialSecondCategory ||
+ officialThirdCategoryOptions.length === 0
+ }
onValueChange={(value) =>
onInputsChange({
...inputs,
@@ -792,7 +842,9 @@ export function AgentWorkflowBrandStorePanel({
emptyText="暂无价格带可选"
theme={theme}
disabled={priceBandOptions.length === 0}
- onValueChange={(value) => onInputsChange({ ...inputs, priceBand: value })}
+ onValueChange={(value) =>
+ onInputsChange({ ...inputs, priceBand: value })
+ }
/>
@@ -863,7 +915,9 @@ function AgentWorkflowPanelDarkV2Component({
latestExternalSelectionsRef.current = selections;
setOptimisticSelections((current) =>
- areWorkflowSelectionStatesEqual(current, selections) ? current : selections
+ areWorkflowSelectionStatesEqual(current, selections)
+ ? current
+ : selections
);
}, [selections]);
@@ -874,7 +928,10 @@ function AgentWorkflowPanelDarkV2Component({
}
pendingSelectionCommitRef.current = null;
- if (selectionCommitTimerRef.current !== null && typeof window !== "undefined") {
+ if (
+ selectionCommitTimerRef.current !== null &&
+ typeof window !== "undefined"
+ ) {
window.clearTimeout(selectionCommitTimerRef.current);
}
selectionCommitTimerRef.current = null;
@@ -912,7 +969,10 @@ function AgentWorkflowPanelDarkV2Component({
const flattenedResolvedSteps = useMemo(
() =>
- flattenVisibleAgentWorkflowSteps(displayConfig.steps, optimisticSelections).filter(
+ flattenVisibleAgentWorkflowSteps(
+ displayConfig.steps,
+ optimisticSelections
+ ).filter(
({ step }) => Array.isArray(step.options) && step.options.length > 0
),
[displayConfig.steps, optimisticSelections]
@@ -927,37 +987,36 @@ function AgentWorkflowPanelDarkV2Component({
);
const workflowDerivedVersionRef = useRef(0);
- useEffect(
- () => {
- const version = workflowDerivedVersionRef.current + 1;
- workflowDerivedVersionRef.current = version;
+ useEffect(() => {
+ const version = workflowDerivedVersionRef.current + 1;
+ workflowDerivedVersionRef.current = version;
- return scheduleWorkflowIdleTask(() => {
- const nextDerivedState = buildWorkflowPanelDerivedState({
- config: resolvedConfig,
- selections: deferredSelections,
- });
-
- if (workflowDerivedVersionRef.current !== version) {
- return;
- }
-
- startTransition(() => {
- setWorkflowDerivedState(nextDerivedState);
- });
+ return scheduleWorkflowIdleTask(() => {
+ const nextDerivedState = buildWorkflowPanelDerivedState({
+ config: resolvedConfig,
+ selections: deferredSelections,
});
- },
- [deferredSelections, resolvedConfig]
- );
+
+ if (workflowDerivedVersionRef.current !== version) {
+ return;
+ }
+
+ startTransition(() => {
+ setWorkflowDerivedState(nextDerivedState);
+ });
+ });
+ }, [deferredSelections, resolvedConfig]);
const progress = workflowDerivedState.progress;
const stepSelectionSummaryMap = useMemo(() => {
- const entries = flattenAgentWorkflowSteps(resolvedConfig.steps).map(({ step }) => [
- step.key,
- getWorkflowStepSelectionSummary({
- step,
- selectionValue: deferredSelections[step.key],
- }),
- ]);
+ const entries = flattenAgentWorkflowSteps(resolvedConfig.steps).map(
+ ({ step }) => [
+ step.key,
+ getWorkflowStepSelectionSummary({
+ step,
+ selectionValue: deferredSelections[step.key],
+ }),
+ ]
+ );
return Object.fromEntries(entries) as Record
;
}, [deferredSelections, resolvedConfig.steps]);
const blockedOptionKeys = useMemo(
@@ -975,21 +1034,30 @@ function AgentWorkflowPanelDarkV2Component({
completedSummary: string;
nextStepTitle: string;
} | null>(null);
- const [activeEmbeddedStepKey, setActiveEmbeddedStepKey] = useState("");
+ const [activeEmbeddedStepKey, setActiveEmbeddedStepKey] =
+ useState("");
const [activeEmbeddedOptionDepth, setActiveEmbeddedOptionDepth] = useState(1);
- const [pendingAutoAdvanceStepKey, setPendingAutoAdvanceStepKey] = useState(null);
+ const [isEmbeddedPathExpanded, setIsEmbeddedPathExpanded] = useState(false);
+ const [pendingAutoAdvanceStepKey, setPendingAutoAdvanceStepKey] = useState<
+ string | null
+ >(null);
const activeEmbeddedStepIndex = Math.max(
- flattenedResolvedSteps.findIndex(({ step }) => step.key === activeEmbeddedStepKey),
+ flattenedResolvedSteps.findIndex(
+ ({ step }) => step.key === activeEmbeddedStepKey
+ ),
0
);
const activeEmbeddedStepEntry =
- flattenedResolvedSteps[activeEmbeddedStepIndex] || flattenedResolvedSteps[0] || null;
+ flattenedResolvedSteps[activeEmbeddedStepIndex] ||
+ flattenedResolvedSteps[0] ||
+ null;
const activeEmbeddedOptionLevels = useMemo(
() =>
activeEmbeddedStepEntry
? getWorkflowStepOptionLevels({
step: activeEmbeddedStepEntry.step,
- selectionValue: optimisticSelections[activeEmbeddedStepEntry.step.key],
+ selectionValue:
+ optimisticSelections[activeEmbeddedStepEntry.step.key],
})
: [],
[activeEmbeddedStepEntry, optimisticSelections]
@@ -999,13 +1067,16 @@ function AgentWorkflowPanelDarkV2Component({
activeEmbeddedStepEntry
? getAgentWorkflowSelectedOptionPath({
step: activeEmbeddedStepEntry.step,
- selectionValue: optimisticSelections[activeEmbeddedStepEntry.step.key],
+ selectionValue:
+ optimisticSelections[activeEmbeddedStepEntry.step.key],
})
: [],
[activeEmbeddedStepEntry, optimisticSelections]
);
const activeEmbeddedOptionLevel =
- activeEmbeddedOptionLevels.find((level) => level.depth === activeEmbeddedOptionDepth) ||
+ activeEmbeddedOptionLevels.find(
+ (level) => level.depth === activeEmbeddedOptionDepth
+ ) ||
activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1] ||
activeEmbeddedOptionLevels[0] ||
null;
@@ -1021,13 +1092,29 @@ function AgentWorkflowPanelDarkV2Component({
return false;
}
- const renderableChildren = activeEmbeddedDeepestSelectedOption.children || [];
+ const renderableChildren =
+ activeEmbeddedDeepestSelectedOption.children || [];
if (renderableChildren.length === 0) {
return false;
}
- return getEnabledAgentWorkflowOptionTree(activeEmbeddedDeepestSelectedOption.children || []).length === 0;
+ return (
+ getEnabledAgentWorkflowOptionTree(
+ activeEmbeddedDeepestSelectedOption.children || []
+ ).length === 0
+ );
}, [activeEmbeddedDeepestSelectedOption]);
+ const activeEmbeddedPrimaryOption = activeEmbeddedSelectedPath[0] || null;
+ const activeEmbeddedStepSummary =
+ (activeEmbeddedStepEntry &&
+ stepSelectionSummaryMap[activeEmbeddedStepEntry.step.key]) ||
+ "";
+ const activeEmbeddedPathStatusLabel =
+ activeEmbeddedSelectedPath.length > 0
+ ? `已选 ${activeEmbeddedSelectedPath.length} 项`
+ : "未选择";
+ const activeEmbeddedPathSummary =
+ activeEmbeddedStepSummary || "先选择当前步骤的主卡片,完整路径会收纳在这里";
useEffect(() => {
if (!embedded) {
@@ -1043,7 +1130,9 @@ function AgentWorkflowPanelDarkV2Component({
if (
activeEmbeddedStepKey &&
- flattenedResolvedSteps.some(({ step }) => step.key === activeEmbeddedStepKey)
+ flattenedResolvedSteps.some(
+ ({ step }) => step.key === activeEmbeddedStepKey
+ )
) {
return;
}
@@ -1065,18 +1154,25 @@ function AgentWorkflowPanelDarkV2Component({
const firstIncompleteDepth =
activeEmbeddedOptionLevels.find((level) => !level.selectedKey)?.depth ||
- activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]?.depth ||
+ activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]
+ ?.depth ||
1;
setActiveEmbeddedOptionDepth((current) => {
const maxDepth =
- activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]?.depth || 1;
+ activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]
+ ?.depth || 1;
if (current < 1 || current > maxDepth) {
return firstIncompleteDepth;
}
return current;
});
- }, [activeEmbeddedOptionDepth, activeEmbeddedOptionLevels, activeEmbeddedStepEntry, embedded]);
+ }, [
+ activeEmbeddedOptionDepth,
+ activeEmbeddedOptionLevels,
+ activeEmbeddedStepEntry,
+ embedded,
+ ]);
useEffect(() => {
if (!embedded || !activeEmbeddedStepEntry) {
@@ -1114,7 +1210,8 @@ function AgentWorkflowPanelDarkV2Component({
setAutoAdvanceNotice({
completedStepTitle: activeEmbeddedStepEntry.step.title,
completedSummary:
- stepSelectionSummaryMap[activeEmbeddedStepEntry.step.key] || "已完成当前步骤选择",
+ stepSelectionSummaryMap[activeEmbeddedStepEntry.step.key] ||
+ "已完成当前步骤选择",
nextStepTitle: nextStep.step.title,
});
setActiveEmbeddedStepKey(nextStep.step.key);
@@ -1145,6 +1242,13 @@ function AgentWorkflowPanelDarkV2Component({
return () => window.clearTimeout(timer);
}, [autoAdvanceNotice]);
+ useEffect(() => {
+ if (!embedded) {
+ return;
+ }
+
+ setIsEmbeddedPathExpanded(false);
+ }, [activeEmbeddedStepKey, embedded]);
const renderOptionLevels = (
step: AgentWorkflowUiConfig["steps"][number],
@@ -1160,7 +1264,8 @@ function AgentWorkflowPanelDarkV2Component({
const currentSelectedOption =
options.find((option) => option.key === currentSelectedKey) || null;
const visibleChildren = currentSelectedOption?.children || [];
- const levelLabel = depth === 1 ? "主卡片" : depth === 2 ? "二级卡片" : "三级卡片";
+ const levelLabel =
+ depth === 1 ? "主卡片" : depth === 2 ? "二级卡片" : "三级卡片";
const handleSelectOption = (optionKey: string) => {
const option = options.find((item) => item.key === optionKey);
if (!option) {
@@ -1256,13 +1361,18 @@ function AgentWorkflowPanelDarkV2Component({
const nextSelections = {
...optimisticSelections,
[activeEmbeddedStepEntry.step.key]:
- nextKeys.length > 0 ? serializeAgentWorkflowSelectionPath(nextKeys) : undefined,
+ nextKeys.length > 0
+ ? serializeAgentWorkflowSelectionPath(nextKeys)
+ : undefined,
};
setPendingAutoAdvanceStepKey(activeEmbeddedStepEntry.step.key);
emitSelectionsChange(nextSelections);
- if (currentSelectedKey !== option.key && (option.children || []).length > 0) {
+ if (
+ currentSelectedKey !== option.key &&
+ (option.children || []).length > 0
+ ) {
setActiveEmbeddedOptionDepth(activeEmbeddedOptionLevel.depth + 1);
} else {
setActiveEmbeddedOptionDepth(activeEmbeddedOptionLevel.depth);
@@ -1280,297 +1390,332 @@ function AgentWorkflowPanelDarkV2Component({
const workflowContent = (
- {showBrandStoreSection ? (
-
-
-
- 1
-
- {firstCategoryLabel}和{secondCategoryLabel}选择
-
-
-
- ) : null}
+ {showBrandStoreSection ? (
+
+
+
+ 1
+
+ {firstCategoryLabel}和{secondCategoryLabel}选择
+
+
+
+ ) : null}
- {/* 工作流步骤 */}
- {embedded ? (
- activeEmbeddedStepEntry ? (
-
1 &&
- "border-l-4 border-l-emerald-500/30"
- )}
- initial={{ opacity: 0, y: 20 }}
- animate={{ opacity: 1, y: 0 }}
- >
-
-
-
- {flattenedResolvedSteps.map(({ step }, stepIndex) => {
- const completed = isAgentWorkflowStepSelectionComplete({
- step,
- selectionValue: optimisticSelections[step.key],
- });
- const active = step.key === activeEmbeddedStepEntry.step.key;
- const stepSelectedPath = getAgentWorkflowSelectedOptionPath({
- step,
- selectionValue: optimisticSelections[step.key],
- });
- const primarySelectedOption = stepSelectedPath[0] || null;
- const selectedCountLabel =
- stepSelectedPath.length > 0
- ? `${stepSelectedPath.length} 项已选`
- : "待选择";
+ {/* 工作流步骤 */}
+ {embedded ? (
+ activeEmbeddedStepEntry ? (
+
1 &&
+ "border-l-4 border-l-emerald-500/30"
+ )}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ >
+
+
+
+ {flattenedResolvedSteps.map(({ step }, stepIndex) => {
+ const completed = isAgentWorkflowStepSelectionComplete({
+ step,
+ selectionValue: optimisticSelections[step.key],
+ });
+ const active =
+ step.key === activeEmbeddedStepEntry.step.key;
+ const stepSelectedPath = getAgentWorkflowSelectedOptionPath(
+ {
+ step,
+ selectionValue: optimisticSelections[step.key],
+ }
+ );
+ const primarySelectedOption = stepSelectedPath[0] || null;
+ const selectedCountLabel =
+ stepSelectedPath.length > 0
+ ? `${stepSelectedPath.length} 项已选`
+ : "待选择";
- return (
-
+
+
+ );
+ })}
+
+
+
+
+ {isEmbeddedPathExpanded ? (
+
+ {activeEmbeddedSelectedPath.length > 0 ? (
+
+ {activeEmbeddedSelectedPath.map(
+ (option, optionIndex) => {
+ const optionDepth = optionIndex + 1;
+ const optionLevelActive =
+ (activeEmbeddedOptionLevel?.depth || 1) ===
+ optionDepth;
+
+ return (
-
-
- );
- })}
-
-
-
-
-
-
- 当前步骤路径
-
-
- {activeEmbeddedStepEntry.step.title}
-
-
-
- {activeEmbeddedSelectedPath.length > 0
- ? `已选 ${activeEmbeddedSelectedPath.length} 项`
- : "还未选择主卡片"}
-
-
-
- {activeEmbeddedSelectedPath.length > 0 ? (
-
- {activeEmbeddedSelectedPath.map((option, optionIndex) => {
- const optionDepth = optionIndex + 1;
- const optionLevelActive =
- (activeEmbeddedOptionLevel?.depth || 1) === optionDepth;
-
- return (
-
- );
- })}
-
- ) : (
-
- 先选择当前步骤的主卡片,完整子节点路径会显示在这里,顶部步骤条只保留紧凑摘要。
-
+ );
+ }
)}
-
-
-
-
- {activeEmbeddedOptionLevel ? (
-
- {autoAdvanceNotice ? (
-
-
-
-
-
-
已完成「{autoAdvanceNotice.completedStepTitle}」
-
-
已自动切换到「{autoAdvanceNotice.nextStepTitle}」
-
-
- 刚刚完成的内容:{autoAdvanceNotice.completedSummary}
-
-
- ) : null}
-
-
-
- {activeEmbeddedOptionLevel.depth === 1
- ? "主卡片"
- : `${activeEmbeddedOptionLevel.depth}级子卡片`}
-
-
- {activeEmbeddedOptionLevel.depth === 1
- ? "先选择当前步骤的主卡片"
- : "当前层级只展示这一层的子节点卡片,选完再进入下一层"}
-
+ ) : (
+
+ 先选择当前步骤的主卡片,完整子节点路径会收纳在这里,需要时再展开查看。
-
-
-
- ) : null}
-
- ) : null
- ) : (
- flattenedResolvedSteps.map(({ step, depth }, stepIndex) => (
-
1 && "ml-3 border-l-4 border-l-emerald-500/30 sm:ml-6"
- )}
- initial={{ opacity: 0, y: 20 }}
- animate={{ opacity: 1, y: 0 }}
- transition={{ delay: 0.15 + stepIndex * 0.05 }}
- >
-
-
- {stepIndex + 2}
-
- {step.title}
- {depth > 1 ? (
-
- {`${depth}级模块`}
-
- ) : null}
-
-
- {stepSelectionSummaryMap[step.key]
- ? `已选:${stepSelectionSummaryMap[step.key]}`
- : "待选择:先确定这一组风格卡片,系统再继续组合 Prompt"}
+ )}
- {step.description && (
- {step.description}
- )}
- {renderOptionLevels(step, step.options || [])}
-
- ))
- )}
+ ) : null}
+
+
+
+ {activeEmbeddedOptionLevel ? (
+
+ {autoAdvanceNotice ? (
+
+
+
+
+
+
+ 已完成「{autoAdvanceNotice.completedStepTitle}」
+
+
+
+ 已自动切换到「{autoAdvanceNotice.nextStepTitle}」
+
+
+
+ 刚刚完成的内容:{autoAdvanceNotice.completedSummary}
+
+
+ ) : null}
+
+
+
+ {activeEmbeddedOptionLevel.depth === 1
+ ? "主卡片"
+ : `${activeEmbeddedOptionLevel.depth}级子卡片`}
+
+
+ {activeEmbeddedOptionLevel.depth === 1
+ ? "先选择当前步骤的主卡片"
+ : "当前层级只展示这一层的子节点卡片,选完再进入下一层"}
+
+
+
+
+
+ ) : null}
+
+ ) : null
+ ) : (
+ flattenedResolvedSteps.map(({ step, depth }, stepIndex) => (
+
1 && "ml-3 border-l-4 border-l-emerald-500/30 sm:ml-6"
+ )}
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ delay: 0.15 + stepIndex * 0.05 }}
+ >
+
+
+ {stepIndex + 2}
+
+ {step.title}
+ {depth > 1 ? (
+
+ {`${depth}级模块`}
+
+ ) : null}
+
+
+ {stepSelectionSummaryMap[step.key]
+ ? `已选:${stepSelectionSummaryMap[step.key]}`
+ : "待选择:先确定这一组风格卡片,系统再继续组合 Prompt"}
+
+ {step.description && (
+ {step.description}
+ )}
+ {renderOptionLevels(step, step.options || [])}
+
+ ))
+ )}
+
);
if (embedded) {
@@ -1597,7 +1742,9 @@ function AgentWorkflowPanelDarkV2Component({
actionLabel="开始选择风格"
secondaryActionLabel={onSkipStep ? "进入风格生图" : undefined}
onActionClick={() => {
- const target = document.getElementById("agent-workflow-content");
+ const target = document.getElementById(
+ "agent-workflow-content"
+ );
if (!target) return;
target.scrollIntoView({ behavior: "smooth", block: "start" });
}}
@@ -1616,73 +1763,86 @@ function AgentWorkflowPanelDarkV2Component({
- {onNextStep ? (
-
-
-
-
-
工作流进度
-
- 已完成 {progress.completed} / {progress.total} 个步骤
- {progress.isComplete ? ",可以直接进入下一步" : ",也可以选择跳过直接进入下一步"}
+ {onNextStep ? (
+
+
+
+
+
+ 工作流进度
+
+
+ 已完成 {progress.completed} / {progress.total} 个步骤
+ {progress.isComplete
+ ? ",可以直接进入下一步"
+ : ",也可以选择跳过直接进入下一步"}
+
+
+
+ {progress.total > 0
+ ? Math.round((progress.completed / progress.total) * 100)
+ : 0}
+ %
-
- {progress.total > 0 ? Math.round((progress.completed / progress.total) * 100) : 0}%
+
+
+ 0 ? (progress.completed / progress.total) * 100 : 0}%`,
+ }}
+ transition={{ duration: 0.45 }}
+ />
+
+
+
+ {onSkipStep ? (
+
+ ) : null}
+
-
-
- 0 ? (progress.completed / progress.total) * 100 : 0}%` }}
- transition={{ duration: 0.45 }}
- />
-
-
-
- {onSkipStep ? (
-
- ) : null}
-
-
-
-
- ) : null}
+
+ ) : null}
{/* 页脚 */}