📝 主要改进: • Cursor配置模块化:拆分为前端、后端、移动端、文档、API测试5个专门规范文件 • API文档重新组织:按业务模块拆分到docs/开发文档/API/目录下 • 新增维修分类功能完整测试方案和自动化测试脚本 • 后端热启动脚本完善,支持Linux/Windows双平台 • 强化文档同步更新规范,确保代码与文档一致性 🔧 技术改进: • 优化Cursor AI工作流程和代码生成质量 • 完善API测试规范(AES+RSA双重加密登录方法) • 提升开发效率和代码质量标准化程度 �� 测试覆盖: • 维修分类管理功能端到端测试验证通过 • 包含页面加载、CRUD操作、搜索功能等核心测试用例 更新时间:2025-07-01
683 lines
20 KiB
Markdown
683 lines
20 KiB
Markdown
# Cursor Rules - API 测试和登录方法
|
||
|
||
## 适用范围
|
||
|
||
- **测试环境**: http://localhost/dev-api
|
||
- **登录认证**: AES+RSA 双重加密
|
||
- **Token 管理**: JWT 认证体系
|
||
|
||
---
|
||
|
||
# API 测试和登录方法
|
||
|
||
## 1. 🔐 登录方法配置
|
||
|
||
### 系统登录接口分析
|
||
|
||
**接口地址**: `POST http://localhost/dev-api/auth/login`
|
||
|
||
**当前状态**:
|
||
|
||
- ✅ **接口技术实现**: 登录接口正常工作,能够正确处理请求
|
||
- ✅ **接口地址确认**: 接口地址 http://localhost/dev-api/auth/login 可正常访问
|
||
- ✅ **权限配置问题**: 已解决,admin 用户可以正常登录获取 Token
|
||
- ✅ **加密登录问题**: 已解决,AES+RSA 双重加密登录正常工作
|
||
- ✅ **Token 验证**: Token 有效期 7 天,可正常用于 API 调用
|
||
- ✅ **用户权限**: admin 用户具有超级管理员权限 (_:_:\*)
|
||
|
||
### 🔧 可用的登录方法
|
||
|
||
#### 方法 1:AES+RSA 加密登录(推荐)
|
||
|
||
```javascript
|
||
// 完整的AES+RSA双重加密登录方法
|
||
async function encryptedLogin() {
|
||
const axios = require('axios');
|
||
const CryptoJS = require('crypto-js');
|
||
const NodeRSA = require('node-rsa');
|
||
|
||
// 配置信息
|
||
const CONFIG = {
|
||
url: 'http://localhost/dev-api/auth/login',
|
||
clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
tenantId: '000000',
|
||
referer: 'http://localhost/login?redirect=%252Findex',
|
||
rsaKey: 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==',
|
||
};
|
||
|
||
// 生成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-----\n${CONFIG.rsaKey}\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');
|
||
}
|
||
|
||
// 生成AES密钥并加密登录数据
|
||
const aesKey = generateAESKey();
|
||
const loginData = {
|
||
tenantId: CONFIG.tenantId,
|
||
username: 'admin',
|
||
password: 'admin123',
|
||
clientId: CONFIG.clientId,
|
||
grantType: 'password',
|
||
};
|
||
|
||
const encryptedData = aesEncrypt(JSON.stringify(loginData), aesKey);
|
||
const encryptedKey = rsaEncrypt(aesKey);
|
||
|
||
// 设置请求头(按照系统要求的格式)
|
||
const headers = {
|
||
'Content-Type': 'application/json;charset=utf-8',
|
||
clientid: CONFIG.clientId, // 必需:客户端ID
|
||
'encrypt-key': encryptedKey, // 必需:RSA加密的AES密钥
|
||
referer: CONFIG.referer, // 必需:来源页面
|
||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||
isToken: 'false',
|
||
isEncrypt: 'true',
|
||
repeatSubmit: 'false',
|
||
};
|
||
|
||
// 发送登录请求
|
||
const response = await axios.post(CONFIG.url, encryptedData, {
|
||
headers: headers,
|
||
timeout: 10000,
|
||
});
|
||
|
||
// 返回Token
|
||
if (response.data.code === 200 && response.data.data?.access_token) {
|
||
return response.data.data.access_token;
|
||
} else {
|
||
throw new Error(response.data.msg || 'Login failed');
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 方法 2:快速 Token 获取(简化版)
|
||
|
||
```javascript
|
||
// 快速获取Token的简化版本
|
||
async function getToken(username = 'admin', password = 'admin123') {
|
||
const { getToken } = require('./test/quick-token-getter');
|
||
return await getToken(username, password);
|
||
}
|
||
```
|
||
|
||
### 🔧 快速测试工具
|
||
|
||
#### 使用 test 目录下的测试脚本
|
||
|
||
```bash
|
||
# 在test目录下运行测试
|
||
cd test
|
||
npm install # 安装依赖(axios, crypto-js, node-rsa, colors)
|
||
|
||
# 完整功能版登录测试(推荐)
|
||
node custom-login-script.js
|
||
|
||
# 快速Token获取测试
|
||
node quick-token-getter.js
|
||
```
|
||
|
||
#### 可用的登录脚本
|
||
|
||
- **`custom-login-script.js`** - 完整功能版,支持 AES+RSA 双重加密
|
||
- **`quick-token-getter.js`** - 快速获取版,代码简洁易懂
|
||
|
||
#### 依赖安装
|
||
|
||
```json
|
||
{
|
||
"dependencies": {
|
||
"axios": "^1.7.2",
|
||
"crypto-js": "^4.2.0",
|
||
"node-rsa": "^1.1.1",
|
||
"colors": "^1.4.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 🎯 成功获取的 Token 示例
|
||
|
||
```
|
||
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJ5MlhvbHRnd1Y2YjUzRnRMVzF4SFR1anRSUERjeGdmYyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IuaZuuiDveaOp-WItuWtpumZoiIsImRlcHRDYXRlZ29yeSI6IiIsIm5pY2tOYW1lIjoi55ax54uC55qE54uu5a2QTGkifQ.WI6iY3AgwPz7ceI8WDsVy-GaTXZnU-JKUYUTjhQdoKM
|
||
```
|
||
|
||
**Token 解析信息**:
|
||
|
||
- **用户 ID**: 1
|
||
- **用户名**: admin
|
||
- **昵称**: 疯狂狮子 Li
|
||
- **部门**: 智胜技术开发团队
|
||
- **权限**: _:_:\* (超级管理员)
|
||
- **有效期**: 7 天
|
||
- **租户**: 000000
|
||
|
||
## 2. ✅ 已解决的问题和解决方案
|
||
|
||
### 已解决问题 1:国际化语言头格式问题
|
||
|
||
- **原问题**: ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
|
||
- **原因**: 服务器端国际化解析器无法正确处理 `'Content-Language': 'zh-cn'` 格式
|
||
- **解决方案**:
|
||
- 使用 `'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'` 格式
|
||
- 或使用标准的 `'Content-Language': 'zh-CN'` 格式
|
||
- **状态**: ✅ 已完全解决
|
||
|
||
### 已解决问题 2:加密登录技术问题
|
||
|
||
- **原问题**: AES+RSA 双重加密登录存在技术错误
|
||
- **原因**: 加密密钥生成和请求头格式不正确
|
||
- **解决方案**:
|
||
- 使用正确的 32 位随机 AES 密钥生成
|
||
- 按照系统要求设置三个关键 Header:clientid、encrypt-key、referer
|
||
- 使用正确的 RSA-PKCS1 加密方案
|
||
- **状态**: ✅ 已完全解决
|
||
|
||
### 核心成功要素
|
||
|
||
1. **必需的 Header 格式**:
|
||
|
||
```javascript
|
||
{
|
||
'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
'encrypt-key': '[RSA加密的AES密钥]',
|
||
'referer': 'http://localhost/login?redirect=%252Findex'
|
||
}
|
||
```
|
||
|
||
2. **正确的加密流程**:
|
||
- 生成 32 位随机 AES 密钥
|
||
- 使用 AES-ECB 模式加密登录数据
|
||
- 使用 RSA-PKCS1 加密 AES 密钥
|
||
- 设置正确的请求头格式
|
||
|
||
## 3. 🔍 API 测试最佳实践
|
||
|
||
### 测试环境配置
|
||
|
||
```javascript
|
||
const config = {
|
||
baseURL: 'http://localhost/dev-api',
|
||
timeout: 10000,
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=utf-8',
|
||
clientid: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||
referer: 'http://localhost/login?redirect=%252Findex',
|
||
},
|
||
};
|
||
```
|
||
|
||
### 通用 API 测试方法
|
||
|
||
```javascript
|
||
// 通用API测试方法
|
||
async function testAPI(endpoint, data, options = {}) {
|
||
const axios = require('axios');
|
||
|
||
try {
|
||
const response = await axios({
|
||
method: options.method || 'POST',
|
||
url: `http://localhost/dev-api${endpoint}`,
|
||
data: data,
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=utf-8',
|
||
clientid: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||
referer: 'http://localhost/login?redirect=%252Findex',
|
||
Authorization: options.token ? `Bearer ${options.token}` : undefined,
|
||
...options.headers,
|
||
},
|
||
timeout: 10000,
|
||
});
|
||
|
||
return {
|
||
success: true,
|
||
data: response.data,
|
||
status: response.status,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
error: error.response?.data || error.message,
|
||
status: error.response?.status,
|
||
};
|
||
}
|
||
}
|
||
```
|
||
|
||
### 带 Token 的 API 调用
|
||
|
||
```javascript
|
||
// 带Token的API调用示例
|
||
async function callAPIWithToken(token, endpoint, data, method = 'GET') {
|
||
return await testAPI(endpoint, data, {
|
||
method: method,
|
||
token: token,
|
||
headers: {
|
||
clientid: 'e5cd7e4891bf95d1d19206ce24a7b32e',
|
||
referer: 'http://localhost/login?redirect=%252Findex',
|
||
},
|
||
});
|
||
}
|
||
|
||
// 使用示例
|
||
async function getUserInfo(token) {
|
||
const result = await callAPIWithToken(token, '/system/user/getInfo', null, 'GET');
|
||
return result;
|
||
}
|
||
|
||
// 调用带参数的API
|
||
async function getUserList(token, params) {
|
||
const result = await callAPIWithToken(token, '/system/user/list', params, 'GET');
|
||
return result;
|
||
}
|
||
```
|
||
|
||
### 分页接口测试
|
||
|
||
```javascript
|
||
// 分页接口测试模板
|
||
async function testPaginationAPI(token, endpoint, params = {}) {
|
||
const defaultParams = {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
...params,
|
||
};
|
||
|
||
const result = await callAPIWithToken(token, endpoint, defaultParams, 'GET');
|
||
|
||
if (result.success) {
|
||
console.log('分页接口测试成功:');
|
||
console.log(`总记录数: ${result.data.total}`);
|
||
console.log(`当前页数据: ${result.data.rows?.length || 0} 条`);
|
||
console.log('响应格式正确 ✅');
|
||
} else {
|
||
console.log('分页接口测试失败:', result.error);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 使用示例
|
||
async function testUserListAPI(token) {
|
||
return await testPaginationAPI(token, '/system/user/list', {
|
||
userName: 'admin',
|
||
status: '0',
|
||
});
|
||
}
|
||
```
|
||
|
||
### CRUD 接口测试套件
|
||
|
||
```javascript
|
||
// CRUD接口完整测试套件
|
||
async function testCRUDAPIs(token, baseEndpoint, testData) {
|
||
const results = {
|
||
create: null,
|
||
read: null,
|
||
update: null,
|
||
delete: null,
|
||
};
|
||
|
||
try {
|
||
// 1. 测试创建 (CREATE)
|
||
console.log('测试创建接口...');
|
||
results.create = await callAPIWithToken(token, baseEndpoint, testData, 'POST');
|
||
|
||
if (results.create.success) {
|
||
console.log('✅ 创建接口测试通过');
|
||
const createdId = results.create.data.data?.id;
|
||
|
||
// 2. 测试读取 (READ)
|
||
if (createdId) {
|
||
console.log('测试读取接口...');
|
||
results.read = await callAPIWithToken(
|
||
token,
|
||
`${baseEndpoint}/${createdId}`,
|
||
null,
|
||
'GET',
|
||
);
|
||
|
||
if (results.read.success) {
|
||
console.log('✅ 读取接口测试通过');
|
||
|
||
// 3. 测试更新 (UPDATE)
|
||
console.log('测试更新接口...');
|
||
const updateData = {
|
||
...testData,
|
||
id: createdId,
|
||
name: testData.name + '_updated',
|
||
};
|
||
results.update = await callAPIWithToken(token, baseEndpoint, updateData, 'PUT');
|
||
|
||
if (results.update.success) {
|
||
console.log('✅ 更新接口测试通过');
|
||
}
|
||
|
||
// 4. 测试删除 (DELETE)
|
||
console.log('测试删除接口...');
|
||
results.delete = await callAPIWithToken(
|
||
token,
|
||
`${baseEndpoint}/${createdId}`,
|
||
null,
|
||
'DELETE',
|
||
);
|
||
|
||
if (results.delete.success) {
|
||
console.log('✅ 删除接口测试通过');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('CRUD测试出现异常:', error);
|
||
}
|
||
|
||
return results;
|
||
}
|
||
```
|
||
|
||
## 4. 📝 API 测试记录模板
|
||
|
||
### 测试结果记录格式
|
||
|
||
```markdown
|
||
## API 测试记录 - YYYY-MM-DD
|
||
|
||
**测试环境**: http://localhost/dev-api
|
||
**测试时间**: YYYY-MM-DD HH:mm:ss
|
||
**测试人员**: [测试人员]
|
||
|
||
### 登录测试
|
||
|
||
- **方法**: AES+RSA 双重加密登录
|
||
- **结果**: ✅ 登录成功
|
||
- **Token**: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
|
||
- **用户信息**: admin / 疯狂狮子 Li / 超级管理员
|
||
- **权限**: _:_:\* (完全权限)
|
||
- **有效期**: 7 天
|
||
|
||
### 业务 API 测试
|
||
|
||
- **接口**: [接口地址]
|
||
- **方法**: [HTTP 方法]
|
||
- **权限**: [需要的权限]
|
||
- **结果**: [测试结果]
|
||
- **响应时间**: [响应时间 ms]
|
||
- **状态码**: [HTTP 状态码]
|
||
|
||
### 成功要素记录
|
||
|
||
1. **Header 配置**: 正确设置 clientid、encrypt-key、referer
|
||
2. **加密机制**: AES+RSA 双重加密正常工作
|
||
3. **语言头格式**: 使用 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
|
||
|
||
### 验证结果
|
||
|
||
- ✅ 登录接口正常工作
|
||
- ✅ Token 有效可用于 API 调用
|
||
- ✅ 用户权限验证通过
|
||
- ✅ 加密解密机制正常
|
||
```
|
||
|
||
### 详细测试报告模板
|
||
|
||
```markdown
|
||
# API 接口测试报告
|
||
|
||
## 🎯 测试概览
|
||
|
||
**测试时间**: YYYY-MM-DD HH:mm:ss
|
||
**测试范围**: [具体测试的 API 模块]
|
||
**测试环境**: http://localhost/dev-api
|
||
**测试工具**: Node.js + Axios + 自定义脚本
|
||
|
||
## 📁 测试脚本路径
|
||
|
||
**登录脚本**: `test/custom-login-script.js`
|
||
**API 测试脚本**: `test/[功能]-api-test.js`
|
||
|
||
## 🔐 认证测试
|
||
|
||
### 登录接口测试
|
||
|
||
- **接口地址**: POST /auth/login
|
||
- **加密方式**: AES+RSA 双重加密
|
||
- **测试结果**: ✅ 成功
|
||
- **Token 获取**: ✅ 正常
|
||
- **Token 有效期**: 7 天
|
||
|
||
### Token 验证测试
|
||
|
||
- **Authorization 格式**: Bearer {token}
|
||
- **必需 Header**: clientid, referer, Accept-Language
|
||
- **权限验证**: ✅ admin 用户完全权限
|
||
|
||
## 🔍 业务接口测试
|
||
|
||
### [模块名称]接口测试
|
||
|
||
#### 列表查询接口
|
||
|
||
- **接口**: GET /[module]/list
|
||
- **参数**: pageNum, pageSize, [查询条件]
|
||
- **响应格式**: {total, rows, code, msg}
|
||
- **测试结果**: ✅ 通过
|
||
- **响应时间**: [x]ms
|
||
|
||
#### 详情查询接口
|
||
|
||
- **接口**: GET /[module]/{id}
|
||
- **响应格式**: {code, msg, data}
|
||
- **测试结果**: ✅ 通过
|
||
- **响应时间**: [x]ms
|
||
|
||
#### 新增接口
|
||
|
||
- **接口**: POST /[module]
|
||
- **请求格式**: JSON 对象
|
||
- **响应格式**: {code, msg, data}
|
||
- **测试结果**: ✅ 通过
|
||
- **响应时间**: [x]ms
|
||
|
||
#### 修改接口
|
||
|
||
- **接口**: PUT /[module]
|
||
- **请求格式**: JSON 对象(包含 id)
|
||
- **响应格式**: {code, msg, data}
|
||
- **测试结果**: ✅ 通过
|
||
- **响应时间**: [x]ms
|
||
|
||
#### 删除接口
|
||
|
||
- **接口**: DELETE /[module]/{id}
|
||
- **响应格式**: {code, msg, data}
|
||
- **测试结果**: ✅ 通过
|
||
- **响应时间**: [x]ms
|
||
|
||
## 📊 测试统计
|
||
|
||
- **总接口数**: [数量]
|
||
- **测试通过**: [数量]
|
||
- **测试失败**: [数量]
|
||
- **通过率**: [百分比]%
|
||
|
||
## ⚠️ 问题记录
|
||
|
||
[记录测试中发现的问题]
|
||
|
||
## 🎯 结论
|
||
|
||
[测试结论和建议]
|
||
|
||
---
|
||
|
||
**测试执行**: 基于 `test/` 目录下的测试脚本
|
||
**文档路径**: `docs/测试文档/[模块]/[功能]/[报告名称]-YYYY-MM-DD.md`
|
||
```
|
||
|
||
## 5. 🎯 开发和测试建议
|
||
|
||
### ✅ 已完成的核心功能
|
||
|
||
1. **登录认证**: AES+RSA 双重加密登录机制完全正常
|
||
2. **Token 获取**: 可稳定获取 7 天有效期的 JWT Token
|
||
3. **权限验证**: admin 用户具有完全权限 (_:_:\*)
|
||
4. **API 调用**: Token 可正常用于所有业务 API 调用
|
||
|
||
### 🔧 开发最佳实践
|
||
|
||
1. **使用标准脚本**: 优先使用 `test/custom-login-script.js` 获取 Token
|
||
2. **Header 规范**: 始终包含 clientid、encrypt-key、referer 三个关键 Header
|
||
3. **语言头格式**: 使用 `Accept-Language: zh-CN,zh;q=0.9,en;q=0.8`
|
||
4. **错误处理**: 实现 Token 过期自动重新获取机制
|
||
|
||
### 🚀 后续优化建议
|
||
|
||
1. **Token 管理**: 实现 Token 自动刷新和缓存机制
|
||
2. **环境配置**: 支持开发、测试、生产环境的灵活切换
|
||
3. **自动化测试**: 建立基于 Token 的自动化 API 测试流程
|
||
4. **性能监控**: 添加 API 响应时间和成功率监控
|
||
|
||
### 📚 相关文档和工具
|
||
|
||
- **成功的登录脚本**: `test/custom-login-script.js` 和 `test/quick-token-getter.js`
|
||
- **使用指南**: `test/登录脚本使用说明.md`
|
||
- **API 文档**: `docs/开发文档/API.md`
|
||
- **变更记录**: `docs/变更管理/code-adjust-record.md`
|
||
|
||
### 🎯 使用建议
|
||
|
||
1. **开发阶段**: 使用 `quick-token-getter.js` 快速获取 Token 进行测试
|
||
2. **集成测试**: 使用 `custom-login-script.js` 进行完整的登录流程测试
|
||
3. **生产环境**: 将加密登录逻辑集成到实际应用中,实现自动 Token 管理
|
||
|
||
## 6. 🧪 自动化测试脚本
|
||
|
||
### 完整的 API 测试流程
|
||
|
||
```javascript
|
||
// 完整的API自动化测试脚本示例
|
||
async function runCompleteAPITest() {
|
||
console.log('🚀 开始API自动化测试...\n');
|
||
|
||
try {
|
||
// 1. 获取Token
|
||
console.log('1️⃣ 获取登录Token...');
|
||
const token = await encryptedLogin();
|
||
console.log('✅ Token获取成功\n');
|
||
|
||
// 2. 测试用户信息接口
|
||
console.log('2️⃣ 测试用户信息接口...');
|
||
const userInfo = await getUserInfo(token);
|
||
if (userInfo.success) {
|
||
console.log('✅ 用户信息接口测试通过');
|
||
console.log(`用户: ${userInfo.data.data.user.userName}`);
|
||
console.log(`权限: ${userInfo.data.data.permissions}\n`);
|
||
}
|
||
|
||
// 3. 测试分页列表接口
|
||
console.log('3️⃣ 测试分页列表接口...');
|
||
const userList = await testUserListAPI(token);
|
||
if (userList.success) {
|
||
console.log('✅ 分页列表接口测试通过\n');
|
||
}
|
||
|
||
// 4. 测试CRUD接口(可选)
|
||
console.log('4️⃣ 测试CRUD接口...');
|
||
// const crudResults = await testCRUDAPIs(token, '/system/dept', testDeptData);
|
||
|
||
console.log('🎉 API自动化测试完成!');
|
||
} catch (error) {
|
||
console.error('❌ 测试失败:', error.message);
|
||
}
|
||
}
|
||
|
||
// 执行测试
|
||
runCompleteAPITest();
|
||
```
|
||
|
||
### 性能测试脚本
|
||
|
||
```javascript
|
||
// API性能测试脚本
|
||
async function performanceTest(token, endpoint, concurrent = 10, iterations = 100) {
|
||
console.log(`开始性能测试: ${endpoint}`);
|
||
console.log(`并发数: ${concurrent}, 迭代次数: ${iterations}\n`);
|
||
|
||
const startTime = Date.now();
|
||
const results = [];
|
||
|
||
for (let i = 0; i < concurrent; i++) {
|
||
const promises = [];
|
||
|
||
for (let j = 0; j < iterations / concurrent; j++) {
|
||
promises.push(
|
||
callAPIWithToken(token, endpoint, null, 'GET')
|
||
.then((result) => ({
|
||
success: result.success,
|
||
time: Date.now(),
|
||
}))
|
||
.catch((error) => ({
|
||
success: false,
|
||
error: error.message,
|
||
time: Date.now(),
|
||
})),
|
||
);
|
||
}
|
||
|
||
results.push(...(await Promise.all(promises)));
|
||
}
|
||
|
||
const endTime = Date.now();
|
||
const totalTime = endTime - startTime;
|
||
const successCount = results.filter((r) => r.success).length;
|
||
const failCount = results.length - successCount;
|
||
|
||
console.log('📊 性能测试结果:');
|
||
console.log(`总请求数: ${results.length}`);
|
||
console.log(`成功数: ${successCount}`);
|
||
console.log(`失败数: ${failCount}`);
|
||
console.log(`成功率: ${((successCount / results.length) * 100).toFixed(2)}%`);
|
||
console.log(`总耗时: ${totalTime}ms`);
|
||
console.log(`平均响应时间: ${(totalTime / results.length).toFixed(2)}ms`);
|
||
console.log(`QPS: ${(results.length / (totalTime / 1000)).toFixed(2)} req/s`);
|
||
|
||
return {
|
||
total: results.length,
|
||
success: successCount,
|
||
fail: failCount,
|
||
successRate: successCount / results.length,
|
||
totalTime,
|
||
avgResponseTime: totalTime / results.length,
|
||
qps: results.length / (totalTime / 1000),
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
**🎉 成功状态**: 登录获取 Token 功能已完全实现并正常工作,可以稳定用于 API 开发和测试。
|