From 07812ea8c4682476f7b03f9db23013c4aaf1fa0e Mon Sep 17 00:00:00 2001 From: python Date: Fri, 5 Dec 2025 14:01:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=96=87=E4=BB=B6=E5=90=8D=E7=A7=B0=E5=92=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=AD=97=E6=AE=B5=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3=E5=92=8C=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MinIO文件位置说明.md | 137 ++++++ MinIO连接测试结果.md | 169 +++++++ __pycache__/app.cpython-312.pyc | Bin 20771 -> 20801 bytes app.py | 43 +- check_minio_files.py | 132 ++++++ get_template_url.py | 117 +++++ .../document_service.cpython-312.pyc | Bin 12388 -> 12484 bytes services/document_service.py | 12 +- test_document_generation.py | 228 ++++++++++ test_minio_connection.py | 361 +++++++++++++++ .../智慧监督AI文书写作接口定义-20251204-2.md | 424 ++++++++++++++++++ 接口调整完成总结.md | 158 +++++++ 接口调整说明.md | 212 +++++++++ 文档生成测试结果.md | 125 ++++++ 模板文件下载链接.md | 86 ++++ 15 files changed, 2178 insertions(+), 26 deletions(-) create mode 100644 MinIO文件位置说明.md create mode 100644 MinIO连接测试结果.md create mode 100644 check_minio_files.py create mode 100644 get_template_url.py create mode 100644 test_document_generation.py create mode 100644 test_minio_connection.py create mode 100644 技术文档/智慧监督AI文书写作接口定义-20251204-2.md create mode 100644 接口调整完成总结.md create mode 100644 接口调整说明.md create mode 100644 文档生成测试结果.md create mode 100644 模板文件下载链接.md diff --git a/MinIO文件位置说明.md b/MinIO文件位置说明.md new file mode 100644 index 0000000..46183b4 --- /dev/null +++ b/MinIO文件位置说明.md @@ -0,0 +1,137 @@ +# MinIO文件位置说明 + +## ✅ 确认:文件没有被删除! + +测试脚本**只删除了本地临时文件**,**不会删除MinIO上的文件**。所有上传的文件都还在MinIO中。 + +--- + +## 📍 测试文件位置 + +### 1. 测试上传的文件 + +找到了 **3个测试文件**,位置在: + +``` +存储桶: finyx +路径前缀: 615873064429507639/TEST/2025/12/ +``` + +具体文件: + +1. **test_file_20251205095549.txt** + - 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095549.txt` + - 大小: 122 字节 + - 上传时间: 2025-12-05 01:55:49 + +2. **test_file_20251205095558.txt** + - 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095558.txt` + - 大小: 122 字节 + - 上传时间: 2025-12-05 01:55:58 + +3. **test_file_20251205095620.txt** + - 完整路径: `615873064429507639/TEST/2025/12/test_file_20251205095620.txt` + - 大小: 122 字节 + - 上传时间: 2025-12-05 01:56:20 + +### 2. 模板文件 + +找到了 **1个模板文件**: + +- **初步核实审批表模板.docx** + - 完整路径: `615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx` + - 大小: 21101 字节 + - 上传时间: 2025-12-02 06:42:56 + +--- + +## 🔍 如何在MinIO中查找文件 + +### 方式1:通过MinIO Web界面 + +1. 登录MinIO Web界面 +2. 选择存储桶:`finyx` +3. 导航到路径: + ``` + finyx/ + └── 615873064429507639/ + ├── TEST/ + │ └── 2025/ + │ └── 12/ + │ ├── test_file_20251205095549.txt + │ ├── test_file_20251205095558.txt + │ └── test_file_20251205095620.txt + └── TEMPLATE/ + └── 2025/ + └── 12/ + └── 初步核实审批表模板.docx + ``` + +### 方式2:使用查询脚本 + +运行检查脚本查看所有文件: + +```bash +python check_minio_files.py +``` + +这个脚本会列出: +- 所有测试文件 +- 所有与租户相关的文件(共442个) +- 所有模板文件 + +--- + +## 📊 文件统计 + +- **测试文件**: 3个(在 `TEST/` 目录下) +- **模板文件**: 1个(在 `TEMPLATE/` 目录下) +- **租户相关文件总数**: 442个 + +--- + +## 🔗 访问文件 + +### 生成访问URL + +如果需要访问这些文件,可以使用以下Python代码生成预签名URL: + +```python +from minio import Minio +from datetime import timedelta + +client = Minio( + 'minio.datacubeworld.com:9000', + access_key='JOLXFXny3avFSzB0uRA5', + secret_key='G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I', + secure=True +) + +# 生成访问URL(7天有效) +object_name = '615873064429507639/TEST/2025/12/test_file_20251205095620.txt' +url = client.presigned_get_object( + 'finyx', + object_name, + expires=timedelta(days=7) +) +print(url) +``` + +--- + +## ✅ 验证结果 + +- ✅ 文件确实存在 +- ✅ 文件没有被删除 +- ✅ 文件路径正确 +- ✅ 可以正常访问 + +如果您在MinIO界面中找不到,请: +1. 确认您查看的是正确的存储桶:`finyx` +2. 导航到正确的路径:`615873064429507639/TEST/2025/12/` +3. 或者运行 `python check_minio_files.py` 查看详细列表 + +--- + +**文件都在,请放心!** 🎉 + diff --git a/MinIO连接测试结果.md b/MinIO连接测试结果.md new file mode 100644 index 0000000..0369ba0 --- /dev/null +++ b/MinIO连接测试结果.md @@ -0,0 +1,169 @@ +# MinIO连接测试结果 + +## ✅ 测试结果:全部通过 + +### 测试时间 +2025-12-05 09:56:20 + +### 测试配置 +- **端点**: `minio.datacubeworld.com:9000` +- **使用HTTPS**: 是 +- **存储桶**: `finyx` +- **访问密钥**: `JOLXFXny3avFSzB0uRA5` +- **密钥**: `G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I` + +--- + +## 📋 测试项目结果 + +| 测试项目 | 状态 | 说明 | +|---------|------|------| +| MinIO连接 | ✅ 通过 | 连接成功,可以访问MinIO服务 | +| 存储桶存在 | ✅ 通过 | 目标存储桶 `finyx` 存在 | +| 列出对象 | ✅ 通过 | 可以正常列出存储桶中的对象 | +| 文件上传 | ✅ 通过 | 测试文件上传成功 | +| URL生成 | ✅ 通过 | 预签名URL生成成功 | +| URL下载 | ✅ 通过 | 通过URL可以成功下载文件 | + +**通过率: 5/5 (100%)** + +--- + +## 🔍 详细测试结果 + +### 1. 连接测试 +- ✅ MinIO服务器连接成功 +- ✅ 可以列出所有存储桶 +- ✅ 目标存储桶 `finyx` 存在且可访问 + +### 2. 文件上传测试 +- ✅ 成功创建测试文件 +- ✅ 成功上传到MinIO +- ✅ 文件路径: `/615873064429507639/TEST/2025/12/test_file_20251205095620.txt` + +### 3. URL生成测试 +- ✅ 预签名URL生成成功 +- ✅ URL有效期: 7天 +- ✅ URL格式正确,包含所有必要的签名参数 + +### 4. 下载测试 +- ✅ 通过预签名URL可以成功下载文件 +- ✅ HTTP状态码: 200 +- ✅ 文件内容完整正确 +- ✅ 内容类型识别正确: `text/plain; charset=utf-8` + +--- + +## 📝 配置验证 + +### 正确的配置方式 + +```python +MINIO_CONFIG = { + 'endpoint': 'minio.datacubeworld.com:9000', # 注意:去掉协议前缀 + 'access_key': 'JOLXFXny3avFSzB0uRA5', + 'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I', + 'secure': True # 使用HTTPS +} +``` + +### 重要提示 + +1. **endpoint格式** + - ✅ 正确: `minio.datacubeworld.com:9000` + - ❌ 错误: `https://minio.datacubeworld.com:9000/` + - 说明: endpoint不应该包含协议前缀(`https://`)和末尾斜杠(`/`) + +2. **secure参数** + - 设置为 `True` 表示使用HTTPS + - 设置为 `False` 表示使用HTTP + +3. **存储桶名称** + - 存储桶 `finyx` 已存在,可以直接使用 + +--- + +## 🔗 URL访问方式 + +### 预签名URL(推荐) + +生成预签名URL,有效期7天: + +```python +from datetime import timedelta + +url = client.presigned_get_object( + bucket_name, + object_name, + expires=timedelta(days=7) +) +``` + +**特点:** +- ✅ 安全,带有签名验证 +- ✅ 可以设置有效期 +- ✅ 无需公开存储桶访问权限 + +### 公共URL(如果存储桶是公共的) + +``` +https://minio.datacubeworld.com:9000/finyx/{object_name} +``` + +**注意:** 这种方式需要存储桶设置为公共访问。 + +--- + +## 💡 使用建议 + +### 1. 文件路径存储 + +根据接口文档要求,数据库存储时使用**相对路径**: + +```python +# 相对路径格式 +file_path = "/615873064429507639/TEST/2025/12/test_file.txt" +``` + +### 2. URL生成 + +在实际使用中,建议: +- 使用预签名URL进行临时访问 +- 根据业务需求设置合适的有效期 +- 不公开存储桶访问权限,保证安全性 + +### 3. 文件组织 + +建议的文件路径组织方式: +``` +{tenant_id}/TEMPLATE/{year}/{month}/文件名.docx +{tenant_id}/GENERATED/{year}/{month}/{document_id}/文件名.docx +``` + +--- + +## ✅ 结论 + +**MinIO配置完全正确,可以正常使用!** + +所有功能测试通过: +- ✅ 连接正常 +- ✅ 上传功能正常 +- ✅ URL生成正常 +- ✅ 下载功能正常 + +可以放心使用此配置进行文档生成和存储。 + +--- + +## 📄 测试文件 + +完整的测试脚本:`test_minio_connection.py` + +可以随时运行此脚本验证MinIO连接状态。 + +--- + +**测试完成时间**: 2025-12-05 09:56:20 +**测试状态**: ✅ 全部通过 + diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc index 40d1173d781f2e82562277c2eff7b0b4d562bcfb..9d2c16fa86e0414b5e1203066be1dc84314861eb 100644 GIT binary patch delta 1529 zcmaJ>ZA@EL7(VCrW4DF2x3q;0O4sty(wRbODGZDQvX7Q+=@$86_+dK2yCS4lZUkIHXo+dw}_%ll;?a4MXLY}cf{o~>L4r{a`!)_x4pnh!;07s=Q`_;6TQ(pif zF|Fg*pl0XcICVO53(*Ad2&vbp7Tm58(Ait6oaa>fJyioK+5RnA?sKxdJ!OJwM*nzF?O+Srk*DCe1rQTY5sj- zczt$uEj+juzO#Pqqr~vo`i(ae?+qoUZpFvmUcWtu4%B9&x)PZ#K0J}Q`$=Ll9KUxn zes3x<^3}%FXUKLqAI%(o#lBlR{65~r=85ZbPlv9oh2Pou{L94sOSsX-&;#uGy%BHj zfbZhAt$_}vf!?NMqgAa6QFR?Q-0|rLmv^@i;$fFky1S(>F}V<5xFUqbs{aYQs+FRj z>KHwrZFDF;_U_@Xr@P$ga676URSrklo+I(c z7be%jBSI>4Q}-e=<;v#2uK!1@@x`R6BgRO6^)+`g=$GT?qyhZF2HTO(V@Bsar?W09 z+n6pU*vvAtU}6)YMNc03)nkN;t6mTCds{73kO}p4uzudh-w_D0F->bA7-Ic+7CoIz z7whlh-T(GlbTQ4gU5YO37#i&Q5Z{+Cm+=1~)Qx`#gCN-|K8>0izEdToz+jA!`lzuW zLgxL3m=iu|L=R3Byru+J`|b9r_PN|}(~lNUget^btu>-4jUId{qP4D4rk^S66UrJj z7Dr94sL3*U@rlX#$3C$w>n|WyYm#LkxA4!GA)rjr+~TOA><7bKF84bWyC~*E;c4@V_2r^Lhv%bC+Xl5S)+!$Xa9z?l(DYwmdBJ zv(_?Vw;sGpTAxuXRCo#LBj70CCsXdW}#J3;+|@pw6N3*H@X5p=|lM zIE#=lZ_p$<~}~lkLc%OaY*pNu4Gcg3A|ZAl0uCt7MZ>(u|rXX^k@gT7cxz z7*7B(lVv4RNd071<7GMIl)1AYMI#qkMaPCC=Ik=3&18f+4p42Dy}*`FiQJX6x=m^P z|76uyvKlsJHEzzzY0Wlh;!%^#T?5yt{}iT*%)ksdr#lWZ@E>#7qRe6a5_#nLx2aU> z<9l9ngIaE&a`yGIesB5_JLBDR+lXg52kvP#;m096{-mc7|H0JZ7Z0>qfBgclT>S9< z)#>}MeTw%UIEAltT5BHMnOM1eapg+>WIQ4C4@;*W+_|JyU}}c&U!6Q=t7$yc-G%!@ zPCUKChJWr(D2Y}0hY+vEk3&9{v)CixH+*%ZGt(Aq5AF#Bf*s1gyG;?|!FlH{?BPu_ zfA&72eIj{0MI&h$8y*+V+t8Vj^th0eb}7!eqJeBg5vIeZ4Py#ZjN^3J3uE}r@KLXy zE}AuZ6cw$SPYQ`$3LA5gX2{?`BwXtn6_SEDED3`eYcQ$Ma3(Suu%C>JDQS?jQo-Vy zh;qn^LMol85EAi}gz2accSm>DOGFYeFDq|0l~&I35-26;DAXUqx0-h2&!cbc{ju-a zxBXMS@9bFSw=ePAKMGCf?(*Tq=i(Fgd+yd{clVOJ`%C-cvFE>czc67d89+nRqS5^m z9y$_(wfM6mTMkka?GiG^$9uiUd?-AER&< z35d3CXkKD`ZcfIFk`X@l|{?=7*CrcVoAq`-Bc2f~z_}g^1}W(JD~t!SD4?{SC17 BcF+I- diff --git a/app.py b/app.py index 4ab56bb..f938eb7 100644 --- a/app.py +++ b/app.py @@ -461,33 +461,26 @@ def generate_document(): example: DOC202411260001 documentName: type: string - description: 文档名称 - example: 请示报告卡_张三.docx - inputData: - type: array - description: 输入数据 + description: 文档名称(第一个生成的文档名称) + example: 初步核实审批表_张三.docx fpolicFieldParamFileList: type: array - description: 文件列表(包含filePath) + description: 生成的文档列表(数量与请求一致) items: type: object properties: fileId: type: integer - description: 文件ID + description: 文件ID(与请求中的fileId一致) example: 1 fileName: type: string - description: 文件名称 - example: 请示报告卡.doc - templateCode: - type: string - description: 模板编码 - example: PRELIMINARY_VERIFICATION_APPROVAL + description: 实际生成的文档名称(.docx格式),与请求中的fileName可能不同 + example: 初步核实审批表_张三.docx filePath: type: string - description: MinIO相对路径 - example: /202511261123/请示报告卡.doc + description: MinIO相对路径(指向生成的文档文件) + example: /615873064429507639/20251205090700/初步核实审批表_张三.docx msg: type: string example: ok @@ -561,13 +554,13 @@ def generate_document(): if field_code: field_data[field_code] = field_value or '' - # 生成文档ID和文档名称(使用第一个文件) + # 生成文档ID document_id = document_service.generate_document_id() - first_file_name = file_list[0].get('fileName', 'document.docx') if file_list else 'document.docx' - document_name = document_service.generate_document_name(first_file_name, field_data) # 处理每个文件 result_file_list = [] + first_document_name = None # 用于存储第一个生成的文档名 + for file_info in file_list: file_id = file_info.get('fileId') file_name = file_info.get('fileName', '') @@ -584,9 +577,16 @@ def generate_document(): file_info=file_info ) + # 使用生成的文档名称(.docx格式),而不是原始文件名 + generated_file_name = result.get('fileName', file_name) + + # 保存第一个文档名作为 documentName + if first_document_name is None: + first_document_name = generated_file_name + result_file_list.append({ 'fileId': file_id, - 'fileName': file_name, + 'fileName': generated_file_name, # 使用生成的文档名 'filePath': result['filePath'] }) @@ -601,11 +601,10 @@ def generate_document(): else: return error_response(3001, f"文件生成失败: {error_msg}") - # 构建返回数据 + # 构建返回数据(不包含inputData,只返回生成的文档信息) return success_response({ 'documentId': document_id, - 'documentName': document_name, - 'inputData': input_data, + 'documentName': first_document_name or 'generated.docx', # 使用第一个生成的文档名 'fpolicFieldParamFileList': result_file_list }) diff --git a/check_minio_files.py b/check_minio_files.py new file mode 100644 index 0000000..4876e09 --- /dev/null +++ b/check_minio_files.py @@ -0,0 +1,132 @@ +""" +检查MinIO中是否有测试文件,并列出所有文件 +""" +from minio import Minio +from datetime import datetime +import os + +# MinIO连接配置 +MINIO_CONFIG = { + 'endpoint': 'minio.datacubeworld.com:9000', + 'access_key': 'JOLXFXny3avFSzB0uRA5', + 'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I', + 'secure': True +} + +BUCKET_NAME = 'finyx' +TENANT_ID = '615873064429507639' + +def check_test_files(): + """检查测试文件是否存在""" + print("="*60) + print("检查MinIO中的测试文件") + print("="*60) + + try: + # 创建MinIO客户端 + client = Minio( + MINIO_CONFIG['endpoint'], + access_key=MINIO_CONFIG['access_key'], + secret_key=MINIO_CONFIG['secret_key'], + secure=MINIO_CONFIG['secure'] + ) + + # 检查存储桶 + if not client.bucket_exists(BUCKET_NAME): + print(f"✗ 存储桶 '{BUCKET_NAME}' 不存在") + return + + print(f"\n✓ 存储桶 '{BUCKET_NAME}' 存在") + + # 查找测试文件(TEST目录下的文件) + print(f"\n查找测试文件(路径包含 TEST)...") + test_files = [] + + objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/TEST/", recursive=True) + for obj in objects: + test_files.append({ + 'name': obj.object_name, + 'size': obj.size, + 'last_modified': obj.last_modified + }) + + if test_files: + print(f"\n找到 {len(test_files)} 个测试文件:") + for i, file_info in enumerate(test_files, 1): + print(f"\n{i}. 文件名称: {file_info['name']}") + print(f" 大小: {file_info['size']} 字节") + print(f" 修改时间: {file_info['last_modified']}") + + # 生成访问URL + from datetime import timedelta + url = client.presigned_get_object( + BUCKET_NAME, + file_info['name'], + expires=timedelta(days=7) + ) + print(f" 访问URL: {url[:100]}...") + else: + print("\n⚠ 未找到测试文件") + print(" 可能原因:") + print(" 1. 文件已被删除") + print(" 2. 文件路径不同") + print(" 3. 文件在其他位置") + + # 列出所有与TENANT_ID相关的文件 + print(f"\n" + "="*60) + print(f"列出所有与租户 {TENANT_ID} 相关的文件") + print("="*60) + + all_files = [] + objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/", recursive=True) + for obj in objects: + all_files.append({ + 'name': obj.object_name, + 'size': obj.size, + 'last_modified': obj.last_modified + }) + + if all_files: + print(f"\n找到 {len(all_files)} 个文件:") + for i, file_info in enumerate(all_files[:20], 1): # 只显示前20个 + print(f"\n{i}. {file_info['name']}") + print(f" 大小: {file_info['size']} 字节") + print(f" 修改时间: {file_info['last_modified']}") + + if len(all_files) > 20: + print(f"\n... 还有 {len(all_files) - 20} 个文件未显示") + else: + print(f"\n⚠ 未找到与租户 {TENANT_ID} 相关的文件") + + # 检查是否有TEMPLATE目录 + print(f"\n" + "="*60) + print("检查模板文件") + print("="*60) + + template_files = [] + objects = client.list_objects(BUCKET_NAME, prefix=f"{TENANT_ID}/TEMPLATE/", recursive=True) + for obj in objects: + template_files.append({ + 'name': obj.object_name, + 'size': obj.size, + 'last_modified': obj.last_modified + }) + + if template_files: + print(f"\n找到 {len(template_files)} 个模板文件:") + for i, file_info in enumerate(template_files, 1): + print(f"\n{i}. {file_info['name']}") + print(f" 大小: {file_info['size']} 字节") + print(f" 修改时间: {file_info['last_modified']}") + else: + print(f"\n⚠ 未找到模板文件") + print(f" 模板文件应该在: {TENANT_ID}/TEMPLATE/ 目录下") + + except Exception as e: + print(f"\n✗ 检查失败: {e}") + import traceback + traceback.print_exc() + +if __name__ == '__main__': + check_test_files() + diff --git a/get_template_url.py b/get_template_url.py new file mode 100644 index 0000000..49ba57d --- /dev/null +++ b/get_template_url.py @@ -0,0 +1,117 @@ +""" +获取模板文件的下载链接 +""" +from minio import Minio +from datetime import timedelta +import requests + +# MinIO连接配置 +MINIO_CONFIG = { + 'endpoint': 'minio.datacubeworld.com:9000', + 'access_key': 'JOLXFXny3avFSzB0uRA5', + 'secret_key': 'G1BR8jStNfovkfH5ou39EmPl34E4l7dGrnd3Cz0I', + 'secure': True +} + +BUCKET_NAME = 'finyx' +OBJECT_NAME = '615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx' + +def get_template_url(): + """生成模板文件的下载链接""" + print("="*60) + print("获取模板文件下载链接") + print("="*60) + + try: + # 创建MinIO客户端 + client = Minio( + MINIO_CONFIG['endpoint'], + access_key=MINIO_CONFIG['access_key'], + secret_key=MINIO_CONFIG['secret_key'], + secure=MINIO_CONFIG['secure'] + ) + + # 检查文件是否存在 + print(f"\n检查文件是否存在...") + try: + stat = client.stat_object(BUCKET_NAME, OBJECT_NAME) + print(f"✓ 文件存在") + print(f" 文件名: {OBJECT_NAME}") + print(f" 文件大小: {stat.size} 字节") + print(f" 最后修改: {stat.last_modified}") + print(f" 内容类型: {stat.content_type}") + except Exception as e: + print(f"✗ 文件不存在或无法访问: {e}") + return + + # 生成预签名URL(7天有效期) + print(f"\n生成预签名URL(7天有效)...") + url = client.presigned_get_object( + BUCKET_NAME, + OBJECT_NAME, + expires=timedelta(days=7) + ) + + print(f"\n" + "="*60) + print("下载链接(7天有效)") + print("="*60) + print(f"\n{url}\n") + + # 生成公共URL(如果存储桶是公共的) + protocol = "https" if MINIO_CONFIG['secure'] else "http" + public_url = f"{protocol}://{MINIO_CONFIG['endpoint']}/{BUCKET_NAME}/{OBJECT_NAME}" + + print("="*60) + print("公共URL(如果存储桶是公共的)") + print("="*60) + print(f"\n{public_url}\n") + + # 测试下载 + print("="*60) + print("测试下载链接") + print("="*60) + + print(f"\n正在测试预签名URL...") + try: + response = requests.get(url, timeout=10, stream=True) + if response.status_code == 200: + print(f"✓ 预签名URL可以正常下载") + print(f" 状态码: {response.status_code}") + print(f" 内容长度: {len(response.content)} 字节") + print(f" 内容类型: {response.headers.get('Content-Type', 'N/A')}") + else: + print(f"✗ 下载失败,状态码: {response.status_code}") + except Exception as e: + print(f"✗ 下载测试失败: {e}") + + print("\n" + "="*60) + print("使用说明") + print("="*60) + print("\n1. 预签名URL(推荐):") + print(f" {url}") + print("\n 特点:") + print(" - 安全,带有签名验证") + print(" - 有效期:7天") + print(" - 可以直接在浏览器中打开下载") + + print("\n2. 公共URL(如果存储桶是公共的):") + print(f" {public_url}") + print("\n 特点:") + print(" - 需要存储桶设置为公共访问") + print(" - 永久有效(如果存储桶保持公共)") + + print("\n" + "="*60) + print("完成") + print("="*60) + + return url, public_url + + except Exception as e: + print(f"\n✗ 错误: {e}") + import traceback + traceback.print_exc() + return None, None + +if __name__ == '__main__': + get_template_url() + diff --git a/services/__pycache__/document_service.cpython-312.pyc b/services/__pycache__/document_service.cpython-312.pyc index 0d27b181ce19cbed5dbf951a7ccafacc7aee6d0d..2c8066369f5a1865b9ad46b94e53cf2de297ca9b 100644 GIT binary patch delta 682 zcmaEoa3qoMG%qg~0}wnYGRkDr+Q@fWk*R}uaxItC=C6u|jGo*ztgD$o@(c{MJT(ki zybv}rS;JMs16RXa!&}3X!ZnAfhO@}Dgb$`JOJK60gz#h~9^uLP%KVJ{lmCm$09jl@ zj0`ngMdnx)-i0f?tIRc7SVfx~t8pqw#!X(TB92wnTevEqS(}wrA2TZQrl;nm7A2OX zrs$>QCu=g@;z-NPNexIW$tY?CI$M)_vZA`=($LA&Hrrr{U8-x%nas(Pt405l+SDxnL`u}flIe&MlZzSa5lbc)Th^lt zO74uzN0migEm@9QFoM{YOs=->|;uzZWb)Z%t7MEESTJE*pFGU1KE==u#0V$ z(o$k%WSMNM?Z#Tv3-rq7>Dp@<8G9$Y>T0nUwF3pJ)F$6mS7ZYR1Lx!ox<|SDfucoI zKt%iG2EEnlmaLL1ia#&_sRJwrLJo3)nHR#NA#_5@XOPr~vdKaEc8v2TPt@;VTsm3G Tz?$Eeg;Dzx1Bfg#0h$H?{M)$Y delta 634 zcmX?-_#}bvG%qg~0}zBc7-qiE*vNNUktvCJaxItC=C6u|jEY<}+^d;D@(c{MJSki? zJeiC&oJFQ3JP^7)i*f9B!iUOu$MpX<`H+!l+W|ZbjPt8j$N-RlD(M!osuDHdKmYI_p zkXVwT$u-$mU2<}rx&kBb%+w|&eeXelu=GECmD?Ivk%_{+`sZyIfOIwK*q?~oK zfZkE=9#9ZW1Q9bQKhRsPZptdTqWA*?kUGF}Amktyn0X;Q8bT+ed 10: + print(f" ... 还有更多对象(总共可能超过10个)") + + print_result(True, f"成功列出对象(显示前10个)") + + except Exception as e: + print_result(False, f"列出对象失败: {str(e)}") + import traceback + traceback.print_exc() + +def cleanup_test_file(local_file_path): + """清理测试文件""" + try: + if local_file_path and os.path.exists(local_file_path): + os.unlink(local_file_path) + print(f"\n✓ 已清理测试文件: {local_file_path}") + except Exception as e: + print(f"\n⚠ 清理测试文件失败: {e}") + +def main(): + """主函数""" + print("\n" + "="*60) + print(" MinIO连接测试") + print("="*60) + print(f"\n配置信息:") + print(f" 端点: {MINIO_CONFIG['endpoint']}") + print(f" 使用HTTPS: {MINIO_CONFIG['secure']}") + print(f" 存储桶: {BUCKET_NAME}") + print(f" 访问密钥: {MINIO_CONFIG['access_key']}") + + test_file_path = None + object_name = None + + try: + # 1. 测试连接 + client, bucket_exists = test_connection() + + if not client: + print("\n✗ 连接失败,无法继续测试") + return + + # 2. 列出对象 + test_list_objects(client) + + # 3. 创建测试文件 + test_file_path = create_test_file() + + # 4. 上传文件 + object_name, relative_path = upload_file(client, test_file_path, bucket_exists) + + # 5. 生成访问URL + access_url = generate_access_url(client, object_name) + + # 6. 测试下载 + download_success = test_download(access_url) + + # 总结 + print_section("测试总结") + + results = { + '连接': client is not None, + '存储桶存在': bucket_exists, + '文件上传': object_name is not None, + 'URL生成': access_url is not None, + 'URL下载': download_success + } + + print("\n测试结果:") + for test_name, success in results.items(): + status = "✓ 通过" if success else "✗ 失败" + print(f" {test_name}: {status}") + + passed = sum(1 for v in results.values() if v) + total = len(results) + + print(f"\n通过率: {passed}/{total} ({passed*100//total if total > 0 else 0}%)") + + if passed == total: + print("\n✓ 所有测试通过!MinIO配置正确,可以正常使用。") + else: + print("\n⚠ 部分测试失败,请检查配置和网络连接。") + + # 显示使用建议 + if object_name: + print("\n" + "="*60) + print(" 使用建议") + print("="*60) + print(f"\n上传的文件路径(用于数据库存储):") + print(f" {relative_path}") + print(f"\n访问URL(预签名,7天有效):") + print(f" {access_url}") + + except KeyboardInterrupt: + print("\n\n测试已中断") + except Exception as e: + print(f"\n✗ 测试过程中发生错误: {e}") + import traceback + traceback.print_exc() + finally: + # 清理测试文件 + if test_file_path: + cleanup_test_file(test_file_path) + +if __name__ == '__main__': + main() + diff --git a/技术文档/智慧监督AI文书写作接口定义-20251204-2.md b/技术文档/智慧监督AI文书写作接口定义-20251204-2.md new file mode 100644 index 0000000..a8ade83 --- /dev/null +++ b/技术文档/智慧监督AI文书写作接口定义-20251204-2.md @@ -0,0 +1,424 @@ +# 修订历史 + +## V 0.3,李季修订(2025-12-05) + +### 主要调整内容 + +#### 1. **文档生成接口优化** +- 返回的 `fileName` 为实际生成的文档名称(.docx格式),而不是请求中的原始文件名 +- 返回的 `filePath` 指向实际生成的文档路径 +- 移除返回数据中的 `inputData`,只返回文档生成相关信息 +- 返回的文档数量与请求的文档数量一致 + +#### 2. **文档名称生成规则** +- 生成的文档名称为:`{基础名称}_{被核查人姓名}.docx` +- 如果没有被核查人姓名,则生成:`{基础名称}.docx` +- 所有生成的文档统一为 `.docx` 格式 + +## V 0.2,李季修订 + +### 主要调整内容 + +#### 1. **接口路径优化** + +- `/paras`→ `/ai/extract` +- `/getDocument`→ `/ai/generate-document` +- *理由:更清晰的语义化路径* + +#### 2. **字段名修正** + +- `filedCode`→ `fieldCode` +- `filedVal`→ `fieldValue` +- *理由:修正拼写错误,保持专业规范* + +#### 3. **关键参数补充** + +**新增参数:** + +- `templateCode`:文档模板标识 +- `businessType`:业务类型分类 +- `documentId`:文档唯一标识 +- `documentName`:生成文档名称 + +#### 4. **返回结构增强** + +- **解析接口**:保持简洁,去除置信度等复杂字段 +- **生成接口**:增加`documentId`和`documentName`,完善文件信息 + +#### 5. **文件路径调整** + +- 返回MinIO相对路径(如`/202511261123/请示报告卡.doc`) +- *理由:使用相对路径,客户端可根据MinIO配置拼接完整URL* + +#### 6. **错误码规范化** + +- 明确业务相关错误码(模板不存在、占位符匹配失败等) + +## V 0.1,陈涛提供 + +--- + +# 1. 解析接口 + +**地址**: `/ai/extract` + +**请求方法**: POST + +**请求参数**: + +```json +{ + "inputData": [ + { + "fieldCode": "clue_info", + "fieldValue": "被举报用户名称是张三,年龄30岁,某公司总经理" + } + ], + "outputData": [ + { + "fieldCode": "target_name" + }, + { + "fieldCode": "target_gender" + } + ] +} +``` + +**返回参数**: + +```json +{ + "code": 0, + "data": { + "outData": [ + { + "fieldCode": "target_name", + "fieldValue": "张三" + }, + { + "fieldCode": "target_gender", + "fieldValue": "男" + } + ] + }, + "msg": "ok", + "path": null, + "extra": null, + "timestamp": "1764204337101", + "errorMsg": "", + "isSuccess": true +} +``` + +--- + +# 2. 文档生成接口 + +**地址**: `/ai/generate-document` + +**请求方法**: POST + +**请求参数**: + +```json +{ + "inputData": [ + { + "fieldCode": "target_name", + "fieldValue": "张三" + }, + { + "fieldCode": "target_gender", + "fieldValue": "男" + }, + { + "fieldCode": "target_organization_and_position", + "fieldValue": "某公司总经理" + } + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + } + ] +} +``` + +**返回参数**: + +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + } + ] + }, + "msg": "ok", + "path": null, + "extra": null, + "timestamp": "1764204337101", + "errorMsg": "", + "isSuccess": true +} +``` + +## 2.1 多文档生成示例 + +如果请求多个文档,返回对应数量的文档: + +**请求参数**: + +```json +{ + "inputData": [ + { + "fieldCode": "target_name", + "fieldValue": "张三" + }, + { + "fieldCode": "target_gender", + "fieldValue": "男" + } + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + }, + { + "fileId": 2, + "fileName": "请示报告卡.doc", + "templateCode": "REPORT_CARD" + } + ] +} +``` + +**返回参数**: + +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + }, + { + "fileId": 2, + "fileName": "请示报告卡_张三.docx", + "filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx" + } + ] + }, + "msg": "ok", + "isSuccess": true +} +``` + +## 2.2 重要说明 + +1. **返回的文档数量**: 与请求中的 `fpolicFieldParamFileList` 数量一致 + - 请求1个文档,返回1个文档 + - 请求多个文档,返回多个文档 + +2. **返回的fileName**: + - 是实际生成的文档名称(.docx格式) + - 不是请求中的原始文件名 + - 格式:`{基础名称}_{被核查人姓名}.docx` 或 `{基础名称}.docx` + +3. **返回的filePath**: + - MinIO相对路径 + - 指向实际生成的文档文件 + - 格式:`/租户ID/时间戳/文档名称.docx` + +4. **文档名称生成规则**: + - 基础名称:从请求的 `fileName` 中提取(去掉扩展名) + - 如果 `inputData` 中包含 `target_name` 字段,则添加 `_{target_name}` 后缀 + - 最终格式统一为 `.docx` + +--- + +# 3. 错误码定义 + +| 错误码 | 说明 | 处理建议 | +| :----- | :------------- | :------------------------- | +| 0 | 成功 | - | +| 1001 | 模板不存在 | 检查templateCode是否正确 | +| 1002 | 占位符匹配失败 | 检查字段编码与模板是否匹配 | +| 2001 | AI解析超时 | 重新尝试解析 | +| 2002 | 字段识别失败 | 检查输入文本质量 | +| 3001 | 文件生成失败 | 重新尝试生成 | +| 3002 | 文件保存失败 | 检查存储服务状态 | + +--- + +# 4. 字段说明 + +## 4.1 公共字段 + +- `templateCode`: 文档模板编码(必填) +- `fieldCode`: 字段编码(需与Word模板中占位符一致) +- `fieldValue`: 字段值 + +## 4.2 文件相关字段 + +- `fileId`: 文件唯一标识(请求和返回中保持一致) +- `fileName`: + - **请求中**: 原始文件名称(如 `初步核实审批表.doc`) + - **返回中**: 实际生成的文档名称(如 `初步核实审批表_张三.docx`) +- `filePath`: MinIO存储的相对路径(返回中提供) + +## 4.3 返回字段 + +- `documentId`: 文档生成批次ID +- `documentName`: 第一个文档的生成名称(用于展示) + +--- + +# 5. 使用流程 + +1. **解析阶段**: 调用 `/ai/extract`接口,输入用户描述文本,AI提取结构化数据 +2. **生成阶段**: 调用 `/ai/generate-document`接口,传入解析结果和模板信息,生成填充后的文档 +3. **下载文档**: 通过返回的filePath使用MinIO预签名URL或客户端拼接完整路径获取生成的文件 + +--- + +# 6. 注意事项 + +1. 字段编码(fieldCode)需与Word模板中的占位符严格对应 +2. 未识别的字段在生成文档时会自动留空 +3. 返回的filePath为MinIO相对路径,需要客户端拼接MinIO访问地址 +4. 生成的文档统一为.docx格式,即使请求中的文件名为.doc +5. 如果某个文档生成失败,整个请求会返回错误,不会部分成功 +6. 返回的文档数量与请求数量一致,每个文档都有独立的fileId和filePath + +--- + +# 7. 示例调用顺序 + +```json +// 1. 解析调用 +请求: POST /ai/extract +{ + "inputData": [ + {"fieldCode": "clue_info", "fieldValue": "被举报用户名称是张三,年龄30岁"} + ], + "outputData": [ + {"fieldCode": "target_name"}, + {"fieldCode": "target_gender"} + ] +} + +响应: +{ + "code": 0, + "data": { + "outData": [ + {"fieldCode": "target_name", "fieldValue": "张三"}, + {"fieldCode": "target_gender", "fieldValue": "男"} + ] + }, + "isSuccess": true +} + +// 2. 生成调用(单文档) +请求: POST /ai/generate-document +{ + "inputData": [ + {"fieldCode": "target_name", "fieldValue": "张三"}, + {"fieldCode": "target_gender", "fieldValue": "男"} + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + } + ] +} + +响应: +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + } + ] + }, + "isSuccess": true +} + +// 3. 生成调用(多文档) +请求: POST /ai/generate-document +{ + "inputData": [ + {"fieldCode": "target_name", "fieldValue": "张三"}, + {"fieldCode": "target_gender", "fieldValue": "男"} + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + }, + { + "fileId": 2, + "fileName": "请示报告卡.doc", + "templateCode": "REPORT_CARD" + } + ] +} + +响应: +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659149", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + }, + { + "fileId": 2, + "fileName": "请示报告卡_张三.docx", + "filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx" + } + ] + }, + "isSuccess": true +} +``` + +--- + +# 8. 版本说明 + +- **V 0.3**: 优化文档生成接口返回结构,返回实际生成的文档名称和路径 +- **V 0.2**: 接口路径优化,字段名修正,参数补充 +- **V 0.1**: 初始版本 + diff --git a/接口调整完成总结.md b/接口调整完成总结.md new file mode 100644 index 0000000..0c5b385 --- /dev/null +++ b/接口调整完成总结.md @@ -0,0 +1,158 @@ +# 文档生成接口调整完成总结 + +## ✅ 所有调整已完成 + +### 1. 代码调整 + +#### ✅ `services/document_service.py` +- 修改 `generate_document` 方法,返回生成的文档名称 +- 使用 `generate_document_name` 方法生成文档名(.docx格式) +- 返回结果包含 `fileName` 和 `filePath` + +#### ✅ `app.py` +- 修改文档生成接口,使用生成的文档名称而不是原始文件名 +- 移除返回数据中的 `inputData` +- 使用第一个生成的文档名作为 `documentName` +- 返回的文档数量与请求数量一致 + +### 2. 接口文档更新 + +#### ✅ `技术文档/智慧监督AI文书写作接口定义-20251204-2.md` +- 新增V 0.3版本说明 +- 详细说明返回结构变化 +- 提供单文档和多文档生成示例 +- 说明文档名称生成规则 + +#### ✅ Swagger文档更新 +- 更新返回结构的说明 +- 移除 `inputData` 字段说明 +- 更新 `fileName` 和 `filePath` 的说明和示例 + +--- + +## 📋 调整前后对比 + +### 请求数据(不变) + +```json +{ + "inputData": [ + { + "fieldCode": "target_name", + "fieldValue": "张三" + } + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + } + ] +} +``` + +### 返回数据对比 + +#### ❌ 调整前 + +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "inputData": [...], // ❌ 不应该返回请求数据 + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", // ❌ 使用原始文件名 + "filePath": "/615873064429507639/20251205090700/初步核实审批表.doc" + } + ] + } +} +``` + +#### ✅ 调整后 + +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", // ✅ 使用生成的文档名 + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" // ✅ 指向生成的文档 + } + ] + } +} +``` + +--- + +## 🎯 核心改进 + +### 1. 返回的fileName +- ✅ 使用实际生成的文档名称 +- ✅ 格式统一为 `.docx` +- ✅ 包含被核查人姓名(如果有) + +### 2. 返回的filePath +- ✅ 指向实际生成的文档文件 +- ✅ 使用生成的文档名 +- ✅ MinIO相对路径格式 + +### 3. 返回结构 +- ✅ 移除了 `inputData` +- ✅ 只返回文档生成相关信息 +- ✅ 结构更清晰 + +### 4. 文档数量 +- ✅ 请求1个文档,返回1个文档 +- ✅ 请求多个文档,返回多个文档 +- ✅ 数量完全对应 + +--- + +## 📄 相关文件 + +### 代码文件 +- `app.py` - 接口实现已更新 +- `services/document_service.py` - 文档生成服务已更新 + +### 文档文件 +- `技术文档/智慧监督AI文书写作接口定义-20251204-2.md` - 新接口文档 +- `接口调整说明.md` - 调整说明 +- `接口调整完成总结.md` - 本文档 + +--- + +## 🔍 验证清单 + +- [x] 代码已更新 +- [x] 返回的fileName使用生成的文档名 +- [x] 返回的filePath指向生成的文档 +- [x] 移除了inputData字段 +- [x] 接口文档已更新 +- [x] Swagger文档已更新 +- [x] 支持单文档生成 +- [x] 支持多文档生成 +- [x] 文档数量对应关系正确 + +--- + +## 🚀 下一步 + +1. **测试接口** - 使用更新后的接口进行测试 +2. **验证返回结果** - 确认返回的fileName和filePath正确 +3. **更新客户端代码** - 根据新的返回结构调整客户端代码 + +--- + +**所有调整已完成,可以开始测试!** 🎉 + diff --git a/接口调整说明.md b/接口调整说明.md new file mode 100644 index 0000000..279c82d --- /dev/null +++ b/接口调整说明.md @@ -0,0 +1,212 @@ +# 文档生成接口调整说明 + +## 📋 调整内容 + +### 1. 返回结构优化 + +#### 调整前的问题 +- 返回数据中包含 `inputData`,与请求数据重复 +- 返回的 `fileName` 是请求中的原始文件名(如 `.doc`),而不是实际生成的文档名 +- 返回结构不够清晰 + +#### 调整后的改进 +- ✅ **移除 `inputData`**:返回数据不再包含请求中的输入数据 +- ✅ **返回实际生成的文档名**:`fileName` 为实际生成的文档名称(`.docx` 格式) +- ✅ **返回数量一致**:返回的文档数量与请求的文档数量完全一致 + +--- + +## 📝 调整详情 + +### 1. 返回的 fileName + +**调整前:** +```json +{ + "fileName": "初步核实审批表.doc" // 使用请求中的原始文件名 +} +``` + +**调整后:** +```json +{ + "fileName": "初步核实审批表_张三.docx" // 使用实际生成的文档名 +} +``` + +**文档名称生成规则:** +- 基础名称:从请求的 `fileName` 中提取(去掉扩展名) +- 如果有 `target_name` 字段,添加 `_{target_name}` 后缀 +- 统一格式为 `.docx` + +### 2. 返回的 filePath + +**调整前:** +```json +{ + "filePath": "/615873064429507639/20251205090700/初步核实审批表.doc" +} +``` + +**调整后:** +```json +{ + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" +} +``` + +**说明:** +- 指向实际生成的文档文件 +- 使用生成的文档名作为路径中的文件名 + +### 3. 返回的数据结构 + +**调整前:** +```json +{ + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "inputData": [...], // ❌ 包含请求数据(已移除) + "fpolicFieldParamFileList": [...] +} +``` + +**调整后:** +```json +{ + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", // ✅ 实际生成的文档名 + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + } + ] +} +``` + +--- + +## 🎯 实际效果 + +### 单文档生成示例 + +**请求:** +```json +{ + "inputData": [ + {"fieldCode": "target_name", "fieldValue": "张三"} + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + } + ] +} +``` + +**返回:** +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659148", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + } + ] + }, + "isSuccess": true +} +``` + +### 多文档生成示例 + +**请求:** +```json +{ + "inputData": [ + {"fieldCode": "target_name", "fieldValue": "张三"} + ], + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表.doc", + "templateCode": "PRELIMINARY_VERIFICATION_APPROVAL" + }, + { + "fileId": 2, + "fileName": "请示报告卡.doc", + "templateCode": "REPORT_CARD" + } + ] +} +``` + +**返回:** +```json +{ + "code": 0, + "data": { + "documentId": "DOC20251205090659149", + "documentName": "初步核实审批表_张三.docx", + "fpolicFieldParamFileList": [ + { + "fileId": 1, + "fileName": "初步核实审批表_张三.docx", + "filePath": "/615873064429507639/20251205090700/初步核实审批表_张三.docx" + }, + { + "fileId": 2, + "fileName": "请示报告卡_张三.docx", + "filePath": "/615873064429507639/20251205090700/请示报告卡_张三.docx" + } + ] + }, + "isSuccess": true +} +``` + +--- + +## ✅ 调整总结 + +### 主要改动 + +1. **返回的 `fileName`** + - 从请求的原始文件名改为实际生成的文档名 + - 格式统一为 `.docx` + +2. **返回的 `filePath`** + - 指向实际生成的文档文件 + - 使用生成的文档名 + +3. **返回的数据结构** + - 移除了 `inputData` 字段 + - 只返回文档生成相关信息 + +4. **文档数量一致性** + - 请求1个文档,返回1个文档 + - 请求多个文档,返回多个文档 + - 数量完全对应 + +--- + +## 📚 相关文档 + +- **接口文档**: `技术文档/智慧监督AI文书写作接口定义-20251204-2.md` +- **代码文件**: + - `app.py` - 接口实现 + - `services/document_service.py` - 文档生成服务 + +--- + +**调整完成!** ✅ + diff --git a/文档生成测试结果.md b/文档生成测试结果.md new file mode 100644 index 0000000..01ddb2a --- /dev/null +++ b/文档生成测试结果.md @@ -0,0 +1,125 @@ +# 文档生成测试结果 + +## ✅ 测试成功 + +### 测试时间 +2025-12-05 02:38:12 + +### 测试内容 +使用虚拟数据生成"初步核实审批表" + +--- + +## 📄 生成的文件信息 + +- **文件名称**: `初步核实审批表_张三.docx` +- **文件大小**: 18,142 字节 +- **文件路径**: `/615873064429507639/20251205103812/初步核实审批表_张三.docx` +- **内容类型**: Word文档 (.docx) +- **模板编码**: `PRELIMINARY_VERIFICATION_APPROVAL` + +--- + +## 📥 下载链接 + +### 预签名URL(7天有效) + +``` +https://minio.datacubeworld.com:9000/finyx/615873064429507639/20251205103812/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8_%E5%BC%A0%E4%B8%89.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T023813Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=baa9adc91aa57e2e5ed17ae130c82f93d41bfba57e3edecc81eb3e0715843156 +``` + +**链接有效期**: 7天(从 2025-12-05 02:38:13 起) + +--- + +## 📋 使用的虚拟数据 + +### 字段列表(15个字段) + +1. **target_name**: 张三 +2. **target_gender**: 男 +3. **target_nationality**: 汉族 +4. **target_date_of_birth**: 198005 +5. **target_place_of_birth**: 山西太原 +6. **target_political_status**: 中共党员 +7. **target_education**: 本科学历 +8. **target_organization_and_position**: 某公司总经理 +9. **target_id_number**: 140101198005150123 +10. **target_contact**: 13800138000 +11. **target_address**: 山西省太原市小店区某某街道123号 +12. **clue_source**: 群众举报 +13. **clue_info**: 被举报人利用职务便利,违规接受他人请托,收受他人财物 +14. **investigation_reason**: 根据群众举报,反映被核查人存在违规违纪问题 +15. **investigation_basis**: 《中国共产党纪律检查机关监督执纪工作规则》相关规定 + +--- + +## ✅ 测试结果 + +| 测试项目 | 状态 | 说明 | +|---------|------|------| +| 文档生成 | ✅ 通过 | 成功生成Word文档 | +| 文件验证 | ✅ 通过 | 文件已上传到MinIO并验证存在 | +| URL生成 | ✅ 通过 | 预签名URL生成成功 | +| 下载测试 | ✅ 可用 | URL可以正常访问下载 | + +--- + +## 🚀 使用方法 + +### 方法1:浏览器直接下载 + +1. 复制上面的预签名URL +2. 在浏览器地址栏中粘贴并访问 +3. 浏览器会自动下载文件 + +### 方法2:使用命令行下载 + +**Windows PowerShell:** +```powershell +Invoke-WebRequest -Uri "https://minio.datacubeworld.com:9000/finyx/615873064429507639/20251205103812/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8_%E5%BC%A0%E4%B8%89.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T023813Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=baa9adc91aa57e2e5ed17ae130c82f93d41bfba57e3edecc81eb3e0715843156" -OutFile "初步核实审批表_张三.docx" +``` + +--- + +## 📝 测试说明 + +### 测试脚本 +测试脚本:`test_document_generation.py` + +### 测试流程 + +1. **准备虚拟数据** - 使用15个字段的虚拟数据 +2. **调用文档生成服务** - 使用 `DocumentService.generate_document()` +3. **下载模板** - 从MinIO下载模板文件 +4. **填充数据** - 将虚拟数据填充到Word模板中 +5. **上传文件** - 将生成的文档上传到MinIO +6. **生成URL** - 生成预签名下载URL + +### 测试验证 + +- ✅ 模板文件可以从MinIO下载 +- ✅ 数据可以正确填充到模板 +- ✅ 生成的文档可以上传到MinIO +- ✅ 预签名URL可以正常访问 + +--- + +## 📊 性能信息 + +- **生成时间**: < 5秒 +- **文件大小**: 18,142 字节 +- **存储位置**: MinIO存储桶 `finyx` + +--- + +## ⚠️ 注意事项 + +1. **链接有效期**: 预签名URL有效期为7天 +2. **文件保留**: 文件会保留在MinIO中,不会自动删除 +3. **重新生成**: 如果需要新的链接,可以运行 `test_document_generation.py` 重新生成 + +--- + +**测试完成!文档已成功生成并可以下载!** 🎉 + diff --git a/模板文件下载链接.md b/模板文件下载链接.md new file mode 100644 index 0000000..4763389 --- /dev/null +++ b/模板文件下载链接.md @@ -0,0 +1,86 @@ +# 模板文件下载链接 + +## 文件信息 + +- **文件路径**: `615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx` +- **文件大小**: 21,101 字节 +- **最后修改**: 2025-12-02 06:42:56 +- **文件类型**: Word文档 (.docx) + +--- + +## 📥 下载链接 + +### 1. 预签名URL(推荐,7天有效) + +``` +https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9 +``` + +**特点:** +- ✅ 安全,带有签名验证 +- ✅ 有效期:7天(从生成时间起) +- ✅ 可以直接在浏览器中打开下载 +- ✅ 已验证可以正常下载 + +### 2. 公共URL(如果存储桶是公共的) + +``` +https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/初步核实审批表模板.docx +``` + +**特点:** +- 需要存储桶设置为公共访问 +- 永久有效(如果存储桶保持公共) +- 可能无法直接访问(取决于存储桶策略) + +--- + +## ✅ 下载测试结果 + +- **状态**: ✅ 可以正常下载 +- **HTTP状态码**: 200 +- **文件大小**: 21,101 字节 +- **内容类型**: `application/vnd.openxmlformats-officedocument.wordprocessingml.document` + +--- + +## 🚀 使用方法 + +### 方法1:浏览器直接下载 + +1. 复制上面的预签名URL +2. 在浏览器地址栏中粘贴并访问 +3. 浏览器会自动下载文件 + +### 方法2:使用命令行下载(Windows PowerShell) + +```powershell +Invoke-WebRequest -Uri "https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9" -OutFile "初步核实审批表模板.docx" +``` + +### 方法3:使用curl + +```bash +curl -o "初步核实审批表模板.docx" "https://minio.datacubeworld.com:9000/finyx/615873064429507639/TEMPLATE/2025/12/%E5%88%9D%E6%AD%A5%E6%A0%B8%E5%AE%9E%E5%AE%A1%E6%89%B9%E8%A1%A8%E6%A8%A1%E6%9D%BF.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JOLXFXny3avFSzB0uRA5%2F20251205%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251205T022430Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=2f80070167b111aeaa7c11b9742e38a60a3c7a8632235ed692ed497ed66fffc9" +``` + +--- + +## 📝 注意事项 + +1. **预签名URL有效期**: 7天(604800秒) + - 生成时间: 2025-12-05 02:24:30 + - 过期时间: 2025-12-12 02:24:30 + +2. **URL更新**: 如果链接过期,可以运行以下命令重新生成: + ```bash + python get_template_url.py + ``` + +3. **文件验证**: 下载后可以验证文件大小是否为 21,101 字节 + +--- + +**链接已验证可用,可以直接使用!** ✅ +