fix: enforce brand matching for references
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-27 21:53:02 +08:00
parent 47a0299090
commit 00c4e067bf

View File

@ -42,6 +42,9 @@ type ExternalTaskDetailCandidate = {
brand?: string;
productBrand?: string;
brand_name?: string;
brand_name_cn?: string;
brandTitle?: string;
brand_title?: string;
categoryName?: string;
shopName?: string;
sceneName?: string;
@ -64,6 +67,10 @@ type ExternalTaskDetailResponse = {
brandName?: string | null;
brand?: string | null;
productBrand?: string | null;
brand_name?: string | null;
brand_name_cn?: string | null;
brandTitle?: string | null;
brand_title?: string | null;
categoryName?: string | null;
shopName?: string | null;
candidateCount?: number;
@ -97,6 +104,29 @@ function normalizeUrlList(value: unknown) {
).slice(0, 64);
}
function getExternalBrandName(value: {
brandName?: string | null;
brand?: string | null;
productBrand?: string | null;
brand_name?: string | null;
brand_name_cn?: string | null;
brandTitle?: string | null;
brand_title?: string | null;
}) {
return (
String(
value.brandName ||
value.brand ||
value.productBrand ||
value.brand_name ||
value.brand_name_cn ||
value.brandTitle ||
value.brand_title ||
""
).trim() || null
);
}
function mapUpstreamErrorStatus(code: string) {
if (
code === "SKU_NOT_FOUND" ||
@ -117,21 +147,15 @@ function mapUpstreamErrorStatus(code: string) {
function normalizeCandidate(
value: ExternalTaskDetailCandidate,
index: number
index: number,
fallbackBrandName?: string | null
): AgentModeReferenceCandidate {
const uploadedAt = String(value.uploadedAt || "").trim() || null;
const taskNo = String(value.taskNo || "").trim() || null;
const materialId = String(value.materialId || "").trim() || null;
const sceneName = String(value.sceneName || "").trim() || null;
const id = taskNo || materialId || `candidate-${index + 1}`;
const brandName =
String(
value.brandName ||
value.brand ||
value.productBrand ||
value.brand_name ||
""
).trim() || null;
const brandName = getExternalBrandName(value) || fallbackBrandName || null;
return {
id,
@ -224,13 +248,6 @@ function filterCandidatesByBrand(
const normalizedRequestedBrand = normalizeComparableName(brandName);
if (!normalizedRequestedBrand) return candidates;
const hasBrandMetadata = candidates.some((candidate) =>
Boolean(normalizeComparableName(candidate.brandName))
);
if (!hasBrandMetadata) {
return candidates;
}
return candidates.filter((candidate) =>
isCandidateMatchedBrand(candidate, normalizedRequestedBrand)
);
@ -267,11 +284,17 @@ export async function GET(request: NextRequest) {
const normalizedKeyword = parsed.keyword.trim().toUpperCase();
const queryType = parsed.queryType as AgentWorkflowMaterialQueryType;
const requestedBrandName = String(parsed.brandName || "").trim();
const upstreamParams = new URLSearchParams({
resourceType: "task-detail",
[queryType]: normalizedKeyword,
});
if (requestedBrandName) {
upstreamParams.set("brandName", requestedBrandName);
}
const upstreamUrl = `${normalizeBaseUrl(
config.baseUrl
)}/standard-model-white-background?resourceType=task-detail&${queryType}=${encodeURIComponent(
normalizedKeyword
)}`;
)}/standard-model-white-background?${upstreamParams.toString()}`;
const upstreamResponse = await fetch(upstreamUrl, {
method: "GET",
@ -299,9 +322,11 @@ export async function GET(request: NextRequest) {
);
}
const requestedBrandName = String(parsed.brandName || "").trim();
const upstreamBrandName = getExternalBrandName(upstreamResult.data);
const sortedCandidates = sortCandidatesByUploadedAtDesc(
(upstreamResult.data.candidates || []).map((item, index) => normalizeCandidate(item, index))
(upstreamResult.data.candidates || []).map((item, index) =>
normalizeCandidate(item, index, upstreamBrandName)
)
);
const normalizedCandidates = filterCandidatesByBrand(sortedCandidates, requestedBrandName)
.filter((candidate) => getRenderableCandidateTargetUrls(candidate, parsed.target).length > 0);
@ -353,12 +378,7 @@ export async function GET(request: NextRequest) {
matchedSku: String(upstreamResult.data.sku || "").trim() || null,
brandName:
selectedCandidate.brandName ||
String(
upstreamResult.data.brandName ||
upstreamResult.data.brand ||
upstreamResult.data.productBrand ||
""
).trim() ||
upstreamBrandName ||
requestedBrandName ||
null,
categoryName: selectedCandidate.categoryName || String(upstreamResult.data.categoryName || "").trim() || null,