fix: keep upload access in direct workflow mode
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-19 16:15:55 +08:00
parent 076e4f55e6
commit 90b6cd442c

View File

@ -160,6 +160,7 @@ const MAX_CHAT_HIDDEN_PROMPT_LENGTH = 4000;
const MAX_CHAT_ATTACHMENT_NAME_LENGTH = 100;
const MAX_AGENT_MODE_QUERY_LENGTH = 64;
const MAX_AGENT_MODE_REFERENCE_COUNT = 40;
const DIRECT_MODEL_UPLOAD_SLOT_COUNT = 4;
const CHAT_UUID_REGEX =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const ALLOWED_CHAT_MEDIA_TYPES = new Set([
@ -1274,6 +1275,19 @@ export function AgentGenerationWorkspaceDarkV2({
},
[hasAgentUploadSlots, modelSlotEnabled, modelSlotIndex, productSlotCount]
);
const isDirectReferenceUploadEnabled = isDirectModelGenerationMode && !hasMaterialStep;
const directReferenceUploadSlots = useMemo(
() =>
Array.from({ length: DIRECT_MODEL_UPLOAD_SLOT_COUNT }, (_, index) => ({
slotIndex: index,
label: `参考图${index + 1}`,
})),
[]
);
const visibleAttachmentUploadSlots = isDirectReferenceUploadEnabled
? directReferenceUploadSlots
: agentUploadSlots;
const hasVisibleAttachmentUploadSlots = visibleAttachmentUploadSlots.length > 0;
const requiredProductUploadCount = hasAgentUploadSlots ? productSlotCount : 0;
const detailReferenceTarget = presetModeConfig.detail.referenceImageSource;
const skuReferenceTarget = presetModeConfig.sku.referenceImageSource;
@ -1383,6 +1397,13 @@ export function AgentGenerationWorkspaceDarkV2({
});
}
if (isDirectReferenceUploadEnabled) {
return attachments
.slice(0, DIRECT_MODEL_UPLOAD_SLOT_COUNT)
.map((attachment) => sanitizeChatAttachment(attachment))
.filter((attachment): attachment is PickedAttachment => Boolean(attachment));
}
if (!isSceneGenerationPreset) {
return attachments
.map((attachment) => sanitizeChatAttachment(attachment))
@ -1439,6 +1460,7 @@ export function AgentGenerationWorkspaceDarkV2({
attachments,
hasMaterialStep,
isDirectModelGenerationMode,
isDirectReferenceUploadEnabled,
isSceneGenerationPreset,
referenceImages,
scenePrimaryReferenceCount,
@ -1451,7 +1473,11 @@ export function AgentGenerationWorkspaceDarkV2({
requiredProductUploadCount - filledProductAttachmentCount,
0
);
const directReferenceAttachmentCount = attachments
.slice(0, DIRECT_MODEL_UPLOAD_SLOT_COUNT)
.filter((item) => Boolean(item?.url)).length;
const productAttachmentSummary = `${selectedProductAttachments.length}/${productSlotCount} 张产品图`;
const directReferenceAttachmentSummary = `已上传 ${directReferenceAttachmentCount}/${DIRECT_MODEL_UPLOAD_SLOT_COUNT} 张参考图`;
const modelAttachmentSummary = modelSlotEnabled
? selectedModelAttachment
? "模特图已带入"
@ -2576,10 +2602,14 @@ export function AgentGenerationWorkspaceDarkV2({
}, [activeResultModeUrls, selectedResultUrl]);
useEffect(() => {
if (isDirectReferenceUploadEnabled) {
setIsAttachmentSlotExpanded(true);
return;
}
if (!selectedAgentPresetId || !hasAgentUploadSlots) {
setIsAttachmentSlotExpanded(false);
}
}, [hasAgentUploadSlots, selectedAgentPresetId]);
}, [hasAgentUploadSlots, isDirectReferenceUploadEnabled, selectedAgentPresetId]);
useEffect(() => {
if (requiresPresetSelection && !selectedAgentPresetId) {
@ -2653,7 +2683,7 @@ export function AgentGenerationWorkspaceDarkV2({
}, [addNode, latestGeneratedGroup, nodes.length, syncGeneratedResultsToCanvas]);
const updateAttachmentAtSlot = useCallback((slotIndex: number, attachment: PickedAttachment | null) => {
const slotCount = Math.max(agentUploadSlots.length, 1);
const slotCount = Math.max(visibleAttachmentUploadSlots.length, 1);
setAttachments((current) => {
const slots: Array<PickedAttachment | null> = Array.from(
{ length: slotCount },
@ -2662,7 +2692,7 @@ export function AgentGenerationWorkspaceDarkV2({
slots[slotIndex] = attachment;
return slots;
});
}, [agentUploadSlots.length]);
}, [visibleAttachmentUploadSlots.length]);
const handleSlotFileChange = useCallback(
async (slotIndex: number, event: React.ChangeEvent<HTMLInputElement>) => {
@ -2688,7 +2718,7 @@ export function AgentGenerationWorkspaceDarkV2({
contentType: file.type || "image/jpeg",
assetId: typeof data.assetId === "string" ? data.assetId : undefined,
});
toast.success(`${agentUploadSlots[slotIndex]?.label || `槽位${slotIndex + 1}`}上传成功`);
toast.success(`${visibleAttachmentUploadSlots[slotIndex]?.label || `槽位${slotIndex + 1}`}上传成功`);
} catch (error) {
toast.error(error instanceof Error ? error.message : "上传失败");
} finally {
@ -2696,7 +2726,7 @@ export function AgentGenerationWorkspaceDarkV2({
event.currentTarget.value = "";
}
},
[agentUploadSlots, updateAttachmentAtSlot]
[updateAttachmentAtSlot, visibleAttachmentUploadSlots]
);
const handleBatchDownloadImages = useCallback(async (params: {
imageUrls: string[];
@ -4244,43 +4274,56 @@ export function AgentGenerationWorkspaceDarkV2({
<div className="space-y-3">
<div className="flex items-center gap-2 text-sm font-semibold text-white">
<ImagePlus className="h-4 w-4 text-emerald-300" />
输入图槽位
{isDirectReferenceUploadEnabled ? "上传参考图" : "输入图槽位"}
</div>
{agentUploadSlots.length > 0 ? (
{hasVisibleAttachmentUploadSlots ? (
<>
<div className="flex flex-wrap gap-2">
<span
className={cn(
"rounded-full border px-3 py-1 text-xs",
attachmentSummaryReady
? "border-emerald-400/25 bg-emerald-500/[0.10] text-emerald-100"
: "border-amber-400/25 bg-amber-500/[0.10] text-amber-100"
)}
>
{productAttachmentSummary}
</span>
{modelAttachmentSummary ? (
{isDirectReferenceUploadEnabled ? (
<div className="flex flex-wrap gap-2">
<span className="rounded-full border border-emerald-400/25 bg-emerald-500/[0.10] px-3 py-1 text-xs text-emerald-100">
{directReferenceAttachmentSummary}
</span>
<span className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-xs text-white/60">
可选上传,也可纯文字生成
</span>
</div>
) : (
<div className="flex flex-wrap gap-2">
<span
className={cn(
"rounded-full border px-3 py-1 text-xs",
selectedModelAttachment
attachmentSummaryReady
? "border-emerald-400/25 bg-emerald-500/[0.10] text-emerald-100"
: "border-white/10 bg-black/20 text-white/60"
: "border-amber-400/25 bg-amber-500/[0.10] text-amber-100"
)}
>
{modelAttachmentSummary}
{productAttachmentSummary}
</span>
) : null}
<span className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-xs text-white/60">
共 {agentUploadSlots.length} 个输入槽位
</span>
</div>
{modelAttachmentSummary ? (
<span
className={cn(
"rounded-full border px-3 py-1 text-xs",
selectedModelAttachment
? "border-emerald-400/25 bg-emerald-500/[0.10] text-emerald-100"
: "border-white/10 bg-black/20 text-white/60"
)}
>
{modelAttachmentSummary}
</span>
) : null}
<span className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-xs text-white/60">
共 {agentUploadSlots.length} 个输入槽位
</span>
</div>
)}
<p className="text-xs leading-6 text-white/55">
{missingAttachmentCount > 0
? `当前还需补充 ${missingAttachmentCount} 张产品图,展开后可继续检查或替换。`
: "产品图已自动带入并准备完成;模特图槽位可按需补充,不选也可以继续生成。"}
{isDirectReferenceUploadEnabled
? "第一步和第二步关闭时,可在这里直接上传商品图、参考图或场景图;生成时会和补充要求一起发送给模型。"
: missingAttachmentCount > 0
? `当前还需补充 ${missingAttachmentCount} 张产品图,展开后可继续检查或替换。`
: "产品图已自动带入并准备完成;模特图槽位可按需补充,不选也可以继续生成。"}
</p>
</>
) : (
@ -4290,14 +4333,20 @@ export function AgentGenerationWorkspaceDarkV2({
)}
</div>
{agentUploadSlots.length > 0 ? (
{hasVisibleAttachmentUploadSlots ? (
<CollapsibleTrigger asChild>
<Button
type="button"
variant="outline"
className="border-white/12 bg-black/25 text-white/82 hover:border-white/22 hover:bg-white/[0.06] hover:text-white"
>
{isAttachmentSlotExpanded ? "收起素材槽位" : "检查/替换素材"}
{isAttachmentSlotExpanded
? isDirectReferenceUploadEnabled
? "收起上传区"
: "收起素材槽位"
: isDirectReferenceUploadEnabled
? "上传参考图"
: "检查/替换素材"}
{isAttachmentSlotExpanded ? (
<ChevronUp className="ml-2 h-4 w-4" />
) : (
@ -4308,14 +4357,16 @@ export function AgentGenerationWorkspaceDarkV2({
) : null}
</div>
{agentUploadSlots.length > 0 ? (
{hasVisibleAttachmentUploadSlots ? (
<CollapsibleContent className="mt-4 space-y-4">
<div className="rounded-[20px] border border-emerald-400/15 bg-emerald-500/[0.06] px-4 py-3 text-xs leading-6 text-emerald-100/80">
上一步已选的白底图和品牌模特图会自动带入对应槽位,这里只保留最终检查与单张上传替换,不再重复展示已选素材列表。
{isDirectReferenceUploadEnabled
? "当前模式不会展示前两步素材选择,上传到这里的图片会作为参考图直接参与本次模型生图。"
: "上一步已选的白底图和品牌模特图会自动带入对应槽位,这里只保留最终检查与单张上传替换,不再重复展示已选素材列表。"}
</div>
<div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
{agentUploadSlots.map((slot, index) => {
{visibleAttachmentUploadSlots.map((slot, index) => {
return (
<motion.div
key={slot.label}
@ -4596,7 +4647,10 @@ export function AgentGenerationWorkspaceDarkV2({
</div>
) : null}
{hasAgentUploadSlots && isAttachmentSlotExpanded ? attachmentSlotPanel : null}
{isDirectReferenceUploadEnabled ||
(hasAgentUploadSlots && isAttachmentSlotExpanded)
? attachmentSlotPanel
: null}
<div className="rounded-[28px] border border-white/12 bg-white/[0.02] p-4">
<h3 className="mb-3 flex items-center gap-2 text-sm font-semibold text-white">