Add Comments
This commit is contained in:
@@ -29,6 +29,7 @@ class ChapterRecord:
|
||||
updated_at: str = field(default_factory=lambda: datetime.utcnow().isoformat() + "Z")
|
||||
|
||||
def to_dict(self) -> Dict[str, object]:
|
||||
"""将记录转换为便于写入manifest.json的序列化字典"""
|
||||
return {
|
||||
"chapterId": self.chapter_id,
|
||||
"slug": self.slug,
|
||||
@@ -54,6 +55,12 @@ class ChapterStorage:
|
||||
"""
|
||||
|
||||
def __init__(self, base_dir: str):
|
||||
"""
|
||||
创建章节存储器。
|
||||
|
||||
Args:
|
||||
base_dir: 所有输出run目录的根路径
|
||||
"""
|
||||
self.base_dir = Path(base_dir)
|
||||
self.base_dir.mkdir(parents=True, exist_ok=True)
|
||||
self._manifests: Dict[str, Dict[str, object]] = {}
|
||||
@@ -133,6 +140,7 @@ class ChapterStorage:
|
||||
return final_path
|
||||
|
||||
def load_chapters(self, run_dir: Path) -> List[Dict[str, object]]:
|
||||
"""从指定run目录读取全部chapter.json并按order排序返回"""
|
||||
payloads: List[Dict[str, object]] = []
|
||||
for child in sorted(run_dir.iterdir()):
|
||||
if not child.is_dir():
|
||||
@@ -161,6 +169,7 @@ class ChapterStorage:
|
||||
# ======== 内部工具 ========
|
||||
|
||||
def _chapter_dir(self, run_dir: Path, slug: str, order: int) -> Path:
|
||||
"""根据slug/order生成稳定的章节目录,确保各章分隔存盘"""
|
||||
safe_slug = self._safe_slug(slug)
|
||||
folder = f"{order:03d}-{safe_slug}"
|
||||
path = run_dir / folder
|
||||
@@ -168,25 +177,31 @@ class ChapterStorage:
|
||||
return path
|
||||
|
||||
def _safe_slug(self, slug: str) -> str:
|
||||
"""移除危险字符,避免生成非法文件夹名"""
|
||||
slug = slug.replace(" ", "-").replace("/", "-")
|
||||
return slug or "section"
|
||||
|
||||
def _raw_stream_path(self, chapter_dir: Path) -> Path:
|
||||
"""返回某章节流式输出对应的raw文件路径"""
|
||||
return chapter_dir / "stream.raw"
|
||||
|
||||
def _key(self, run_dir: Path) -> str:
|
||||
"""将run目录解析为字典缓存的键,避免重复读取磁盘"""
|
||||
return str(run_dir.resolve())
|
||||
|
||||
def _manifest_path(self, run_dir: Path) -> Path:
|
||||
"""获取manifest.json的实际文件路径"""
|
||||
return run_dir / "manifest.json"
|
||||
|
||||
def _write_manifest(self, run_dir: Path, manifest: Dict[str, object]):
|
||||
"""将内存中的manifest快照全量写回磁盘"""
|
||||
self._manifest_path(run_dir).write_text(
|
||||
json.dumps(manifest, ensure_ascii=False, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def _read_manifest(self, run_dir: Path) -> Dict[str, object]:
|
||||
"""从磁盘读取已有manifest,用于进程重启或多实例协作"""
|
||||
manifest_path = self._manifest_path(run_dir)
|
||||
if manifest_path.exists():
|
||||
return json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
|
||||
@@ -16,6 +16,7 @@ class DocumentComposer:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化装订器并记录已使用的锚点,避免重复"""
|
||||
self._seen_anchors: Set[str] = set()
|
||||
|
||||
def build_document(
|
||||
|
||||
@@ -30,6 +30,7 @@ class TemplateSection:
|
||||
outline: List[str] = field(default_factory=list)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""将章节实体序列化为字典,方便传给LLM或落盘"""
|
||||
return {
|
||||
"title": self.title,
|
||||
"slug": self.slug,
|
||||
@@ -185,6 +186,7 @@ def _build_slug(number: str, title: str) -> str:
|
||||
|
||||
|
||||
def _slugify_text(text: str) -> str:
|
||||
"""对任意文本做降噪与转写,得到URL友好的slug片段"""
|
||||
text = unicodedata.normalize("NFKD", text)
|
||||
text = text.replace("·", "-").replace(" ", "-")
|
||||
text = re.sub(r"[^0-9a-zA-Z\u4e00-\u9fff-]+", "-", text)
|
||||
@@ -193,6 +195,7 @@ def _slugify_text(text: str) -> str:
|
||||
|
||||
|
||||
def _ensure_unique_slug(slug: str, used: set) -> str:
|
||||
"""若slug重复则自动追加序号,直到在used集合中唯一"""
|
||||
if slug not in used:
|
||||
used.add(slug)
|
||||
return slug
|
||||
|
||||
Reference in New Issue
Block a user