- {detailReplacementQueryType === "sku" ? "当前按SKU命中" : "支持SPU/SKU自动识别"}
+
+ {([
+ ["spu", "按SPU查询"],
+ ["sku", "按SKU查询"],
+ ["productId", "按商品ID查询"],
+ ] as Array<[AgentWorkflowReferenceQueryType, string]>).map(([queryType, label]) => (
+
+ ))}
+
+ {detailReplacementQueryType === "productId" ? (
+
+ ) : null}
@@ -5858,7 +6066,11 @@ export function AgentGenerationWorkspaceDarkV2({
query: e.target.value,
})
}
- placeholder={`输入 SPU 或 SKU,查询任务整套中的${detailReferenceSourceLabel}参考图`}
+ placeholder={
+ detailReplacementQueryType === "productId"
+ ? "输入商品ID,查询并拉取详情图片"
+ : `输入 ${detailReplacementQueryType === "sku" ? "SKU" : "SPU"},查询任务整套中的${detailReferenceSourceLabel}参考图`
+ }
className="h-12 rounded-[22px] border-white/10 bg-black/20 text-sm text-white placeholder:text-white/22 focus:border-emerald-400/30"
/>
) : null}
diff --git a/lib/agents/mode-workspace-state.ts b/lib/agents/mode-workspace-state.ts
index 8c17f56db..5c47ee438 100644
--- a/lib/agents/mode-workspace-state.ts
+++ b/lib/agents/mode-workspace-state.ts
@@ -3,6 +3,8 @@ import type {
AgentModeReferenceCandidate,
AgentModeWorkspaceState,
AgentWorkflowMaterialQueryType,
+ AgentWorkflowProductDetailChannel,
+ AgentWorkflowReferenceQueryType,
} from "@/types/agent";
import {
createEmptyAgentDetailBriefForm,
@@ -17,6 +19,7 @@ export function createEmptyAgentModeWorkspaceState(): AgentModeWorkspaceState {
method: "reference_replace",
query: "",
queryType: "spu",
+ productDetailChannel: "taobao",
candidates: [],
selectedCandidateId: null,
references: [],
@@ -61,6 +64,7 @@ function normalizeReferenceItems(value: unknown): AgentDetailReplacementReferenc
sortOrder: Number.isFinite(Number(raw.sortOrder))
? Math.max(0, Math.min(999, Math.round(Number(raw.sortOrder))))
: index,
+ passthrough: raw.passthrough === true,
assignedProductIndex: Number.isFinite(Number(raw.assignedProductIndex))
? Math.max(0, Math.min(9, Math.round(Number(raw.assignedProductIndex))))
: null,
@@ -73,6 +77,17 @@ function normalizeQueryType(value: unknown, fallback: AgentWorkflowMaterialQuery
return value === "sku" || value === "spu" ? value : fallback;
}
+function normalizeReferenceQueryType(
+ value: unknown,
+ fallback: AgentWorkflowReferenceQueryType
+) {
+ return value === "sku" || value === "spu" || value === "productId" ? value : fallback;
+}
+
+function normalizeProductDetailChannel(value: unknown): AgentWorkflowProductDetailChannel {
+ return value === "1688" || value === "douyin" || value === "jd" ? value : "taobao";
+}
+
function normalizeGenerationSlots(value: unknown) {
if (!Array.isArray(value)) return createEmptyAgentDetailSlots();
const base = createEmptyAgentDetailSlots();
@@ -138,6 +153,7 @@ function normalizeCandidate(value: unknown, index: number): AgentModeReferenceCa
materialId: String(raw.materialId || "").trim() || null,
taskNo: String(raw.taskNo || "").trim() || null,
productModel: String(raw.productModel || "").trim() || null,
+ brandName: String(raw.brandName || "").trim() || null,
categoryName: String(raw.categoryName || "").trim() || null,
shopName: String(raw.shopName || "").trim() || null,
sceneName: String(raw.sceneName || "").trim() || null,
@@ -175,7 +191,8 @@ export function normalizeAgentModeWorkspaceState(value: unknown): AgentModeWorks
detailReplacement: {
method: detailRaw.method === "ai_detail_generate" ? "ai_detail_generate" : "reference_replace",
query: String(detailRaw.query || detailRaw.spuQuery || "").trim(),
- queryType: normalizeQueryType(detailRaw.queryType, "spu"),
+ queryType: normalizeReferenceQueryType(detailRaw.queryType, "spu"),
+ productDetailChannel: normalizeProductDetailChannel(detailRaw.productDetailChannel),
candidates: normalizeCandidates(detailRaw.candidates),
selectedCandidateId: String(detailRaw.selectedCandidateId || "").trim() || null,
references: normalizeReferenceItems(detailRaw.references),
diff --git a/lib/agents/workflow-material-config.ts b/lib/agents/workflow-material-config.ts
index b231f85d7..43f927eb5 100644
--- a/lib/agents/workflow-material-config.ts
+++ b/lib/agents/workflow-material-config.ts
@@ -13,6 +13,14 @@ export const defaultAgentWorkflowMaterialApiConfig: AgentWorkflowMaterialApiConf
enabled: false,
baseUrl: "https://sc.jiansun.vip/api/external",
apiKey: "",
+ productDetailEnabled: false,
+ productDetailBaseUrl: "",
+ productDetailApiKey: "",
+ productDetailPath: "",
+ productDetailMethod: "GET",
+ productDetailDefaultChannel: "taobao",
+ productDetailSyncAnalysis: true,
+ productDetailForceReanalyze: false,
};
function sanitizeText(value: unknown, maxLength: number) {
@@ -206,6 +214,19 @@ export function normalizeAgentWorkflowMaterialApiConfig(
baseUrl:
sanitizeText(raw.baseUrl, 255) || defaultAgentWorkflowMaterialApiConfig.baseUrl,
apiKey: sanitizeText(raw.apiKey, 500),
+ productDetailEnabled: raw.productDetailEnabled === true,
+ productDetailBaseUrl: sanitizeText(raw.productDetailBaseUrl, 500),
+ productDetailApiKey: sanitizeText(raw.productDetailApiKey, 500),
+ productDetailPath: sanitizeText(raw.productDetailPath, 500),
+ productDetailMethod: raw.productDetailMethod === "POST" ? "POST" : "GET",
+ productDetailDefaultChannel:
+ raw.productDetailDefaultChannel === "1688" ||
+ raw.productDetailDefaultChannel === "douyin" ||
+ raw.productDetailDefaultChannel === "jd"
+ ? raw.productDetailDefaultChannel
+ : "taobao",
+ productDetailSyncAnalysis: raw.productDetailSyncAnalysis !== false,
+ productDetailForceReanalyze: raw.productDetailForceReanalyze === true,
};
}
@@ -216,5 +237,6 @@ export function normalizeAgentWorkflowMaterialApiConfigForPublic(
return {
...config,
apiKey: "",
+ productDetailApiKey: "",
};
}
diff --git a/types/agent.ts b/types/agent.ts
index 08907d91d..8472df26b 100644
--- a/types/agent.ts
+++ b/types/agent.ts
@@ -209,6 +209,14 @@ export interface AgentWorkflowMaterialApiConfig {
enabled: boolean;
baseUrl: string;
apiKey: string;
+ productDetailEnabled?: boolean;
+ productDetailBaseUrl?: string;
+ productDetailApiKey?: string;
+ productDetailPath?: string;
+ productDetailMethod?: "GET" | "POST";
+ productDetailDefaultChannel?: AgentWorkflowProductDetailChannel;
+ productDetailSyncAnalysis?: boolean;
+ productDetailForceReanalyze?: boolean;
}
export interface AgentWorkflowGoodsInfoApiConfig {
@@ -219,6 +227,8 @@ export interface AgentWorkflowGoodsInfoApiConfig {
}
export type AgentWorkflowMaterialQueryType = "sku" | "spu";
+export type AgentWorkflowReferenceQueryType = AgentWorkflowMaterialQueryType | "productId";
+export type AgentWorkflowProductDetailChannel = "taobao" | "1688" | "douyin" | "jd";
export interface AgentWorkflowBrandModelImage {
id: string;
@@ -417,7 +427,8 @@ export interface AgentModeReferenceCandidate {
export interface AgentDetailReplacementState {
method: AgentDetailMethod;
query: string;
- queryType: AgentWorkflowMaterialQueryType;
+ queryType: AgentWorkflowReferenceQueryType;
+ productDetailChannel?: AgentWorkflowProductDetailChannel;
candidates: AgentModeReferenceCandidate[];
selectedCandidateId?: string | null;
references: AgentDetailReplacementReferenceItem[];