Files
ai-doc-template-system/docs/architecture.md
T
2026-07-01 19:50:29 +08:00

139 lines
4.5 KiB
Markdown

# 系统架构设计
> AI 文档模板生成系统 — 架构决策与模块设计
---
## 整体架构
```
┌─────────────────────────────────────────────────────┐
│ 前端 (Vue3) │
│ TemplateEdit.vue │
│ ├─ LeftMenu.vue 左侧菜单 │
│ ├─ TopToolbar.vue 顶部工具栏 │
│ ├─ WordPreview.vue 中间文档预览 │
│ ├─ ConfigPanel.vue 左侧配置面板 │
│ └─ StructureTree.vue 右侧结构树 │
├────────────────── HTTP/REST ────────────────────────┤
│ 后端 (FastAPI) │
│ ├─ api/ RESTful 接口 │
│ ├─ services/ 业务逻辑层 │
│ │ ├─ doc_parser.py Word 解析引擎 │
│ │ ├─ html_generator.py HTML 预览生成 │
│ │ ├─ template_service.py 模板业务 │
│ │ └─ storage.py 文件存储 │
│ └─ models/ SQLAlchemy 数据模型 │
├─────────────────── 数据层 ───────────────────────────┤
│ MySQL 8.0 (结构化) MinIO (文件) │
└─────────────────────────────────────────────────────┘
```
---
## 核心流程 数据流
### 上传模板
```
用户 → 上传 .docx
→ POST /api/templates/upload
→ validate_file() 校验格式和大小
→ save_file() 保存到 MinIO/本地
→ create_template_record() 写入 template 表
→ parse_document() 解析标题/段落
→ parse_tables() 解析表格
→ generate_block_id() 生成唯一 ID
→ save_blocks() 写入 template_block 表
← 返回 template_id
```
### 进入编辑页
```
GET /api/templates/{id}
→ 查询 template 表 → 基本信息
→ 查询 template_block 表 → blocks + tree
→ 调用 html_generator → preview_html
→ 查询 block_config 表 → 已有配置 keyed by block_id
← 返回完整数据
前端渲染四栏布局
```
### 保存配置
```
用户配置区域 → 点击保存
→ POST /api/templates/{id}/blocks/{blockId}/config
→ upsert block_config 表
→ 更新 configs 缓存
← 返回成功
前端更新保存状态 + 树节点颜色
```
---
## 关键设计
### block_id 是统一索引
```
Word 解析 → block_id → 数据库存储
点击交互 → block_id → 定位 + 高亮
配置保存 → block_id → 存储提示词
AI 生成 → block_id → 绑定数据来源
Word 回填 → block_id → 定位原始位置
```
所有模块通过 block_id 串联,不依赖 Word 内 XML 路径。
### HTML 预览 vs Word 回填
| 维度 | HTML 预览 | Word 回填 |
|------|----------|----------|
| 用途 | 前端展示+交互 | 最终导出 |
| 数据来源 | 解析结果 | 原始 docx |
| 样式要求 | 接近即可 | 尽量保留 |
| 操作 | 点击选中+配置 | 替换内容 |
| 技术 | python-docx → HTML | python-docx 直接操作 |
### 分阶段策略
第一阶段只做预览+标注+配置。
HTML 预览只需"看到内容+点击",不需要"和 Word 一模一样"。
Word 回填保留给第三阶段,那时再精细化处理样式映射。
---
## 数据流时序
### 点击区域 → 配置联动
```
用户点击预览区段落
→ WordPreview 捕获 click 事件
→ event.target.closest('[data-block-id]')
→ selectionStore.selectBlock(blockId)
→ watch 触发:
├─ ConfigPanel: 加载该 block 的 config (已有/默认)
├─ StructureTree: 高亮对应节点
└─ WordPreview: 添加高亮样式
```
### 保存配置
```
ConfigPanel 点击保存
→ saving=true
→ POST /api/templates/{id}/blocks/{blockId}/config
→ 成功:
├─ saving=false
├─ uiStore.saveStatus = 'saved'
├─ templateStore.updateConfig(blockId, config)
├─ WordPreview 更新区域颜色
└─ StructureTree 更新状态圆点
→ 失败:
├─ saving=false
└─ ElMessage.error('保存失败')
```