# AI 文档模板生成系统 · 需求规格说明书 ## 一、功能需求 ### 1.1 模板管理 | 功能 | 描述 | 优先级 | |------|------|--------| | 模板列表 | 卡片式展示所有模板,含名称、段落数、状态、最后编辑时间 | P0 | | 新建模板 | 上传 .docx 文件,自动解析段落结构 | P0 | | 模板编辑器(三栏) | 左栏段落列表、中栏文档预览、右栏段落配置 | P0 | | 段落标注 | 配置每个段落的编辑方式、模型、提示词、参考文件 | P0 | | 保存模板 | 将段落配置持久化到数据库 | P0 | ### 1.2 模型管理 | 功能 | 描述 | 优先级 | |------|------|--------| | 模型列表 | 卡片式展示所有 AI 模型,含启用/禁用开关 | P0 | | 添加/编辑模型 | 弹窗表单:名称、厂商、API 格式、地址、Key(加密存储) | P0 | | 默认模型分配 | 设置文本/表格/图表各自的默认生成模型 | P0 | ### 1.3 执行生成 | 功能 | 描述 | 优先级 | |------|------|--------| | 选择模板 | 下拉选择已保存的模板 | P0 | | 上传参考文件 | 按段落需上传的文件类型提示并上传 | P0 | | 开始生成 | 启动多段落并行 AI 生成 | P0 | | 实时进度 | SSE 推送每个段落的生成状态 | P0 | | 取消生成 | 中断正在进行的生成任务 | P1 | ### 1.4 生成记录 | 功能 | 描述 | 优先级 | |------|------|--------| | 统计卡片 | 总次数、成功、失败、中断 | P0 | | 历史列表 | 卡片式展示已生成文档 | P0 | | 筛选 | 按模板、按状态筛选 | P1 | | 预览 | 跳转到预览编辑页 | P0 | | 下载 | 下载已生成的 Word 文档 | P0 | ### 1.5 预览编辑 | 功能 | 描述 | 优先级 | |------|------|--------| | 富文本编辑 | 在线编辑文档内容 | P0 | | AI 内容标注 | AI 生成的段落标紫色边框+模型来源 | P0 | | 重新生成单段落 | 对某一段落单独重新请求 AI | P0 | | 导出 Word | 保留原始模板样式 | P0 | | 导出 PDF | 通过 LibreOffice 转换 | P1 | ## 二、段落解析规则 ### 2.1 段落边界定义 段落以 Word 内置标题样式为边界: ``` Heading 1 → 一级段落(如 "一、经营指标") Heading 2 → 二级段落(如 "1.1 营收分析") Heading 3 → 三级段落 无标题样式 → 合并到上一个标题下的正文内容 表格 → 独立段落,归属于前一个标题 ``` ### 2.2 标题下的正文内容 标题与下一个标题之间的所有正文、表格、图片: - 作为该段落的 `content` 字段 - 供 AI 生成时作为上下文参考 - 导出时保留原样式 ### 2.3 AI 返回格式约定 AI 输出必须是结构化 JSON: ```json { "content": [ {"type": "text", "text": "正文内容..."}, {"type": "table", "headers": ["列1","列2"], "rows": [["a","b"],["c","d"]]}, {"type": "text", "text": "更多正文..."} ] } ``` 后端解析逻辑: - type=text → 替换文档中对应段落的文本 - type=table → 在对应位置插入 Word 表格,表格样式参照该段落附近已有表格 ### 2.4 正文内编号处理 AI 生成的 1、2、3 编号属于该段落的内部子结构,不拆分为新段落。导出时作为该段落的正文内容,应用该段落的样式。 ## 三、导出策略 采用 **基于原模板替换内容** 策略: 1. 解析时记录每个段落在原始 docx 中的段落索引 + xpath 2. 导出时复制原始模板文件 3. 遍历每个段落,找到对应位置替换内容: - 纯文本:替换 `` 节点文本 - 表格:删除原有表格占位,插入新表格的 XML 节点 4. 样式完全不修改(字体、字号、颜色、行距、段间距、页边距、页眉页脚、页码全部保留) ## 四、AI 并行生成设计 ``` 用户点击"开始生成" │ ▼ 解析模板段落依赖关系(当前无依赖,全部并行) │ ▼ 创建 asyncio.Task 池,Semaphore 控制并发数(默认 5) │ ├── 段落1 → AI 请求 → SSE 推送完成 ├── 段落2 → AI 请求 → SSE 推送完成 ├── 段落3 → AI 请求 → SSE 推送完成 ├── 段落4 → AI 请求 → SSE 推送完成 └── 段落5 → AI 请求 → SSE 推送完成 │ ▼ 所有 Task 完成后,统一更新文档状态为 completed │ ▼ SSE 推送 "全部完成",前端跳转到预览编辑 ``` ## 五、数据结构 ### 5.1 模板 (template) ``` id: int (PK) name: str description: str file_path: str # 原始模板文件路径 paragraph_count: int status: str # draft / ready created_at: datetime updated_at: datetime ``` ### 5.2 段落 (paragraph) ``` id: int (PK) template_id: int (FK) sort_index: int title: str # 段落标题 content: str # 正文内容(供 AI 参考) style_json: json # 完整样式定义 is_table: bool table_json: json # 表格结构 edit_mode: str # manual / ai model_id: int (FK, nullable) need_prompt: bool prompt_text: str need_file: bool file_note: str output_format: str # text / table / mixed / chart created_at: datetime updated_at: datetime ``` ### 5.3 AI 模型 (ai_model) ``` id: int (PK) name: str provider: str api_format: str # anthropic / openai api_endpoint: str api_key_encrypted: str status: str # enabled / disabled created_at: datetime updated_at: datetime ``` ### 5.4 生成文档 (document) ``` id: int (PK) template_id: int (FK) name: str para_count_done: int para_count_total: int status: str # pending / generating / completed / failed / cancelled file_path: str # 生成的文档路径 error: str created_at: datetime updated_at: datetime ```