auto-save 2026-05-17 19:32 (~4)
This commit is contained in:
@@ -1,131 +1,5 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "d3ee267",
|
||||
"message": "auto-save 2026-05-15 10:31 (~1)",
|
||||
"ts": "2026-05-15T10:31:58+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 10:31 (~1)",
|
||||
"ts": "2026-05-15T02:33:08Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "919cf8f",
|
||||
"message": "auto-save 2026-05-15 10:37 (~1)",
|
||||
"ts": "2026-05-15T10:37:36+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 10:37 (~1)",
|
||||
"ts": "2026-05-15T02:43:08Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "48007a7",
|
||||
"message": "auto-save 2026-05-15 10:43 (~1)",
|
||||
"ts": "2026-05-15T10:43:15+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "d58c710",
|
||||
"message": "auto-save 2026-05-15 10:48 (~1)",
|
||||
"ts": "2026-05-15T10:48:49+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 10:48 (~1)",
|
||||
"ts": "2026-05-15T02:53:08Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "0debed8",
|
||||
"message": "auto-save 2026-05-15 10:54 (~1)",
|
||||
"ts": "2026-05-15T10:54:23+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "6b593cc",
|
||||
"message": "auto-save 2026-05-15 11:00 (~1)",
|
||||
"ts": "2026-05-15T11:01:11+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 11:00 (~1)",
|
||||
"ts": "2026-05-15T03:04:44Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "9e5d853",
|
||||
"message": "auto-save 2026-05-15 11:07 (~1)",
|
||||
"ts": "2026-05-15T11:07:11+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "4d66653",
|
||||
"message": "auto-save 2026-05-15 11:12 (~1)",
|
||||
"ts": "2026-05-15T11:12:45+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 11:12 (~1)",
|
||||
"ts": "2026-05-15T03:14:44Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 6,
|
||||
"hash": "08aed2a",
|
||||
"message": "auto-save 2026-05-15 11:18 (+1, ~4)",
|
||||
"ts": "2026-05-15T11:18:18+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "e6b2768",
|
||||
"message": "auto-save 2026-05-15 11:23 (~1)",
|
||||
"ts": "2026-05-15T11:23:51+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 11:23 (~1)",
|
||||
"ts": "2026-05-15T03:24:44Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 5,
|
||||
"hash": "55a9a9d",
|
||||
"message": "auto-save 2026-05-15 11:29 (+1, ~3)",
|
||||
"ts": "2026-05-15T11:29:23+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-15 11:29 (+1, ~3)",
|
||||
"ts": "2026-05-15T03:34:44Z",
|
||||
"type": "session-heartbeat"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "967a827",
|
||||
"message": "auto-save 2026-05-15 11:34 (~1)",
|
||||
"ts": "2026-05-15T11:34:55+08:00",
|
||||
"type": "commit"
|
||||
},
|
||||
{
|
||||
"files_changed": 1,
|
||||
"hash": "7bf9e0f",
|
||||
@@ -3273,6 +3147,123 @@
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-17 16:43 (~4)",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T16:54:22+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-17 16:54 (~4)",
|
||||
"hash": "9798e97",
|
||||
"files_changed": 4
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T16:56:40+08:00",
|
||||
"type": "commit",
|
||||
"message": "feat: optimize product pool uploads",
|
||||
"hash": "84108ee",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T08:58:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:08:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:18:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:28:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:38:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:48:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T09:58:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:08:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:18:27Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:28:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:38:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:48:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T10:58:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T11:08:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T11:18:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: optimize product pool uploads",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T19:24:23+08:00",
|
||||
"type": "commit",
|
||||
"message": "fix: tolerate product view model output",
|
||||
"hash": "a9d5962",
|
||||
"files_changed": 2
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-17T11:28:28Z",
|
||||
"type": "session-heartbeat",
|
||||
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:fix: tolerate product view model output",
|
||||
"files_changed": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
70
api/main.py
70
api/main.py
@@ -4274,12 +4274,54 @@ PRODUCT_VIEW_LABELS = {
|
||||
"back_bottom": "背面/底部",
|
||||
}
|
||||
|
||||
PRODUCT_BACKGROUND_VALUES = ["white", "black", "simple", "complex", "unknown"]
|
||||
PRODUCT_USE_TAG_VALUES = [
|
||||
"hero_packshot",
|
||||
"wearing_scale",
|
||||
"inner_contact",
|
||||
"side_thickness",
|
||||
"asymmetry",
|
||||
"button_detail",
|
||||
"back_bottom",
|
||||
"material_texture",
|
||||
]
|
||||
|
||||
|
||||
def default_product_use_tags(view: str) -> list[str]:
|
||||
defaults = {
|
||||
"front": ["hero_packshot", "asymmetry"],
|
||||
"left_45": ["hero_packshot", "asymmetry", "button_detail"],
|
||||
"right_45": ["hero_packshot", "asymmetry", "button_detail"],
|
||||
"side_thickness": ["side_thickness", "wearing_scale"],
|
||||
"inner_contacts": ["inner_contact", "wearing_scale"],
|
||||
"back_bottom": ["back_bottom", "material_texture"],
|
||||
}
|
||||
return defaults.get(view, ["hero_packshot"])
|
||||
|
||||
|
||||
def normalize_product_use_tags(tags: object, view: str) -> list[str]:
|
||||
if isinstance(tags, str):
|
||||
raw_tags = re.split(r"[,,/、\s]+", tags)
|
||||
elif isinstance(tags, list):
|
||||
raw_tags = [str(x) for x in tags]
|
||||
else:
|
||||
raw_tags = []
|
||||
result = []
|
||||
for tag in raw_tags + default_product_use_tags(view):
|
||||
tag = str(tag).strip()
|
||||
if tag in PRODUCT_USE_TAG_VALUES and tag not in result:
|
||||
result.append(tag)
|
||||
return result[:4]
|
||||
|
||||
|
||||
def fallback_product_view(index: int) -> dict:
|
||||
view = PRODUCT_VIEW_VALUES[min(index, len(PRODUCT_VIEW_VALUES) - 1)]
|
||||
return {
|
||||
"view": view,
|
||||
"background": "unknown",
|
||||
"use_tags": default_product_use_tags(view),
|
||||
"note": f"{PRODUCT_VIEW_LABELS.get(view, view)}参考;模型识别不可用时按上传顺序自动标注,请人工只检查备注。",
|
||||
"risk": "模型识别不可用,按上传顺序兜底",
|
||||
"confidence": 0.25,
|
||||
}
|
||||
|
||||
@@ -4300,21 +4342,37 @@ def parse_product_view_response(raw: str, index: int) -> dict:
|
||||
flags=re.I,
|
||||
)
|
||||
confidence_match = re.search(r'["\']?confidence["\']?\s*[::]\s*["\']?([0-9.]+)', text, flags=re.I)
|
||||
background_match = re.search(r'["\']?background["\']?\s*[::]\s*["\']?([a-z0-9_]+)', text, flags=re.I)
|
||||
tags_match = re.search(r'["\']?use_tags["\']?\s*[::]\s*\[([\s\S]*?)\]', text, flags=re.I)
|
||||
risk_match = re.search(
|
||||
r'["\']?risk["\']?\s*[::]\s*["\']?([\s\S]*?)(?:["\']?\s*[,}]\s*$)',
|
||||
text,
|
||||
flags=re.I,
|
||||
)
|
||||
data = {
|
||||
"view": view_match.group(1) if view_match else "",
|
||||
"background": background_match.group(1) if background_match else "unknown",
|
||||
"use_tags": re.findall(r"[a-z_]+", tags_match.group(1)) if tags_match else [],
|
||||
"note": note_match.group(1) if note_match else "",
|
||||
"risk": risk_match.group(1) if risk_match else "",
|
||||
"confidence": confidence_match.group(1) if confidence_match else 0.45,
|
||||
}
|
||||
view = str(data.get("view") or "").strip().strip('"\' ,。')
|
||||
if view not in PRODUCT_VIEW_VALUES:
|
||||
return fallback_product_view(index)
|
||||
background = str(data.get("background") or "unknown").strip().strip('"\' ,。')
|
||||
if background not in PRODUCT_BACKGROUND_VALUES:
|
||||
background = "unknown"
|
||||
use_tags = normalize_product_use_tags(data.get("use_tags"), view)
|
||||
note = str(data.get("note") or "").strip().strip('"\' ,,。')
|
||||
note = re.sub(r"\s+", " ", note)[:220] or f"{PRODUCT_VIEW_LABELS.get(view, view)}参考"
|
||||
risk = str(data.get("risk") or "").strip().strip('"\' ,,。')
|
||||
risk = re.sub(r"\s+", " ", risk)[:120]
|
||||
try:
|
||||
confidence = max(0.0, min(1.0, float(data.get("confidence", 0.5))))
|
||||
except Exception:
|
||||
confidence = 0.5
|
||||
return {"view": view, "note": note, "confidence": confidence}
|
||||
return {"view": view, "background": background, "use_tags": use_tags, "note": note, "risk": risk, "confidence": confidence}
|
||||
|
||||
|
||||
def analyze_product_view(ref_path: Path, index: int) -> dict:
|
||||
@@ -4324,10 +4382,13 @@ def analyze_product_view(ref_path: Path, index: int) -> dict:
|
||||
prompt = (
|
||||
"You are inspecting a product reference image for a SKG neck-and-shoulder wearable massage device. The background may be white, black, or simple studio color. "
|
||||
"Classify the camera/view angle into exactly one enum: front, left_45, right_45, side_thickness, inner_contacts, back_bottom. "
|
||||
"Also write a concise Chinese note for video generation, focused on visible structure, asymmetry, thickness, inner massage contacts, buttons, opening width, and shoulder-neck wearing scale. "
|
||||
"Classify background into exactly one enum: white, black, simple, complex, unknown. Do not request or perform background conversion. "
|
||||
"Add use_tags from this enum only: hero_packshot, wearing_scale, inner_contact, side_thickness, asymmetry, button_detail, back_bottom, material_texture. "
|
||||
"Also write a concise Chinese note for video generation, focused on visible structure, asymmetry, thickness, inner massage contacts, buttons, opening width, shoulder-neck wearing scale, and what this image is best used for in video generation. "
|
||||
"Write risk in Chinese only if this reference may mislead video generation, such as cropped product, hand blocking, low detail, strong reflection, or background confusion; otherwise use empty string. "
|
||||
"If uncertain, choose the closest useful view; do not ask the user. "
|
||||
"Output one-line strict JSON only. Do not use markdown or line breaks. "
|
||||
"{\"view\":\"front|left_45|right_45|side_thickness|inner_contacts|back_bottom\", \"note\":\"中文备注\", \"confidence\":0.0}."
|
||||
"{\"view\":\"front|left_45|right_45|side_thickness|inner_contacts|back_bottom\", \"background\":\"white|black|simple|complex|unknown\", \"use_tags\":[\"hero_packshot\"], \"note\":\"中文备注\", \"risk\":\"\", \"confidence\":0.0}."
|
||||
)
|
||||
try:
|
||||
resp = llm().chat.completions.create(
|
||||
@@ -4364,7 +4425,10 @@ def analyze_product_views(job_id: str, req: AnalyzeProductViewsReq) -> dict:
|
||||
items.append({
|
||||
"index": index,
|
||||
"view": result["view"],
|
||||
"background": result.get("background", "unknown"),
|
||||
"use_tags": result.get("use_tags", default_product_use_tags(result["view"])),
|
||||
"note": result["note"],
|
||||
"risk": result.get("risk", ""),
|
||||
"confidence": result["confidence"],
|
||||
})
|
||||
used = {item["view"] for item in items}
|
||||
|
||||
@@ -89,7 +89,10 @@ type ProductRefItem = {
|
||||
id: string
|
||||
ref: ImageRef
|
||||
view: string
|
||||
background: string
|
||||
useTags: string[]
|
||||
note: string
|
||||
risk: string
|
||||
source: "upload" | "ai"
|
||||
confidence?: number
|
||||
}
|
||||
@@ -105,6 +108,25 @@ const PRODUCT_VIEW_SLOTS = [
|
||||
|
||||
const MAX_PRODUCT_REFS_PER_VIDEO = 6
|
||||
|
||||
const PRODUCT_BACKGROUND_LABELS: Record<string, string> = {
|
||||
white: "白底",
|
||||
black: "黑底",
|
||||
simple: "纯色/简单",
|
||||
complex: "复杂背景",
|
||||
unknown: "背景未知",
|
||||
}
|
||||
|
||||
const PRODUCT_USE_TAG_LABELS: Record<string, string> = {
|
||||
hero_packshot: "主外观",
|
||||
wearing_scale: "佩戴比例",
|
||||
inner_contact: "触点",
|
||||
side_thickness: "厚度",
|
||||
asymmetry: "非对称",
|
||||
button_detail: "按键",
|
||||
back_bottom: "背底",
|
||||
material_texture: "材质",
|
||||
}
|
||||
|
||||
const controlClass =
|
||||
"h-10 rounded-md border border-white/10 bg-black/55 px-3 text-[12px] text-white outline-none transition focus:border-cyan-300/60 disabled:cursor-not-allowed disabled:opacity-40"
|
||||
|
||||
@@ -330,12 +352,39 @@ function productViewLabel(view: string) {
|
||||
return PRODUCT_VIEW_SLOTS.find((slot) => slot.value === view)?.label ?? view
|
||||
}
|
||||
|
||||
function productBackgroundLabel(background: string) {
|
||||
return PRODUCT_BACKGROUND_LABELS[background] ?? PRODUCT_BACKGROUND_LABELS.unknown
|
||||
}
|
||||
|
||||
function defaultProductUseTags(view: string) {
|
||||
const defaults: Record<string, string[]> = {
|
||||
front: ["hero_packshot", "asymmetry"],
|
||||
left_45: ["hero_packshot", "asymmetry", "button_detail"],
|
||||
right_45: ["hero_packshot", "asymmetry", "button_detail"],
|
||||
side_thickness: ["side_thickness", "wearing_scale"],
|
||||
inner_contacts: ["inner_contact", "wearing_scale"],
|
||||
back_bottom: ["back_bottom", "material_texture"],
|
||||
}
|
||||
return defaults[view] ?? ["hero_packshot"]
|
||||
}
|
||||
|
||||
function normalizeProductUseTags(tags: string[] | undefined, view: string) {
|
||||
const result: string[] = []
|
||||
for (const tag of [...(tags ?? []), ...defaultProductUseTags(view)]) {
|
||||
if (PRODUCT_USE_TAG_LABELS[tag] && !result.includes(tag)) result.push(tag)
|
||||
}
|
||||
return result.slice(0, 4)
|
||||
}
|
||||
|
||||
function createProductRefItem(
|
||||
ref: ImageRef,
|
||||
index: number,
|
||||
source: ProductRefItem["source"] = "upload",
|
||||
view?: string,
|
||||
note?: string,
|
||||
background = "unknown",
|
||||
useTags?: string[],
|
||||
risk = "",
|
||||
confidence?: number,
|
||||
): ProductRefItem {
|
||||
const slot = PRODUCT_VIEW_SLOTS[index] ?? PRODUCT_VIEW_SLOTS[PRODUCT_VIEW_SLOTS.length - 1]
|
||||
@@ -344,7 +393,10 @@ function createProductRefItem(
|
||||
id: productRefKey(ref, index),
|
||||
ref,
|
||||
view: view ?? targetSlot.value,
|
||||
background,
|
||||
useTags: normalizeProductUseTags(useTags, view ?? targetSlot.value),
|
||||
note: note ?? targetSlot.hint,
|
||||
risk,
|
||||
source,
|
||||
confidence,
|
||||
}
|
||||
@@ -353,7 +405,11 @@ function createProductRefItem(
|
||||
function productReferenceNotes(items: ProductRefItem[]) {
|
||||
if (!items.length) return ""
|
||||
return items
|
||||
.map((item, index) => `${index + 1}. ${productViewLabel(item.view)}:${item.note || "无补充备注"}`)
|
||||
.map((item, index) => {
|
||||
const tags = item.useTags.map((tag) => PRODUCT_USE_TAG_LABELS[tag]).filter(Boolean).join("/")
|
||||
const risk = item.risk ? `;风险:${item.risk}` : ""
|
||||
return `${index + 1}. ${productViewLabel(item.view)}|${productBackgroundLabel(item.background)}|${tags}:${item.note || "无补充备注"}${risk}`
|
||||
})
|
||||
.join(";")
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,10 @@ export async function generateProductAngleAsset(
|
||||
export interface ProductViewAnalysisItem {
|
||||
index: number
|
||||
view: string
|
||||
background?: string
|
||||
use_tags?: string[]
|
||||
note: string
|
||||
risk?: string
|
||||
confidence: number
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user