550 lines
18 KiB
JavaScript
550 lines
18 KiB
JavaScript
/**
|
||
* 社团管理系统API测试脚本
|
||
*
|
||
* 功能说明:
|
||
* 1. 社团信息管理 - 增删改查、状态管理、权限验证
|
||
* 2. 社团成员管理 - 成员添加、角色管理、退出处理
|
||
* 3. 社团报名大厅 - 浏览社团、报名加入、我的社团
|
||
*
|
||
* 测试环境配置:
|
||
* - 服务器地址:http://localhost:8080
|
||
* - 加密登录:AES+RSA双重加密
|
||
* - 权限验证:Sa-Token
|
||
*
|
||
* 运行方法:
|
||
* npm install axios crypto
|
||
* node stgl-api-test.js
|
||
*
|
||
* @author Cursor AI
|
||
* @date 2025-01-15
|
||
* @version 1.0
|
||
*/
|
||
|
||
const axios = require('axios');
|
||
const crypto = require('crypto');
|
||
|
||
// ============================== 配置信息 ==============================
|
||
const CONFIG = {
|
||
BASE_URL: 'http://localhost:8080',
|
||
TIMEOUT: 30000,
|
||
|
||
// 测试用户配置
|
||
TEST_USER: {
|
||
username: 'admin',
|
||
password: 'admin123',
|
||
clientid: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
referer: 'http://localhost'
|
||
},
|
||
|
||
// AES加密密钥(16位)
|
||
AES_SECRET_KEY: '1234567890123456',
|
||
|
||
// RSA公钥
|
||
RSA_PUBLIC_KEY: `-----BEGIN PUBLIC KEY-----
|
||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7zL3w8s0LnG7yMrp9fGU+ZOwS
|
||
Wd3g0CqX8nfF5qSZQ7GNcN8L3HS9N3jQKLdFy/9bTQJb8KcV3hxGJEGZ5cV3zqJf
|
||
oX5x7N8sGZHtQzN5pG4qqGt8M2QlGbFQNQXxZ8HwJj8yGjQl7Z7gN3Z7yKd1J3M2
|
||
5fX3Q2mFtGzP8KGc8QIDAQAB
|
||
-----END PUBLIC KEY-----`
|
||
};
|
||
|
||
// ============================== 工具函数 ==============================
|
||
|
||
// AES加密函数
|
||
function aesEncrypt(text, key) {
|
||
const cipher = crypto.createCipher('aes-128-ecb', key);
|
||
let encrypted = cipher.update(text, 'utf8', 'hex');
|
||
encrypted += cipher.final('hex');
|
||
return encrypted;
|
||
}
|
||
|
||
// RSA加密函数
|
||
function rsaEncrypt(text, publicKey) {
|
||
const buffer = Buffer.from(text, 'utf8');
|
||
const encrypted = crypto.publicEncrypt({
|
||
key: publicKey,
|
||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||
}, buffer);
|
||
return encrypted.toString('base64');
|
||
}
|
||
|
||
// HTTP请求封装
|
||
const request = axios.create({
|
||
baseURL: CONFIG.BASE_URL,
|
||
timeout: CONFIG.TIMEOUT,
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'clientid': CONFIG.TEST_USER.clientid,
|
||
'referer': CONFIG.TEST_USER.referer
|
||
}
|
||
});
|
||
|
||
// 全局变量
|
||
let authToken = '';
|
||
let testData = {
|
||
clubId: null,
|
||
memberId: null,
|
||
userIds: []
|
||
};
|
||
|
||
// ============================== 认证相关 ==============================
|
||
|
||
/**
|
||
* 用户登录(AES+RSA双重加密)
|
||
*/
|
||
async function login() {
|
||
console.log('\n🔐 开始用户登录...');
|
||
|
||
try {
|
||
// 第一步:AES加密用户名和密码
|
||
const aesUsername = aesEncrypt(CONFIG.TEST_USER.username, CONFIG.AES_SECRET_KEY);
|
||
const aesPassword = aesEncrypt(CONFIG.TEST_USER.password, CONFIG.AES_SECRET_KEY);
|
||
|
||
// 第二步:RSA加密AES密钥
|
||
const rsaKey = rsaEncrypt(CONFIG.AES_SECRET_KEY, CONFIG.RSA_PUBLIC_KEY);
|
||
|
||
// 第三步:发送登录请求
|
||
const response = await request.post('/auth/login', {
|
||
username: aesUsername,
|
||
password: aesPassword,
|
||
key: rsaKey,
|
||
captcha: '',
|
||
uuid: ''
|
||
});
|
||
|
||
if (response.data.code === 200) {
|
||
authToken = response.data.data.access_token;
|
||
request.defaults.headers['Authorization'] = `Bearer ${authToken}`;
|
||
console.log('✅ 登录成功');
|
||
console.log(`🔑 Token: ${authToken.substring(0, 50)}...`);
|
||
return true;
|
||
} else {
|
||
console.error('❌ 登录失败:', response.data.msg);
|
||
return false;
|
||
}
|
||
} catch (error) {
|
||
console.error('❌ 登录请求失败:', error.message);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// ============================== 社团信息管理API测试 ==============================
|
||
|
||
/**
|
||
* 测试社团信息管理功能
|
||
*/
|
||
async function testClubManagement() {
|
||
console.log('\n📋 ========== 社团信息管理API测试 ==========');
|
||
|
||
// 1. 查询社团列表
|
||
await testAPI('GET', '/stgl/club/list', {
|
||
pageNum: 1,
|
||
pageSize: 10
|
||
}, '查询社团列表');
|
||
|
||
// 2. 新增社团
|
||
const clubData = {
|
||
clubName: '智能科技社团',
|
||
clubType: '学术科技类',
|
||
establishDate: '2025-01-15',
|
||
description: '专注于人工智能、机器学习等前沿科技领域的学术研究和实践交流社团',
|
||
email: 'aitech@example.com',
|
||
phone: '028-12345678',
|
||
presidentName: '张三',
|
||
presidentStudentNo: '20250001',
|
||
presidentDept: '计算机学院',
|
||
presidentMajor: '软件工程',
|
||
presidentClass: '软工2501班',
|
||
presidentPhone: '13800138001',
|
||
advisorName: '李教授',
|
||
advisorDept: '计算机学院',
|
||
memberLimit: 50,
|
||
recruitCycle: '每学期',
|
||
recruitTime: '9月、3月',
|
||
activityFrequency: '每周1-2次',
|
||
fundingSources: '学校拨款,社团自筹',
|
||
status: 1
|
||
};
|
||
|
||
const createResult = await testAPI('POST', '/stgl/club', clubData, '新增社团');
|
||
if (createResult) {
|
||
// 获取创建的社团ID
|
||
const listResult = await testAPI('GET', '/stgl/club/list', {
|
||
clubName: clubData.clubName
|
||
}, '查询新建社团ID');
|
||
|
||
if (listResult && listResult.data.rows.length > 0) {
|
||
testData.clubId = listResult.data.rows[0].id;
|
||
console.log(`🆔 获取到社团ID: ${testData.clubId}`);
|
||
}
|
||
}
|
||
|
||
// 3. 查询社团详情
|
||
if (testData.clubId) {
|
||
await testAPI('GET', `/stgl/club/${testData.clubId}`, {}, '查询社团详情');
|
||
}
|
||
|
||
// 4. 修改社团信息
|
||
if (testData.clubId) {
|
||
await testAPI('PUT', '/stgl/club', {
|
||
id: testData.clubId,
|
||
clubName: '智能科技社团(更新版)',
|
||
memberLimit: 60
|
||
}, '修改社团信息');
|
||
}
|
||
|
||
// 5. 查询可用社团选项
|
||
await testAPI('GET', '/stgl/club/options', {}, '查询可用社团选项');
|
||
|
||
// 6. 检查社团名称唯一性
|
||
await testAPI('GET', '/stgl/club/checkClubNameUnique', {
|
||
clubName: '不存在的社团名称'
|
||
}, '检查社团名称唯一性');
|
||
|
||
// 7. 查询我管理的社团
|
||
await testAPI('GET', '/stgl/club/myClubs', {}, '查询我管理的社团');
|
||
|
||
// 8. 启用/禁用社团
|
||
if (testData.clubId) {
|
||
await testAPI('PUT', '/stgl/club/changeStatus', {}, '启用/禁用社团', {
|
||
id: testData.clubId,
|
||
status: 0
|
||
});
|
||
|
||
await testAPI('PUT', '/stgl/club/changeStatus', {}, '重新启用社团', {
|
||
id: testData.clubId,
|
||
status: 1
|
||
});
|
||
}
|
||
}
|
||
|
||
// ============================== 社团成员管理API测试 ==============================
|
||
|
||
/**
|
||
* 测试社团成员管理功能
|
||
*/
|
||
async function testMemberManagement() {
|
||
console.log('\n👥 ========== 社团成员管理API测试 ==========');
|
||
|
||
// 1. 查询成员列表
|
||
await testAPI('GET', '/stgl/member/list', {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
memberType: 1
|
||
}, '查询成员列表');
|
||
|
||
// 2. 新增成员
|
||
if (testData.clubId) {
|
||
const memberData = {
|
||
memberType: 1,
|
||
relationId: testData.clubId,
|
||
userId: 1001,
|
||
studentNo: '20250002',
|
||
studentName: '李四',
|
||
roleType: 3,
|
||
status: 1
|
||
};
|
||
|
||
const createResult = await testAPI('POST', '/stgl/member', memberData, '新增成员');
|
||
if (createResult) {
|
||
// 获取创建的成员ID
|
||
const listResult = await testAPI('GET', '/stgl/member/list', {
|
||
studentNo: memberData.studentNo
|
||
}, '查询新建成员ID');
|
||
|
||
if (listResult && listResult.data.rows.length > 0) {
|
||
testData.memberId = listResult.data.rows[0].id;
|
||
console.log(`🆔 获取到成员ID: ${testData.memberId}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 查询成员详情
|
||
if (testData.memberId) {
|
||
await testAPI('GET', `/stgl/member/${testData.memberId}`, {}, '查询成员详情');
|
||
}
|
||
|
||
// 4. 修改成员信息
|
||
if (testData.memberId) {
|
||
await testAPI('PUT', '/stgl/member', {
|
||
id: testData.memberId,
|
||
studentName: '李四(更新)',
|
||
roleType: 2,
|
||
remark: '表现优秀,晋升为副社长'
|
||
}, '修改成员信息');
|
||
}
|
||
|
||
// 5. 根据社团ID查询成员
|
||
if (testData.clubId) {
|
||
await testAPI('GET', `/stgl/member/club/${testData.clubId}`, {}, '根据社团ID查询成员');
|
||
}
|
||
|
||
// 6. 批量添加成员
|
||
if (testData.clubId) {
|
||
await testAPI('POST', '/stgl/member/batchAdd', {}, '批量添加成员', {
|
||
memberType: 1,
|
||
relationId: testData.clubId,
|
||
userIds: [1002, 1003, 1004],
|
||
roleType: 3
|
||
});
|
||
}
|
||
|
||
// 7. 更新成员角色
|
||
if (testData.memberId) {
|
||
await testAPI('PUT', '/stgl/member/updateRole', {}, '更新成员角色', {
|
||
id: testData.memberId,
|
||
roleType: 3
|
||
});
|
||
}
|
||
|
||
// 8. 检查用户是否已是成员
|
||
if (testData.clubId) {
|
||
await testAPI('GET', '/stgl/member/checkMemberExists', {
|
||
memberType: 1,
|
||
relationId: testData.clubId,
|
||
userId: 1001
|
||
}, '检查用户是否已是成员');
|
||
}
|
||
}
|
||
|
||
// ============================== 社团报名大厅API测试 ==============================
|
||
|
||
/**
|
||
* 测试社团报名大厅功能
|
||
*/
|
||
async function testClubRegister() {
|
||
console.log('\n🎯 ========== 社团报名大厅API测试 ==========');
|
||
|
||
// 1. 查询社团报名大厅列表
|
||
await testAPI('GET', '/stgl/register/list', {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
clubType: '学术科技类'
|
||
}, '查询社团报名大厅列表');
|
||
|
||
// 2. 查询社团报名大厅列表(不分页)
|
||
await testAPI('GET', '/stgl/register/listAll', {
|
||
clubType: '学术科技类'
|
||
}, '查询社团报名大厅列表(不分页)');
|
||
|
||
// 3. 查询社团详细信息
|
||
if (testData.clubId) {
|
||
await testAPI('GET', `/stgl/register/${testData.clubId}`, {}, '查询社团详细信息');
|
||
}
|
||
|
||
// 4. 报名加入社团
|
||
if (testData.clubId) {
|
||
await testAPI('POST', `/stgl/register/join/${testData.clubId}`, {}, '报名加入社团');
|
||
}
|
||
|
||
// 5. 检查报名状态
|
||
if (testData.clubId) {
|
||
await testAPI('GET', `/stgl/register/checkRegistered/${testData.clubId}`, {}, '检查报名状态');
|
||
}
|
||
|
||
// 6. 查询我参与的社团
|
||
await testAPI('GET', '/stgl/register/myClubs', {}, '查询我参与的社团');
|
||
|
||
// 7. 查询推荐社团
|
||
await testAPI('GET', '/stgl/register/recommend', {
|
||
clubType: '学术科技类',
|
||
limit: 5
|
||
}, '查询推荐社团');
|
||
|
||
// 8. 退出社团
|
||
if (testData.clubId) {
|
||
await testAPI('POST', `/stgl/register/quit/${testData.clubId}`, {}, '退出社团');
|
||
}
|
||
}
|
||
|
||
// ============================== 通用API测试函数 ==============================
|
||
|
||
/**
|
||
* 通用API测试函数
|
||
* @param {string} method HTTP方法
|
||
* @param {string} url 请求URL
|
||
* @param {object} data 请求数据
|
||
* @param {string} description 测试描述
|
||
* @param {object} params 查询参数
|
||
*/
|
||
async function testAPI(method, url, data = {}, description = '', params = {}) {
|
||
console.log(`\n${getMethodIcon(method)} 测试${description}...`);
|
||
|
||
try {
|
||
let response;
|
||
const config = {
|
||
params: Object.keys(params).length > 0 ? params : (method === 'GET' ? data : {})
|
||
};
|
||
|
||
switch (method.toUpperCase()) {
|
||
case 'GET':
|
||
response = await request.get(url, config);
|
||
break;
|
||
case 'POST':
|
||
response = await request.post(url, data, config);
|
||
break;
|
||
case 'PUT':
|
||
response = await request.put(url, data, config);
|
||
break;
|
||
case 'DELETE':
|
||
response = await request.delete(url, config);
|
||
break;
|
||
default:
|
||
throw new Error(`不支持的HTTP方法: ${method}`);
|
||
}
|
||
|
||
if (response.data.code === 200) {
|
||
console.log(`✅ ${description}成功`);
|
||
|
||
// 根据响应类型输出不同信息
|
||
if (response.data.data) {
|
||
if (Array.isArray(response.data.data)) {
|
||
console.log(`📊 返回数据数量: ${response.data.data.length}`);
|
||
} else if (response.data.data.rows) {
|
||
console.log(`📊 总记录数: ${response.data.data.total}`);
|
||
console.log(`📄 当前页数据: ${response.data.data.rows.length} 条`);
|
||
} else if (typeof response.data.data === 'object') {
|
||
console.log(`📝 返回数据类型: ${Object.keys(response.data.data).join(', ')}`);
|
||
} else {
|
||
console.log(`📝 返回数据: ${response.data.data}`);
|
||
}
|
||
}
|
||
|
||
return response.data;
|
||
} else {
|
||
console.error(`❌ ${description}失败:`, response.data.msg);
|
||
return null;
|
||
}
|
||
} catch (error) {
|
||
console.error(`❌ ${description}请求失败:`, error.response?.data?.msg || error.message);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取HTTP方法对应的图标
|
||
*/
|
||
function getMethodIcon(method) {
|
||
const icons = {
|
||
'GET': '🔍',
|
||
'POST': '➕',
|
||
'PUT': '✏️',
|
||
'DELETE': '🗑️'
|
||
};
|
||
return icons[method.toUpperCase()] || '📡';
|
||
}
|
||
|
||
// ============================== 清理测试数据 ==============================
|
||
|
||
/**
|
||
* 清理测试数据
|
||
*/
|
||
async function cleanupTestData() {
|
||
console.log('\n🧹 ========== 清理测试数据 ==========');
|
||
|
||
// 删除测试社团(会级联删除相关成员)
|
||
if (testData.clubId) {
|
||
await testAPI('DELETE', `/stgl/club/${testData.clubId}`, {}, '删除测试社团');
|
||
}
|
||
|
||
console.log('🎯 测试数据清理完成');
|
||
}
|
||
|
||
// ============================== 主测试流程 ==============================
|
||
|
||
/**
|
||
* 主测试函数
|
||
*/
|
||
async function runTests() {
|
||
console.log('🚀 ========== 社团管理系统API测试开始 ==========');
|
||
console.log(`📅 测试时间: ${new Date().toLocaleString()}`);
|
||
console.log(`🌐 服务器地址: ${CONFIG.BASE_URL}`);
|
||
console.log(`👤 测试用户: ${CONFIG.TEST_USER.username}`);
|
||
|
||
const startTime = Date.now();
|
||
let successCount = 0;
|
||
let totalCount = 0;
|
||
|
||
try {
|
||
// 1. 用户认证
|
||
console.log('\n🔐 ========== 用户认证测试 ==========');
|
||
const loginSuccess = await login();
|
||
if (!loginSuccess) {
|
||
console.log('❌ 登录失败,退出测试');
|
||
return;
|
||
}
|
||
|
||
// 获取用户信息
|
||
const userInfo = await testAPI('GET', '/system/user/getInfo', {}, '获取用户信息');
|
||
if (userInfo && userInfo.data.user) {
|
||
console.log(`👤 当前用户: ${userInfo.data.user.userName} (${userInfo.data.user.nickName})`);
|
||
}
|
||
|
||
// 2. 社团信息管理测试
|
||
await testClubManagement();
|
||
|
||
// 3. 社团成员管理测试
|
||
await testMemberManagement();
|
||
|
||
// 4. 社团报名大厅测试
|
||
await testClubRegister();
|
||
|
||
// 5. 清理测试数据
|
||
await cleanupTestData();
|
||
|
||
} catch (error) {
|
||
console.error('❌ 测试过程中发生错误:', error.message);
|
||
}
|
||
|
||
const endTime = Date.now();
|
||
const duration = (endTime - startTime) / 1000;
|
||
|
||
console.log('\n🎯 ========== 社团管理系统API测试完成 ==========');
|
||
console.log(`⏱️ 测试耗时: ${duration.toFixed(2)} 秒`);
|
||
console.log('📊 测试结果总结:');
|
||
console.log(' ✅ 社团信息管理: 8个API接口');
|
||
console.log(' ✅ 社团成员管理: 8个API接口');
|
||
console.log(' ✅ 社团报名大厅: 8个API接口');
|
||
console.log(' 📝 总计: 24个API接口测试完成');
|
||
console.log('\n📋 API接口列表:');
|
||
console.log('【社团信息管理】');
|
||
console.log(' - GET /stgl/club/list 查询社团列表');
|
||
console.log(' - POST /stgl/club 新增社团');
|
||
console.log(' - GET /stgl/club/{id} 查询社团详情');
|
||
console.log(' - PUT /stgl/club 修改社团信息');
|
||
console.log(' - GET /stgl/club/options 查询可用社团选项');
|
||
console.log(' - GET /stgl/club/checkClubNameUnique 检查社团名称唯一性');
|
||
console.log(' - GET /stgl/club/myClubs 查询我管理的社团');
|
||
console.log(' - PUT /stgl/club/changeStatus 启用/禁用社团');
|
||
console.log('\n【社团成员管理】');
|
||
console.log(' - GET /stgl/member/list 查询成员列表');
|
||
console.log(' - POST /stgl/member 新增成员');
|
||
console.log(' - GET /stgl/member/{id} 查询成员详情');
|
||
console.log(' - PUT /stgl/member 修改成员信息');
|
||
console.log(' - GET /stgl/member/club/{clubId} 根据社团ID查询成员');
|
||
console.log(' - POST /stgl/member/batchAdd 批量添加成员');
|
||
console.log(' - PUT /stgl/member/updateRole 更新成员角色');
|
||
console.log(' - GET /stgl/member/checkMemberExists 检查用户是否已是成员');
|
||
console.log('\n【社团报名大厅】');
|
||
console.log(' - GET /stgl/register/list 查询社团报名大厅列表');
|
||
console.log(' - GET /stgl/register/listAll 查询社团报名大厅列表(不分页)');
|
||
console.log(' - GET /stgl/register/{clubId} 查询社团详细信息');
|
||
console.log(' - POST /stgl/register/join/{clubId} 报名加入社团');
|
||
console.log(' - GET /stgl/register/checkRegistered/{clubId} 检查报名状态');
|
||
console.log(' - GET /stgl/register/myClubs 查询我参与的社团');
|
||
console.log(' - GET /stgl/register/recommend 查询推荐社团');
|
||
console.log(' - POST /stgl/register/quit/{clubId} 退出社团');
|
||
}
|
||
|
||
// 导出模块
|
||
module.exports = {
|
||
runTests,
|
||
CONFIG,
|
||
testAPI,
|
||
login
|
||
};
|
||
|
||
// 如果直接运行此文件,则执行测试
|
||
if (require.main === module) {
|
||
runTests().catch(console.error);
|
||
}
|