Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
aef3ad69
提交
aef3ad69
authored
4月 22, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat 重构方案
上级
208093f8
流水线
#585
已通过 于阶段
in 1 分 48 秒
变更
6
流水线
1
全部展开
显示空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
277 行增加
和
485 行删除
+277
-485
前端重构方案.md
src/views/intelligentTranslation/前端重构方案.md
+272
-0
后端接口方案.md
src/views/intelligentTranslation/后端接口方案.md
+0
-0
块级响应式渲染改造清单.md
src/views/intelligentTranslation/块级响应式渲染改造清单.md
+0
-134
开发实施方案.md
src/views/intelligentTranslation/开发实施方案.md
+0
-351
版式识别与样式还原字段说明.pdf
src/views/intelligentTranslation/版式识别与样式还原字段说明.pdf
+0
-0
vite.config.js
vite.config.js
+5
-0
没有找到文件。
src/views/intelligentTranslation/前端重构方案.md
0 → 100644
浏览文件 @
aef3ad69
# 智能翻译文档对比页前端重构实施方案
## 方案进度概述
-
当前阶段:重构方案定稿
-
目标:将现有全量渲染的文档对比页重构为页级懒加载架构
-
面向对象:大模型执行与前端开发协作
-
约束:原有接口不能改,只能基于新增接口重构
## 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. 结论
前端最终采用:
> 页级懒加载渲染架构。
即:
-
页作为最小渲染单位
-
可见页才挂载真实内容
-
页外只保留轻量壳
-
目录和滚动按页同步
-
图片、表格、富文本做二级懒加载
这是当前场景下最稳妥、最可落地、最利于后续扩展的方案。
src/views/intelligentTranslation/后端接口方案.md
0 → 100644
浏览文件 @
aef3ad69
差异被折叠。
点击展开。
src/views/intelligentTranslation/块级响应式渲染改造清单.md
deleted
100644 → 0
浏览文件 @
208093f8
# 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 与页面联调验证。
src/views/intelligentTranslation/开发实施方案.md
deleted
100644 → 0
浏览文件 @
208093f8
# 智能翻译模块接口接入开发实施方案
## 方案进度概述
-
当前阶段:
**阶段 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、状态查询失败、页面卸载均已处理
src/views/intelligentTranslation/版式识别与样式还原字段说明.pdf
deleted
100644 → 0
浏览文件 @
208093f8
File deleted
vite.config.js
浏览文件 @
aef3ad69
...
...
@@ -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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论