提交 aef3ad69 authored 作者: 张伊明's avatar 张伊明

feat 重构方案

上级 208093f8
流水线 #585 已通过 于阶段
in 1 分 48 秒
# 智能翻译文档对比页前端重构实施方案
## 方案进度概述
- 当前阶段:重构方案定稿
- 目标:将现有全量渲染的文档对比页重构为页级懒加载架构
- 面向对象:大模型执行与前端开发协作
- 约束:原有接口不能改,只能基于新增接口重构
## 1. 需求理解
当前页面的核心问题不是单纯“慢”,而是:
1. 整包数据过大
2. 页和块一次性全量挂载
3. 富文本、图片、表格混合渲染
4. 目录与滚动状态依赖大量 DOM
因此前端重构的目标不是“微调样式”,而是从渲染架构上切换到更适合大文档的方式。
## 2. 最终结论
> 以“页”为最小渲染单位,采用“页级懒加载 + 视口内挂载 + 页外轻量壳 + 页内二级懒加载”的混合方案。
这是当前场景下最稳、最容易落地、也最符合文档阅读习惯的方案。
## 3. 重构目标
### 3.1 功能目标
- 支持超长文档平稳展示
- 支持目录跳转
- 支持页码同步
- 支持图片、表格、标题、正文正常展示
- 支持当前页高亮与章节高亮
### 3.2 性能目标
- 首屏加载更快
- 滚动更稳定
- 大文档不掉帧
- 降低一次性 DOM 规模
### 3.3 可维护性目标
- 页、块、节点职责分离
- 渲染逻辑可分层扩展
- 后续方便接搜索、高亮、差异对比
## 4. 重构原则
1. 页是最小渲染单位
2. 目录只负责导航,不参与重渲染
3. 可见页才挂载真实内容
4. 页外只保留占位壳
5. 图片、表格、富文本做二级懒加载
6. 原始完整结果保留,但不直接驱动 UI 全量渲染
## 5. 页面结构设计
### 5.1 页面容器
文件建议:`src/views/intelligentTranslation/documentCompare.vue`
职责:
- 请求文档摘要、目录、页索引、页内容
- 管理当前页、当前章节、加载状态
- 维护滚动容器
- 协调页面跳转和状态同步
### 5.2 页列表组件
文件建议:`PageList.vue`
职责:
- 遍历页元信息
- 判断页是否进入视口附近
- 决定挂载真实内容还是仅显示页壳
- 控制页缓存策略
### 5.3 页内容组件
文件建议:`PageBlock.vue`
职责:
- 渲染单页内部节点
-`semantic_type` 分发渲染子组件
- 处理 absolute 与 flow 两种布局模式
### 5.4 节点子组件
建议拆分:
- `HeadingNode.vue`
- `TextNode.vue`
- `ImageNode.vue`
- `TableNode.vue`
- `RichHtmlNode.vue`
职责:
- 各类节点独立渲染
- 减少单组件复杂度
- 控制 `v-html` 使用范围
### 5.5 目录树组件
文件建议:`ArticleNavTree.vue`
职责:
- 渲染标题目录
- 点击跳页
- 当前章节高亮
## 6. 状态设计
建议状态如下:
```js
const rawResult = ref(null)
const summary = ref(null)
const pageIndexList = ref([])
const outlineTree = ref([])
const pageBlockMap = ref(new Map())
const visiblePageSet = ref(new Set())
const mountedPageCache = ref(new Map())
const currentPageId = ref('')
const currentNodeKey = ref('')
const compareScrollRef = ref(null)
```
### 状态含义
- `rawResult`:原始完整结果,兼容旧逻辑
- `summary`:文档摘要数据
- `pageIndexList`:页级索引列表
- `outlineTree`:目录树
- `pageBlockMap`:页到节点的映射
- `visiblePageSet`:当前需要挂载的页集合
- `mountedPageCache`:已挂载页缓存
- `currentPageId`:当前激活页
- `currentNodeKey`:当前目录高亮节点
- `compareScrollRef`:滚动容器引用
## 7. 数据获取顺序
### 7.1 初始化顺序
1. 请求 `document-meta`
2. 解析出摘要、页索引、目录树
3. 请求首屏页内容 `document-page`
4. 根据滚动位置继续按需请求其他页
### 7.2 页内按需顺序
当某页进入视口附近:
1. 请求该页完整内容
2. 挂载页真实 DOM
### 7.3 目录跳转顺序
点击目录节点时:
1. 根据 `page_idx` 找目标页
2. 若该页未挂载,先请求页内容
3. 滚动到目标页
4. 更新当前页和章节高亮
## 8. 渲染策略
### 8.1 首屏策略
首屏只挂载:
- 当前页
- 当前页前 1 页
- 当前页后 2 页
其他页只渲染页壳,不渲染真实内容。
### 8.2 视口内挂载策略
使用 `IntersectionObserver` 或滚动监听判断页面是否进入视口附近:
- 进入可视区:挂载真实内容
- 离开较远:保留占位或卸载
### 8.3 页内二级懒加载策略
页内对重资源进一步控制:
- 图片 `loading="lazy"`
- 表格默认只渲染摘要或首屏片段
- 富文本仅对必要节点使用 `v-html`
### 8.4 页外壳策略
未挂载页仍保留:
- 页码
- 页面尺寸占位
- 可选的轻量标题摘要
这样可以保证滚动长度和定位稳定。
## 9. 现有代码改造重点
### 9.1 不再全量 `v-for` 渲染所有页内容
当前逻辑需要从“所有页一次性渲染”改成“页壳 + 条件挂载”。
### 9.2 控制 `v-html` 范围
只在确实需要富文本还原的节点使用 `v-html`,且尽量局部化。
### 9.3 目录与页级状态绑定
当前页、章节高亮、跳转定位统一使用页级索引,不再依赖海量 block DOM 计算。
### 9.4 图片和表格独立组件化
图片和表格不要和普通文本混成一个大渲染函数,必须独立拆组件。
## 10. 推荐组件结构
```text
documentCompare.vue
├── ArticleNavTree.vue
├── PageList.vue
│ ├── PageShell.vue
│ └── PageBlock.vue
│ ├── HeadingNode.vue
│ ├── TextNode.vue
│ ├── ImageNode.vue
│ ├── TableNode.vue
│ └── RichHtmlNode.vue
└── ComparePanel.vue
```
## 11. 实施步骤
### 第 1 步:接入新接口,但不改 UI
目标:先把数据链路切到新接口,保留现有页面结构。
验收:
- 能拿到摘要、页索引、目录
- 能按页拿到内容
### 第 2 步:改成页壳 + 条件挂载
目标:只挂载视口附近页。
验收:
- 非可见页不再创建真实 DOM
- 首屏明显变快
### 第 3 步:拆分页内节点组件
目标:降低单文件复杂度。
验收:
- 标题、正文、图片、表格分组件渲染
### 第 4 步:改造目录跳转和滚动同步
目标:按页同步当前章节。
验收:
- 点击目录可准确跳转
- 滚动时高亮正确
### 第 5 步:增加页内二级懒加载
目标:处理大图、大表和富文本。
验收:
- 长文档滚动更流畅
- 图片/表格不会拖慢主线程
## 12. 风险与注意事项
- 不能直接把整包 JSON 当唯一 UI 数据源长期使用
- 需要保证 `page_idx``node_id` 稳定唯一
- `bbox_norm` 优先使用,缺失时再由 `bbox` 换算
- `reading_order` 必须稳定,否则页内顺序会错乱
- `style_spans` 的字符区间必须与文本严格对齐
## 13. 验收标准
### 功能验收
- 文档正常渲染
- 目录可跳转
- 当前页可同步
- 图片、表格、标题、正文正常展示
### 性能验收
- 首屏快于原方案
- 长文档滚动不卡顿
- 不再出现明显“截断感”
### 结构验收
- 组件职责清晰
- 渲染链路分层明确
- 后续可继续拓展搜索和对比能力
## 14. 结论
前端最终采用:
> 页级懒加载渲染架构。
即:
- 页作为最小渲染单位
- 可见页才挂载真实内容
- 页外只保留轻量壳
- 目录和滚动按页同步
- 图片、表格、富文本做二级懒加载
这是当前场景下最稳妥、最可落地、最利于后续扩展的方案。
# 智能翻译文档对比页后端接口说明书
## 方案进度概述
- 当前阶段:正式接口说明书整理
- 目标:在不修改原有接口的前提下,新增少量、低冗余、可直接落地的后端接口,支撑前端页级懒加载渲染
- 原则:只保留渲染必须数据,合并可合并接口,去除重复字段和中间态字段
- 适用对象:后端开发、联调开发、接口测试
## 1. 需求背景
当前 `src/views/intelligentTranslation/merged_ans.json` 是完整合并结果,内部同时包含文档摘要、页信息、节点信息、布局信息、样式信息与富文本内容。若前端一次性加载整包数据,会造成:
- 首屏加载慢
- 响应体积大
- 页内 DOM 节点过多
- 富文本、图片、表格渲染成本高
- 用户感知“内容像被截断”
因此需要在**不改原有接口**的前提下,新增更适合页面渲染的接口。
## 2. 设计原则
1. 原有接口保持不变,继续兼容旧逻辑
2. 新接口尽量少,优先合并相近能力
3. 返回结果只保留前端渲染必须字段
4. 大字段、重复字段、可计算字段尽量不返回
5. 支持页级加载
## 3. 数据来源与拆分范围
### 3.1 主要数据来源
新接口的数据来源为 `merged_ans.json` 中的三类信息:
- `document_meta`:文档级信息
- `pages`:页级索引信息
- `merged_nodes`:页内节点信息
### 3.2 拆分目标
后端只需要输出前端实际渲染所需的数据:
- 文档摘要
- 页级索引
- 目录树
- 页内容
## 4. 字段说明
下面仅说明新增接口会使用到的关键字段。
### 4.1 文档级字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|
| `source_file_name` | 原始文件名 | 是 | 用于页面标题和调试 |
| `source_file_type` | 文件类型 | 是 | 如 pdf |
| `page_count` | 总页数 | 是 | 用于总览和分页 |
| `created_at` | 结果生成时间 | 否 | 用于记录与排查 |
### 4.2 页级字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|
| `page_idx` | 页码,从 0 开始 | 是 | 页唯一标识 |
| `width` | 页面宽度 | 是 | 用于坐标换算 |
| `height` | 页面高度 | 是 | 用于坐标换算 |
| `rotation` | 页面旋转角度 | 否 | 默认 0 |
| `node_ids` | 本页节点 id 列表 | 是 | 用于快速定位与页级懒加载 |
| `node_count` | 节点数量 | 否 | 统计信息 |
| `has_image` | 是否包含图片 | 否 | 用于渲染优化 |
| `has_table` | 是否包含表格 | 否 | 用于渲染优化 |
### 4.3 节点级字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|---|
| `node_id` | 节点唯一 id | 是 | 前端定位主键 |
| `page_idx` | 所属页码 | 是 | 用于归属与跳转 |
| `semantic_type` | 语义类型 | 是 | 决定节点渲染方式 |
| `reading_order` | 阅读顺序 | 是 | 页内排序依据 |
| `content_payload` | 内容载荷 | 是 | 仅保留必须字段 |
| `layout` | 布局信息 | 是 | 页内版式还原 |
| `style_spans` | 局部样式片段 | 否 | 富文本节点需要时再返回 |
### 4.4 `semantic_type` 建议枚举
| 值 | 含义 | 用途 |
|---|---|---|
| `heading` | 标题 | 目录生成、章节跳转 |
| `paragraph` | 正文段落 | 普通文本展示 |
| `list_item` | 列表项 | 列表渲染 |
| `table` | 表格 | 表格组件渲染 |
| `image` | 图片 | 图片组件渲染 |
| `caption` | 图注/表注 | 辅助说明 |
| `header` | 页眉 | 版式还原 |
| `footer` | 页脚 | 版式还原 |
| `unknown` | 未知 | 兜底 |
### 4.5 `content_payload` 建议字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|---|
| `type` | 内容类型 | 是 | text/html/table/image |
| `text` | 纯文本内容 | 是 | 标题、正文最常用 |
| `html` | 富文本 HTML | 否 | 仅必要节点返回 |
| `heading_level` | 标题级别 | 否 | 仅标题需要 |
| `table_body_html` | 表格 HTML | 否 | 仅表格需要 |
| `img_path` | 原图路径 | 否 | 仅图片需要 |
| `preview_img_path` | 预览图路径 | 否 | 图片懒加载使用 |
| `alt_text` | 图片替代文本 | 否 | 无障碍或兜底 |
| `caption` | 图注/表注 | 否 | 辅助说明 |
### 4.6 `layout` 建议字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|---|
| `bbox_norm` | 归一化坐标框 | 是 | 优先用于渲染 |
| `bbox` | 像素坐标框 | 否 | bbox_norm 缺失时兜底 |
| `angle` | 旋转角度 | 否 | 默认 0 |
| `reading_order` | 阅读顺序 | 是 | 页内排序 |
| `page_idx` | 页码 | 是 | 与节点归属一致 |
### 4.7 `style_spans` 建议字段
| 字段 | 含义 | 是否必需 | 说明 |
|---|---|---:|---|
| `start` | 起始字符下标 | 是 | 样式区间开始 |
| `end` | 结束字符下标 | 是 | 样式区间结束 |
| `style.bold` | 是否加粗 | 否 | 富文本样式 |
| `style.italic` | 是否斜体 | 否 | 富文本样式 |
| `style.underline` | 是否下划线 | 否 | 富文本样式 |
| `style.color_hex` | 字体颜色 | 否 | 富文本样式 |
## 5. 接口设计总览
> 说明:以下均为新增接口。旧接口保持不变。
考虑到“能合并尽量合并”的要求,后端最终只保留 **2 个新增接口**
1. 文档摘要接口:返回文档基本信息、统计信息、页索引和目录树
2. 页内容接口:返回某一页可渲染的完整节点数据
---
## 6. 接口 1:文档摘要接口
### 6.1 接口名称
`GET /intelligent-translation/document-meta`
### 6.2 用途
一次性返回文档基础信息、统计信息、页索引摘要和目录树。前端初始化时优先调用该接口。
### 6.3 请求参数
无需额外参数。
### 6.4 返回参数
| 字段 | 类型 | 含义 | 是否必需 |
|---|---|---|---:|
| `document_meta` | object | 文档基础信息 | 是 |
| `statistics` | object | 统计信息 | 是 |
| `pages` | array | 页索引列表 | 是 |
| `outline` | array | 目录树 | 是 |
### 6.5 返回示例
```json
{
"code": 0,
"message": "success",
"data": {
"document_meta": {
"source_file_name": "xxx.pdf",
"source_file_type": "pdf",
"page_count": 148,
"created_at": "2026-04-21T11:00:39.246595Z"
},
"statistics": {
"page_count": 148,
"node_count": 1320,
"heading_count": 86,
"image_count": 34,
"table_count": 12
},
"pages": [
{
"page_idx": 0,
"width": 612,
"height": 792,
"rotation": 0,
"node_ids": ["page0_node0", "page0_node1"],
"node_count": 11,
"has_image": true,
"has_table": false
}
],
"outline": [
{
"id": "page0_node0",
"title": "Office of Science ...",
"page_idx": 0,
"level": 1,
"children": []
}
]
}
}
```
### 6.6 返回字段说明
- `document_meta`:文档基本属性
- `statistics`:文档整体统计
- `pages`:页级轻量索引,用于页壳渲染和跳页
- `outline`:标题目录树,用于导航
---
## 7. 接口 2:页内容接口
### 7.1 接口名称
`GET /intelligent-translation/document-page?page_idx=12`
### 7.2 用途
返回指定页的完整可渲染内容。前端在视口内挂载该页时调用。
### 7.3 请求参数
| 参数 | 类型 | 是否必需 | 说明 |
|---|---|---:|---|
| `page_idx` | number | 是 | 目标页码,从 0 开始 |
### 7.4 返回参数
| 字段 | 类型 | 含义 | 是否必需 |
|---|---|---|---:|
| `page` | object | 页基本信息 | 是 |
| `nodes` | array | 该页节点列表 | 是 |
### 7.5 `page` 字段说明
| 字段 | 含义 | 是否必需 |
|---|---|---:|
| `page_idx` | 页码 | 是 |
| `width` | 页面宽度 | 是 |
| `height` | 页面高度 | 是 |
| `rotation` | 页面旋转角度 | 否 |
### 7.6 `nodes` 字段说明
| 字段 | 含义 | 是否必需 |
|---|---|---:|
| `node_id` | 节点唯一 id | 是 |
| `semantic_type` | 语义类型 | 是 |
| `page_idx` | 所属页码 | 是 |
| `content_payload` | 内容载荷 | 是 |
| `layout` | 布局信息 | 是 |
| `style_spans` | 样式片段 | 否 |
### 7.7 `content_payload` 允许返回的最小字段
| 字段 | 用途 |
|---|---|
| `type` | 内容类型分发 |
| `text` | 纯文本渲染 |
| `html` | 富文本渲染 |
| `heading_level` | 目录/标题层级 |
| `table_body_html` | 表格渲染 |
| `img_path` | 图片渲染 |
| `preview_img_path` | 图片预览 |
| `alt_text` | 图片替代文本 |
| `caption` | 图注/表注 |
### 7.8 返回示例
```json
{
"code": 0,
"message": "success",
"data": {
"page": {
"page_idx": 12,
"width": 612,
"height": 792,
"rotation": 0
},
"nodes": [
{
"node_id": "page12_node0",
"semantic_type": "heading",
"page_idx": 12,
"content_payload": {
"type": "text",
"text": "Section Title",
"html": "<b>Section Title</b>",
"heading_level": 2
},
"layout": {
"bbox": [119, 204, 880, 338],
"bbox_norm": [0.12, 0.205, 0.881, 0.339],
"angle": 0,
"reading_order": 0,
"page_idx": 12
},
"style_spans": []
}
]
}
}
```
### 7.9 使用场景
- 页面滚动进入某页时加载
- 目录跳转到某页时加载
- 页壳替换为真实内容时加载
## 8. 后端拆分规则
### 8.1 文档摘要接口返回什么
保留:
- 文档基本信息
- 统计信息
- 页索引
- 目录树
去除:
- 节点完整正文
- 大 HTML
- 重复的布局信息
### 8.2 页内容接口返回什么
保留:
- 页信息
- 页内节点完整可渲染数据
去除:
- 与当前页无关的其他页内容
- 文档级统计信息
- 目录树
## 9. 开发实现建议
1. 直接从现有 `merged_ans.json` 构造两个接口返回体
2. 先实现 `document-meta`,让前端可初始化
3. 再实现 `document-page`,支撑页级加载
4. 保持旧接口不变,避免历史页面受影响
## 10. 验收标准
### 10.1 接口正确性
- 各接口返回字段稳定
- 页索引与页内容一致
- 节点 id 可唯一定位
### 10.2 性能要求
- `document-meta` 返回体轻量
- `document-page` 只返回单页数据
- 不再出现整包大响应作为前端主入口
### 10.3 联调要求
- 前端可先拿摘要和目录
- 前端可按页加载内容
## 11. 结论
后端新增接口最终收敛为 2 个:
- `document-meta`
- `document-page`
其中 `document-meta` 已合并页索引和目录,避免重复接口。整体目标是:**只保留渲染必须数据,降低响应体积,支撑前端页级懒加载渲染。**
# documentCompare 块级响应式渲染改造清单(面向大模型)
## 目标约束
- 单页渲染容器宽度 = 中英文对比区域的一半(即单列宽度)
- 页面宽高比固定为 `21:29.7`(A4 纵向)
- 按 JSON 的 `bbox_norm` 做块级响应式定位渲染
- 块内文本按现有 `style_spans` 做样式还原(非字符几何定位)
## 执行范围
- 目标文件:`src/views/intelligentTranslation/documentCompare.vue`
- 数据源:`src/views/intelligentTranslation/merged_ans.json`
## 一、页面尺寸与比例改造
1. 在英文列与中文列内引入页面画布容器:
- 外层:`page-canvas-wrapper`
- 内层:`page-canvas`
2. `page-canvas` 宽度取当前列可用宽度(100%),高度通过比例自动推导:
- 推荐:`aspect-ratio: 21 / 29.7;`
3. 每个 `page-block` 改为 `position: relative` 的定位容器。
4. 页面中的节点块改为 `position: absolute`,由 `bbox_norm` 映射位置和尺寸。
## 二、数据结构补齐(块级定位)
`buildNormalizedBlocks` 中为每个节点补齐:
- `bboxNorm`: `layout.bbox_norm`
- `bbox`: `layout.bbox`
- `readingOrder`: `layout.reading_order`
- `pageIdx`: `node.page_idx`
- `blockType`: `mapSemanticTypeToNodeType(...)` 的返回值
- `imagePath`: `content_payload.img_path || content_payload.preview_img_path || ''`
新增校验函数:
- `isValidBboxNorm([l,t,r,b])`
- `l >= 0`
- `t >= 0`
- `r <= 1`
- `b <= 1`
- `r > l`
- `b > t`
降级策略:
-`bbox_norm` 无效但 `bbox` 有值,可按 `pages[pageIdx].width/height` 转换为归一化坐标。
- 若仍不可用,节点回退为流式渲染模式。
## 三、块级响应式定位算法
新增方法 `getBlockStyle(item)`,返回绝对定位样式:
- `left: ${l * 100}%`
- `top: ${t * 100}%`
- `width: ${(r - l) * 100}%`
- `height: ${(b - t) * 100}%`
- `position: 'absolute'`
- `overflow: 'hidden'`
说明:
- `[l,t,r,b]` 来自 `item.bboxNorm`
- 同一页节点渲染前按 `readingOrder` 升序排序
## 四、英文区块渲染规则
英文列渲染优先级:
1. `table`:渲染 `tableHtml`
2. `image`:渲染 `<img :src="getEnglishImageSrc(item)" @error="onEnglishImageError(item)" />`
3. 其它文本:渲染 `renderBlockHtml(item.text, item.styleSpans)`
要求:
- 图片链接不可访问时自动降级占位图
- 图片样式:`object-fit: contain; width: 100%; height: 100%`
## 五、中文区块渲染规则
中文列沿用同样的定位方式(`getBlockStyle(item)`):
1. `table``translatedTableHtml || tableHtml`
2. `image`:可先复用英文图片或占位图
3. 文本:`translatedText || text`
## 六、响应式要求
1. 容器宽度变化时无需重算像素,百分比定位自动生效。
2. 同一页的中英文画布高度保持一致。
3. 窄屏可切换为上下布局,但 `page-canvas` 比例保持 `21:29.7`
4. 滚动同步保持页级逻辑,不引入复杂块级联动。
## 七、样式改造点(SCSS)
新增/调整:
- `.page-canvas { position: relative; width: 100%; aspect-ratio: 21 / 29.7; }`
- `.page-node { position: absolute; box-sizing: border-box; }`
- `.page-node__content { width: 100%; height: 100%; overflow: hidden; }`
- `.page-node--image img { width: 100%; height: 100%; object-fit: contain; }`
注意:
- 旧的流式双栏样式保留为 fallback(可配置开关控制)。
- 避免父容器错误 `overflow` 导致块裁剪。
## 八、稳定性与调试开关
建议增加常量:
- `ENABLE_ABSOLUTE_LAYOUT = true`
- `ENABLE_DEBUG_BOX = false`
行为:
- `ENABLE_DEBUG_BOX = true` 时,为每个节点显示边框/类型标签,便于核对布局。
- 页级有效 `bbox_norm` 命中率低于阈值(如 70%)时,该页回退流式渲染。
## 九、验收标准
1. 单页比例恒定为 `21:29.7`
2. 缩放窗口后块位置保持稳定,不出现明显漂移。
3. 英文列图片正常显示,失效链接显示占位图。
4. 左侧导航点击可定位到对应内容。
5. 不新增 lint 报错。
## 十、建议实施顺序
1. 先改英文列为绝对定位并验证图片、标题位置。
2. 再同步改造中文列。
3. 最后补充 fallback 与调试开关。
4. 完成后执行 lint 与页面联调验证。
# 智能翻译模块接口接入开发实施方案
## 方案进度概述
- 当前阶段:**阶段 5(异常处理与收尾)已完成**
- 下一阶段:**联调验收与真实数据回归测试**
- 当前阻塞项:**暂无**
- 实施原则:**每完成一步,经用户验收确认后,先更新本文档中的进度概述与阶段状态,再开始下一步**
---
## 1. 需求理解
智能翻译模块需由当前的本地 Mock/占位逻辑,切换为真实接口驱动的文档翻译流程,核心链路如下:
1.`index.vue` 页面上传 PDF 文件并点击“翻译”。
2. 调用提交接口,获取任务 ID。
3. 跳转到 `documentCompare.vue` 页面后,根据任务 ID 轮询状态接口。
4. 任务未完成时展示等待界面,并每秒轮询一次。
5. 任务完成后关闭等待界面,调用结果接口获取翻译数据。
6. 将结果数据渲染到页面中:
- 英文部分展示接口返回的原始内容或结构化内容
- 译文部分先置空,后续可扩展人工编辑或 AI 补全
---
## 2. 接口链路方案
### 2.1 提交翻译任务接口
- 方法:`POST`
- 地址:`http://172.19.21.16:8019/tools/api/v1/doc-detail-pdf/submit`
- Header:
- `Client-ID: test_client`
- `X-API-Key: test_key`
- Body:
- 文件字段名:`files`
#### 预期返回
```json
{
"code": 0,
"message": "submit success",
"data": {
"task_id": "12418428891750955941",
"filename": "test.pdf",
"file_path": "/app/Datas/uploads/12418428891750955941/test.pdf",
"task_ids": [
"12418428891750955941"
]
}
}
```
#### 处理逻辑
- 用户在 `index.vue` 上传 PDF 后点击“AI翻译”
- 前端将文件组装为 `FormData`
- 调用提交接口
- 提取返回的 `task_id`
- 携带 `task_id` 跳转到 `documentCompare.vue`
---
### 2.2 查询任务状态接口
- 方法:`GET`
- 地址:`http://172.19.21.16:8019/tools/api/v1/doc-detail-pdf/status/{taskId}`
- Header:
- 同上
#### 预期返回
```json
{
"code": 0,
"message": "status success",
"data": {
"tool_id": "doc-detail-pdf",
"task_id": "660469818111596",
"status": "succeeded",
"progress": 0,
"file_path": "/app/Datas/uploads/12418428891750955941/test.pdf",
"time_finish": "1776680370634331224"
}
}
```
#### 处理逻辑
- `documentCompare.vue` 页面根据 `taskId` 启动轮询
- 轮询频率:**1 秒一次**
- 只要接口返回不是 `status success`,就保持等待界面
- 当返回 `status success` 时,停止轮询并进入结果获取阶段
---
### 2.3 获取翻译结果接口
- 方法:`GET`
- 地址:`http://172.19.21.16:8019/tools/api/v1/doc-detail-pdf/result/{taskId}`
- Header:
- 同上
#### 预期返回
- 返回结构与 `merged_ans.json` 类似
- 该数据用于渲染文档翻译结果
#### 处理逻辑
- 状态成功后立即请求结果接口
- 将返回数据映射为页面可渲染结构
- 英文部分展示接口返回内容
- 译文部分默认置空
---
## 3. 页面级实施方案
### 3.1 `index.vue`
#### 目标
将当前页面的“上传 PDF + 点击翻译”改为真实提交接口调用。
#### 实施内容
1. 保留 PDF 上传能力。
2. 校验文件类型,仅允许 PDF。
3. 点击“AI翻译”时:
- 检查是否已选择文件
- 组装 `FormData`
- 调用提交接口
4. 提交成功后:
- 提取 `task_id`
- 跳转到 `documentCompare.vue`
- 通过路由参数传递 `task_id`
#### 验收标准
- 选择 PDF 后点击翻译可发起真实请求
- 成功后能拿到 `task_id`
- 页面能正确跳转到对比页
---
### 3.2 `documentCompare.vue`
#### 目标
实现任务轮询、等待态展示、结果拉取和结果渲染。
#### 实施内容
1. 页面进入时读取 `taskId`
2. 展示等待界面。
3. 每秒轮询状态接口。
4. 当状态完成时:
- 关闭等待界面
- 请求结果接口
5. 将结果渲染到页面中。
#### 验收标准
- 未完成任务时持续等待且不闪退
- 完成后自动进入结果展示
- 不重复发起多余轮询
- 离开页面时轮询能正确停止
---
## 4. 数据渲染规则
### 4.1 英文部分
- 使用结果接口返回的数据直接渲染
- 保持文档结构尽量原样展示
- 如果接口返回的是分段/页结构,则按结构组织渲染
### 4.2 译文部分
- 默认置空
- 可显示空态提示,如“暂无译文”
- 为后续人工修订或二次翻译预留输入区域
### 4.3 文档结构适配
由于结果数据来源于 `merged_ans.json` 类似结构,建议增加一层适配处理:
- 原始接口字段
- 页面展示字段
- 空值兜底字段
- 顺序结构字段
---
## 5. 关键技术点
### 5.1 文件上传
- 使用 `FormData`
- 字段名必须为 `files`
- 仅允许 PDF
### 5.2 轮询控制
- 建议使用递归 `setTimeout`,更易控制停止与重试
- 轮询周期:1 秒
- 进入结果阶段后立即停止轮询
### 5.3 生命周期处理
- 组件卸载时清理轮询
- 路由切换时避免重复定时器
- 请求失败时展示错误状态并允许重试
### 5.4 状态管理
建议维护以下状态:
- `taskId`
- `loading`
- `polling`
- `status`
- `resultData`
- `errorMessage`
---
## 6. 分步实施计划
### 阶段 1:接口封装
- 封装提交接口
- 封装状态查询接口
- 封装结果查询接口
- 统一请求头配置
**验收标准**
- 三个接口可独立调通
- 返回结构可正确解析
---
### 阶段 2:`index.vue` 提交链路改造
- 替换 Mock 翻译逻辑
- 点击翻译时调用提交接口
- 成功后跳转并传递 `taskId`
**验收标准**
- 上传 PDF 后可成功创建任务
- 能跳转到对比页
---
### 阶段 3:`documentCompare.vue` 轮询等待
- 实现进入页自动轮询
- 未完成时展示等待界面
- 完成后停止轮询
**验收标准**
- 任务未完成时能持续等待
- 任务完成后自动进入下一步
---
### 阶段 4:结果获取与渲染
- 请求结果接口
- 将返回数据映射到页面结构
- 英文区渲染原始内容
- 译文区默认空
**验收标准**
- 页面能展示真实翻译结果
- 数据结构与 UI 对应正确
---
### 阶段 5:异常处理与收尾
- 上传失败提示
- 状态轮询失败处理
- 结果接口异常处理
- 页面卸载清理定时器
**验收标准**
- 网络异常时不崩溃
- 错误信息可见且可恢复
---
## 7. 风险与待确认项
### 风险
1. 接口返回的结果结构可能与 `merged_ans.json` 存在差异,需要做适配层。
2. `status success` 的判断条件需要严格确认,避免误判。
3. 结果接口是否支持大文件完整返回,需要确认前端展示性能。
4. `documentCompare.vue` 的 UI 结构可能需要根据结果数据做一定调整。
### 待确认项
1. 路由参数传递方式:`query` 还是 `params`
2. 结果页是否需要支持多任务历史记录
3. 英文/译文是否需要可编辑
4. 翻译完成后是否需要自动保存到本地或后端
---
## 8. 进度更新规则
1. 每完成一个阶段,先进行自检。
2. 自检通过后,向用户汇报当前阶段结果。
3. 等待用户验收确认。
4. 验收通过后,更新本文档中的:
- 方案进度概述
- 当前阶段状态
- 已完成事项
- 下一步计划
5. 再开始下一阶段。
---
## 9. 交付物
- 本开发实施方案文档
- 接口封装代码
- `index.vue` 提交链路改造
- `documentCompare.vue` 轮询与结果渲染
- 异常处理与清理逻辑
---
## 10. 本轮执行结果(2026-04-21)
- 已完成:阶段 1(提交/状态/结果接口封装),新增 `src/api/intelligentTranslation/index.js`
- 已完成:阶段 2(提交链路改造),`index.vue` 已接入真实提交接口并携带 `taskId` 跳转
- 已完成:阶段 3(轮询等待),`documentCompare.vue` 进入页面后按 1 秒轮询状态并支持停止
- 已完成:阶段 4(结果渲染),状态成功后自动请求结果接口并渲染英文侧,译文侧默认空
- 已完成:阶段 5(异常与收尾),缺少任务 ID、状态查询失败、页面卸载均已处理
......@@ -122,6 +122,11 @@ export default defineConfig({
target: 'http://8.140.26.4:10029/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/intelligent-api/, '')
},
'/doc-detail-pdf-api': {
target: 'http://172.19.21.16:8019/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/doc-detail-pdf-api/, '/tools/api/v1/doc-detail-pdf')
}
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论