提交 958142f1 authored 作者: 陈泽健's avatar 陈泽健

docs(prd): 更新ERP上传功能需求文档和配置

- 添加图片处理流程说明,包括调用openclaw/upload/richtext接口上传图片
- 更新接口调用地址为https://office.ubainsyun.com:5082/api/uerp/openclaw/upload/richtext
- 添加图片URL前缀拼接逻辑,将相对路径拼接为完整访问地址
- 更新计划执行文档版本至V1.1,标记为已完成状态
- 修改word转换为使用mammoth库实现,添加图片验证和保存功能
- 更新配置文件中的测试单ID和相关配置项
- 添加详细的接口日志输出
上级 19fc40b4
......@@ -315,7 +315,7 @@ ERP_API_KEY = "9adc1ce611544fae9bbbc5f6b1d6ce87"
ERP_BASE_URL = "https://office.ubainsyun.com:5082/api/uerp"
# 测试单ID(可配置)
ERP_DEVELOPTESTING_ID = 407
ERP_DEVELOPTESTING_ID = 397
# 报告类型ID(可配置,2=测试报告)
ERP_TYPE_ID = 2
......@@ -327,8 +327,8 @@ ERP_RETRY_INTERVAL = 5
ERP_MAX_RETRIES = 3
# ERP接口路径
ERP_UPLOAD_IMAGE_URL = "/openclaw/upload/richtext" # 上传图片接口
ERP_CREATE_REPORT_URL = "/openclaw/report" # 创建报告接口
ERP_UPLOAD_IMAGE_URL = "/openclaw/upload/richtext" # 上传图片接口路径
ERP_CREATE_REPORT_URL = "/openclaw/report" # 创建报告接口路径
# 请求超时时间(秒)
ERP_REQUEST_TIMEOUT = 30
......@@ -336,3 +336,10 @@ ERP_REQUEST_TIMEOUT = 30
# 图片处理配置
ERP_SAVE_IMAGES_TEMP = True # 是否将提取的图片保存到temp目录供检查
ERP_VALIDATE_IMAGES = True # 是否验证图片有效性
# 调试配置
ERP_SAVE_HTML_TEMP = True # 是否将转换后的HTML保存到temp目录供调试
# 图片URL前缀配置
ERP_IMAGE_URL_PREFIX = "https://office.ubainsyun.com:5015/" # 图片URL前缀,用于拼接完整的访问地址(末尾含斜杠)
......@@ -30,6 +30,8 @@ from src.config import (
ERP_REQUEST_TIMEOUT,
ERP_SAVE_IMAGES_TEMP,
ERP_VALIDATE_IMAGES,
ERP_SAVE_HTML_TEMP,
ERP_IMAGE_URL_PREFIX,
TEMP_DIR,
)
......@@ -162,8 +164,14 @@ def upload_image_to_erp(img_bytes: bytes, idx: int, logger: logging.Logger) -> O
result = resp.json()
if result.get('success') == 1:
logger.info(f"✓ 图片{idx}上传成功: {result['data']['url']}")
return result['data']['url']
original_url = result['data']['url']
# 拼接URL前缀
full_url = f"{ERP_IMAGE_URL_PREFIX}{original_url}"
logger.info(f"✓ 图片{idx}上传成功")
logger.info(f" 原始URL: {original_url}")
logger.info(f" 前缀: {ERP_IMAGE_URL_PREFIX}")
logger.info(f" 完整URL: {full_url}")
return full_url
else:
error_code = result.get('error', 0)
# 4xx错误不重试
......@@ -336,6 +344,27 @@ def word_to_html_with_images(file_path: str, logger: logging.Logger) -> Optional
logger.info(f"✓ Word转HTML完成")
logger.info(f" - 处理图片数量: {len(image_urls)}")
logger.info(f" - HTML内容长度: {len(html_content)} 字符")
# 保存HTML到temp目录供调试
if ERP_SAVE_HTML_TEMP:
try:
temp_dir = TEMP_DIR / "erp_upload_html"
temp_dir.mkdir(parents=True, exist_ok=True)
# 生成文件名:使用原文件名+时间戳
from datetime import datetime
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
html_filename = f"report_{timestamp}.html"
save_path = temp_dir / html_filename
with open(save_path, 'w', encoding='utf-8') as f:
f.write(html_content)
logger.info(f"✓ HTML已保存到: {save_path}")
logger.info(f" 可以在浏览器中打开查看图片信息")
except Exception as e:
logger.warning(f"⚠ 保存HTML失败: {str(e)}")
return html_content
except Exception as e:
......
......@@ -6,7 +6,7 @@
>
> 适用对象:第三方系统对接开发人员
---
---
## 一、概述
......
......@@ -75,6 +75,13 @@ import mammoth
return html_content
```
#### 图片处理
- 将图片文件通过调用接口`openclaw/upload/richtext` 上传图片,返回图片URL。在[Docs/PRD/自动化生成功能测试报告/ERP对接PRD/PRD_测试列表_测试报告_例子说明.md]
文档中第144行有示例
- 接口调用地址改为:https://office.ubainsyun.com:5082/api/uerp/openclaw/upload/richtext
- 再将相应信息的url字段值补充前缀拼接 `https://office.ubainsyun.com:5015/ + url`
- 最后拼接到富文本中,最终传参给ERP创建测试报告接口。
#### ERP对接方式
- API key值为:9adc1ce611544fae9bbbc5f6b1d6ce87
- 生产环境为:https://office.ubainsyun.com:5082/api/uerp
......
# _PRD_报告生成后自动调用ERP上传_计划执行
> 版本:V1.0
> 版本:V1.1
> 创建日期:2026-03-28
> 更新日期:2026-03-28
> 适用范围:功能测试报告自动化生成工具 - ERP上传功能
> 来源:基于《_PRD_报告生成后自动调用ERP上传_优化需求文档.md》
> 状态:待执行
> 状态:已完成
## 更新记录
| 版本 | 日期 | 更新内容 |
|------|------|----------|
| V1.0 | 2026-03-28 | 初始版本,ERP上传功能开发 |
| V1.1 | 2026-03-28 | 更新为mammoth实现,添加图片验证和保存功能 |
---
......@@ -21,11 +22,12 @@
### 1.2 目标
- 报告生成完成后,自动询问用户是否上传到ERP
- 将Word报告转换为HTML富文本格式
- 使用mammoth库将Word报告转换为HTML富文本格式
- 提取报告中的图片并单独上传到ERP获取URL
- 调用ERP接口创建测试报告记录
- 支持CLI和GUI两种交互方式
- 完善的重试机制和日志记录
- 完善的重试机制和详细日志记录
- 图片有效性验证和本地保存
### 1.3 涉及文件
**需求文档:**
......@@ -33,13 +35,13 @@
- `Docs/PRD/自动化生成功能测试报告/ERP对接PRD/PRD_测试列表_测试报告_例子说明.md`
**需要修改的代码文件:**
| 序号 | 文件名 | 操作 | 功能描述 |
|-----|--------|------|----------|
| 1 | `src/erp_uploader.py` | 新建 | ERP上传核心模块 |
| 2 | `src/config.py` | 修改 | 添加ERP相关配置项 |
| 3 | `src/cli.py` | 修改 | 报告生成后添加上传提示 |
| 4 | `src/gui.py` | 修改 | GUI模式添加上传按钮 |
| 5 | `requirements.txt` | 修改 | 添加mammoth依赖 |
| 序号 | 文件名 | 操作 | 功能描述 | 状态 |
|-----|--------|------|----------|------|
| 1 | `src/erp_uploader.py` | 新建 | ERP上传核心模块 | ✅ 完成 |
| 2 | `src/config.py` | 修改 | 添加ERP相关配置项 | ✅ 完成 |
| 3 | `src/cli.py` | 修改 | 报告生成后添加上传提示 | ✅ 完成 |
| 4 | `src/gui.py` | 修改 | GUI模式添加上传按钮 | ✅ 完成 |
| 5 | `requirements.txt` | 修改 | 添加mammoth和Pillow依赖 | ✅ 完成 |
---
......@@ -57,7 +59,7 @@
#### 2.2.1 上传图片接口
```
POST /openclaw/upload/richtext
POST https://office.ubainsyun.com:5082/api/uerp/openclaw/upload/richtext
Content-Type: multipart/form-data
```
......@@ -71,7 +73,7 @@ Content-Type: multipart/form-data
{
"success": 1,
"data": {
"url": "https://office.ubainsyun.com:5015/upload/xxx.png"
"url": "upload/xxx.png"
}
}
```
......@@ -117,19 +119,25 @@ cli.py / gui.py (交互层)
│ │
│ ┌─────────────────────────────────────┐ │
│ │ word_to_html_with_images() │ │
│ │ - 读取Word文档 │ │
│ │ - 提取图片 │ │
│ │ - 使用mammoth读取Word文档 │ │
│ │ - 图片验证(PIL) │ │
│ │ - 图片保存到temp目录 │ │
│ │ - 上传图片获取URL │ │
│ │ - 转换为HTML │ │
│ │ - 替换图片路径 │ │
│ │ - 去除水印 │ │
│ │ - 自动替换HTML中的图片为URL │ │
│ │ - 保存HTML到temp目录供调试 │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ upload_report_to_erp() │ │
│ │ - 调用ERP接口 │ │
│ │ - 重试机制(最多3次,间隔5秒) │ │
│ │ - 错误处理 │ │
│ │ - 详细日志记录 │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ validate_and_save_image() │ │
│ │ - PIL图片完整性验证 │ │
│ │ - 保存到temp/erp_upload_images/ │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
......@@ -146,6 +154,13 @@ config.py (配置层)
- ERP_TYPE_ID
- ERP_RETRY_INTERVAL
- ERP_MAX_RETRIES
- ERP_UPLOAD_IMAGE_URL
- ERP_CREATE_REPORT_URL
- ERP_REQUEST_TIMEOUT
- ERP_SAVE_IMAGES_TEMP
- ERP_VALIDATE_IMAGES
- ERP_SAVE_HTML_TEMP
- ERP_IMAGE_URL_PREFIX
```
### 3.2 数据流向
......@@ -155,15 +170,19 @@ Word报告文件 (.docx)
mammoth 加载文档
├──→ 遍历文档中的图片
├──→ 图片验证 (PIL)
│ ↓
│ 验证通过 → 保存到temp/erp_upload_images/
│ ↓
│ 上传到ERP (POST /openclaw/upload/richtext)
│ 上传到ERP (POST https://office.ubainsyun.com:5082/api/uerp/openclaw/upload/richtext)
│ ↓
│ 获取图片URL
│ 获取图片URL (如: upload/20260328.png)
│ ↓
│ 返回URL给mammoth替换图片src
│ 拼接URL前缀 (https://office.ubainsyun.com:5015/)
│ ↓
│ 完整URL (https://office.ubainsyun.com:5015/upload/20260328.png)
└──→ 转换为HTML (图片已替换为URL)
└──→ 转换为HTML (图片自动替换为完整URL)
调用创建报告接口 (POST /openclaw/report)
......@@ -183,481 +202,228 @@ mammoth 加载文档
# ERP上传配置
ERP_API_KEY = "9adc1ce611544fae9bbbc5f6b1d6ce87"
ERP_BASE_URL = "https://office.ubainsyun.com:5082/api/uerp"
ERP_DEVELOPTESTING_ID = 407 # 测试单ID,可配置
ERP_TYPE_ID = 2 # 报告类型ID,可配置
ERP_RETRY_INTERVAL = 5 # 重试间隔(秒)
ERP_MAX_RETRIES = 3 # 最大重试次数
ERP_DEVELOPTESTING_ID = 407
ERP_TYPE_ID = 2
ERP_RETRY_INTERVAL = 5
ERP_MAX_RETRIES = 3
ERP_UPLOAD_IMAGE_URL = "/uerp/openclaw/upload/richtext" # 上传图片接口路径
ERP_CREATE_REPORT_URL = "/openclaw/report"
ERP_REQUEST_TIMEOUT = 30
# ERP接口路径
ERP_UPLOAD_IMAGE_URL = "/openclaw/upload/richtext" # 上传图片接口
ERP_CREATE_REPORT_URL = "/openclaw/report" # 创建报告接口
# 图片处理配置
ERP_SAVE_IMAGES_TEMP = True # 是否保存图片到temp目录
ERP_VALIDATE_IMAGES = True # 是否验证图片有效性
# ERP请求超时时间(秒)
ERP_REQUEST_TIMEOUT = 30
```
# 调试配置
ERP_SAVE_HTML_TEMP = True # 是否保存HTML到temp目录供调试
---
# 图片URL前缀配置
ERP_IMAGE_URL_PREFIX = "https://office.ubainsyun.com:5015/" # 图片URL前缀(末尾含斜杠)
```
### 4.2 erp_uploader.py - ERP上传模块(新建)
**职责:**
- Word文档转换为HTML(图片单独处理)
- Word文档转换为HTML(使用mammoth)
- 图片验证(使用PIL)
- 图片保存到temp目录
- 图片上传到ERP
- 测试报告上传到ERP
- 重试机制
- 日志记录
- 详细日志记录
**导出函数:**
```python
def word_to_html_with_images(file_path: str, logger: logging.Logger) -> str
"""
将Word转HTML,图片单独上传获取URL
:param file_path: Word文件路径
:param logger: 日志记录器
:return: HTML字符串,图片已替换为ERP URL
"""
def upload_image_to_erp(image_bytes: bytes, idx: int, logger: logging.Logger) -> Optional[str]
"""
上传单张图片到ERP(含重试机制)
:param image_bytes: 图片字节数据
:param idx: 图片索引
:param logger: 日志记录器
:return: 图片URL,失败返回None
"""
def setup_logger(name: str = "erp_uploader") -> logging.Logger
"""设置日志记录器,添加StreamHandler"""
def validate_and_save_image(img_bytes: bytes, idx: int, content_type: str, logger: logging.Logger) -> bool
"""验证图片有效性并保存到temp目录"""
def upload_image_to_erp(img_bytes: bytes, idx: int, logger: logging.Logger) -> Optional[str]
"""上传单张图片到ERP(含重试机制)"""
def create_report_in_erp(content: str, logger: logging.Logger) -> Optional[int]
"""
在ERP中创建测试报告(含重试机制)
:param content: HTML格式的报告内容
:param logger: 日志记录器
:return: 报告ID,失败返回None
"""
def upload_report_to_erp(file_path: str, logger: logging.Logger) -> bool
"""
上传报告到ERP的完整流程
:param file_path: Word报告文件路径
:param logger: 日志记录器
:return: 是否上传成功
"""
def ask_upload_confirmation_cli() -> bool
"""
控制台交互:询问用户是否上传报告
:return: 用户选择(True=上传,False=不上传)
"""
"""在ERP中创建测试报告(含重试机制)"""
def setup_logger(name: str = "erp_uploader") -> logging.Logger
"""
设置日志记录器
:param name: 日志记录器名称
:return: 配置好的日志记录器
"""
def word_to_html_with_images(file_path: str, logger: logging.Logger) -> Optional[str]
"""使用mammoth将Word转HTML,图片上传到ERP"""
def upload_report_to_erp(file_path: str, logger: logging.Logger = None) -> bool
"""上传报告到ERP的完整流程"""
def ask_upload_confirmation_cli(report_path: str) -> bool
"""控制台交互:询问用户是否上传报告"""
```
**详细设计:**
**关键实现:**
#### 4.2.1 word_to_html_with_images() - mammoth转换
#### 4.2.1 图片验证和保存
```python
def word_to_html_with_images(file_path: str, logger: logging.Logger) -> str:
def validate_and_save_image(img_bytes: bytes, idx: int, content_type: str, logger: logging.Logger) -> bool:
"""验证图片有效性并保存到temp目录"""
# 1. PIL验证
if ERP_VALIDATE_IMAGES:
from PIL import Image
img = Image.open(BytesIO(img_bytes))
img.verify()
logger.info(f"图片验证通过: {img.format}, {img.width}x{img.height}")
# 2. 保存到temp
if ERP_SAVE_IMAGES_TEMP:
save_path = TEMP_DIR / "erp_upload_images" / f"image_{idx}.png"
with open(save_path, 'wb') as f:
f.write(img_bytes)
logger.info(f"图片已保存: {save_path}")
return True
```
#### 4.2.2 mammoth转换
```python
def word_to_html_with_images(file_path: str, logger: logging.Logger) -> Optional[str]:
"""使用mammoth将Word转HTML,图片上传到ERP"""
image_urls = []
def upload_image_handler(image):
"""mammoth图片处理回调函数"""
img_bytes = image["bytes"]
url = upload_image_to_erp(img_bytes, len(image_urls), logger)
if url:
image_urls.append(url)
return {"src": url}
return {"src": ""}
with image.open() as f:
img_bytes = f.read()
# 验证并保存图片
validate_and_save_image(img_bytes, idx, image.content_type, logger)
# 上传图片
url = upload_image_to_erp(img_bytes, idx, logger)
return {"src": url} if url else {"src": ""}
import mammoth
with open(file_path, "rb") as docx_file:
result = mammoth.convert_to_html(
docx_file,
convert_image=mammoth.images.inline(upload_image_handler)
)
return result.value
```
#### 4.2.2 upload_image_to_erp() - 含重试机制
```python
def upload_image_to_erp(img_data: bytes, idx: int, logger: logging.Logger) -> Optional[str]:
"""
上传单张图片到ERP(含重试机制)
- 最多重试3次,间隔5秒
- 仅对网络超时和5xx错误重试
- 4xx错误不重试
"""
for attempt in range(ERP_MAX_RETRIES):
try:
# 保存临时文件
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
tmp.write(img_data)
tmp_path = tmp.name
# 上传
with open(tmp_path, 'rb') as f:
files = {'file': f}
headers = {'X-Api-Key': ERP_API_KEY}
resp = requests.post(
f'{ERP_BASE_URL}{ERP_UPLOAD_IMAGE_URL}',
headers=headers,
files=files,
timeout=30
)
result = resp.json()
if result.get('success') == 1:
logger.info(f"图片{idx}上传成功: {result['data']['url']}")
return result['data']['url']
else:
error_code = result.get('error', 0)
# 4xx错误不重试
if 400 <= error_code < 500:
logger.error(f"图片{idx}上传失败(客户端错误): {result.get('msg')}")
return None
if attempt < ERP_MAX_RETRIES - 1:
logger.warning(f"图片{idx}上传失败,{ERP_RETRY_INTERVAL}秒后重试({attempt+1}/{ERP_MAX_RETRIES}): {result.get('msg')}")
time.sleep(ERP_RETRY_INTERVAL)
else:
logger.error(f"图片{idx}上传失败(已达最大重试次数): {result.get('msg')}")
except requests.exceptions.Timeout:
if attempt < ERP_MAX_RETRIES - 1:
logger.warning(f"图片{idx}上传超时,{ERP_RETRY_INTERVAL}秒后重试({attempt+1}/{ERP_MAX_RETRIES})")
time.sleep(ERP_RETRY_INTERVAL)
else:
logger.error(f"图片{idx}上传超时(已达最大重试次数)")
except Exception as e:
logger.error(f"图片{idx}上传异常: {str(e)}")
break
finally:
# 清理临时文件
if os.path.exists(tmp_path):
os.remove(tmp_path)
return None
return result.value
```
#### 4.2.3 create_report_in_erp() - 含重试机制
#### 4.2.2.2 图片URL拼接逻辑
```python
def create_report_in_erp(content: str, logger: logging.Logger) -> Optional[int]:
"""
在ERP中创建测试报告(含重试机制)
- 最多重试3次,间隔5秒
- 仅对网络超时和5xx错误重试
"""
for attempt in range(ERP_MAX_RETRIES):
try:
data = {
'developtesting_id': ERP_DEVELOPTESTING_ID,
'type_id': ERP_TYPE_ID,
'content': content,
'descript': '',
'copyuserList': []
}
headers = {
'X-Api-Key': ERP_API_KEY,
'Content-Type': 'application/json'
}
resp = requests.post(
f'{ERP_BASE_URL}{ERP_CREATE_REPORT_URL}',
headers=headers,
json=data,
timeout=30
)
result = resp.json()
if result.get('success') == 1:
report_id = result['data']['create']
logger.info(f"报告创建成功! ERP报告ID: {report_id}")
return report_id
else:
error_code = result.get('error', 0)
# 4xx错误不重试
if 400 <= error_code < 500:
logger.error(f"报告创建失败(客户端错误): {result.get('msg')}")
return None
if attempt < ERP_MAX_RETRIES - 1:
logger.warning(f"报告创建失败,{ERP_RETRY_INTERVAL}秒后重试({attempt+1}/{ERP_MAX_RETRIES}): {result.get('msg')}")
time.sleep(ERP_RETRY_INTERVAL)
else:
logger.error(f"报告创建失败(已达最大重试次数): {result.get('msg')}")
except requests.exceptions.Timeout:
if attempt < ERP_MAX_RETRIES - 1:
logger.warning(f"报告创建超时,{ERP_RETRY_INTERVAL}秒后重试({attempt+1}/{ERP_MAX_RETRIES})")
time.sleep(ERP_RETRY_INTERVAL)
else:
logger.error(f"报告创建超时(已达最大重试次数)")
except Exception as e:
logger.error(f"报告创建异常: {str(e)}")
break
return None
def upload_image_to_erp(img_bytes: bytes, idx: int, logger: logging.Logger) -> Optional[str]:
"""上传单张图片到ERP(含重试机制)"""
# ...上传代码...
result = resp.json()
if result.get('success') == 1:
original_url = result['data']['url']
# 拼接URL前缀
full_url = f"{ERP_IMAGE_URL_PREFIX}{original_url}"
logger.info(f"✓ 图片{idx}上传成功")
logger.info(f" 原始URL: {original_url}")
logger.info(f" 前缀: {ERP_IMAGE_URL_PREFIX}")
logger.info(f" 完整URL: {full_url}")
return full_url
```
#### 4.2.3 word_to_html_with_images() - 完整实现
```python
def word_to_html_with_images(file_path: str, logger: logging.Logger) -> str:
"""
使用mammoth将Word转HTML,图片上传到ERP
"""
logger.info(f"开始处理Word文档: {file_path}")
**URL拼接说明:**
image_urls = []
image_index = [0]
| 步骤 | 说明 | 示例 |
|------|------|------|
| 1 | 上传图片到ERP(5082端口) | POST https://office.ubainsyun.com:5082/api/uerp/openclaw/upload/richtext |
| 2 | ERP返回相对路径URL | `upload/20260328.png` |
| 3 | 拼接前缀 | `https://office.ubainsyun.com:5015/` + `upload/20260328.png` |
| 4 | 得到完整URL | `https://office.ubainsyun.com:5015/upload/20260328.png` |
| 5 | 替换HTML中的图片src | `<img src="https://office.ubainsyun.com:5015/upload/20260328.png">` |
def upload_image_handler(image):
"""mammoth图片处理回调函数"""
img_bytes = image["bytes"]
idx = image_index[0]
image_index[0] += 1
**为什么要拼接前缀:**
- ERP返回的URL是相对路径(如 `upload/20260328.png`),无法直接在富文本中访问
- 需要拼接ERP服务器地址(`https://office.ubainsyun.com:5015/`)才能在公网访问
- 完整的URL才能在HTML富文本中正常显示图片
- 注意:前缀末尾已包含斜杠 `/`,拼接时无需额外添加
url = upload_image_to_erp(img_bytes, idx, logger)
if url:
logger.info(f"图片{idx}上传成功: {url}")
image_urls.append(url)
return {"src": url}
else:
logger.warning(f"图片{idx}上传失败")
return {"src": ""}
try:
import mammoth
with open(file_path, "rb") as docx_file:
result = mammoth.convert_to_html(
docx_file,
convert_image=mammoth.images.inline(upload_image_handler)
)
html_content = result.value
logger.info(f"Word转HTML完成,处理了{len(image_urls)}张图片")
return html_content
except Exception as e:
logger.error(f"Word转HTML处理失败: {str(e)}")
return None
#### 4.2.3 日志输出
```python
# 详细接口日志
logger.info(f"=== 图片{idx}上传请求 ===")
logger.info(f"请求URL: {url}")
logger.info(f"请求Headers: X-Api-Key={ERP_API_KEY[:10]}...")
logger.info(f"请求Files: file=image.png (size={len(img_bytes)} bytes)")
logger.info(f"响应状态码: {resp.status_code}")
logger.info(f"响应内容: {resp.text}")
```
**依赖:**
- `mammoth` - Word文档转HTML(纯Python)
- `requests` - HTTP请求
- `logging` - 日志记录
---
### 4.3 cli.py - 命令行交互模块(修改)
**修改内容:**
`generate_report_main()` 函数的末尾(报告生成完成后)添加上传提示
**修改位置:** 第336-346行之后
`generate_report_main()` 函数末尾添加上传提示
**新增代码:**
```python
def generate_report_main(...) -> List[str]:
# ... 现有代码 ...
# 步骤6:完成
print(f"\n报告已保存到:")
for report in generated_reports:
print(f" - {report}")
# ===== 新增:ERP上传功能 =====
# 检查是否有docx格式的报告
docx_reports = [r for r in generated_reports if r.endswith('.docx')]
if docx_reports:
from src.erp_uploader import ask_upload_confirmation_cli, upload_report_to_erp, setup_logger
logger = setup_logger()
for report_path in docx_reports:
# 询问用户是否上传
if ask_upload_confirmation_cli(report_path):
print(f"\n正在上传报告到ERP...")
success = upload_report_to_erp(report_path, logger)
if success:
print(f" [OK] 报告已成功上传到ERP")
else:
print(f" [X] 报告上传失败,请查看日志")
else:
print(f" [!] 跳过上传: {report_path}")
# ===== 新增结束 =====
return generated_reports
```
**新增函数:**
```python
def ask_upload_confirmation_cli(report_path: str) -> bool:
"""
控制台交互:询问用户是否上传报告到ERP
:param report_path: 报告文件路径
:return: 用户选择(True=上传,False=不上传)
"""
while True:
print(f"\n是否将报告上传到ERP测试单?")
print(f" 报告文件: {report_path}")
choice = input(" 请输入 Y/N (默认=N): ").strip().upper()
if not choice:
choice = 'N'
if choice == 'Y':
return True
elif choice == 'N':
return False
else:
print(" 输入错误,请输入 Y 或 N")
```
---
### 4.4 gui.py - GUI界面模块(修改)
# ERP上传功能
docx_reports = [r for r in generated_reports if r.endswith('.docx')]
if docx_reports:
from src.erp_uploader import ask_upload_confirmation_cli, upload_report_to_erp, setup_logger
**修改内容:**
在报告生成完成后,添加上传提示对话框
**修改位置:** 报告生成完成后的回调函数
**新增代码:**
```python
def ask_upload_confirmation_gui(report_path: str) -> bool:
"""
GUI交互:询问用户是否上传报告到ERP
:param report_path: 报告文件路径
:return: 用户选择(True=上传,False=不上传)
"""
from tkinter import messagebox
result = messagebox.askyesno(
"上传报告到ERP",
f"报告已生成完成!\n\n是否将报告上传到ERP测试单?\n\n报告文件:\n{report_path}"
)
return result
def upload_report_with_gui(report_path: str, log_callback=None) -> bool:
"""
GUI模式下的报告上传函数
:param report_path: 报告文件路径
:param log_callback: 日志回调函数
:return: 是否上传成功
"""
from src.erp_uploader import upload_report_to_erp, setup_logger
# 设置日志,使用回调函数输出到GUI
logger = setup_logger()
if log_callback:
handler = GUILogHandler(log_callback)
logger.addHandler(handler)
for report_path in docx_reports:
if ask_upload_confirmation_cli(report_path):
print(f"\n正在上传报告到ERP...")
success = upload_report_to_erp(report_path, logger)
if success:
print(f" [OK] 报告已成功上传到ERP")
else:
print(f" [X] 报告上传失败,请查看日志")
```
return upload_report_to_erp(report_path, logger)
### 4.4 requirements.txt(修改)
class GUILogHandler(logging.Handler):
"""自定义日志处理器,将日志输出到GUI"""
def __init__(self, callback):
super().__init__()
self.callback = callback
**新增依赖:**
```txt
# Word转HTML
mammoth>=1.8.0
def emit(self, record):
msg = self.format(record)
self.callback(msg)
```
**界面修改:**
在报告生成完成后,弹出上传确认对话框:
```
┌─────────────────────────────────────────────────┐
│ 上传报告到ERP │
├─────────────────────────────────────────────────┤
│ │
│ 报告已生成完成! │
│ │
│ 是否将报告上传到ERP测试单? │
│ │
│ 报告文件: │
│ reports/项目名称_功能测试报告_2026年03月28日.docx│
│ │
│ [是(Y)] [否(N)] │
└─────────────────────────────────────────────────┘
# 图片处理(用于ERP上传时验证图片)
Pillow>=10.0.0
```
---
## 5. 执行计划
### 5.1 阶段划分
| 阶段 | 任务 | 预计工作量 | 依赖 | 状态 |
|-----|------|----------|------|------|
| **阶段1** | 修改config.py,添加ERP配置项 | 0.5天 | - | ⏳ 待执行 |
| **阶段2** | 实现erp_uploader.py核心模块 | 2天 | 阶段1 | ⏳ 待执行 |
| **阶段3** | 修改cli.py,添加CLI上传功能 | 0.5天 | 阶段2 | ⏳ 待执行 |
| **阶段4** | 修改gui.py,添加GUI上传功能 | 1天 | 阶段2 | ⏳ 待执行 |
| **阶段5** | 更新requirements.txt | 0.1天 | 阶段1 | ⏳ 待执行 |
| **阶段6** | 集成测试 | 1天 | 阶段3,4,5 | ⏳ 待执行 |
| **阶段7** | 文档更新 | 0.5天 | 阶段6 | ⏳ 待执行 |
### 5.2 里程碑
| 里程碑 | 完成标准 | 状态 |
|-------|---------|------|
| M1: 配置完成 | config.py新增ERP配置项 | ⏳ 待达成 |
| M2: 核心模块完成 | erp_uploader.py实现完成 | ⏳ 待达成 |
| M3: CLI集成完成 | CLI模式可正常上传报告 | ⏳ 待达成 |
| M4: GUI集成完成 | GUI模式可正常上传报告 | ⏳ 待达成 |
| M5: 测试完成 | 集成测试通过,无重大BUG | ⏳ 待达成 |
---
### 5.1 开发步骤
## 6. 测试计划
| 步骤 | 操作 | 状态 |
|-----|------|------|
| 1 | 创建erp_uploader.py模块 | ✅ 完成 |
| 2 | 添加ERP配置到config.py | ✅ 完成 |
| 3 | 修改cli.py添加上传提示 | ✅ 完成 |
| 4 | 修改gui.py添加上传功能 | ✅ 完成 |
| 5 | 更新requirements.txt | ✅ 完成 |
| 6 | 修复Image对象访问问题 | ✅ 完成 |
| 7 | 添加详细日志输出 | ✅ 完成 |
| 8 | 添加图片验证和保存功能 | ✅ 完成 |
| 9 | 集成测试 | ⏳ 待测试 |
### 6.1 单元测试
### 5.2 验证方法
| 模块 | 测试内容 |
|------|----------|
| erp_uploader.py | 图片提取、图片上传、HTML转换、报告创建、重试机制 |
| config.py | 配置项正确性 |
```bash
cd AuxiliaryTool/FunctionalTestReportGeneration
### 6.2 集成测试
# 安装依赖
pip install mammoth Pillow
测试场景:
1. CLI模式完整流程测试
2. GUI模式完整流程测试
3. 网络异常重试测试
4. ERP接口异常处理测试
5. 含图片报告上传测试
6. 无图片报告上传测试
# CLI模式测试
python run.py --testcase testcases/测试用例.xlsx --buglist testcases/BUG列表.xlsx
### 6.3 测试数据
**测试报告:** `reports/中国石油兰州石化项目_功能进度测试报告_2026年03月27日.docx`
---
## 7. 风险与应对
| 风险 | 影响 | 概率 | 应对措施 |
|-----|------|------|---------|
| Spire.Doc免费版功能限制 | 中 | 中 | 先验证免费版功能是否满足需求,必要时考虑替代方案 |
| 图片路径格式变化 | 中 | 中 | 支持多种可能的路径格式,动态替换 |
| ERP接口不稳定 | 高 | 中 | 实现重试机制,记录详细日志 |
| 网络超时 | 中 | 高 | 设置timeout参数,实现重试机制 |
| 大文件处理超时 | 低 | 低 | 增加处理超时时间,显示进度 |
# GUI模式测试
python run.py --gui
```
---
## 8. 验收标准
## 6. 测试规范
### 8.1 功能验收
### 6.1 功能验收
- [ ] 报告生成后自动提示用户是否上传
- [ ] Word报告能正确转换为HTML格式
......@@ -669,8 +435,12 @@ class GUILogHandler(logging.Handler):
- [ ] 日志记录完整,便于问题排查
- [ ] CLI模式交互正常
- [ ] GUI模式交互正常
- [ ] 图片验证功能正常
- [ ] 图片保存到temp目录功能正常
- [ ] HTML保存到temp目录功能正常
- [ ] HTML中图片URL正确显示
### 8.2 代码质量验收
### 6.2 代码质量验收
- [ ] 符合代码规范要求(中文注释)
- [ ] 每个函数有docstring说明
......@@ -679,29 +449,43 @@ class GUILogHandler(logging.Handler):
---
## 9. 参考文档
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
- 问题总结: `Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md`
- 方法总结: `Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md`
- 文档规范: `Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md`
- 测试规范: `Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md`
---
## 10. 执行结果记录
## 7. 执行结果记录
### 10.1 问题记录
### 7.1 问题记录
| 日期 | 问题描述 | 解决方案 | 状态 |
|------|----------|---------|------|
| - | - | - | - |
| 2026-03-28 | 'Image' object is not subscriptable | 使用属性访问 | ✅ 已解决 |
| 2026-03-28 | 'Image' object has no attribute 'bytes' | 使用as_bytes()方法 | ✅ 已解决 |
| 2026-03-28 | 'Image' object has no attribute 'as_bytes' | 使用open().read()方法 | ✅ 已解决 |
| 2026-03-28 | 'closing' object has no attribute 'read' | 使用with语句管理 | ✅ 已解决 |
| 2026-03-28 | 没有日志输出 | 添加StreamHandler | ✅ 已解决 |
### 10.2 变更记录
### 7.2 变更记录
| 日期 | 变更内容 | 变更原因 | 状态 |
|------|----------|----------|------|
| - | - | - | - |
| 2026-03-28 | 从Spire.Doc改为mammoth | Spire.Doc兼容性问题 | ✅ 完成 |
| 2026-03-28 | 添加图片验证和保存功能 | 便于调试和验证 | ✅ 完成 |
| 2026-03-28 | 添加详细接口日志 | 便于问题排查 | ✅ 完成 |
### 7.3 文件修改记录
| 文件 | 修改内容 | 日期 |
|------|----------|------|
| `src/erp_uploader.py` | 新建,包含所有ERP上传功能 | 2026-03-28 |
| `src/config.py` | 添加ERP配置和图片处理配置 | 2026-03-28 |
| `src/cli.py` | 添加ERP上传提示 | 2026-03-28 |
| `src/gui.py` | 添加ERP上传功能 | 2026-03-28 |
| `requirements.txt` | 添加mammoth和Pillow | 2026-03-28 |
---
## 8. 参考文档
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
- 问题总结: `Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md`
- ERP对接PRD: `Docs/PRD/自动化生成功能测试报告/ERP对接PRD/PRD_测试列表_测试报告_例子说明.md`
---
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论