Files
hzdyjs/.cursor/cursorrules-api-test.md
T
zlwu 28232d5d46 feat: 移动端开发规范重大更新
- 🔥 完全重写 .cursor/cursorrules-mobile.md (940行)
  * 基于实际mobile工程Vue 3.4.21+uniapp+uview-plus架构
  * 移除所有JeeSite相关内容,精准匹配实际项目
  * 新增11个完整章节:技术栈、项目结构、页面开发、组件规范等

- 📚 创建完整规范文档 docs/开发文档/移动端开发规范总结.md (800+行)
  * 涵盖从项目架构到部署的全流程指导
  * 提供可直接使用的页面和组件模板
  * 包含现代CSS变量设计系统和用户体验优化

- 🔄 同步更新主配置文件 .cursorrules
  * 更新移动端技术栈描述
  * 调整为Vue 3.4.21+uniapp+uview-plus 3.4.45架构

- 📝 完善变更记录
  * 详细记录规范更新背景和技术价值
  * 为后续维护提供完整历史记录

核心价值:解决规范与实际项目不匹配问题,为Cursor AI提供准确的移动端开发上下文,确保生成代码完全符合实际项目架构。
2025-07-04 15:51:33 +08:00

30 KiB
Raw Blame History

Cursor Rules - API 测试和登录方法

适用范围


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 加密登录(推荐)

// 完整的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 获取(简化版)

// 快速获取Token的简化版本
async function getToken(username = 'admin', password = 'admin123') {
    const { getToken } = require('./test/quick-token-getter');
    return await getToken(username, password);
}

🔧 快速测试工具

使用 test 目录下的测试脚本

# 在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 - 快速获取版,代码简洁易懂

依赖安装

{
    "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 格式:

    {
      'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e',
      'encrypt-key': '[RSA加密的AES密钥]',
      'referer': 'http://localhost/login?redirect=%252Findex'
    }
    
  2. 正确的加密流程:

    • 生成 32 位随机 AES 密钥
    • 使用 AES-ECB 模式加密登录数据
    • 使用 RSA-PKCS1 加密 AES 密钥
    • 设置正确的请求头格式

3. 🔍 API 测试最佳实践

测试环境配置

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 测试方法

// 通用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 调用

// 带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;
}

分页接口测试

// 分页接口测试模板
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 接口测试套件

// 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. 🐍 Python API 测试最佳实践

💡 基于场地预约 API 测试脚本的成功经验

⚠️ 本规范基于test/场地预约API测试脚本.py的开发实践制定,适用于所有新 API 模块测试

🔧 强制加密登录要求

所有 API 测试脚本必须使用 AES+RSA 双重加密登录,禁止简化登录和无认证访问

# 强制依赖检查
try:
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_v1_5
    CRYPTO_AVAILABLE = True
    print("✅ 加密库已加载,将使用AES+RSA双重加密登录")
except ImportError:
    print("❌ 错误:缺少必需的加密库!")
    print("🔧 请安装加密库:pip install pycryptodome")
    print("📖 参考文档:.cursor/cursorrules-api-test.md")
    print("🚫 脚本退出,必须使用加密登录方式")
    exit(1)

📋 标准测试脚本结构

基于场地预约 API 测试的成功模式:

class [Module]APITest:
    def __init__(self, base_url="http://localhost/dev-api"):
        self.base_url = base_url
        self.session = requests.Session()
        self.token = None
        self.user_info = None

        # API测试配置 - 参考cursorrules-api-test.md
        self.config = {
            'clientId': 'e5cd7e4891bf95d1d19206ce24a7b32e',
            'tenantId': '000000',
            'referer': 'http://localhost/login?redirect=%252Findex',
            'rsaKey': 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
        }

        # 设置标准Headers
        self.session.headers.update({
            'Content-Type': 'application/json;charset=utf-8',
            'clientid': self.config['clientId'],
            'referer': self.config['referer'],
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'isToken': 'false',
            'isEncrypt': 'false',
            'repeatSubmit': 'false'
        })

    def generate_aes_key(self):
        """生成32位随机AES密钥"""
        chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
        return ''.join(random.choices(chars, k=32))

    def aes_encrypt(self, data, key):
        """AES加密 - ECB模式"""
        key_bytes = key.encode('utf-8')
        data_bytes = data.encode('utf-8')
        padded_data = pad(data_bytes, AES.block_size)
        cipher = AES.new(key_bytes, AES.MODE_ECB)
        encrypted_data = cipher.encrypt(padded_data)
        return base64.b64encode(encrypted_data).decode('utf-8')

    def rsa_encrypt(self, aes_key):
        """RSA加密AES密钥"""
        pem_key = f"-----BEGIN PUBLIC KEY-----\n{self.config['rsaKey']}\n-----END PUBLIC KEY-----"
        rsa_key = RSA.import_key(pem_key)
        aes_key_base64 = base64.b64encode(aes_key.encode('utf-8')).decode('utf-8')
        cipher = PKCS1_v1_5.new(rsa_key)
        encrypted_data = cipher.encrypt(aes_key_base64.encode('utf-8'))
        return base64.b64encode(encrypted_data).decode('utf-8')

    def login(self, username="admin", password="admin123"):
        """强制AES+RSA双重加密登录"""
        self.log("🔐 开始AES+RSA双重加密登录...")

        try:
            # 生成AES密钥
            aes_key = self.generate_aes_key()

            # 构造登录数据
            login_data = {
                "tenantId": self.config['tenantId'],
                "username": username,
                "password": password,
                "clientId": self.config['clientId'],
                "grantType": "password"
            }

            # AES加密登录数据
            login_json = json.dumps(login_data, separators=(',', ':'))
            encrypted_data = self.aes_encrypt(login_json, aes_key)

            # RSA加密AES密钥
            encrypted_key = self.rsa_encrypt(aes_key)

            # 设置加密登录Headers
            headers = {
                'Content-Type': 'application/json;charset=utf-8',
                'clientid': self.config['clientId'],
                'encrypt-key': encrypted_key,
                'referer': self.config['referer'],
                'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                'isToken': 'false',
                'isEncrypt': 'true',
                'repeatSubmit': 'false'
            }

            # 发送登录请求
            response = self.session.post(
                f"{self.base_url}/auth/login",
                data=encrypted_data,
                headers=headers,
                timeout=10
            )

            if response.status_code == 200:
                result = response.json()
                if result.get('code') == 200 and result.get('data'):
                    # 获取Token
                    token_fields = ['access_token', 'token', 'accessToken']
                    for field in token_fields:
                        if field in result['data']:
                            self.token = result['data'][field]
                            break

                    if self.token:
                        self.user_info = result['data']

                        # 设置认证header
                        self.session.headers.update({
                            'Authorization': f'Bearer {self.token}',
                            'isToken': 'true',
                            'isEncrypt': 'false'
                        })

                        self.log("✅ AES+RSA双重加密登录成功!")
                        return True

            self.log("❌ AES+RSA双重加密登录失败")
            return False

        except Exception as e:
            self.log(f"❌ 登录异常: {str(e)}")
            return False

    def get_server_info(self):
        """检测服务可用性"""
        test_endpoints = ["/actuator/health", "/auth/login"]
        for endpoint in test_endpoints:
            try:
                response = self.session.get(f"{self.base_url}{endpoint}", timeout=5)
                if response.status_code in [200, 401, 403]:
                    self.log(f"✓ 服务可用: {endpoint}")
                    return True
            except:
                continue
        return False

    def api_request(self, method, url, data=None, params=None):
        """标准API请求封装"""
        try:
            full_url = f"{self.base_url}{url}"

            if method.upper() == 'GET':
                response = self.session.get(full_url, params=params)
            elif method.upper() == 'POST':
                response = self.session.post(full_url, json=data, params=params)
            elif method.upper() == 'PUT':
                response = self.session.put(full_url, json=data)
            elif method.upper() == 'DELETE':
                response = self.session.delete(full_url)

            self.log(f"{method} {url} - HTTP {response.status_code}")

            if response.status_code == 200:
                return response.json()
            else:
                self.log(f"请求失败: {response.text}")
                return None

        except Exception as e:
            self.log(f"请求异常: {str(e)}")
            return None

    def test_entity_management(self):
        """基础实体管理测试(CRUD)"""
        # 1. 查询列表
        # 2. 新增数据
        # 3. 查询详情
        # 4. 修改数据
        # 5. 删除数据
        pass

    def test_business_features(self):
        """业务功能测试"""
        # 特定业务规则和功能测试
        pass

    def test_business_rules(self):
        """业务规则验证测试"""
        # 边界条件和异常情况测试
        pass

    def cleanup_test_data(self):
        """清理测试数据"""
        # 删除测试过程中创建的数据
        pass

    def run_all_tests(self):
        """执行完整测试流程"""
        # 1. 检测服务可用性
        if not self.get_server_info():
            self.log("后端服务不可用,测试终止")
            return False

        # 2. 强制加密登录
        if not self.login():
            self.log("❌ AES+RSA双重加密登录失败,测试终止")
            return False

        try:
            # 3. 执行各类测试
            self.test_entity_management()
            self.test_business_features()
            self.test_business_rules()
        finally:
            # 4. 清理测试数据
            self.cleanup_test_data()

        return True

🚨 强制性要求

每个新的 API 测试脚本必须遵循:

  1. 强制加密登录:不得使用简化登录或无认证访问
  2. 完整功能覆盖:测试所有 API 接口(通常 16 个)
  3. 业务规则验证:包含边界条件和异常情况测试
  4. 自动数据清理:测试完成后清理创建的数据
  5. 详细日志记录:每个步骤都有清晰的日志输出

📦 依赖要求

# 必需的Python包
pip install requests pycryptodome

🎯 测试脚本命名规范

test/
├── [模块名]API测试脚本.py          # 主测试脚本
├── [模块名]API批量测试脚本.py      # 批量测试脚本(可选)
└── [模块名]API性能测试脚本.py      # 性能测试脚本(可选)

📊 测试覆盖标准

基于场地预约 API 的 16 个接口模式:

基础管理接口(6 个):

  • ✅ 分页查询列表测试
  • ✅ 查询详情测试
  • ✅ 新增功能测试
  • ✅ 修改功能测试
  • ✅ 删除功能测试
  • ✅ 获取可用选项测试

业务功能接口(4 个):

  • ✅ 查询我的数据测试
  • ✅ 查询待处理数据测试
  • ✅ 业务规则检查测试
  • ✅ 审批操作测试

辅助功能接口(6 个):

  • ✅ 导出 Excel 测试
  • ✅ 导入 Excel 测试
  • ✅ 统计数据测试
  • ✅ 批量操作测试
  • ✅ 启用操作测试
  • ✅ 禁用操作测试

5. 📝 API 测试记录模板

测试结果记录格式

## 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 调用
-   ✅ 用户权限验证通过
-   ✅ 加密解密机制正常

详细测试报告模板

# 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 测试流程

// 完整的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();

性能测试脚本

// 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 开发和测试。