From 9a6418eb931da876d90fe19dc74eca186397dbce Mon Sep 17 00:00:00 2001 From: Zhang Youjie Date: Thu, 16 Apr 2026 16:12:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BA=90=E8=BD=A6=E5=9E=8B=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E7=BC=96=E8=BE=91=EF=BC=9B=E5=8A=A0=E5=88=86=E9=A1=B5=EF=BC=8C?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=86=85=E5=AE=B9=E7=9A=84=E6=96=B0?= =?UTF-8?q?=E5=BB=BA=E6=8C=89=E9=92=AE=EF=BC=8C=E7=B2=BE=E7=AE=80=E7=8A=B6?= =?UTF-8?q?=E6=80=81=EF=BC=8C=E9=A2=84=E8=A7=88=E5=AF=B9=E9=BD=90=EF=BC=88?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E4=BA=86=E5=8E=9F=E7=89=88=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BA=86=E4=B8=80=E7=A7=8D=E9=A2=84=E8=A7=88=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=EF=BC=8C=E9=80=89=E4=B8=93=E9=A2=98=E9=A1=B5=E6=97=B6?= =?UTF-8?q?=E5=8F=98=E5=8C=96=E8=A1=A8=E5=8D=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content-library/MiniAppContentLibrary.tsx | 528 +++++++++++++----- 1 file changed, 385 insertions(+), 143 deletions(-) diff --git a/audi-content-portal/src/components/content-library/MiniAppContentLibrary.tsx b/audi-content-portal/src/components/content-library/MiniAppContentLibrary.tsx index 430a918..cdd7451 100644 --- a/audi-content-portal/src/components/content-library/MiniAppContentLibrary.tsx +++ b/audi-content-portal/src/components/content-library/MiniAppContentLibrary.tsx @@ -27,6 +27,14 @@ import { type WorkflowStatus = "draft" | "prepublished" | "published" +type TopicSection = { + id: string + title: string + imageUrl: string + specLeftLabel: string + specRightLabel: string +} + type SourceSnapshot = { title: string subtitle: string @@ -34,6 +42,9 @@ type SourceSnapshot = { description: string ctaText: string imageUrls: string[] + topicNavTitle?: string + topicHeroTitle?: string + topicSections?: TopicSection[] } type MiniAppContent = { @@ -48,6 +59,9 @@ type MiniAppContent = { ctaText: string scheduledPublishAt: string imageUrls: string[] + topicNavTitle?: string + topicHeroTitle?: string + topicSections?: TopicSection[] workflowStatus: WorkflowStatus updatedBy: string updatedAt: string @@ -135,6 +149,24 @@ const CONTENTS: MiniAppContent[] = [ imageUrls: [ "/images/cars/q3-1.jpg", ], + topicNavTitle: "Q3详情", + topicHeroTitle: "先锋设计", + topicSections: [ + { + id: "q3-topic-1", + title: "RS竞速套件", + imageUrl: "/images/cars/q3-1.jpg", + specLeftLabel: "长", + specRightLabel: "宽", + }, + { + id: "q3-topic-2", + title: "宽体低趴 超长轴距", + imageUrl: "/images/cars/q3-2.jpg", + specLeftLabel: "长", + specRightLabel: "宽", + }, + ], workflowStatus: "draft", updatedBy: "内容运营专员", updatedAt: "2026-04-11 08:40", @@ -180,7 +212,7 @@ const CONTENTS: MiniAppContent[] = [ id: "c7", sourceCarId: "rs7", sourceCarName: "Audi RS7", - pageType: "车型页", + pageType: "专题页", title: "Audi RS7 Performance", subtitle: "高性能美学,锋芒尽释", highlights: "V8双涡轮\nquattro四驱\nRS专属运动套件", @@ -292,6 +324,29 @@ const SOURCE_CAR_OPTIONS = [ { id: "rs7", name: "Audi RS7" }, ] as const +function createTopicSectionsFromImages(images: string[]) { + const picks = images.slice(0, 2) + const fallback = ["/images/cars/a7-1.jpg", "/images/cars/a7-2.jpg"] + const selected = picks.length > 0 ? picks : fallback + + return selected.map((imageUrl, index) => ({ + id: `topic-section-${index + 1}`, + title: index === 0 ? "RS竞速套件" : "宽体低趴 超长轴距", + imageUrl, + specLeftLabel: "长", + specRightLabel: "宽", + })) +} + +function buildTopicPatch(sourceCarName: string, snapshot?: SourceSnapshot): Pick { + const hero = snapshot?.topicHeroTitle ?? snapshot?.subtitle ?? "先锋设计" + return { + topicNavTitle: snapshot?.topicNavTitle ?? `${sourceCarName || "车型"}详情`, + topicHeroTitle: hero, + topicSections: snapshot?.topicSections ?? createTopicSectionsFromImages(snapshot?.imageUrls ?? []), + } +} + function workflowBadgeClass(status: WorkflowStatus) { switch (status) { case "draft": @@ -336,6 +391,9 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, ctaText: "立即预约试驾", scheduledPublishAt: "", imageUrls: [], + topicNavTitle: `${newContentRequest.sourceCarName}详情`, + topicHeroTitle: "先锋设计", + topicSections: createTopicSectionsFromImages([]), workflowStatus: "draft", updatedBy: "内容运营专员", updatedAt: nowString(), @@ -388,8 +446,9 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, subtitle: source.subtitle, highlights: source.highlights, description: source.description, - ctaText: source.ctaText, - imageUrls: source.imageUrls, + ctaText: item.pageType === "专题页" ? "预约体验" : source.ctaText, + imageUrls: item.pageType === "专题页" ? [] : source.imageUrls, + ...buildTopicPatch(item.sourceCarName, source), }, })) onAddAuditLog(`内容运营专员发起 ${item.sourceCarName} 源数据重置(待保存生效)`) @@ -429,6 +488,9 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, ctaText: "立即预约试驾", scheduledPublishAt: "", imageUrls: [], + topicNavTitle: "车型详情", + topicHeroTitle: "先锋设计", + topicSections: createTopicSectionsFromImages([]), workflowStatus: "draft", updatedBy: "内容运营专员", updatedAt: nowString(), @@ -464,6 +526,38 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, updateContent(item.id, { imageUrls: item.imageUrls.filter((_, i) => i !== idx) }) } + const updateTopicSection = (item: MiniAppContent, sectionId: string, patch: Partial) => { + const sections = item.topicSections ?? [] + updateContent(item.id, { + topicSections: sections.map((section) => (section.id === sectionId ? { ...section, ...patch } : section)), + }) + } + + const addTopicSection = (item: MiniAppContent) => { + const sections = item.topicSections ?? [] + if (sections.length >= 6) return + updateContent(item.id, { + topicSections: [ + ...sections, + { + id: `${item.id}-topic-${Date.now()}`, + title: `专题模块 ${sections.length + 1}`, + imageUrl: item.imageUrls[0] ?? "", + specLeftLabel: "长", + specRightLabel: "宽", + }, + ], + }) + } + + const removeTopicSection = (item: MiniAppContent, sectionId: string) => { + const sections = item.topicSections ?? [] + if (sections.length <= 1) return + updateContent(item.id, { + topicSections: sections.filter((section) => section.id !== sectionId), + }) + } + const renderActions = (item: MiniAppContent) => { const actions: React.ReactNode[] = [] @@ -513,6 +607,10 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, if (viewMode === "editor" && selected) { const isNewContent = !selected.sourceCarId const canResetFromSource = Boolean(selected.sourceCarId && SOURCE_SNAPSHOTS[selected.sourceCarId]) + const isTopicPage = selected.pageType === "专题页" + const topicSections = (selected.topicSections && selected.topicSections.length > 0) + ? selected.topicSections + : createTopicSectionsFromImages(selected.imageUrls) const previewHeroImage = selected.imageUrls[0] const highlights = selected.highlights .split("\n") @@ -543,6 +641,35 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, 基于官网源车型生成的内容实体(MiniAppContent)。 +
+ + {isNewContent && canEdit ? ( + + ) : ( + + )} +
+
{isNewContent && canEdit ? ( @@ -553,15 +680,17 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, const nextId = e.target.value const option = SOURCE_CAR_OPTIONS.find((item) => item.id === nextId) const snapshot = SOURCE_SNAPSHOTS[nextId] + const sourceName = option?.name ?? "" updateContent(selected.id, { sourceCarId: nextId, - sourceCarName: option?.name ?? "", + sourceCarName: sourceName, title: snapshot?.title ?? selected.title, subtitle: snapshot?.subtitle ?? selected.subtitle, highlights: snapshot?.highlights ?? selected.highlights, description: snapshot?.description ?? selected.description, - ctaText: snapshot?.ctaText ?? selected.ctaText, - imageUrls: snapshot?.imageUrls ?? selected.imageUrls, + ctaText: selected.pageType === "专题页" ? "预约体验" : (snapshot?.ctaText ?? selected.ctaText), + imageUrls: selected.pageType === "专题页" ? [] : (snapshot?.imageUrls ?? selected.imageUrls), + ...buildTopicPatch(sourceName, snapshot), }) if (snapshot) { onAddAuditLog(`内容运营专员选择来源车型 ${option?.name ?? nextId} 并载入官网基线内容`) @@ -578,59 +707,104 @@ export function MiniAppContentLibrary({ roleView, workflowConfig, onAddAuditLog, )}
-
- - {isNewContent && canEdit ? ( - - ) : ( - - )} -
+ {isTopicPage ? ( + <> +
+ + updateContent(selected.id, { topicNavTitle: e.target.value })} + /> +
-
- - updateContent(selected.id, { title: e.target.value })} /> -
+
+ + updateContent(selected.id, { topicHeroTitle: e.target.value })} + /> +
-
- - updateContent(selected.id, { subtitle: e.target.value })} /> -
+
+ + updateContent(selected.id, { ctaText: e.target.value })} /> +
-
- -