Files
hzdyjs/test/附件上传功能测试.js
T
2025-06-30 20:33:58 +08:00

357 lines
12 KiB
JavaScript

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const colors = require('colors');
/**
* 附件上传功能测试脚本
* 功能:测试新增报修单时附件是否能正确上传并记录到数据库
* 作者:wuzilong/Cursor AI辅助
* 时间:2025-06-30 19:15:00
*/
// 配置信息
const CONFIG = {
baseURL: 'http://localhost/dev-api',
clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
timeout: 30000,
};
// 全局Token
let authToken = '';
/**
* 获取登录Token
*/
async function getAuthToken() {
const CryptoJS = require('crypto-js');
const NodeRSA = require('node-rsa');
// 生成32位随机AES密钥
function generateAESKey() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 32; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// AES加密
function aesEncrypt(data, key) {
const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
return CryptoJS.AES.encrypt(data, keyUtf8, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
}).toString();
}
// RSA加密AES密钥
function rsaEncrypt(aesKey) {
const pemKey = `-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==\n-----END PUBLIC KEY-----`;
const rsaKey = new NodeRSA(pemKey);
rsaKey.setOptions({ encryptionScheme: 'pkcs1' });
const aesKeyBase64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(aesKey));
return rsaKey.encrypt(aesKeyBase64, 'base64');
}
try {
console.log('🔐 正在获取登录Token...'.yellow);
const aesKey = generateAESKey();
const loginData = {
tenantId: '000000',
username: 'admin',
password: 'admin123',
clientId: CONFIG.clientId,
grantType: 'password',
};
const encryptedData = aesEncrypt(JSON.stringify(loginData), aesKey);
const encryptedKey = rsaEncrypt(aesKey);
const response = await axios.post(`${CONFIG.baseURL}/auth/login`, encryptedData, {
headers: {
'Content-Type': 'application/json;charset=utf-8',
clientid: CONFIG.clientId,
'encrypt-key': encryptedKey,
referer: 'http://localhost/login?redirect=%252Findex',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
isToken: 'false',
isEncrypt: 'true',
},
timeout: CONFIG.timeout,
});
if (response.data.code === 200 && response.data.data?.access_token) {
authToken = response.data.data.access_token;
console.log('✅ 登录成功'.green);
return authToken;
} else {
throw new Error(`登录失败: ${response.data.msg}`);
}
} catch (error) {
console.error('❌ 登录失败:'.red, error.message);
throw error;
}
}
/**
* 创建测试报修工单
*/
async function createTestRepairOrder() {
try {
console.log('\n📝 正在创建测试报修工单...'.yellow);
const orderData = {
title: '附件上传测试工单',
description: '这是一个用于测试附件上传功能的报修工单',
repairLocation: '测试地点A座101',
categoryId: '1', // 假设的维修类型ID
priorityLevel: 3,
reporterName: '测试用户',
reporterPhone: '13800138000',
reporterDept: '技术部',
expectedFinishTime: new Date(Date.now() + 24 * 60 * 60 * 1000)
.toISOString()
.slice(0, 19)
.replace('T', ' '),
remark: '测试备注信息',
};
const response = await axios.post(`${CONFIG.baseURL}/pm/repairOrder`, orderData, {
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json;charset=utf-8',
clientid: CONFIG.clientId,
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
},
timeout: CONFIG.timeout,
});
if (response.data.code === 200) {
console.log('🐛 完整响应数据:', JSON.stringify(response.data, null, 2)); // 调试信息
const orderId = response.data.data;
console.log('✅ 工单创建成功'.green, `工单ID: ${orderId}`);
return orderId;
} else {
throw new Error(`工单创建失败: ${response.data.msg}`);
}
} catch (error) {
console.error('❌ 创建工单失败:'.red, error.response?.data || error.message);
throw error;
}
}
/**
* 创建测试文件
*/
function createTestFile() {
const testContent = `测试附件内容
创建时间: ${new Date().toLocaleString()}
文件用途: 验证附件上传功能
测试编号: ATT-${Date.now()}`;
const fileName = `test-attachment-${Date.now()}.txt`;
fs.writeFileSync(fileName, testContent, 'utf8');
console.log(`📎 已创建测试文件: ${fileName}`.cyan);
return fileName;
}
/**
* 上传附件到工单
*/
async function uploadAttachment(orderId, fileName) {
try {
console.log(`\n📤 正在上传附件到工单 ${orderId}...`.yellow);
const formData = new FormData();
formData.append('orderId', orderId.toString());
formData.append('uploadStage', '1');
formData.append('file', fs.createReadStream(fileName), {
filename: fileName,
contentType: 'text/plain',
});
formData.append('description', '测试附件描述');
const response = await axios.post(`${CONFIG.baseURL}/pm/attachment/upload`, formData, {
headers: {
Authorization: `Bearer ${authToken}`,
clientid: CONFIG.clientId,
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
...formData.getHeaders(),
},
timeout: CONFIG.timeout,
});
if (response.data.code === 200) {
console.log('✅ 附件上传成功'.green);
console.log('📋 附件信息:'.cyan, {
id: response.data.data.id,
fileName: response.data.data.fileName,
filePath: response.data.data.filePath,
orderId: response.data.data.orderId,
});
return response.data.data;
} else {
throw new Error(`附件上传失败: ${response.data.msg}`);
}
} catch (error) {
console.error('❌ 附件上传失败:'.red, error.response?.data || error.message);
throw error;
}
}
/**
* 验证附件是否记录到数据库
*/
async function verifyAttachmentInDatabase(orderId) {
try {
console.log(`\n🔍 正在验证工单 ${orderId} 的附件记录...`.yellow);
const response = await axios.get(`${CONFIG.baseURL}/pm/attachment/order/${orderId}`, {
headers: {
Authorization: `Bearer ${authToken}`,
clientid: CONFIG.clientId,
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
},
timeout: CONFIG.timeout,
});
if (response.data.code === 200) {
const attachments = response.data.data || [];
console.log(`📊 数据库查询结果: 找到 ${attachments.length} 个附件`.cyan);
if (attachments.length > 0) {
console.log('✅ 附件已成功记录到数据库'.green);
attachments.forEach((att, index) => {
console.log(`📎 附件 ${index + 1}:`.cyan, {
id: att.id,
fileName: att.fileName,
fileSize: att.fileSize,
orderId: att.orderId,
createTime: att.createTime,
});
});
return true;
} else {
console.log('❌ 数据库中未找到附件记录'.red);
return false;
}
} else {
throw new Error(`查询附件失败: ${response.data.msg}`);
}
} catch (error) {
console.error('❌ 验证数据库记录失败:'.red, error.response?.data || error.message);
return false;
}
}
/**
* 清理测试数据
*/
async function cleanup(orderId, fileName) {
try {
console.log('\n🧹 正在清理测试数据...'.yellow);
// 删除测试文件
if (fs.existsSync(fileName)) {
fs.unlinkSync(fileName);
console.log(`🗑️ 已删除测试文件: ${fileName}`.gray);
}
// 删除测试工单(可选)
// 注意:实际环境中可能不需要删除,用于保留测试记录
/*
await axios.delete(`${CONFIG.baseURL}/pm/repairOrder/${orderId}`, {
headers: {
'Authorization': `Bearer ${authToken}`,
'clientid': CONFIG.clientId
}
});
console.log(`🗑️ 已删除测试工单: ${orderId}`.gray);
*/
console.log('✅ 清理完成'.gray);
} catch (error) {
console.error('❌ 清理失败:'.red, error.message);
}
}
/**
* 主测试函数
*/
async function runAttachmentTest() {
console.log('🚀 开始附件上传功能测试'.rainbow);
console.log('=' * 50);
let orderId = null;
let fileName = null;
try {
// 1. 获取登录Token
await getAuthToken();
// 2. 创建测试工单
orderId = await createTestRepairOrder();
// 3. 创建测试文件
fileName = createTestFile();
// 4. 上传附件
await uploadAttachment(orderId, fileName);
// 5. 验证数据库记录
const isRecorded = await verifyAttachmentInDatabase(orderId);
// 6. 测试结果
console.log('\n📊 测试结果总结'.rainbow);
console.log('=' * 30);
if (isRecorded) {
console.log('🎉 测试通过: 附件上传功能正常,数据已记录到数据库'.green.bold);
} else {
console.log('⚠️ 测试失败: 附件未正确记录到数据库'.red.bold);
console.log('🔧 建议检查以下问题:'.yellow);
console.log(' 1. 后端附件上传接口是否正常工作');
console.log(' 2. 数据库连接和表结构是否正确');
console.log(' 3. orderId 是否正确传递给上传接口');
console.log(' 4. 上传阶段参数是否正确');
}
} catch (error) {
console.error('\n💥 测试过程中发生错误:'.red.bold, error.message);
console.log('🔧 故障排查建议:'.yellow);
console.log(' 1. 检查后端服务是否正常运行');
console.log(' 2. 验证API接口路径和权限配置');
console.log(' 3. 查看后端日志获取详细错误信息');
console.log(' 4. 确认数据库表结构和字段是否正确');
} finally {
// 清理测试数据
if (orderId && fileName) {
await cleanup(orderId, fileName);
}
}
}
// 执行测试
if (require.main === module) {
runAttachmentTest()
.then(() => {
console.log('\n✅ 测试脚本执行完成'.green);
process.exit(0);
})
.catch((error) => {
console.error('\n❌ 测试脚本执行失败:'.red, error.message);
process.exit(1);
});
}
module.exports = {
runAttachmentTest,
getAuthToken,
createTestRepairOrder,
uploadAttachment,
verifyAttachmentInDatabase,
};