fix: refine detail replacement workflow
This commit is contained in:
parent
29f94248f4
commit
b98196b96e
@ -6135,6 +6135,19 @@ export async function POST(request: Request) {
|
|||||||
const replacementSourceType = isDetailReplacementPreset
|
const replacementSourceType = isDetailReplacementPreset
|
||||||
? "detail_replacement"
|
? "detail_replacement"
|
||||||
: "sku_replacement";
|
: "sku_replacement";
|
||||||
|
console.info("[Chat API] Replacement reference decision:", {
|
||||||
|
mode: replacementSourceType,
|
||||||
|
referenceIndex: referenceIndex + 1,
|
||||||
|
totalReferences: replacementReferences.length,
|
||||||
|
referenceLabel: reference.label,
|
||||||
|
referenceImageUrl: reference.imageUrl,
|
||||||
|
pairedProductIndex:
|
||||||
|
typeof pairedProductIndex === "number" ? pairedProductIndex + 1 : null,
|
||||||
|
shouldReplace: referenceDecision.shouldReplace,
|
||||||
|
reason: referenceDecision.reason,
|
||||||
|
detectionModelName: referenceDecision.detectionModelName,
|
||||||
|
detectionSource: referenceDecision.detectionSource,
|
||||||
|
});
|
||||||
const referenceSourceImageUrls = Array.from(
|
const referenceSourceImageUrls = Array.from(
|
||||||
new Set([
|
new Set([
|
||||||
...sharedUploadedImageUrls,
|
...sharedUploadedImageUrls,
|
||||||
@ -6144,6 +6157,13 @@ export async function POST(request: Request) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!referenceDecision.shouldReplace) {
|
if (!referenceDecision.shouldReplace) {
|
||||||
|
console.info("[Chat API] Replacement reference skipped and reused:", {
|
||||||
|
mode: replacementSourceType,
|
||||||
|
referenceIndex: referenceIndex + 1,
|
||||||
|
totalReferences: replacementReferences.length,
|
||||||
|
referenceLabel: reference.label,
|
||||||
|
reason: referenceDecision.reason,
|
||||||
|
});
|
||||||
await emitReplacementResultMessage({
|
await emitReplacementResultMessage({
|
||||||
reference,
|
reference,
|
||||||
bodyText: referenceDecision.reason,
|
bodyText: referenceDecision.reason,
|
||||||
@ -6185,6 +6205,15 @@ export async function POST(request: Request) {
|
|||||||
hasModelImage: Boolean(modelInputImageUrl),
|
hasModelImage: Boolean(modelInputImageUrl),
|
||||||
pairedProductIndex,
|
pairedProductIndex,
|
||||||
});
|
});
|
||||||
|
console.info("[Chat API] Replacement image generation started:", {
|
||||||
|
mode: replacementSourceType,
|
||||||
|
referenceIndex: referenceIndex + 1,
|
||||||
|
totalReferences: replacementReferences.length,
|
||||||
|
referenceLabel: reference.label,
|
||||||
|
pairedProductIndex:
|
||||||
|
typeof pairedProductIndex === "number" ? pairedProductIndex + 1 : null,
|
||||||
|
sourceImageCount: sourceImageUrls.length,
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await generateCanvasImage({
|
const result = await generateCanvasImage({
|
||||||
@ -6204,6 +6233,14 @@ export async function POST(request: Request) {
|
|||||||
if (!firstImage) {
|
if (!firstImage) {
|
||||||
throw new Error("未返回结果图片");
|
throw new Error("未返回结果图片");
|
||||||
}
|
}
|
||||||
|
console.info("[Chat API] Replacement image generation completed:", {
|
||||||
|
mode: replacementSourceType,
|
||||||
|
referenceIndex: referenceIndex + 1,
|
||||||
|
totalReferences: replacementReferences.length,
|
||||||
|
referenceLabel: reference.label,
|
||||||
|
modelDisplayName: resolvedModelDisplayName,
|
||||||
|
resultImageUrl: firstImage.originalUrl,
|
||||||
|
});
|
||||||
await emitReplacementResultMessage({
|
await emitReplacementResultMessage({
|
||||||
reference,
|
reference,
|
||||||
image: firstImage,
|
image: firstImage,
|
||||||
|
|||||||
@ -130,11 +130,22 @@ function getCandidateTargetUrls(
|
|||||||
return target === "detail" ? candidate.detailImageUrls : candidate.skuImageUrls;
|
return target === "detail" ? candidate.detailImageUrls : candidate.skuImageUrls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRenderableCandidateTargetUrls(
|
||||||
|
candidate: AgentModeReferenceCandidate,
|
||||||
|
target: "main" | "detail" | "sku"
|
||||||
|
) {
|
||||||
|
const urls = getCandidateTargetUrls(candidate, target);
|
||||||
|
if (target === "detail" && urls.length > 1) {
|
||||||
|
return urls.slice(1);
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
function buildReferenceItems(params: {
|
function buildReferenceItems(params: {
|
||||||
candidate: AgentModeReferenceCandidate;
|
candidate: AgentModeReferenceCandidate;
|
||||||
target: "main" | "detail" | "sku";
|
target: "main" | "detail" | "sku";
|
||||||
}): AgentDetailReplacementReferenceItem[] {
|
}): AgentDetailReplacementReferenceItem[] {
|
||||||
const urls = getCandidateTargetUrls(params.candidate, params.target);
|
const urls = getRenderableCandidateTargetUrls(params.candidate, params.target);
|
||||||
const targetLabel =
|
const targetLabel =
|
||||||
params.target === "main"
|
params.target === "main"
|
||||||
? "主图参考图"
|
? "主图参考图"
|
||||||
@ -252,7 +263,7 @@ export async function GET(request: NextRequest) {
|
|||||||
(upstreamResult.data.candidates || []).map((item, index) => normalizeCandidate(item, index))
|
(upstreamResult.data.candidates || []).map((item, index) => normalizeCandidate(item, index))
|
||||||
)
|
)
|
||||||
.filter((candidate) => isCandidateMatchedStore(candidate, requestedStoreName))
|
.filter((candidate) => isCandidateMatchedStore(candidate, requestedStoreName))
|
||||||
.filter((candidate) => getCandidateTargetUrls(candidate, parsed.target).length > 0);
|
.filter((candidate) => getRenderableCandidateTargetUrls(candidate, parsed.target).length > 0);
|
||||||
|
|
||||||
if (normalizedCandidates.length === 0) {
|
if (normalizedCandidates.length === 0) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@ -249,12 +249,14 @@ function buildReferenceCardsFromCandidate(params: {
|
|||||||
const candidate = params.candidate;
|
const candidate = params.candidate;
|
||||||
if (!candidate) return [] as AgentModeWorkspaceState["detailReplacement"]["references"];
|
if (!candidate) return [] as AgentModeWorkspaceState["detailReplacement"]["references"];
|
||||||
|
|
||||||
const urls =
|
const rawUrls =
|
||||||
params.target === "main"
|
params.target === "main"
|
||||||
? candidate.mainImageUrls || []
|
? candidate.mainImageUrls || []
|
||||||
: params.target === "detail"
|
: params.target === "detail"
|
||||||
? candidate.detailImageUrls || []
|
? candidate.detailImageUrls || []
|
||||||
: candidate.skuImageUrls || [];
|
: candidate.skuImageUrls || [];
|
||||||
|
const urls =
|
||||||
|
params.target === "detail" && rawUrls.length > 1 ? rawUrls.slice(1) : rawUrls;
|
||||||
const targetLabel = `${getTaskDetailReferenceSourceLabel(params.target)}参考图`;
|
const targetLabel = `${getTaskDetailReferenceSourceLabel(params.target)}参考图`;
|
||||||
const prefix =
|
const prefix =
|
||||||
candidate.sceneName || candidate.taskNo || candidate.productModel || "候选整套";
|
candidate.sceneName || candidate.taskNo || candidate.productModel || "候选整套";
|
||||||
@ -273,12 +275,13 @@ function buildReferenceCardsFromCandidate(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatCandidateMeta(candidate: AgentModeReferenceCandidate, target: AgentTaskDetailReferenceSource) {
|
function formatCandidateMeta(candidate: AgentModeReferenceCandidate, target: AgentTaskDetailReferenceSource) {
|
||||||
const imageCount =
|
const rawImageCount =
|
||||||
target === "main"
|
target === "main"
|
||||||
? candidate.mainImageUrls.length
|
? candidate.mainImageUrls.length
|
||||||
: target === "detail"
|
: target === "detail"
|
||||||
? candidate.detailImageUrls.length
|
? candidate.detailImageUrls.length
|
||||||
: candidate.skuImageUrls.length;
|
: candidate.skuImageUrls.length;
|
||||||
|
const imageCount = target === "detail" && rawImageCount > 1 ? rawImageCount - 1 : rawImageCount;
|
||||||
const uploadedAt = candidate.uploadedAt ? new Date(candidate.uploadedAt) : null;
|
const uploadedAt = candidate.uploadedAt ? new Date(candidate.uploadedAt) : null;
|
||||||
const timeText =
|
const timeText =
|
||||||
uploadedAt && !Number.isNaN(uploadedAt.getTime())
|
uploadedAt && !Number.isNaN(uploadedAt.getTime())
|
||||||
@ -303,12 +306,14 @@ function getCandidatePreviewUrl(
|
|||||||
candidate: AgentModeReferenceCandidate,
|
candidate: AgentModeReferenceCandidate,
|
||||||
target: AgentTaskDetailReferenceSource
|
target: AgentTaskDetailReferenceSource
|
||||||
) {
|
) {
|
||||||
const targetUrls =
|
const rawTargetUrls =
|
||||||
target === "main"
|
target === "main"
|
||||||
? candidate.mainImageUrls || []
|
? candidate.mainImageUrls || []
|
||||||
: target === "detail"
|
: target === "detail"
|
||||||
? candidate.detailImageUrls || []
|
? candidate.detailImageUrls || []
|
||||||
: candidate.skuImageUrls || [];
|
: candidate.skuImageUrls || [];
|
||||||
|
const targetUrls =
|
||||||
|
target === "detail" && rawTargetUrls.length > 1 ? rawTargetUrls.slice(1) : rawTargetUrls;
|
||||||
return (
|
return (
|
||||||
targetUrls[0] ||
|
targetUrls[0] ||
|
||||||
candidate.mainImageUrls[0] ||
|
candidate.mainImageUrls[0] ||
|
||||||
@ -321,23 +326,56 @@ function getCandidateTargetCount(
|
|||||||
candidate: AgentModeReferenceCandidate,
|
candidate: AgentModeReferenceCandidate,
|
||||||
target: AgentTaskDetailReferenceSource
|
target: AgentTaskDetailReferenceSource
|
||||||
) {
|
) {
|
||||||
return target === "main"
|
const rawCount =
|
||||||
? candidate.mainImageUrls.length
|
target === "main"
|
||||||
: target === "detail"
|
? candidate.mainImageUrls.length
|
||||||
? candidate.detailImageUrls.length
|
: target === "detail"
|
||||||
: candidate.skuImageUrls.length;
|
? candidate.detailImageUrls.length
|
||||||
|
: candidate.skuImageUrls.length;
|
||||||
|
return target === "detail" && rawCount > 1 ? rawCount - 1 : rawCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReplacementCardStatus = "waiting" | "queued" | "generating" | "completed" | "missing";
|
type ReplacementCardStatus =
|
||||||
|
| "waiting"
|
||||||
|
| "queued"
|
||||||
|
| "generating"
|
||||||
|
| "completed"
|
||||||
|
| "passthrough"
|
||||||
|
| "fallback"
|
||||||
|
| "missing";
|
||||||
|
|
||||||
|
function inferReplacementCardStatusFromText(text: string | null | undefined): ReplacementCardStatus | null {
|
||||||
|
const normalized = normalizeAssistantText(String(text || ""))
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim();
|
||||||
|
if (!normalized) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.includes("生成失败,当前先沿用参考图")) {
|
||||||
|
return "fallback";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
normalized.includes("沿用参考图") ||
|
||||||
|
normalized.includes("未检测到可替换的家具主体") ||
|
||||||
|
normalized.includes("视觉判断失败")
|
||||||
|
) {
|
||||||
|
return "passthrough";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "completed";
|
||||||
|
}
|
||||||
|
|
||||||
function getReplacementCardStatus(params: {
|
function getReplacementCardStatus(params: {
|
||||||
index: number;
|
index: number;
|
||||||
resultUrl: string | null;
|
resultUrl: string | null;
|
||||||
|
resultText?: string | null;
|
||||||
generatedCount: number;
|
generatedCount: number;
|
||||||
isGenerating: boolean;
|
isGenerating: boolean;
|
||||||
}) : ReplacementCardStatus {
|
}) : ReplacementCardStatus {
|
||||||
if (params.resultUrl) {
|
if (params.resultUrl) {
|
||||||
return "completed";
|
return inferReplacementCardStatusFromText(params.resultText) || "completed";
|
||||||
}
|
}
|
||||||
if (params.isGenerating) {
|
if (params.isGenerating) {
|
||||||
return params.index === params.generatedCount ? "generating" : "queued";
|
return params.index === params.generatedCount ? "generating" : "queued";
|
||||||
@ -350,6 +388,16 @@ function getReplacementCardStatus(params: {
|
|||||||
|
|
||||||
function getReplacementCardStatusMeta(status: ReplacementCardStatus) {
|
function getReplacementCardStatusMeta(status: ReplacementCardStatus) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
case "passthrough":
|
||||||
|
return {
|
||||||
|
label: "沿用参考图",
|
||||||
|
className: "border-cyan-400/30 bg-cyan-500/[0.10] text-cyan-200",
|
||||||
|
};
|
||||||
|
case "fallback":
|
||||||
|
return {
|
||||||
|
label: "失败已沿用",
|
||||||
|
className: "border-amber-400/30 bg-amber-500/[0.10] text-amber-200",
|
||||||
|
};
|
||||||
case "completed":
|
case "completed":
|
||||||
return {
|
return {
|
||||||
label: "已生成",
|
label: "已生成",
|
||||||
@ -619,7 +667,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
const hasMaterialStep = Boolean(materialSelectionPanel);
|
const hasMaterialStep = Boolean(materialSelectionPanel);
|
||||||
const hasWorkflowStyleStep = Boolean(workflowStylePanel) || hasBrandModelStep;
|
const hasWorkflowStyleStep = Boolean(workflowStylePanel) || hasBrandModelStep;
|
||||||
|
|
||||||
const { messages, setMessages, sendMessage, status } = useChat<ChatMessage>({
|
const { messages, setMessages, sendMessage, status, stop } = useChat<ChatMessage>({
|
||||||
id: chatId,
|
id: chatId,
|
||||||
messages: historyMessages,
|
messages: historyMessages,
|
||||||
experimental_throttle: 100,
|
experimental_throttle: 100,
|
||||||
@ -871,48 +919,78 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
}
|
}
|
||||||
return generatedGroups[generatedGroups.length - 1] || null;
|
return generatedGroups[generatedGroups.length - 1] || null;
|
||||||
}, [generatedGroups, messages]);
|
}, [generatedGroups, messages]);
|
||||||
|
const latestReplacementResults = useMemo(
|
||||||
|
() =>
|
||||||
|
replacementGeneratedGroupsAfterLastUser.map((group) => ({
|
||||||
|
url: group.imageUrls[0] || null,
|
||||||
|
text: group.text || "",
|
||||||
|
})),
|
||||||
|
[replacementGeneratedGroupsAfterLastUser]
|
||||||
|
);
|
||||||
const latestReplacementResultUrls = useMemo(
|
const latestReplacementResultUrls = useMemo(
|
||||||
() =>
|
() =>
|
||||||
replacementGeneratedGroupsAfterLastUser.flatMap((group) => group.imageUrls),
|
latestReplacementResults
|
||||||
[replacementGeneratedGroupsAfterLastUser]
|
.map((item) => item.url)
|
||||||
|
.filter((url): url is string => Boolean(url)),
|
||||||
|
[latestReplacementResults]
|
||||||
);
|
);
|
||||||
const displayedResultUrl = selectedResultUrl || latestGeneratedGroup?.imageUrls[0] || null;
|
const displayedResultUrl = selectedResultUrl || latestGeneratedGroup?.imageUrls[0] || null;
|
||||||
const isGenerating = status === "streaming" || status === "submitted";
|
const isGenerating = status === "streaming" || status === "submitted";
|
||||||
const detailResultCards = useMemo(
|
const detailResultCards = useMemo(
|
||||||
() =>
|
() =>
|
||||||
detailReplacementReferenceCards.map((card, index) => {
|
detailReplacementReferenceCards.map((card, index) => {
|
||||||
const resultUrl = latestReplacementResultUrls[index] || null;
|
const resultMeta = latestReplacementResults[index];
|
||||||
|
const resultUrl = resultMeta?.url || null;
|
||||||
return {
|
return {
|
||||||
...card,
|
...card,
|
||||||
index,
|
index,
|
||||||
resultUrl,
|
resultUrl,
|
||||||
|
resultText: resultMeta?.text || "",
|
||||||
status: getReplacementCardStatus({
|
status: getReplacementCardStatus({
|
||||||
index,
|
index,
|
||||||
resultUrl,
|
resultUrl,
|
||||||
generatedCount: latestReplacementResultUrls.length,
|
resultText: resultMeta?.text || "",
|
||||||
|
generatedCount: latestReplacementResults.length,
|
||||||
isGenerating,
|
isGenerating,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
[detailReplacementReferenceCards, isGenerating, latestReplacementResultUrls]
|
[detailReplacementReferenceCards, isGenerating, latestReplacementResults]
|
||||||
);
|
);
|
||||||
const skuResultCards = useMemo(
|
const skuResultCards = useMemo(
|
||||||
() =>
|
() =>
|
||||||
skuReplacementReferenceCards.map((card, index) => {
|
skuReplacementReferenceCards.map((card, index) => {
|
||||||
const resultUrl = latestReplacementResultUrls[index] || null;
|
const resultMeta = latestReplacementResults[index];
|
||||||
|
const resultUrl = resultMeta?.url || null;
|
||||||
return {
|
return {
|
||||||
...card,
|
...card,
|
||||||
index,
|
index,
|
||||||
resultUrl,
|
resultUrl,
|
||||||
|
resultText: resultMeta?.text || "",
|
||||||
status: getReplacementCardStatus({
|
status: getReplacementCardStatus({
|
||||||
index,
|
index,
|
||||||
resultUrl,
|
resultUrl,
|
||||||
generatedCount: latestReplacementResultUrls.length,
|
resultText: resultMeta?.text || "",
|
||||||
|
generatedCount: latestReplacementResults.length,
|
||||||
isGenerating,
|
isGenerating,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
[isGenerating, latestReplacementResultUrls, skuReplacementReferenceCards]
|
[isGenerating, latestReplacementResults, skuReplacementReferenceCards]
|
||||||
|
);
|
||||||
|
const detailProcessedCount = useMemo(
|
||||||
|
() =>
|
||||||
|
detailResultCards.filter((card) =>
|
||||||
|
["completed", "passthrough", "fallback"].includes(card.status)
|
||||||
|
).length,
|
||||||
|
[detailResultCards]
|
||||||
|
);
|
||||||
|
const skuProcessedCount = useMemo(
|
||||||
|
() =>
|
||||||
|
skuResultCards.filter((card) =>
|
||||||
|
["completed", "passthrough", "fallback"].includes(card.status)
|
||||||
|
).length,
|
||||||
|
[skuResultCards]
|
||||||
);
|
);
|
||||||
const sceneResultCardCount = Math.max(
|
const sceneResultCardCount = Math.max(
|
||||||
allGeneratedImages.length,
|
allGeneratedImages.length,
|
||||||
@ -1376,6 +1454,11 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
workflowContext?.promptText,
|
workflowContext?.promptText,
|
||||||
workflowContext?.summaryText,
|
workflowContext?.summaryText,
|
||||||
]);
|
]);
|
||||||
|
const handleStopGeneration = useCallback(() => {
|
||||||
|
stop();
|
||||||
|
setMessages((current) => current);
|
||||||
|
toast.info("已停止当前生成任务");
|
||||||
|
}, [setMessages, stop]);
|
||||||
|
|
||||||
const handleDownloadOriginalImage = useCallback(async (imageUrl: string) => {
|
const handleDownloadOriginalImage = useCallback(async (imageUrl: string) => {
|
||||||
const raw = String(imageUrl || "").trim();
|
const raw = String(imageUrl || "").trim();
|
||||||
@ -2088,34 +2171,47 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
imageGenConfig={currentModel?.imageGenConfig || undefined}
|
imageGenConfig={currentModel?.imageGenConfig || undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<div className="flex gap-3">
|
||||||
onClick={handleSend}
|
<Button
|
||||||
disabled={
|
onClick={handleSend}
|
||||||
isGenerating ||
|
disabled={
|
||||||
!selectedAgentPresetId ||
|
isGenerating ||
|
||||||
(hasAgentUploadSlots && !hasSatisfiedSlotRequirement)
|
!selectedAgentPresetId ||
|
||||||
}
|
(hasAgentUploadSlots && !hasSatisfiedSlotRequirement)
|
||||||
className={cn(
|
}
|
||||||
"h-11 w-full gap-2 rounded-[24px]",
|
className={cn(
|
||||||
"bg-gradient-to-r from-emerald-500 to-teal-500",
|
"h-11 flex-1 gap-2 rounded-[24px]",
|
||||||
"text-white font-medium",
|
"bg-gradient-to-r from-emerald-500 to-teal-500",
|
||||||
"hover:from-emerald-400 hover:to-teal-400",
|
"text-white font-medium",
|
||||||
"shadow-[0_0_24px_rgba(16,185,129,0.24)]",
|
"hover:from-emerald-400 hover:to-teal-400",
|
||||||
"disabled:opacity-30"
|
"shadow-[0_0_24px_rgba(16,185,129,0.24)]",
|
||||||
)}
|
"disabled:opacity-30"
|
||||||
>
|
)}
|
||||||
|
>
|
||||||
|
{isGenerating ? (
|
||||||
|
<>
|
||||||
|
<Loader2 className="h-4 w-4 animate-spin" />
|
||||||
|
{isReplacementPreset ? "批量替换中..." : "生成中..."}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ArrowUp className="h-4 w-4" />
|
||||||
|
{isReplacementPreset ? "开始批量替换" : "开始生成"}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
{isGenerating ? (
|
{isGenerating ? (
|
||||||
<>
|
<Button
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
type="button"
|
||||||
{isReplacementPreset ? "批量替换中..." : "生成中..."}
|
variant="outline"
|
||||||
</>
|
onClick={handleStopGeneration}
|
||||||
) : (
|
className="h-11 shrink-0 rounded-[24px] border-white/12 bg-black/30 px-4 text-white hover:bg-white/[0.08]"
|
||||||
<>
|
>
|
||||||
<ArrowUp className="h-4 w-4" />
|
<X className="mr-2 h-4 w-4" />
|
||||||
{isReplacementPreset ? "开始批量替换" : "开始生成"}
|
停止生成
|
||||||
</>
|
</Button>
|
||||||
)}
|
) : null}
|
||||||
</Button>
|
</div>
|
||||||
{slotRequirementMessage ? (
|
{slotRequirementMessage ? (
|
||||||
<div className="rounded-[18px] border border-amber-400/20 bg-amber-500/[0.08] px-4 py-3 text-xs leading-6 text-amber-100/90">
|
<div className="rounded-[18px] border border-amber-400/20 bg-amber-500/[0.08] px-4 py-3 text-xs leading-6 text-amber-100/90">
|
||||||
{slotRequirementMessage}
|
{slotRequirementMessage}
|
||||||
@ -2213,7 +2309,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isDetailReplacementPreset ? (
|
{isDetailReplacementPreset ? (
|
||||||
<div className="grid flex-1 min-h-0 grid-cols-1 gap-0 xl:grid-cols-[320px_minmax(0,1fr)_360px]">
|
<div className="grid flex-1 min-h-0 grid-cols-1 gap-0 xl:grid-cols-[320px_repeat(2,minmax(0,1fr))]">
|
||||||
<div className="border-b border-white/10 p-4 xl:border-b-0 xl:border-r">
|
<div className="border-b border-white/10 p-4 xl:border-b-0 xl:border-r">
|
||||||
<div className="mb-3 flex items-center justify-between">
|
<div className="mb-3 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
@ -2422,7 +2518,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="agent-dark-scrollbar max-h-[620px] space-y-3 overflow-y-auto pr-1">
|
<div className="agent-dark-scrollbar grid max-h-[620px] grid-cols-1 gap-3 overflow-y-auto pr-1">
|
||||||
{detailReplacementReferenceCards.length > 0 ? (
|
{detailReplacementReferenceCards.length > 0 ? (
|
||||||
detailReplacementReferenceCards.map((card, index) => (
|
detailReplacementReferenceCards.map((card, index) => (
|
||||||
(() => {
|
(() => {
|
||||||
@ -2496,11 +2592,11 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-full border border-white/10 bg-white/[0.03] px-3 py-1 text-xs text-emerald-200/80">
|
<div className="rounded-full border border-white/10 bg-white/[0.03] px-3 py-1 text-xs text-emerald-200/80">
|
||||||
已接通
|
已处理 {detailProcessedCount}/{detailResultCards.length || 0}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="agent-dark-scrollbar max-h-[720px] space-y-3 overflow-y-auto pr-1">
|
<div className="agent-dark-scrollbar grid max-h-[720px] grid-cols-1 gap-3 overflow-y-auto pr-1">
|
||||||
{detailResultCards.length > 0 ? (
|
{detailResultCards.length > 0 ? (
|
||||||
detailResultCards.map((card) => (
|
detailResultCards.map((card) => (
|
||||||
(() => {
|
(() => {
|
||||||
@ -2577,7 +2673,11 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
)}
|
)}
|
||||||
<div className="border-t border-white/10 px-3 py-2 text-[11px] text-white/45">
|
<div className="border-t border-white/10 px-3 py-2 text-[11px] text-white/45">
|
||||||
{card.resultUrl
|
{card.resultUrl
|
||||||
? "已生成,可继续逐屏调整文字或重新执行。"
|
? card.status === "passthrough"
|
||||||
|
? "当前参考图未检测到可替换产品,本屏直接沿用参考图展示。"
|
||||||
|
: card.status === "fallback"
|
||||||
|
? "当前参考图替换失败,本屏先沿用参考图展示。"
|
||||||
|
: "已生成,可继续逐屏调整文字或重新执行。"
|
||||||
: card.status === "generating"
|
: card.status === "generating"
|
||||||
? "当前正在生成这一屏,请稍候。"
|
? "当前正在生成这一屏,请稍候。"
|
||||||
: card.status === "queued"
|
: card.status === "queued"
|
||||||
@ -2948,7 +3048,7 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-full border border-white/10 bg-white/[0.03] px-3 py-1 text-xs text-emerald-200/80">
|
<div className="rounded-full border border-white/10 bg-white/[0.03] px-3 py-1 text-xs text-emerald-200/80">
|
||||||
已接通
|
已处理 {skuProcessedCount}/{skuResultCards.length || 0}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -3022,7 +3122,11 @@ export function AgentGenerationWorkspaceDarkV2({
|
|||||||
)}
|
)}
|
||||||
<div className="border-t border-white/10 px-3 py-2 text-[11px] text-white/45">
|
<div className="border-t border-white/10 px-3 py-2 text-[11px] text-white/45">
|
||||||
{card.resultUrl
|
{card.resultUrl
|
||||||
? "已生成,可继续逐张检查并后续批量下载。"
|
? card.status === "passthrough"
|
||||||
|
? "当前参考图未检测到可替换产品,这一张直接沿用参考图展示。"
|
||||||
|
: card.status === "fallback"
|
||||||
|
? "当前参考图替换失败,这一张先沿用参考图展示。"
|
||||||
|
: "已生成,可继续逐张检查并后续批量下载。"
|
||||||
: card.status === "generating"
|
: card.status === "generating"
|
||||||
? "当前正在生成这一张,请稍候。"
|
? "当前正在生成这一张,请稍候。"
|
||||||
: card.status === "queued"
|
: card.status === "queued"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user