fix: use spu for detail reference search

This commit is contained in:
Your Name 2026-06-02 13:48:01 +08:00
parent 51e8393f95
commit 70cf96afaf
5 changed files with 79 additions and 14 deletions

View File

@ -97,6 +97,14 @@ function sanitizeGoodsInfoText(value: unknown, maxLength = 255) {
return String(value || "").trim().slice(0, maxLength);
}
function deriveSpuFromSku(value: unknown) {
const normalized = String(value || "").trim().toUpperCase();
if (!/[0-9]{2}$/.test(normalized) || normalized.length <= 2) {
return "";
}
return normalized.slice(0, -2);
}
function createGoodsInfoSignature(timespan: string, secret: string) {
const secretBuffer = Buffer.from(String(secret || "").trim(), "utf8");
if (secretBuffer.length !== 8) {
@ -817,7 +825,7 @@ export async function GET(request: NextRequest) {
query: normalizedKeyword,
queryType: "sku",
matchedSku,
matchedSpu: goodsInfo?.matchedSpu || productModel,
matchedSpu: goodsInfo?.matchedSpu || productModel || deriveSpuFromSku(matchedSku),
materialId: String(upstreamResult.data.materialId || "").trim() || null,
productModel,
zipUrl: String(upstreamResult.data.downloadUrls?.zip || "").trim() || null,

View File

@ -957,11 +957,11 @@ export async function GET(request: NextRequest) {
materialQueryType === "spu" && goodsLookup?.matchedSpu
? goodsLookup.matchedSpu.trim().toUpperCase()
: normalizedKeyword;
if (materialQueryType === "spu" && goodsLookup?.matchedSpu) {
console.info("[Agent Workflow Reference Search] Resolved SKU input to SPU:", {
if (materialQueryType === "spu" && resolvedMaterialKeyword !== normalizedKeyword) {
console.info("[Agent Workflow Reference Search] Resolved SPU query keyword:", {
keyword: normalizedKeyword,
resolvedSpu: resolvedMaterialKeyword,
matchedSku: goodsLookup.matchedSku || null,
matchedSku: goodsLookup?.matchedSku || null,
});
}
if (

View File

@ -1610,9 +1610,22 @@ export function AgentGenerationWorkspaceDarkV2({
);
const workflowBrandName = getCurrentWorkflowBrandName();
const getCurrentWorkflowPrimarySpu = useCallback(
() =>
String((getLatestWorkflowContext?.() ?? workflowContext)?.primarySku || "")
.trim(),
() => {
const latestWorkflowContext = getLatestWorkflowContext?.() ?? workflowContext;
const explicitSpu = String(latestWorkflowContext?.primarySpu || "").trim();
if (explicitSpu) {
return explicitSpu;
}
const primaryReferenceSpu = latestWorkflowContext?.referenceImages
?.find((image) => image.source === "primary" && image.productModel)
?.productModel?.trim();
if (primaryReferenceSpu) {
return primaryReferenceSpu;
}
return String(latestWorkflowContext?.primarySku || "").trim();
},
[getLatestWorkflowContext, workflowContext]
);
const workflowPrimarySpu = getCurrentWorkflowPrimarySpu();
@ -4210,16 +4223,17 @@ export function AgentGenerationWorkspaceDarkV2({
modelSlotEnabled && AGENT_DETAIL_MODEL_SLOT_INDEX >= 0
? getAttachmentIdentityKey(selectedModelAttachment)
: null;
const latestWorkflowContext = getLatestWorkflowContext?.() ?? workflowContext;
const workflowPrimarySpu = getCurrentWorkflowPrimarySpu().trim().toUpperCase();
const workflowPriceBand = String(latestWorkflowContext?.priceBand || "").trim();
updateDetailReplacementState((current) => {
let changed = false;
const nextBrief = {
...(current.brief || createEmptyAgentDetailBriefForm()),
};
const workflowPrimarySku = String(workflowContext?.primarySku || "").trim();
const workflowPriceBand = String(workflowContext?.priceBand || "").trim();
if (!nextBrief.productSpu && workflowPrimarySku) {
nextBrief.productSpu = workflowPrimarySku;
if (!nextBrief.productSpu && workflowPrimarySpu) {
nextBrief.productSpu = workflowPrimarySpu;
changed = true;
}
if (!nextBrief.priceBand && workflowPriceBand) {
@ -4346,14 +4360,15 @@ export function AgentGenerationWorkspaceDarkV2({
});
}, [
detailGenerationProductSlotIndexes,
getCurrentWorkflowPrimarySpu,
getLatestWorkflowContext,
isDetailReplacementPreset,
modelSlotEnabled,
referenceImages,
selectedModelAttachment,
selectedProductAttachments,
updateDetailReplacementState,
workflowContext?.priceBand,
workflowContext?.primarySku,
workflowContext,
]);
const updateDetailGenerationMethod = useCallback(
(method: "reference_replace" | "ai_detail_generate") => {

View File

@ -219,6 +219,33 @@ function normalizeWorkflowText(value: string) {
.trim();
}
function normalizeWorkflowProductCode(value: unknown) {
return String(value || "").trim().toUpperCase();
}
function deriveSpuFromSku(value: unknown) {
const normalized = normalizeWorkflowProductCode(value);
if (!/[0-9]{2}$/.test(normalized) || normalized.length <= 2) {
return "";
}
return normalized.slice(0, -2);
}
function resolveWorkflowSpu(params: {
inputValue: string;
result?: AgentWorkflowMaterialSelections["primary"]["result"] | null;
}) {
const result = params.result || null;
return (
normalizeWorkflowProductCode(result?.matchedSpu) ||
normalizeWorkflowProductCode(result?.productModel) ||
(result?.queryType === "spu" ? normalizeWorkflowProductCode(result?.query) : "") ||
(result?.queryType === "sku"
? deriveSpuFromSku(result?.matchedSku || result?.query || params.inputValue)
: "")
);
}
function sanitizeWorkflowPromptFragment(value: string) {
return normalizeWorkflowText(value)
.replace(/请按选项[\d一二三四五六七八九十]+执行[。.]?/g, "")
@ -416,11 +443,22 @@ export function buildAgentWorkflowComposerContext(params: {
materials: params.materials,
selectedBrandModel: params.selectedBrandModel,
});
const primaryWorkflowSpu = resolveWorkflowSpu({
inputValue: params.inputs.primarySku,
result: params.materials?.primary?.result || null,
});
const secondaryWorkflowSpu = resolveWorkflowSpu({
inputValue: params.inputs.secondarySku,
result: params.materials?.secondary?.result || null,
});
const summaryParts: string[] = [];
if (params.inputs.primarySku.trim()) {
summaryParts.push(`主SKU:${params.inputs.primarySku.trim()}`);
}
if (primaryWorkflowSpu && primaryWorkflowSpu !== params.inputs.primarySku.trim().toUpperCase()) {
summaryParts.push(`主SPU:${primaryWorkflowSpu}`);
}
if (params.inputs.secondarySku.trim()) {
summaryParts.push(`搭配SKU:${params.inputs.secondarySku.trim()}`);
}
@ -592,7 +630,9 @@ export function buildAgentWorkflowComposerContext(params: {
return {
primarySku: params.inputs.primarySku.trim() || undefined,
primarySpu: primaryWorkflowSpu || undefined,
secondarySku: params.inputs.secondarySku.trim() || undefined,
secondarySpu: secondaryWorkflowSpu || undefined,
brand: params.inputs.brand.trim() || undefined,
store: params.inputs.store.trim() || undefined,
officialSecondCategory: params.inputs.officialSecondCategory.trim() || undefined,
@ -641,7 +681,7 @@ export function getSelectedWorkflowReferenceImages(params: {
source,
sourceLabel,
sku: result.matchedSku || fallbackSku || undefined,
productModel: result.productModel || null,
productModel: result.productModel || result.matchedSpu || null,
label: item.label,
name: item.fileName || item.label,
url: item.imageUrl,

View File

@ -348,7 +348,9 @@ export interface AgentWorkflowComposerSelection {
export interface AgentWorkflowComposerContext {
primarySku?: string;
primarySpu?: string;
secondarySku?: string;
secondarySpu?: string;
brand?: string;
store?: string;
officialSecondCategory?: string;