Fix-Multiple Directories

This commit is contained in:
马一丁
2025-11-15 02:08:24 +08:00
parent 62b8276aa8
commit 8aa114df4a
+50
View File
@@ -59,6 +59,8 @@ class HTMLRenderer:
self.heading_label_map: Dict[str, Dict[str, Any]] = {} self.heading_label_map: Dict[str, Dict[str, Any]] = {}
self.primary_heading_index = 0 self.primary_heading_index = 0
self.secondary_heading_index = 0 self.secondary_heading_index = 0
self.toc_rendered = False
self.hero_kpi_signature: tuple | None = None
# ====== 公共入口 ====== # ====== 公共入口 ======
@@ -78,6 +80,7 @@ class HTMLRenderer:
self.heading_counter = 0 self.heading_counter = 0
self.metadata = self.document.get("metadata", {}) or {} self.metadata = self.document.get("metadata", {}) or {}
raw_chapters = self.document.get("chapters", []) or [] raw_chapters = self.document.get("chapters", []) or []
self.toc_rendered = False
self.chapters = self._prepare_chapters(raw_chapters) self.chapters = self._prepare_chapters(raw_chapters)
self.chapter_anchor_map = { self.chapter_anchor_map = {
chapter.get("chapterId"): chapter.get("anchor") chapter.get("chapterId"): chapter.get("anchor")
@@ -90,6 +93,8 @@ class HTMLRenderer:
metadata = self.metadata metadata = self.metadata
theme_tokens = metadata.get("themeTokens") or self.document.get("themeTokens", {}) theme_tokens = metadata.get("themeTokens") or self.document.get("themeTokens", {})
title = metadata.get("title") or metadata.get("query") or "智能舆情报告" title = metadata.get("title") or metadata.get("query") or "智能舆情报告"
hero_kpis = (metadata.get("hero") or {}).get("kpis")
self.hero_kpi_signature = self._kpi_signature_from_items(hero_kpis)
head = self._render_head(title, theme_tokens) head = self._render_head(title, theme_tokens)
body = self._render_body() body = self._render_body()
@@ -320,12 +325,15 @@ class HTMLRenderer:
""" """
if not self.toc_entries: if not self.toc_entries:
return "" return ""
if self.toc_rendered:
return ""
toc_config = self.metadata.get("toc") or {} toc_config = self.metadata.get("toc") or {}
toc_title = toc_config.get("title") or "📚 目录" toc_title = toc_config.get("title") or "📚 目录"
toc_items = "".join( toc_items = "".join(
self._format_toc_entry(entry) self._format_toc_entry(entry)
for entry in self.toc_entries for entry in self.toc_entries
) )
self.toc_rendered = True
return f""" return f"""
<nav class="toc"> <nav class="toc">
<div class="toc-title">{self._escape_html(toc_title)}</div> <div class="toc-title">{self._escape_html(toc_title)}</div>
@@ -965,6 +973,8 @@ class HTMLRenderer:
def _render_kpi_grid(self, block: Dict[str, Any]) -> str: def _render_kpi_grid(self, block: Dict[str, Any]) -> str:
"""渲染KPI卡片栅格,包含指标值与涨跌幅""" """渲染KPI卡片栅格,包含指标值与涨跌幅"""
if self._should_skip_overview_kpi(block):
return ""
cards = "" cards = ""
for item in block.get("items", []): for item in block.get("items", []):
delta = item.get("delta") delta = item.get("delta")
@@ -1051,6 +1061,46 @@ class HTMLRenderer:
""" """
return table_html return table_html
# ====== Front-matter guards ======
def _kpi_signature_from_items(self, items: Any) -> tuple | None:
"""将KPI数组转换为可比较的签名"""
if not isinstance(items, list):
return None
normalized = []
for raw in items:
normalized_item = self._normalize_kpi_item(raw)
if normalized_item:
normalized.append(normalized_item)
return tuple(normalized) if normalized else None
def _normalize_kpi_item(self, item: Any) -> tuple[str, str, str, str, str] | None:
if not isinstance(item, dict):
return None
def normalize(value: Any) -> str:
if value is None:
return ""
if isinstance(value, (int, float)):
return str(value)
return str(value).strip()
label = normalize(item.get("label"))
value = normalize(item.get("value"))
unit = normalize(item.get("unit"))
delta = normalize(item.get("delta"))
tone = normalize(item.get("deltaTone") or item.get("tone"))
return label, value, unit, delta, tone
def _should_skip_overview_kpi(self, block: Dict[str, Any]) -> bool:
"""若KPI内容与封面一致,则判定为重复总览"""
if not self.hero_kpi_signature:
return False
block_signature = self._kpi_signature_from_items(block.get("items"))
if not block_signature:
return False
return block_signature == self.hero_kpi_signature
# ====== Inline 渲染 ====== # ====== Inline 渲染 ======
def _normalize_inline_payload(self, run: Dict[str, Any]) -> tuple[str, List[Dict[str, Any]]]: def _normalize_inline_payload(self, run: Dict[str, Any]) -> tuple[str, List[Dict[str, Any]]]: