update:1.更新导入导出功能,支持大纲细化结构

This commit is contained in:
xiamuceer
2025-11-19 14:50:28 +08:00
parent fb4ccad402
commit 8b66945823
2 changed files with 69 additions and 24 deletions
+5
View File
@@ -20,6 +20,11 @@ class ChapterExportData(BaseModel):
status: str = "draft" status: str = "draft"
created_at: Optional[str] = None created_at: Optional[str] = None
# 大纲细化功能新增字段
outline_title: Optional[str] = None # 关联的大纲标题(用于导入时重建关联)
sub_index: Optional[int] = None # 大纲下的子章节序号
expansion_plan: Optional[Dict[str, Any]] = None # 展开规划详情(JSON对象)
class CharacterExportData(BaseModel): class CharacterExportData(BaseModel):
"""角色导出数据""" """角色导出数据"""
+64 -24
View File
@@ -144,18 +144,41 @@ class ImportExportService:
) )
chapters = result.scalars().all() chapters = result.scalars().all()
return [ # 构建大纲ID到标题的映射
ChapterExportData( outline_mapping = {}
if chapters:
outline_ids = [ch.outline_id for ch in chapters if ch.outline_id]
if outline_ids:
outline_result = await db.execute(
select(Outline).where(Outline.id.in_(outline_ids))
)
outlines = outline_result.scalars().all()
outline_mapping = {ol.id: ol.title for ol in outlines}
exported_chapters = []
for ch in chapters:
# 解析expansion_plan JSON
expansion_plan = None
if ch.expansion_plan:
try:
expansion_plan = json.loads(ch.expansion_plan) if isinstance(ch.expansion_plan, str) else ch.expansion_plan
except:
expansion_plan = None
exported_chapters.append(ChapterExportData(
title=ch.title, title=ch.title,
content=ch.content, content=ch.content,
summary=ch.summary, summary=ch.summary,
chapter_number=ch.chapter_number, chapter_number=ch.chapter_number,
word_count=ch.word_count or 0, word_count=ch.word_count or 0,
status=ch.status, status=ch.status,
created_at=ch.created_at.isoformat() if ch.created_at else None created_at=ch.created_at.isoformat() if ch.created_at else None,
) outline_title=outline_mapping.get(ch.outline_id) if ch.outline_id else None,
for ch in chapters sub_index=ch.sub_index,
] expansion_plan=expansion_plan
))
return exported_chapters
@staticmethod @staticmethod
async def _export_characters(project_id: str, db: AsyncSession) -> List[CharacterExportData]: async def _export_characters(project_id: str, db: AsyncSession) -> List[CharacterExportData]:
@@ -482,26 +505,26 @@ class ImportExportService:
logger.info(f"创建项目成功: {new_project.id}") logger.info(f"创建项目成功: {new_project.id}")
# 导入章节 # 导入角色(包括组织)- 需要先导入角色,因为大纲可能需要角色信息
chapters_count = await ImportExportService._import_chapters(
new_project.id, data.get("chapters", []), db
)
statistics["chapters"] = chapters_count
logger.info(f"导入章节数: {chapters_count}")
# 导入角色(包括组织)
char_mapping = await ImportExportService._import_characters( char_mapping = await ImportExportService._import_characters(
new_project.id, data.get("characters", []), db new_project.id, data.get("characters", []), db
) )
statistics["characters"] = len(char_mapping) statistics["characters"] = len(char_mapping)
logger.info(f"导入角色数: {len(char_mapping)}") logger.info(f"导入角色数: {len(char_mapping)}")
# 导入大纲 # 导入大纲 - 需要在章节之前导入,以便建立关联
outlines_count = await ImportExportService._import_outlines( outline_mapping = await ImportExportService._import_outlines(
new_project.id, data.get("outlines", []), db new_project.id, data.get("outlines", []), db
) )
statistics["outlines"] = outlines_count statistics["outlines"] = len(outline_mapping)
logger.info(f"导入大纲数: {outlines_count}") logger.info(f"导入大纲数: {len(outline_mapping)}")
# 导入章节 - 使用大纲映射重建关联关系
chapters_count = await ImportExportService._import_chapters(
new_project.id, data.get("chapters", []), outline_mapping, db
)
statistics["chapters"] = chapters_count
logger.info(f"导入章节数: {chapters_count}")
# 导入关系 # 导入关系
relationships_count = await ImportExportService._import_relationships( relationships_count = await ImportExportService._import_relationships(
@@ -558,11 +581,23 @@ class ImportExportService:
async def _import_chapters( async def _import_chapters(
project_id: str, project_id: str,
chapters_data: List[Dict], chapters_data: List[Dict],
outline_mapping: Dict[str, str],
db: AsyncSession db: AsyncSession
) -> int: ) -> int:
"""导入章节""" """导入章节"""
count = 0 count = 0
for ch_data in chapters_data: for ch_data in chapters_data:
# 根据大纲标题查找对应的新大纲ID
outline_id = None
outline_title = ch_data.get("outline_title")
if outline_title and outline_title in outline_mapping:
outline_id = outline_mapping[outline_title]
# 处理expansion_plan
expansion_plan = ch_data.get("expansion_plan")
if expansion_plan and isinstance(expansion_plan, dict):
expansion_plan = json.dumps(expansion_plan, ensure_ascii=False)
chapter = Chapter( chapter = Chapter(
project_id=project_id, project_id=project_id,
title=ch_data.get("title"), title=ch_data.get("title"),
@@ -570,7 +605,10 @@ class ImportExportService:
summary=ch_data.get("summary"), summary=ch_data.get("summary"),
chapter_number=ch_data.get("chapter_number"), chapter_number=ch_data.get("chapter_number"),
word_count=ch_data.get("word_count", 0), word_count=ch_data.get("word_count", 0),
status=ch_data.get("status", "draft") status=ch_data.get("status", "draft"),
outline_id=outline_id,
sub_index=ch_data.get("sub_index"),
expansion_plan=expansion_plan
) )
db.add(chapter) db.add(chapter)
count += 1 count += 1
@@ -617,9 +655,10 @@ class ImportExportService:
project_id: str, project_id: str,
outlines_data: List[Dict], outlines_data: List[Dict],
db: AsyncSession db: AsyncSession
) -> int: ) -> Dict[str, str]:
"""导入大纲""" """导入大纲,返回标题到ID的映射"""
count = 0 outline_mapping = {}
for ol_data in outlines_data: for ol_data in outlines_data:
outline = Outline( outline = Outline(
project_id=project_id, project_id=project_id,
@@ -629,9 +668,10 @@ class ImportExportService:
order_index=ol_data.get("order_index") order_index=ol_data.get("order_index")
) )
db.add(outline) db.add(outline)
count += 1 await db.flush() # 获取ID
outline_mapping[ol_data.get("title")] = outline.id
return count return outline_mapping
@staticmethod @staticmethod
async def _import_relationships( async def _import_relationships(