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提供准确的移动端开发上下文,确保生成代码完全符合实际项目架构。
This commit is contained in:
1 parent
e8ece1b612
commit
28232d5d46
131 files changed
+17170
-5479
No files matched your search
@@ -399,7 +399,304 @@ async function testCRUDAPIs(token, baseEndpoint, testData) {
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 📝 API 测试记录模板
|
||||
## 4. 🐍 Python API 测试最佳实践
|
||||
|
||||
### 💡 基于场地预约 API 测试脚本的成功经验
|
||||
|
||||
**⚠️ 本规范基于`test/场地预约API测试脚本.py`的开发实践制定,适用于所有新 API 模块测试**
|
||||
|
||||
#### 🔧 强制加密登录要求
|
||||
|
||||
**所有 API 测试脚本必须使用 AES+RSA 双重加密登录,禁止简化登录和无认证访问**
|
||||
|
||||
```python
|
||||
# 强制依赖检查
|
||||
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 测试的成功模式**:
|
||||
|
||||
```python
|
||||
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. **详细日志记录**:每个步骤都有清晰的日志输出
|
||||
|
||||
#### 📦 依赖要求
|
||||
|
||||
```bash
|
||||
# 必需的Python包
|
||||
pip install requests pycryptodome
|
||||
```
|
||||
|
||||
#### 🎯 测试脚本命名规范
|
||||
|
||||
```
|
||||
test/
|
||||
├── [模块名]API测试脚本.py # 主测试脚本
|
||||
├── [模块名]API批量测试脚本.py # 批量测试脚本(可选)
|
||||
└── [模块名]API性能测试脚本.py # 性能测试脚本(可选)
|
||||
```
|
||||
|
||||
#### 📊 测试覆盖标准
|
||||
|
||||
**基于场地预约 API 的 16 个接口模式**:
|
||||
|
||||
**基础管理接口(6 个)**:
|
||||
|
||||
- ✅ 分页查询列表测试
|
||||
- ✅ 查询详情测试
|
||||
- ✅ 新增功能测试
|
||||
- ✅ 修改功能测试
|
||||
- ✅ 删除功能测试
|
||||
- ✅ 获取可用选项测试
|
||||
|
||||
**业务功能接口(4 个)**:
|
||||
|
||||
- ✅ 查询我的数据测试
|
||||
- ✅ 查询待处理数据测试
|
||||
- ✅ 业务规则检查测试
|
||||
- ✅ 审批操作测试
|
||||
|
||||
**辅助功能接口(6 个)**:
|
||||
|
||||
- ✅ 导出 Excel 测试
|
||||
- ✅ 导入 Excel 测试
|
||||
- ✅ 统计数据测试
|
||||
- ✅ 批量操作测试
|
||||
- ✅ 启用操作测试
|
||||
- ✅ 禁用操作测试
|
||||
|
||||
## 5. 📝 API 测试记录模板
|
||||
|
||||
### 测试结果记录格式
|
||||
|
||||
|
||||
Reference in new issue
Block a user