Files
hzdyjs/test_overseas_attachment.py
T
2025-10-14 16:41:19 +08:00

311 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
出国申请附件功能诊断脚本
用于测试附件接口和排查附件内容不显示的问题
"""
import requests
import json
import sys
from datetime import datetime
from Crypto.Cipher import AES, PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
import base64
import hashlib
# ==================== 配置区 ====================
BASE_URL = "http://localhost:8080"
USERNAME = "admin" # 请修改为实际用户名
PASSWORD = "admin123" # 请修改为实际密码
# RSA公钥(需要从后端获取)
PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpSA3zw+7sCf6M9yZzH4p4V4i/
ktlKPMwReLYQz0MdIj7v0xnP9h/EhGClQKJzU6EZNx8ZX8P2xVLIVMqD8pqKXLxX
j6SLvSKJKvFPPCF7P3rKqW8Y4aNwXZvFKQXlWUmE5lEJpH6P8RqYXZ0XHQZ1iyKK
CqMZXGLH1Q0PJKWmDQIDAQAB
-----END PUBLIC KEY-----"""
# ==================== 加密工具函数 ====================
def generate_aes_key():
"""生成AES密钥"""
return get_random_bytes(16)
def aes_encrypt(data, key):
"""AES加密"""
cipher = AES.new(key, AES.MODE_ECB)
# PKCS7 padding
padding_length = 16 - len(data) % 16
padded_data = data + chr(padding_length) * padding_length
encrypted = cipher.encrypt(padded_data.encode('utf-8'))
return base64.b64encode(encrypted).decode('utf-8')
def rsa_encrypt(data, public_key):
"""RSA加密"""
rsa_key = RSA.import_key(public_key)
cipher = PKCS1_v1_5.new(rsa_key)
encrypted = cipher.encrypt(data)
return base64.b64encode(encrypted).decode('utf-8')
# ==================== API请求函数 ====================
class APIClient:
def __init__(self, base_url):
self.base_url = base_url
self.token = None
self.headers = {
'Content-Type': 'application/json',
'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e',
'referer': 'http://localhost'
}
def login(self, username, password):
"""登录获取token"""
print("=" * 60)
print("【步骤1】用户登录")
print("=" * 60)
try:
# 生成AES密钥
aes_key = generate_aes_key()
aes_key_str = base64.b64encode(aes_key).decode('utf-8')
# AES加密用户名和密码
encrypted_username = aes_encrypt(username, aes_key)
encrypted_password = aes_encrypt(password, aes_key)
# RSA加密AES密钥
encrypted_aes_key = rsa_encrypt(aes_key, PUBLIC_KEY)
# 构建登录请求
login_data = {
"username": encrypted_username,
"password": encrypted_password,
"key": encrypted_aes_key,
"code": "",
"uuid": ""
}
print(f"请求URL: {self.base_url}/auth/login")
print(f"用户名: {username}")
response = requests.post(
f"{self.base_url}/auth/login",
headers=self.headers,
json=login_data
)
result = response.json()
print(f"响应状态码: {response.status_code}")
print(f"响应内容: {json.dumps(result, ensure_ascii=False, indent=2)}")
if result.get('code') == 200 and 'data' in result:
self.token = result['data'].get('access_token')
self.headers['Authorization'] = f"Bearer {self.token}"
print(f"✅ 登录成功!Token: {self.token[:50]}...")
return True
else:
print(f"❌ 登录失败: {result.get('msg', '未知错误')}")
return False
except Exception as e:
print(f"❌ 登录异常: {str(e)}")
import traceback
traceback.print_exc()
return False
def get(self, url, params=None):
"""发送GET请求"""
try:
response = requests.get(
f"{self.base_url}{url}",
headers=self.headers,
params=params
)
return response.json()
except Exception as e:
print(f"❌ 请求异常: {str(e)}")
return None
def post(self, url, data=None):
"""发送POST请求"""
try:
response = requests.post(
f"{self.base_url}{url}",
headers=self.headers,
json=data
)
return response.json()
except Exception as e:
print(f"❌ 请求异常: {str(e)}")
return None
# ==================== 测试函数 ====================
def test_overseas_attachment(client):
"""测试出国申请附件功能"""
print("\n" + "=" * 60)
print("【步骤2】查询出国申请列表")
print("=" * 60)
# 查询申请列表
result = client.get("/rs/overseas/application/list", {
"pageNum": 1,
"pageSize": 10
})
if not result or result.get('code') != 200:
print(f"❌ 查询申请列表失败: {result.get('msg') if result else '请求失败'}")
return
rows = result.get('rows', [])
if not rows:
print("❌ 没有找到任何出国申请记录")
print("💡 建议:请先创建一条出国申请记录")
return
print(f"✅ 找到 {len(rows)} 条申请记录")
# 显示前5条记录
print("\n申请记录列表(前5条):")
for i, app in enumerate(rows[:5], 1):
print(f"{i}. ID={app.get('applicationId')}, "
f"申请人={app.get('applicantName')}, "
f"目的地={app.get('destination')}, "
f"状态={app.get('statusText')}")
# 选择第一条记录进行测试
test_application = rows[0]
application_id = test_application.get('applicationId')
print("\n" + "=" * 60)
print(f"【步骤3】查询申请详情(ID: {application_id})")
print("=" * 60)
detail_result = client.get(f"/rs/overseas/application/detail/{application_id}")
if not detail_result or detail_result.get('code') != 200:
print(f"❌ 查询申请详情失败: {detail_result.get('msg') if detail_result else '请求失败'}")
return
detail_data = detail_result.get('data', {})
print(f"✅ 申请详情查询成功")
print(f"申请人: {detail_data.get('applicantName')}")
print(f"目的地: {detail_data.get('destination')}")
print(f"开始日期: {detail_data.get('startDate')}")
print(f"结束日期: {detail_data.get('endDate')}")
print("\n" + "=" * 60)
print(f"【步骤4】查询附件列表(申请ID: {application_id})")
print("=" * 60)
attachment_result = client.get(f"/rs/overseas/attachment/list/{application_id}")
print(f"请求URL: {BASE_URL}/rs/overseas/attachment/list/{application_id}")
print(f"请求头: {json.dumps({k: v[:50] + '...' if len(v) > 50 else v for k, v in client.headers.items()}, ensure_ascii=False, indent=2)}")
if not attachment_result:
print("❌ 附件接口请求失败")
return
print(f"\n响应内容:")
print(json.dumps(attachment_result, ensure_ascii=False, indent=2))
if attachment_result.get('code') != 200:
print(f"\n❌ 查询附件列表失败")
print(f"错误代码: {attachment_result.get('code')}")
print(f"错误信息: {attachment_result.get('msg')}")
# 检查是否是权限问题
if attachment_result.get('code') in [401, 403]:
print("\n⚠️ 这是权限问题!")
print("请检查以下几点:")
print("1. 当前用户是否有 'rs:overseas:query' 权限")
print("2. 菜单权限配置是否正确")
print("3. 角色权限是否已授予")
return
attachment_list = attachment_result.get('data', [])
print(f"\n✅ 附件列表查询成功")
print(f"附件数量: {len(attachment_list)}")
if not attachment_list:
print("\n⚠️ 该申请暂无附件")
print("💡 建议:")
print("1. 在前端点击'添加附件'按钮上传附件")
print("2. 或使用API直接上传附件进行测试")
else:
print("\n附件列表详情:")
print("-" * 100)
for i, attachment in enumerate(attachment_list, 1):
print(f"\n附件 {i}:")
print(f" - 附件ID: {attachment.get('attachmentId')}")
print(f" - 附件标题: {attachment.get('attachmentTitle')}")
print(f" - 附件说明: {attachment.get('attachmentContent', '无')}")
print(f" - 原始文件名: {attachment.get('fileOriginalName')}")
print(f" - 文件名: {attachment.get('fileName')}")
print(f" - 文件路径: {attachment.get('filePath')}")
print(f" - 文件大小: {attachment.get('fileSizeFormatted', attachment.get('fileSize'))}")
print(f" - MIME类型: {attachment.get('mimeType', '未知')}")
print(f" - 上传时间: {attachment.get('uploadTime', '未知')}")
print(f" - 上传人: {attachment.get('uploadUserName', '未知')}")
print("\n" + "=" * 60)
print("【诊断结果】")
print("=" * 60)
if not attachment_list:
print("🔍 问题原因分析:")
print("1. 该申请确实没有附件数据")
print("2. 附件接口返回正常,但数据为空")
print("\n🔧 解决方案:")
print("1. 请在前端点击'添加附件'按钮上传附件")
print("2. 确认附件上传后,再次查看详情")
else:
print("✅ 附件数据存在且接口返回正常")
print("\n🔍 如果前端仍然看不到附件,可能的原因:")
print("1. 前端组件的数据绑定问题")
print("2. Vue响应式数据未更新")
print("3. 条件渲染判断错误")
print("4. 浏览器控制台可能有JavaScript错误")
print("\n🔧 建议检查:")
print("1. 打开浏览器F12开发者工具")
print("2. 查看Console标签页是否有错误")
print("3. 查看Network标签页确认API请求是否成功")
print("4. 检查Vue Devtools中viewAttachmentList的值")
def main():
"""主函数"""
print("=" * 60)
print("出国申请附件功能诊断脚本")
print("=" * 60)
print(f"基础URL: {BASE_URL}")
print(f"用户名: {USERNAME}")
print(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
# 创建API客户端
client = APIClient(BASE_URL)
# 登录
if not client.login(USERNAME, PASSWORD):
print("\n❌ 登录失败,无法继续测试")
sys.exit(1)
# 测试附件功能
test_overseas_attachment(client)
print("\n" + "=" * 60)
print("诊断完成")
print("=" * 60)
if __name__ == "__main__":
main()