Files
hzdyjs/.cursorrules.backup-20250701-122609
T
zlwu 249b1dfeb4 feat: 完善项目开发规范和测试文档体系
📝 主要改进:
• Cursor配置模块化:拆分为前端、后端、移动端、文档、API测试5个专门规范文件
• API文档重新组织:按业务模块拆分到docs/开发文档/API/目录下
• 新增维修分类功能完整测试方案和自动化测试脚本
• 后端热启动脚本完善,支持Linux/Windows双平台
• 强化文档同步更新规范,确保代码与文档一致性

🔧 技术改进:
• 优化Cursor AI工作流程和代码生成质量
• 完善API测试规范(AES+RSA双重加密登录方法)
• 提升开发效率和代码质量标准化程度

�� 测试覆盖:
• 维修分类管理功能端到端测试验证通过
• 包含页面加载、CRUD操作、搜索功能等核心测试用例

更新时间:2025-07-01
2025-07-01 17:53:05 +08:00

2359 lines
77 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Cursor Rules - 项目开发规范
## 项目结构说明
- **前端工程**:`web/` (基于Vue 3 + TypeScript + Element Plus)
- **后端工程**:`backend/` (基于RuoYi-Vue-Plus + Spring Boot 3.4.6)
- **移动端工程**:`mobile/` (基于uniapp + uView UI构建的校园管理移动端应用)
- **文档管理**:`docs/` (项目的需求、设计、开发、测试、部署文档)
---
# 第一部分:项目文档管理规范
## 1. 文档结构管理 (docs/)
### 🔴 文档目录组织(中文化架构)
```
docs/
├── 项目总览/ # 项目基本信息和架构概览
│ ├── README.md # 项目总览主文档
│ └── 项目总览模板.md # 项目总览标准模板
├── 业务模块/ # 业务模块文档(为AI提供业务上下文)
│ ├── README.md # 业务模块管理总览
│ ├── 业务模块开发模板.md # 业务模块标准开发模板
│ ├── hq-satisfaction-survey/ # 后勤满意度调查模块
│ ├── hall-reservation/ # 报告厅预约模块
│ ├── system-management/ # 系统管理模块
│ └── user-management/ # 用户管理模块
├── 变更管理/ # 变更管理中心
│ ├── README.md # 变更管理流程和规范
│ └── code-adjust-record.md # 代码调整记录
├── 开发文档/ # 开发指南和技术规范
│ ├── README.md # 开发文档总览
│ ├── API.md # API接口完整文档
│ └── API文档模板.md # API文档标准模板
├── 设计文档/ # 设计文档
│ ├── README.md # 设计文档说明
│ └── database/ # 数据库设计
│ ├── hzdyjs_xg.sql # 完整数据库模型
│ ├── 01-workflow-module.sql # 工作流模块SQL
│ ├── 02-code-generator-module.sql # 代码生成模块SQL
│ ├── 03-logistics-module.sql # 后勤管理模块SQL
│ ├── 04-job-scheduler-module.sql # 任务调度模块SQL
│ ├── 05-system-management-module.sql # 系统管理模块SQL
│ ├── 06-test-module.sql # 测试模块SQL
│ ├── SQL文件说明.md # SQL文件拆分说明
│ ├── mysql-database-standard.md # MySQL数据库建设规范
│ ├── database_msg.md # 环境配置信息
│ └── README.md # 数据库设计说明
├── 需求文档/ # 需求文档
│ ├── README.md # 需求管理说明
│ ├── 后勤报告厅预约需求/ # 报告厅预约系统需求
│ └── 后勤满意度调查需求/ # 满意度调查系统需求
├── 测试文档/ # 测试文档(按需求维度组织)
│ ├── README.md # 测试文档管理总览
│ ├── 后勤管理/ # 后勤管理相关测试文档
│ │ ├── 物业报修/ # 物业报修系统测试文档
│ │ ├── 满意度调查/ # 满意度调查系统测试文档
│ │ └── 报告厅预约/ # 报告厅预约系统测试文档
│ ├── 系统管理/ # 系统管理相关测试文档
│ ├── 用户管理/ # 用户管理相关测试文档
│ └── 工作流管理/ # 工作流管理相关测试文档
├── 部署文档/ # 部署文档
│ └── README.md # 部署指南
├── 中间件配置/ # 中间件配置文档
│ ├── README.md # 中间件配置说明
│ └── mysql-config.md # MySQL配置文档
├── 知识库/ # 知识库
├── 报告文档/ # 报告文档
├── structure-optimization-plan.md # 文档结构优化方案
└── README.md # 文档体系总说明
```
### 🔴 重要文档说明
- **工程本地启动指导.md** (项目根目录):包含完整的环境配置和启动指南
- **技术要求更新**:Node.js 20.15.x+, npm 10.7.x+
- **数据库环境**:支持本地安装或使用阿里云测试环境
- **前端访问地址**:http://localhost (非3000端口)
## 2. 🚨 强制性文档同步更新规则
### 📋 核心原则:代码与文档必须同步更新
**⚠️ 超级重要:每次使用Cursor AI进行代码调整后,必须立即同步更新相应的项目文档!**
### 🔴 强制更新触发条件
每次代码调整必须检查并更新以下文档:
#### 后端代码调整时的强制文档更新:
- **✅ API接口变更**:
- 必须立即更新 `docs/开发文档/API.md`
- 新增接口:添加完整接口文档(地址、参数、响应、权限、示例)
- 修改接口:更新参数说明、响应格式、错误码
- 删除接口:标记为已废弃,说明替代方案
- 权限变更:更新权限要求说明
- **✅ 数据库变更**:
- 更新 `docs/设计文档/database/` 下的相关文档
- 新增表:添加表结构说明和字段注释
- 修改表:更新字段变更和索引调整
- 数据迁移:记录迁移脚本和注意事项
- **✅ 业务逻辑变更**:
- 更新对应 `docs/业务模块/[模块名称]/` 下的业务文档
- 更新业务流程图和业务规则说明
- 修改用户故事和功能需求
- **✅ 配置变更**:
- 更新 `docs/中间件配置/` 下的配置文档
- 更新 `docs/部署文档/` 下的部署说明
#### 前端代码调整时的强制文档更新:
- **✅ 页面功能变更**:
- 更新对应业务模块的用户操作文档
- 更新UI设计规范文档
- **✅ API调用变更**:
- 检查前端API调用是否与后端API文档一致
- 更新API对接说明文档
- **✅ 组件变更**:
- 更新组件使用说明和属性文档
#### 移动端代码调整时的强制文档更新:
- **✅ 功能变更**:更新移动端功能说明文档
- **✅ API对接变更**:更新移动端API调用文档
- **✅ 用户流程变更**:更新用户操作指南
#### 📚 docs文档变更时的强制同步更新规则:
**⚠️ 超级重要:每当docs/目录下的文档结构或重要内容发生变更时,必须立即同步更新.cursorrules文件!**
- **🔴 文档结构变更**:
- 新增/删除目录:同步更新.cursorrules中的"文档目录组织"章节
- 重命名目录:更新所有相关路径引用
- 调整文档层级:更新文档结构说明
- **🔴 重要文档变更**:
- 新增标准模板:在"文档模板体系"中添加说明
- 更新开发规范:同步调整.cursorrules中对应的规范要求
- 修改工作流程:更新"文档更新标准工作流程"
- **🔴 技术环境变更**:
- 环境要求调整:更新.cursorrules中的技术栈规范
- 配置信息变更:同步更新相关配置说明
- 启动流程调整:更新开发指导相关内容
- **🔴 业务模块变更**:
- 新增业务模块:在.cursorrules中添加模块说明
- 模块架构调整:更新业务模块文档管理规范
- API接口变更:确保.cursorrules中的API规范同步
**强制检查清单**:
- [ ] .cursorrules中的文档目录结构是否与实际一致
- [ ] 重要文档路径引用是否全部更新
- [ ] 新增的开发规范是否已同步到.cursorrules
- [ ] 技术要求和环境配置是否保持一致
### ⏰ 时间填写强制性规范
**🚨 重要:每次记录变更必须填写真实的当前时间!**
#### 强制性时间填写要求:
1. **变更时间**:必须填写变更发生的实际时间,不得使用错误或虚假时间
2. **时间格式**:严格按照 `YYYY-MM-DD HH:mm:ss` 格式填写
3. **时区规范**:使用北京时间(UTC+8)
4. **获取方法**:
- 在macOS/Linux系统中使用 `date "+%Y-%m-%d %H:%M:%S"` 命令
- 在Windows系统中使用 `Get-Date -Format "yyyy-MM-dd HH:mm:ss"` 命令
- 或使用当前系统显示的时间
5. **验证要求**:变更时间必须与实际代码修改时间相符
#### 错误示例:
- ❌ 使用1月份时间但实际是6月份
- ❌ 使用固定模板时间不修改
- ❌ 时间格式不正确
#### 正确示例:
- ✅ 2025-06-30 15:43:20 (实际是6月30日下午3点43分)
- ✅ 2025-06-30 18:30:00 (实际是6月30日晚上6点30分)
### 📝 变更记录排序规范
**🚨 重要:变更记录必须按照倒序排列,最新记录在最上面!**
#### 记录排序要求:
1. **排序原则**:按时间倒序排列,最新的变更记录放在文件最上面
2. **新增记录**:每次新增变更记录都必须插入到文件开头(标题下方)
3. **时间顺序**:确保后面的记录时间早于前面的记录时间
4. **便于查看**:这样安排便于快速查看最近的变更情况
#### 正确的排序示例:
```markdown
# 代码调整记录
## 调整记录 - 2025-06-30 18:30:00 ← 最新记录
## 调整记录 - 2025-06-30 15:43:20 ← 次新记录
## 调整记录 - 2025-06-29 10:20:00 ← 更早记录
## 调整记录 - 2025-06-28 14:15:00 ← 最早记录
```
#### 错误示例:
- ❌ 新记录添加到文件末尾
- ❌ 时间顺序混乱
- ❌ 按正序排列(最早在上面)
### 🔄 文档更新标准工作流程
#### Cursor AI 辅助开发的文档更新流程:
```
1. **AI代码生成/修改完成**
↓
2. **立即检查文档更新需求**
- 是否涉及API变更?
- 是否涉及数据库变更?
- 是否涉及业务逻辑变更?
- 是否涉及配置变更?
- 是否涉及docs文档结构变更?
↓
3. **立即更新相关文档**(不得延后!)
- 使用标准模板格式
- 确保信息准确完整
- 添加真实示例
- ⚠️ 填写真实的当前时间,不得使用模板时间
↓
4. **检查并更新.cursorrules文件**(重要!)
- 如有docs文档结构变更,同步更新.cursorrules
- 如有技术要求变更,同步更新技术栈规范
- 如有开发流程变更,同步更新工作流程
↓
5. **记录变更日志**(按倒序插入到当日文件开头!)
- 检查并创建当日变更记录文件:`code-adjust-record-YYYY-MM-DD-{username}.md`
- 在当日文件开头添加新记录(倒序排列)
- 无需维护索引文件,专注于自己的变更记录
- 标注已同步更新的文档列表
- 标注是否已更新.cursorrules文件
↓
6. **验证文档准确性**
- 确保文档与实际代码一致
- 验证示例可以正常运行
- 验证.cursorrules与实际项目状态一致
- 确认记录时间排序正确
↓
7. **提交代码和文档变更**
```
### 📝 变更记录文件管理规范
**🚨 重要:从2025-06-30开始,变更记录按日期和用户分文件管理!**
#### 📁 文件命名规范
- **文件格式**: `code-adjust-record-YYYY-MM-DD-{username}.md`
- **存放位置**: `docs/变更管理/` 目录
- **命名示例**: `code-adjust-record-2025-06-30-zlwu.md`
- **获取用户名**: 使用 `git config --get user.name` 命令获取
- **获取日期**: 使用 `date "+%Y-%m-%d"` 命令获取
#### 🔄 文件创建和使用流程
1. **检查当日文件是否存在**:
```bash
USERNAME=$(git config --get user.name)
TODAY=$(date "+%Y-%m-%d")
FILENAME="docs/变更管理/code-adjust-record-${TODAY}-${USERNAME}.md"
```
2. **文件不存在时创建新文件**:
- 使用标准模板创建当日变更记录文件
- 文件头包含日期、用户名、排序说明
3. **记录变更时**:
- 在当日文件开头插入新记录(倒序排列)
- 无需维护索引文件,每人管理自己的变更记录
#### 👥 多用户协作规范
- **独立管理**: 每个用户有独立的日变更文件,完全避免多人同时编辑冲突
- **无需协调**: 不需要维护共享索引文件,每人管理自己的变更记录
- **用户名一致性**: 确保git用户名配置正确,保持文件命名的一致性
- **文件归档**: 历史文件保留,便于追溯和审计
- **查找便利**: 通过文件名快速定位特定日期和用户的变更记录
#### 📋 每日变更文件标准格式
```markdown
# 代码调整记录 - YYYY-MM-DD - {username}
> 📅 **记录日期**: YYYY-MM-DD
> 👤 **记录人员**: {username}
> 📌 **排序说明**: 本文件按照时间倒序排列,最新的变更记录在最上面
## 调整记录 - YYYY-MM-DD HH:mm:ss
**变更ID**: CHG-YYYYMMDD-001
**变更时间**: YYYY-MM-DD HH:mm:ss (⚠️必须填写真实的当前时间!)
**变更人员**: [开发者姓名/Cursor AI辅助]
**变更类型**: 🆕新功能/🐛Bug修复/🔧重构优化/📚文档更新/⚙️配置调整
**影响级别**: 🔴重大变更/🟡中等变更/🟢小变更
### 📋 变更概述
**变更目的**: [简述变更原因和目标,1-2句话]
**影响范围**: [列出受影响的模块、功能或文件]
### 📁 涉及文件
**后端文件**:
- backend/[具体文件路径1]
- backend/[具体文件路径2]
**前端文件**:
- web/[具体文件路径1]
- web/[具体文件路径2]
**配置文件**:
- [配置文件路径]
### 🔧 变更内容详述
**业务逻辑变更**:
1. [具体业务逻辑的变更说明]
2. [新增或修改的业务规则]
**技术实现变更**:
1. [技术方案的调整说明]
2. [代码结构的优化内容]
**接口变更**:
- **新增接口**: [新增接口列表]
- **修改接口**: [修改的接口及变更内容]
- **废弃接口**: [废弃的接口及替代方案]
**数据库变更**:
- **新增表**: [新增表及字段说明]
- **修改表**: [表结构变更内容]
- **数据迁移**: [数据迁移脚本或说明]
### 📖 文档同步更新记录
**API文档**:
- [ ] ✅ 已更新 docs/开发文档/API.md
- [ ] ✅ 已更新模块API接口设计文档
**业务文档**:
- [ ] ✅ 已更新业务模块文档
- [ ] ✅ 已更新用户操作手册
**技术文档**:
- [ ] ✅ 已更新数据库设计文档
- [ ] ✅ 已更新架构设计文档
**其他文档**:
- [ ] ✅ 已更新部署文档
- [ ] ✅ 已更新配置文档
**规范文件**:
- [ ] ✅ 已检查并同步更新.cursorrules文件
- [ ] ✅ 已确认文档结构与.cursorrules一致
### 🧪 测试验证
**功能测试**:
- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] 功能验收测试通过
**文档验证**:
- [ ] 文档内容与代码实现一致
- [ ] 示例代码可以正常运行
- [ ] 接口文档已验证准确性
### 📝 备注
**已知问题**: [如有已知问题需要说明]
**后续计划**: [后续的改进或扩展计划]
**相关链接**: [相关的Issue、PR或文档链接]
---
```
## 3. 🔧 业务模块文档管理(为Cursor AI提供完整上下文)
### 业务模块文档标准结构
每个业务模块都必须包含以下完整文档:
```
业务模块/[模块名称]/
├── README.md # 模块总览
├── 需求分析/
│ ├── 业务需求说明.md # 详细业务需求
│ ├── 功能需求清单.md # 功能点清单
│ ├── 非功能需求.md # 性能、安全要求
│ └── 用户故事.md # 用户使用场景
├── 技术设计/
│ ├── 数据库设计.md # 表结构设计
│ ├── API接口设计.md # 接口定义
│ ├── 架构设计.md # 模块架构
│ └── 技术选型.md # 技术决策说明
├── 实现文档/
│ ├── 后端实现说明.md # 后端代码结构
│ ├── 前端实现说明.md # 前端代码结构
│ ├── 关键业务逻辑.md # 核心算法逻辑
│ └── 代码规范.md # 编码规范
├── 测试文档/
│ ├── 测试计划.md # 测试策略
│ ├── 测试用例.md # 具体测试用例
│ └── 测试报告.md # 测试结果
└── 运维文档/
├── 部署指南.md # 部署步骤
├── 监控配置.md # 监控指标
└── 故障处理.md # 常见问题
```
### 🤖 Cursor AI 开发提示词模板
#### 新功能开发提示词:
```
基于以下业务模块文档为 [功能名称] 开发代码:
业务上下文:docs/业务模块/[模块名称]/需求分析/
技术规范:docs/业务模块/[模块名称]/技术设计/
代码结构:docs/业务模块/[模块名称]/实现文档/
API规范:docs/开发文档/API.md
请确保:
1. 遵循项目编码规范
2. 使用标准的代码结构
3. 添加完整的注释
4. 生成单元测试代码
5. 立即更新相关文档
开发完成后请同步更新:
- docs/开发文档/API.md(如涉及API)
- docs/业务模块/[模块名称]/相关文档
- docs/变更管理/code-adjust-record.md
```
#### 文档更新提示词:
```
根据刚才的代码变更,请更新以下文档:
变更内容:[具体变更说明]
影响模块:[模块名称]
需要更新的文档:
1. docs/开发文档/API.md - [具体更新内容]
2. docs/业务模块/[模块名称]/[具体文档] - [具体更新内容]
3. docs/设计文档/database/ - [如涉及数据库变更]
请使用标准的文档模板格式,确保信息准确完整。
```
## 4. 📚 API文档管理规范
### 🔴 强制性API文档更新规则
**⚠️ 超级重要:任何API接口的新增、修改、删除都必须立即同步更新 `docs/开发文档/API.md` 文档!**
### API文档标准格式
使用 `docs/开发文档/API文档模板.md` 中的标准格式:
```markdown
#### 接口名称
**接口地址**: `HTTP方法 /api/路径`
**接口描述**: 接口功能的详细描述
**权限要求**: 权限代码或"需要登录"
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| param1 | String | Y | 参数说明 | "example" |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {}
}
```
**错误码**:
| 错误码 | 说明 | 解决方案 |
|--------|------|----------|
| 400001 | 参数错误 | 检查请求参数 |
```
### 🚨 API变更强制检查清单
当进行以下操作时,必须更新 `docs/开发文档/API.md`:
**Controller层变更**:
- [ ] 新增Controller类 → 在API.md中添加新的模块章节
- [ ] 新增@RequestMapping方法 → 添加完整的接口文档
- [ ] 修改@RequestMapping路径 → 更新接口地址
- [ ] 修改HTTP方法 → 更新接口方法
- [ ] 删除接口方法 → 标记为已废弃并说明替代方案
**参数和响应变更**:
- [ ] 新增请求参数 → 更新请求参数表格
- [ ] 修改参数类型或必填属性 → 更新参数说明
- [ ] 修改响应数据结构 → 更新响应示例
- [ ] 新增错误码 → 更新错误码说明表
**权限和安全变更**:
- [ ] 新增@SaCheckPermission注解 → 更新权限要求
- [ ] 修改权限代码 → 更新权限说明
- [ ] 修改接口访问级别 → 更新权限要求说明
## 5. 📊 文档模板体系
### 已创建的标准模板:
- **`docs/项目总览/项目总览模板.md`** - 项目基本信息模板
- **`docs/业务模块/业务模块开发模板.md`** - 业务模块开发标准模板
- **`docs/开发文档/API文档模板.md`** - API接口文档标准模板
### 模板使用规范:
1. **新项目或模块开发时**:复制对应模板,替换占位符
2. **文档更新时**:参考模板格式,保持结构一致
3. **Cursor AI生成文档时**:使用模板作为格式参考
## 6. 🔍 文档质量控制
### 文档完整性检查清单:
- [ ] 文档结构符合标准模板
- [ ] 内容与实际代码实现一致
- [ ] API文档包含完整示例
- [ ] 业务逻辑描述清晰准确
- [ ] 技术实现说明详细
- [ ] 变更历史有完整记录
- [ ] 所有占位符已替换为真实内容
### 文档准确性验证:
- [ ] API接口示例可以正常调用
- [ ] 数据库脚本可以成功执行
- [ ] 配置文档与实际配置一致
- [ ] 部署文档可以成功部署
## 7. 🧪 测试文档管理规范
### 🔴 测试文档组织原则
- **按需求维度分类**:测试文档必须按照业务需求模块进行组织,不得混合存放
- **结论性文档独立存放**:测试结论性文档必须存放在 `docs/测试文档/` 目录下
- **测试代码独立存放**:测试相关代码必须只存放在 `test/` 目录下
- **日期标识规范**:每次创建的测试文档必须以日期结尾来区分版本
### 🔴 测试文档目录结构规范
```
docs/测试文档/
├── README.md # 测试文档管理总览
├── [业务模块]/ # 按业务模块分类
│ ├── [具体功能]/ # 具体功能测试
│ │ ├── [功能]接口测试报告-YYYY-MM-DD.md # 接口测试报告
│ │ ├── [功能]功能测试报告-YYYY-MM-DD.md # 功能测试报告
│ │ ├── [功能]性能测试报告-YYYY-MM-DD.md # 性能测试报告
│ │ └── [功能]集成测试报告-YYYY-MM-DD.md # 集成测试报告
│ └── ...
└── ...
test/
├── package.json # 测试依赖配置
├── [功能]-api-test.js # API接口测试脚本
├── [功能]-detailed-test.js # 详细测试分析脚本
├── [功能]-performance-test.js # 性能测试脚本
└── ...
```
### 🔴 测试文档强制要求
#### 1. 测试结论性文档放置规则
- **强制位置**:必须放置在 `docs/测试文档/` 目录下
- **分类方式**:按照需求维度创建子文件夹存放
- **命名规范**:文档名称必须以日期结尾(格式:YYYY-MM-DD)
- **示例路径**:
```
docs/测试文档/后勤管理/物业报修/物业报修接口测试报告-2025-01-26.md
docs/测试文档/系统管理/用户管理/用户管理功能测试报告-2025-01-26.md
```
#### 2. 测试代码存放规则
- **强制位置**:只能存放在 `test/` 目录下
- **禁止混合**:test目录下不得存放测试结论性文档
- **代码分类**:按功能模块组织测试脚本
- **示例文件**:
```
test/pm-repair-api-test.js # 物业报修API测试
test/user-management-test.js # 用户管理测试
test/custom-login-script.js # 登录认证工具
```
#### 3. 测试文档必含信息
每个测试结论性文档必须包含以下信息:
- **📁 测试代码路径**:明确标注对应的测试脚本位置
- **🔧 使用方法**:详细说明如何运行测试脚本
- **📊 测试结果**:完整的测试结果和数据分析
- **🎯 结论建议**:明确的测试结论和改进建议
- **⚠️ 问题记录**:发现的问题和解决方案
#### 测试文档标准模板格式:
```markdown
# [功能模块]测试报告
## 🎯 测试概览
**测试时间**: YYYY-MM-DD HH:mm:ss (⚠️必须填写真实的当前时间!)
**测试范围**: [具体测试范围]
**需求模块**: [所属业务模块]
## 📁 测试代码路径
**测试脚本位置**:
- **主要测试脚本**: `test/[功能]-api-test.js`
- **详细分析脚本**: `test/[功能]-detailed-test.js`
- **辅助工具脚本**: `test/[工具名].js`
**使用方法**:
```bash
cd test
npm install
node [功能]-api-test.js
```
## ✅ 测试结果总结
[测试结果详细内容]
## 🎯 结论
[测试结论和建议]
---
**测试执行**: 基于 `test/` 目录下的测试脚本
**文档路径**: `docs/测试文档/[模块]/[功能]/[报告名称]-YYYY-MM-DD.md`
```
### 🔴 强制工作流程
#### 测试执行流程:
```
1. **编写测试代码**
- 在 test/ 目录下创建测试脚本
- 确保代码可独立运行
↓
2. **执行测试**
- 运行测试脚本获取结果
- 记录详细的测试数据
↓
3. **创建测试报告**
- 在 docs/测试文档/ 按需求维度创建报告
- 文档名称必须包含日期后缀
- 必须包含测试代码路径信息
↓
4. **清理test目录**
- 删除test目录下的结论性文档
- 只保留测试代码和配置文件
↓
5. **更新文档索引**
- 更新相关README.md文件
- 在变更记录中记录测试活动
```
### 🔴 违规检查和纠正
- **检查要点**:
- [ ] test/目录下是否只有代码文件
- [ ] docs/测试文档/下是否按需求维度组织
- [ ] 测试报告是否包含代码路径信息
- [ ] 文档命名是否包含日期后缀
- **纠正措施**:
- 立即移动错误放置的文档到正确位置
- 补充缺失的测试代码路径信息
- 按规范重新组织文档结构
---
# 第二部分:Web前端开发规范 (web/)
## 1. 技术栈规范
### 核心技术
- **框架**: Vue 3.5.13 + TypeScript 5.8.3
- **UI组件库**: Element Plus 2.9.8
- **构建工具**: Vite 7.0.9
- **状态管理**: Pinia
- **路由管理**: Vue Router 4
- **HTTP客户端**: Axios
- **代码风格**: ESLint + Prettier
- **Node.js**: 20.15.x+ (推荐 20.15.0)
- **npm**: 10.7.x+
### 环境要求
- **开发环境**: 支持本地环境或阿里云测试环境
- **数据库**: MySQL/Redis 支持本机安装或使用阿里云环境
- **前端访问**: http://localhost (默认80端口)
- **后端服务**: http://localhost:8080
## 2. Art Design Pro UI 规范
### 设计理念
基于 Art Design Pro 的设计语言,追求现代化、精致、用户友好的界面体验。注重细节、动效和用户交互的流畅性。
### 颜色系统
#### 主色调 (Primary Colors)
```css
--art-primary: 93, 135, 255; /* 主品牌色 - 蓝色 */
--art-secondary: 73, 190, 255; /* 辅助色 - 天蓝色 */
--art-success: 19, 222, 185; /* 成功色 - 绿色 */
--art-warning: 255, 174, 31; /* 警告色 - 橙色 */
--art-error: 250, 137, 107; /* 错误色 - 红色 */
--art-info: 83, 155, 255; /* 信息色 - 蓝色 */
--art-danger: 255, 77, 79; /* 危险色 - 红色 */
```
#### 背景色系统
```css
/* 浅色主题 */
--art-bg-color: #fafbfc; /* 页面底色 */
--art-main-bg-color: #ffffff; /* 主要内容背景 */
--art-bg-primary: 236, 242, 255; /* 主色背景 */
--art-bg-secondary: 232, 247, 255; /* 辅助背景 */
--art-bg-success: 230, 255, 250; /* 成功背景 */
--art-bg-warning: 254, 245, 229; /* 警告背景 */
--art-bg-error: 253, 237, 232; /* 错误背景 */
/* 暗色主题 */
html.dark {
--art-bg-color: #070707; /* 页面底色 */
--art-main-bg-color: #161618; /* 主要内容背景 */
}
```
### 轮廓式按钮设计系统
#### 🎨 设计理念
全面采用轮廓式(Outline)按钮设计,提供更加优雅、现代和一致的用户界面体验。
#### 核心规范
- **Primary按钮**: 轮廓式主色设计,主色边框和文字,5%透明度主色背景
- **Success按钮**: 轮廓式成功色设计,成功色边框和文字,5%透明度成功色背景
- **Warning按钮**: 轮廓式警告色设计,警告色边框和文字,5%透明度警告色背景
- **Danger按钮**: 轮廓式危险色设计,危险色边框和文字,5%透明度危险色背景
- **Info按钮**: 轮廓式信息色设计,信息色边框和文字,5%透明度信息色背景
- **Default按钮**: 白色背景,灰色边框,灰色文字
#### 交互效果
- **悬浮状态**: 上移1px + 背景透明度变为10% + 边框透明度变为80% + 彩色阴影
- **点击状态**: 98%缩放 + 0.1s快速过渡 + 背景透明度变为15%
- **禁用状态**: 50%透明度,禁用所有交互和变换
## 3. 组件开发规范
### Vue组件结构标准
```vue
<template>
<div class="component-container">
<!-- 组件内容 -->
</div>
</template>
<script setup lang="ts" name="ComponentName">
// 1. 引入依赖
import { ref, reactive, computed, onMounted } from 'vue';
import type { ComponentProps, ComponentEmits } from './types';
// 2. 定义Props和Emits
const props = defineProps<ComponentProps>();
const emits = defineEmits<ComponentEmits>();
// 3. 响应式数据
const loading = ref(false);
const formData = reactive({});
// 4. 计算属性
const computedValue = computed(() => {
return /* 计算逻辑 */;
});
// 5. 方法定义
const handleClick = () => {
// 方法实现
};
// 6. 生命周期
onMounted(() => {
// 组件挂载后的逻辑
});
</script>
<style lang="scss" scoped>
.component-container {
// 样式实现
}
</style>
```
### 页面开发规范
#### 列表页面标准模板
```vue
<template>
<div class="p-2 page-container">
<!-- 搜索区域 -->
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<!-- 搜索表单项 -->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<!-- 表格区域 -->
<el-card shadow="never" class="button-card table-card">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<!-- 数据表格 -->
<el-table v-loading="loading" border :data="dataList" :height="tableHeight">
<el-table-column type="selection" width="55" align="center" />
<!-- 数据列 -->
<el-table-column label="操作" align="center" width="160">
<template #default="scope">
<!-- 操作按钮 -->
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList" />
</el-card>
</div>
</template>
```
## 4. API开发规范
### API接口定义标准
```typescript
// api/[module]/index.ts
import request from '@/utils/request';
import type { AxiosPromise } from 'axios';
import type { DataVO, DataForm, DataQuery } from './types';
/**
* 查询数据列表
* @param query 查询参数
*/
export const listData = (query?: DataQuery): AxiosPromise<DataVO[]> => {
return request({
url: '/api/data/list',
method: 'get',
params: query
});
};
```
## 5. 项目架构规范
### 目录结构标准
```
web/src/
├── api/ # API接口定义
├── assets/ # 静态资源
├── components/ # 通用组件
├── views/ # 页面视图
├── layout/ # 布局组件
├── router/ # 路由配置
├── store/ # 状态管理
├── utils/ # 工具函数
├── plugins/ # 插件配置
├── types/ # 全局类型定义
└── main.ts # 应用入口
```
---
# 第三部分:后端开发规范 (backend/)
## 1. 技术栈规范
### 核心技术
- **框架**: Spring Boot 3.4.6
- **Java版本**: JDK 17/21
- **Web容器**: Undertow
- **ORM框架**: MyBatis-Plus 3.5.12
- **数据库**: MySQL/Oracle/PostgreSQL/SQLServer (多数据库支持)
- **缓存**: Redis 5-7 + Redisson 3.45.1
- **权限认证**: Sa-Token 1.42.0 + JWT
- **任务调度**: SnailJob 1.5.0
- **工作流**: Warm-Flow 1.7.3
## 2. 项目结构规范
### 后端模块结构
```
backend/
├── ruoyi-admin/ # 管理后台启动模块
├── ruoyi-common/ # 公共模块组
│ ├── ruoyi-common-core/ # 核心模块
│ ├── ruoyi-common-mybatis/ # MyBatis配置
│ ├── ruoyi-common-redis/ # Redis配置
│ ├── ruoyi-common-satoken/ # Sa-Token配置
│ └── ... (其他公共模块)
├── ruoyi-modules/ # 业务模块组
│ ├── ruoyi-system/ # 系统管理模块
│ ├── ruoyi-demo/ # 示例模块
│ └── ... (其他业务模块)
├── ruoyi-extend/ # 扩展模块组
└── script/ # 脚本和SQL
```
## 3. 开发规范
### 代码规范
- **严格遵守**: Alibaba Java开发手册
- **命名规范**:
- 类名: PascalCase (如: UserController)
- 方法名: camelCase (如: getUserList)
- 常量: UPPER_SNAKE_CASE (如: MAX_RETRY_COUNT)
- 包名: 全小写 (如: org.dromara.system)
### 🔴 数据库规范(强制性)
- **⚠️ 超级重要**: 所有数据库操作必须严格遵循 `docs/设计文档/database/mysql-database-standard.md` 规范
- **现有数据库模型**: 参考 `docs/设计文档/database/hzdyjs_xg.sql` 中的完整表结构
- **环境配置**: 开发环境数据库信息见 `docs/设计文档/database/database_msg.md`
#### 🚨 强制性核心规范
1. **所有业务表必须包含标准基础字段**
2. **统一使用雪花ID (bigint(20)) 作为主键**
3. **强制使用逻辑删除,禁止物理删除**
4. **所有表必须支持多租户**
5. **完整的中文注释是必须的**
6. **禁止使用数据库外键约束**,关联关系通过应用层维护
#### 🔴 强制性基础字段模板
```sql
-- 所有业务表必须包含以下字段(顺序和类型必须完全一致)
`id` bigint(20) NOT NULL COMMENT '主键ID',
`tenant_id` varchar(20) NOT NULL DEFAULT '000000' COMMENT '租户编号',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_by` bigint(20) DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint(20) DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`deleted` tinyint(1) DEFAULT 0 COMMENT '删除标志(0代表存在 1代表删除)',
-- 业务字段在此处添加
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_tenant_id` (`tenant_id`),
KEY `idx_deleted` (`deleted`),
KEY `idx_create_time` (`create_time`)
```
#### 🔴 AI开发强制要求
当使用AI进行数据库开发时:
1. **必须先阅读** `docs/设计文档/database/mysql-database-standard.md` 规范
2. **必须使用标准模板**,不得随意修改基础字段
3. **必须保持与现有表结构的一致性**
4. **建表后必须立即更新** `hzdyjs_xg.sql` 文件
5. **必须在变更记录中记录** 数据库变更
### 🔴 API接口规范(强制性)
**⚠️ 超级重要:所有API接口必须严格遵循以下统一规范!**
#### 🔐 请求头规范(强制性)
**所有需要认证的接口必须在请求头中包含Token,格式如下:**
```json
{
"Content-Type": "application/json;charset=utf-8",
"Authorization": "Bearer {access_token}",
"clientid": "e5cd7e4891bf95d1d19206ce24a7b32e",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"referer": "http://localhost/login?redirect=%252Findex"
}
```
**请求头字段说明**:
- **Authorization**: `Bearer ` + Token值(⚠️注意Bearer后面有一个空格)
- **clientid**: 客户端ID,用于权限验证
- **Content-Type**: 请求内容类型,必须为application/json;charset=utf-8
- **Accept-Language**: 语言设置,用于国际化
- **referer**: 来源页面,用于安全验证
**Token格式强制要求**:
- ✅ 正确:`"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."`
- ❌ 错误:`"Authorization": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."`(缺少Bearer前缀)
- ❌ 错误:`"Authorization": "Bearer eyJ0eXAi..."`(Bearer后面没有空格)
#### 📊 统一响应格式(必须遵循)
**基础响应格式(分页列表)**:
```json
{
"total": 7,
"rows": [],
"code": 200,
"msg": "查询成功"
}
```
#### 🎯 响应格式详细说明
**1. 分页列表响应**
```json
{
"total": 100,
"rows": [
{
"id": 1,
"name": "示例数据1",
"createTime": "2025-06-30 12:00:00"
},
{
"id": 2,
"name": "示例数据2",
"createTime": "2025-06-30 12:01:00"
}
],
"code": 200,
"msg": "查询成功"
}
```
**2. 非分页列表响应**
```json
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"name": "示例数据1"
},
{
"id": 2,
"name": "示例数据2"
}
]
}
```
**3. 单条数据响应**
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"name": "示例数据",
"createTime": "2025-06-30 12:00:00"
}
}
```
**4. 操作成功响应(无数据)**
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
**5. 错误响应**
```json
{
"code": 400,
"msg": "参数错误:用户名不能为空",
"data": null
}
```
#### 📋 状态码规范
**成功状态码**:
- `200` - 操作成功
- `201` - 创建成功
**客户端错误(4xx)**:
- `400` - 请求参数错误
- `401` - 未认证/认证失败
- `403` - 无权限访问
- `404` - 资源不存在
- `409` - 数据冲突
**服务端错误(5xx)**:
- `500` - 服务器内部错误
- `502` - 网关错误
- `503` - 服务不可用
#### 🚨 接口开发强制要求
**1. Controller返回格式**
```java
// ✅ 正确 - 分页接口直接返回TableDataInfo
@GetMapping("/list")
public TableDataInfo<UserVo> list(UserBo bo, PageQuery pageQuery) {
TableDataInfo<UserVo> result = userService.queryPageList(bo, pageQuery);
return result;
}
// ✅ 正确 - 非分页接口使用R类型包装
@GetMapping("/options")
public R<List<UserVo>> options() {
List<UserVo> list = userService.selectUserOptions();
return R.ok(list);
}
// ❌ 错误 - 分页接口使用R类型包装
@GetMapping("/list")
public R<TableDataInfo<UserVo>> list(UserBo bo, PageQuery pageQuery) {
TableDataInfo<UserVo> result = userService.queryPageList(bo, pageQuery);
return R.ok(result); // 这会产生多层嵌套
}
```
**2. 分页接口规范**
```java
// 分页查询直接返回 TableDataInfo 数据
@GetMapping("/list")
public TableDataInfo<UserVo> list(UserBo bo, PageQuery pageQuery) {
TableDataInfo<UserVo> result = userService.queryPageList(bo, pageQuery);
return result;
}
// 返回格式:
// {
// "total": 100,
// "rows": [...],
// "code": 200,
// "msg": "查询成功"
// }
```
**3. 非分页列表接口**
```java
// 非分页列表查询(下拉选项等)
@GetMapping("/options")
public R<List<UserVo>> options() {
List<UserVo> list = userService.selectUserOptions();
return R.ok(list);
}
// 返回格式:
// {
// "code": 200,
// "msg": "查询成功",
// "data": [...]
// }
```
**4. 单条数据接口**
```java
// 单条数据查询
@GetMapping("/{id}")
public R<UserVo> getInfo(@PathVariable Long id) {
UserVo user = userService.queryById(id);
return R.ok(user);
}
// 返回格式:
// {
// "code": 200,
// "msg": "操作成功",
// "data": {...}
// }
```
**5. 操作类接口**
```java
// 新增/修改/删除操作
@PostMapping
public R<Void> add(@RequestBody UserBo bo) {
boolean result = userService.insertByBo(bo);
return result ? R.ok() : R.fail("操作失败");
}
// 成功返回格式:
// {
// "code": 200,
// "msg": "操作成功",
// "data": null
// }
// 失败返回格式:
// {
// "code": 500,
// "msg": "操作失败",
// "data": null
// }
```
#### 🔍 接口命名规范
**RESTful风格**:
- `GET /api/users` - 查询用户列表
- `GET /api/users/{id}` - 查询单个用户
- `POST /api/users` - 新增用户
- `PUT /api/users` - 修改用户(传完整对象)
- `PATCH /api/users/{id}` - 部分更新用户
- `DELETE /api/users/{id}` - 删除用户
**特殊功能接口**:
- `GET /api/users/options` - 获取用户下拉选项
- `GET /api/users/statistics` - 获取用户统计数据
- `POST /api/users/batch` - 批量操作用户
- `POST /api/users/{id}/enable` - 启用用户
- `POST /api/users/{id}/disable` - 禁用用户
#### 🛡️ 权限控制规范
```java
// 每个接口必须添加权限注解
@SaCheckPermission("system:user:list")
@GetMapping("/list")
public R<TableDataInfo<UserVo>> list(UserBo bo, PageQuery pageQuery) {
// 接口实现
}
```
#### 📝 参数验证规范
```java
// 使用Bean Validation进行参数校验
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody UserBo bo) {
// 接口实现
}
// VO类中的验证注解
public class UserBo {
@NotBlank(message = "用户名不能为空", groups = {AddGroup.class, EditGroup.class})
@Size(max = 30, message = "用户名长度不能超过30个字符")
private String userName;
@NotBlank(message = "手机号不能为空", groups = {AddGroup.class, EditGroup.class})
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
```
#### 🚨 接口开发检查清单
**每个新接口必须检查**:
- [ ] 是否在请求头中正确使用了Bearer Token格式?
- [ ] 分页接口是否直接返回TableDataInfo格式?
- [ ] 非分页接口是否使用R类型包装返回结果?
- [ ] 是否遵循了统一的响应格式规范?
- [ ] 是否添加了@SaCheckPermission权限注解?
- [ ] 是否添加了@Operation接口描述?
- [ ] 是否进行了参数校验?
- [ ] 是否符合RESTful命名规范?
- [ ] 是否包含了必要的请求头(clientid、Content-Type等)?
- [ ] 是否在API文档中记录了接口信息?
#### 💥 违规后果
**如果发现接口不符合统一规范,必须立即修改!不符合规范的接口不允许合并到主分支。**
### 🔴 API开发强制性工作流程
#### 步骤1:编写后端代码
- 创建Controller、Service、Mapper等
- 实现业务逻辑和数据处理
- 添加权限控制和参数验证
#### 步骤2:立即更新API文档(强制性)
**⚠️ 代码写完后立即执行,不得延后!**
- 打开 `docs/开发文档/API.md` 文件
- 按照 `docs/开发文档/API文档模板.md` 的标准格式添加或更新接口文档
- 包含完整的接口信息(地址、参数、响应、权限等)
- 添加真实的请求和响应示例
#### 步骤3:记录代码调整日志
- 在 `docs/变更管理/code-adjust-record.md` 中记录本次变更
- 特别说明API接口的变更内容
- 标注文档已同步更新
#### 步骤4:验证和测试
- 测试API接口功能是否正常
- 验证API文档的准确性
- 确保文档示例与实际响应一致
#### 🚨 违规后果
**如果发现API变更未同步更新文档,该代码变更将被视为不完整,必须立即补齐文档。**
## 4. 🔐 菜单界面和接口权限配置规范
### 🚨 权限配置核心原理
**⚠️ 超级重要:每个菜单界面和相关接口都必须在`sys_menu`表中配置对应的权限数据!**
#### 权限配置核心概念
1. **菜单权限**:控制用户是否能看到某个菜单项
2. **按钮权限**:控制用户是否能看到和使用某个功能按钮
3. **接口权限**:通过Sa-Token注解控制用户是否能调用某个API接口
4. **角色权限**:通过`sys_role_menu`表关联,控制哪个角色拥有哪些权限
#### 权限验证机制
```
用户登录 → 获取用户角色 → 查询角色权限(sys_role_menu) → 验证接口权限(@SaCheckPermission) → 允许/拒绝访问
```
### 🔴 sys_menu表结构和权限配置
#### sys_menu表核心字段说明
```sql
-- sys_menu表核心字段
`menu_id` bigint(20) 菜单ID(主键)
`menu_name` varchar(50) 菜单名称
`parent_id` bigint(20) 父菜单ID(0表示一级菜单)
`order_num` int(4) 显示顺序
`path` varchar(200) 路由地址
`component` varchar(255) 组件路径
`menu_type` char(1) 菜单类型(M目录 C菜单 F按钮)
`visible` char(1) 菜单状态(0显示 1隐藏)
`status` char(1) 菜单状态(0正常 1停用)
`perms` varchar(100) 权限标识(如:system:user:list)
`icon` varchar(100) 菜单图标
```
#### 权限标识(perms)命名规范
```
格式:[模块名]:[功能名]:[操作名]
示例:
- pm:repairOrder:list # 报修工单列表查询
- pm:repairOrder:add # 报修工单新增
- pm:repairOrder:edit # 报修工单修改
- pm:repairOrder:remove # 报修工单删除
- pm:repairOrder:statistics # 报修统计数据
- pm:category:list # 维修分类列表
- pm:category:options # 维修分类下拉选项
```
### 🔧 权限配置标准工作流程
#### 📋 新增功能权限配置流程
**步骤1:分析权限需求**
```
1. 确定主菜单名称和路径
2. 列出所有功能按钮(新增、修改、删除、查询等)
3. 列出所有API接口及对应权限
4. 确定权限标识命名
```
**步骤2:权限配置SQL编写**
使用UPSERT逻辑(先判断后操作):
```sql
-- 权限配置标准模板(UPSERT逻辑)
-- ==========================================
-- [模块名]权限配置脚本
-- 功能:为[模块名]添加完整权限配置
-- 时间:YYYY-MM-DD HH:mm:ss
-- 说明:使用UPSERT逻辑,避免重复插入
-- ==========================================
-- 第一步:检查并插入主菜单
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT
2100, '物业管理', 0, 6, 'pm', NULL,
'', 1, 0, 'M', '0', '0',
'', 'tool', 1, now(), 1, now(), '物业管理模块'
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
-- 第二步:检查并插入子菜单
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT
2110, '报修管理', 2100, 1, 'repairOrder', 'pm/repairOrder/index',
'', 1, 0, 'C', '0', '0',
'pm:repairOrder:list', 'form', 1, now(), 1, now(), '报修工单管理'
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2110);
-- 第三步:批量插入功能权限(如果不存在)
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT * FROM (
SELECT 2111, '查询', 2110, 1, '', '', '', 1, 0, 'F', '0', '0', 'pm:repairOrder:query', '#', 1, now(), 1, now(), '查询权限' UNION ALL
SELECT 2112, '新增', 2110, 2, '', '', '', 1, 0, 'F', '0', '0', 'pm:repairOrder:add', '#', 1, now(), 1, now(), '新增权限' UNION ALL
SELECT 2113, '修改', 2110, 3, '', '', '', 1, 0, 'F', '0', '0', 'pm:repairOrder:edit', '#', 1, now(), 1, now(), '修改权限'
) AS temp
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = temp.menu_id);
-- 第四步:为admin角色分配权限(如果未分配)
INSERT IGNORE INTO sys_role_menu (role_id, menu_id)
SELECT 1, menu_id FROM sys_menu WHERE menu_id BETWEEN 2100 AND 2199;
```
**步骤3:更新现有权限**
```sql
-- 更新现有权限信息(如果需要修改)
UPDATE sys_menu
SET
menu_name = '新的菜单名称',
path = '新的路径',
perms = '新的权限标识',
update_time = now(),
update_by = 1,
remark = '权限更新说明'
WHERE menu_id = 2110 AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2110);
```
### 🔄 权限配置操作规范
#### 🚨 强制性检查清单
**每次新增功能时必须检查**:
- [ ] 是否需要新增主菜单?
- [ ] 是否需要新增子菜单?
- [ ] 列出所有需要的功能权限(CRUD等)
- [ ] 列出所有API接口及权限标识
- [ ] 确认权限标识命名符合规范
- [ ] 权限配置是否使用UPSERT逻辑?
- [ ] 是否为相关角色分配了权限?
#### 🔍 权限配置验证方法
**验证SQL模板**:
```sql
-- 1. 验证权限是否已正确配置
SELECT menu_id, menu_name, perms, menu_type
FROM sys_menu
WHERE perms LIKE 'pm:%'
ORDER BY menu_id;
-- 2. 验证角色权限分配
SELECT rm.role_id, r.role_name, m.menu_name, m.perms
FROM sys_role_menu rm
JOIN sys_role r ON rm.role_id = r.role_id
JOIN sys_menu m ON rm.menu_id = m.menu_id
WHERE m.perms LIKE 'pm:%'
ORDER BY rm.role_id, m.menu_id;
-- 3. 验证用户权限(通过角色)
SELECT u.user_name, r.role_name, m.menu_name, m.perms
FROM sys_user u
JOIN sys_user_role ur ON u.user_id = ur.user_id
JOIN sys_role r ON ur.role_id = r.role_id
JOIN sys_role_menu rm ON r.role_id = rm.role_id
JOIN sys_menu m ON rm.menu_id = m.menu_id
WHERE u.user_name = 'admin' AND m.perms LIKE 'pm:%'
ORDER BY m.menu_id;
```
### 🎯 Controller权限注解规范
#### 标准权限注解使用
```java
@RestController
@RequestMapping("/pm/repairOrder")
@Api(tags = "报修工单管理")
public class PmRepairOrderController extends BaseController {
// 列表查询 - 对应菜单权限
@SaCheckPermission("pm:repairOrder:list")
@GetMapping("/list")
@Operation(summary = "查询报修工单列表")
public TableDataInfo<PmRepairOrderVo> list(PmRepairOrderBo bo, PageQuery pageQuery) {
return repairOrderService.queryPageList(bo, pageQuery);
}
// 详情查询 - 对应按钮权限
@SaCheckPermission("pm:repairOrder:query")
@GetMapping("/{id}")
@Operation(summary = "获取报修工单详细信息")
public R<PmRepairOrderVo> getInfo(@PathVariable Long id) {
return R.ok(repairOrderService.queryById(id));
}
// 新增功能 - 对应按钮权限
@SaCheckPermission("pm:repairOrder:add")
@PostMapping
@Operation(summary = "新增报修工单")
public R<Void> add(@RequestBody PmRepairOrderBo bo) {
return toAjax(repairOrderService.insertByBo(bo));
}
// 修改功能 - 对应按钮权限
@SaCheckPermission("pm:repairOrder:edit")
@PutMapping
@Operation(summary = "修改报修工单")
public R<Void> edit(@RequestBody PmRepairOrderBo bo) {
return toAjax(repairOrderService.updateByBo(bo));
}
// 删除功能 - 对应按钮权限
@SaCheckPermission("pm:repairOrder:remove")
@DeleteMapping("/{ids}")
@Operation(summary = "删除报修工单")
public R<Void> remove(@PathVariable Long[] ids) {
return toAjax(repairOrderService.deleteWithValidByIds(List.of(ids)));
}
// 统计数据 - 对应功能权限
@SaCheckPermission("pm:repairOrder:statistics")
@GetMapping("/statistics")
@Operation(summary = "获取报修统计数据")
public R<Map<String, Object>> statistics() {
return R.ok(repairOrderService.getStatistics());
}
// 下拉选项 - 对应功能权限
@SaCheckPermission("pm:repairOrder:generateOrderNo")
@PostMapping("/generateOrderNo")
@Operation(summary = "生成工单编号")
public R<String> generateOrderNo() {
return R.ok(repairOrderService.generateOrderNo());
}
}
```
#### 权限注解检查清单
- [ ] 每个Controller方法都有@SaCheckPermission注解
- [ ] 权限标识与sys_menu表中的perms字段一致
- [ ] 权限标识命名符合[模块]:[功能]:[操作]规范
- [ ] 所有权限标识都已在sys_menu表中配置
### 🖥️ 前端权限控制规范
#### Vue页面权限控制
```vue
<template>
<div class="app-container">
<!-- 功能按钮权限控制 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['pm:repairOrder:add']"
type="primary"
plain
icon="Plus"
@click="handleAdd">
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['pm:repairOrder:edit']"
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['pm:repairOrder:remove']"
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete">
删除
</el-button>
</el-col>
</el-row>
<!-- 表格操作列权限控制 -->
<el-table-column label="操作" align="center" width="160">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button
v-hasPermi="['pm:repairOrder:edit']"
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
v-hasPermi="['pm:repairOrder:remove']"
link
type="danger"
icon="Delete"
@click="handleDelete(scope.row)">
</el-button>
</el-tooltip>
</template>
</el-table-column>
</div>
</template>
```
#### API调用权限检查
```typescript
// api调用前的权限检查(可选)
import { checkPermi } from '@/utils/permission';
// 在调用API前检查权限
const handleAdd = () => {
if (!checkPermi(['pm:repairOrder:add'])) {
ElMessage.error('您没有新增权限');
return;
}
// 执行新增操作
router.push('/pm/repairOrder/add');
};
const handleEdit = (row: any) => {
if (!checkPermi(['pm:repairOrder:edit'])) {
ElMessage.error('您没有修改权限');
return;
}
// 执行修改操作
router.push(`/pm/repairOrder/edit/${row.id}`);
};
```
### 📋 权限配置标准模板
#### 完整权限配置脚本模板
```sql
-- ==========================================
-- [模块名称]权限配置脚本
-- 功能:为[模块名称]添加完整权限配置
-- 时间:YYYY-MM-DD HH:mm:ss (⚠️必须填写真实时间!)
-- 说明:使用UPSERT逻辑,支持重复执行
-- ==========================================
-- 清理旧数据(谨慎使用,仅在测试环境)
-- DELETE FROM sys_role_menu WHERE menu_id BETWEEN [起始ID] AND [结束ID];
-- DELETE FROM sys_menu WHERE menu_id BETWEEN [起始ID] AND [结束ID];
-- 第一部分:主菜单配置
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT
[主菜单ID], '[主菜单名称]', 0, [排序号], '[路径]', NULL,
'', 1, 0, 'M', '0', '0',
'', '[图标]', 1, now(), 1, now(), '[模块描述]'
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = [主菜单ID]);
-- 第二部分:子菜单配置
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT
[子菜单ID], '[子菜单名称]', [主菜单ID], [排序号], '[路径]', '[组件路径]',
'', 1, 0, 'C', '0', '0',
'[模块]:[功能]:list', '[图标]', 1, now(), 1, now(), '[功能描述]'
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = [子菜单ID]);
-- 第三部分:功能权限配置(批量插入)
INSERT INTO sys_menu (
menu_id, menu_name, parent_id, order_num, path, component,
query_param, is_frame, is_cache, menu_type, visible, status,
perms, icon, create_by, create_time, update_by, update_time, remark
)
SELECT * FROM (
-- 基础CRUD权限
SELECT [权限ID1], '[功能名称]查询', [子菜单ID], 1, '', '', '', 1, 0, 'F', '0', '0', '[模块]:[功能]:query', '#', 1, now(), 1, now(), '查询权限' UNION ALL
SELECT [权限ID2], '[功能名称]新增', [子菜单ID], 2, '', '', '', 1, 0, 'F', '0', '0', '[模块]:[功能]:add', '#', 1, now(), 1, now(), '新增权限' UNION ALL
SELECT [权限ID3], '[功能名称]修改', [子菜单ID], 3, '', '', '', 1, 0, 'F', '0', '0', '[模块]:[功能]:edit', '#', 1, now(), 1, now(), '修改权限' UNION ALL
SELECT [权限ID4], '[功能名称]删除', [子菜单ID], 4, '', '', '', 1, 0, 'F', '0', '0', '[模块]:[功能]:remove', '#', 1, now(), 1, now(), '删除权限' UNION ALL
-- 特殊功能权限
SELECT [权限ID5], '[特殊功能名称]', [子菜单ID], 5, '', '', '', 1, 0, 'F', '0', '0', '[模块]:[功能]:[特殊操作]', '#', 1, now(), 1, now(), '[特殊功能描述]'
) AS temp
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = temp.menu_id);
-- 第四部分:权限分配(为admin角色分配权限)
INSERT IGNORE INTO sys_role_menu (role_id, menu_id)
SELECT 1, menu_id FROM sys_menu WHERE menu_id BETWEEN [起始ID] AND [结束ID];
-- 第五部分:验证配置结果
SELECT '权限配置验证' as message,
COUNT(*) as menu_count,
(SELECT COUNT(*) FROM sys_role_menu WHERE role_id = 1 AND menu_id BETWEEN [起始ID] AND [结束ID]) as role_permission_count
FROM sys_menu
WHERE menu_id BETWEEN [起始ID] AND [结束ID];
```
### 🧪 权限配置测试和验证
#### 权限测试标准流程
```
1. **权限配置验证**
- 检查sys_menu表中权限记录
- 检查sys_role_menu表中角色权限分配
- 验证权限标识命名规范
↓
2. **后端接口测试**
- 使用Token调用接口
- 验证权限认证是否正常
- 测试无权限用户访问是否被拒绝
↓
3. **前端界面测试**
- 登录系统查看菜单是否显示
- 检查功能按钮是否根据权限显示/隐藏
- 验证无权限用户的界面表现
↓
4. **权限缓存测试**
- 重启服务后权限是否正常
- 重新登录后权限是否正确加载
- 权限变更后是否需要重新登录
```
#### 权限测试脚本模板
```javascript
// 权限验证测试脚本
async function testPermissions(token, permissions) {
const results = [];
for (const perm of permissions) {
try {
const response = await callAPIWithToken(token, perm.endpoint, perm.data, perm.method);
results.push({
permission: perm.name,
endpoint: perm.endpoint,
success: response.success,
status: response.status,
message: response.success ? '权限验证通过' : '权限验证失败'
});
} catch (error) {
results.push({
permission: perm.name,
endpoint: perm.endpoint,
success: false,
status: 'ERROR',
message: error.message
});
}
}
return results;
}
// 使用示例
const permissionTests = [
{ name: 'pm:repairOrder:list', endpoint: '/pm/repairOrder/list', method: 'GET', data: null },
{ name: 'pm:repairOrder:add', endpoint: '/pm/repairOrder', method: 'POST', data: {} },
{ name: 'pm:repairOrder:statistics', endpoint: '/pm/repairOrder/statistics', method: 'GET', data: null }
];
// 执行权限测试
testPermissions(token, permissionTests).then(results => {
console.log('权限测试结果:', results);
});
```
### 🚨 权限配置强制要求总结
#### 必须遵循的规范
1. **⚠️ 每个新功能都必须配置权限**:菜单权限 + 按钮权限 + 接口权限
2. **⚠️ 使用UPSERT逻辑**:权限配置脚本必须支持重复执行
3. **⚠️ 权限标识规范**:严格按照[模块]:[功能]:[操作]格式命名
4. **⚠️ Controller注解必须**:每个接口方法都要有@SaCheckPermission注解
5. **⚠️ 前端权限控制**:功能按钮必须使用v-hasPermi指令控制
6. **⚠️ 权限测试验证**:配置完成后必须进行完整的权限测试
7. **⚠️ 文档同步更新**:权限配置必须在API文档中说明
#### 违规检查清单
- [ ] 新功能是否缺少权限配置?
- [ ] Controller方法是否缺少权限注解?
- [ ] 权限标识命名是否符合规范?
- [ ] 前端按钮是否有权限控制?
- [ ] 权限配置是否支持重复执行?
- [ ] 是否进行了权限功能测试?
- [ ] API文档是否更新了权限信息?
## 5. 标准代码模板
### Controller模板
```java
@RestController
@RequestMapping("/system/user")
@Api(tags = "用户管理")
public class SysUserController extends BaseController {
@Autowired
private ISysUserService userService;
@SaCheckPermission("system:user:list")
@GetMapping("/list")
@Operation(summary = "查询用户列表")
public TableDataInfo<SysUserVo> list(SysUserBo user, PageQuery pageQuery) {
return userService.queryPageList(user, pageQuery);
}
}
```
### Service模板
```java
@Service
public class SysUserServiceImpl implements ISysUserService {
@Autowired
private SysUserMapper userMapper;
@Override
public TableDataInfo<SysUserVo> queryPageList(SysUserBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<SysUser> lqw = buildQueryWrapper(bo);
Page<SysUserVo> result = userMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
}
```
---
# 第四部分:移动端开发规范 (mobile/)
## 1. 技术栈规范
### 核心技术
- **框架**: uni-app
- **UI组件库**: uView UI
- **开发语言**: JavaScript/TypeScript
- **状态管理**: Vuex
- **HTTP客户端**: uni.request 封装
## 2. 项目结构规范
### 移动端目录结构
```
mobile/
├── src/
│ ├── api/ # API接口定义
│ ├── components/ # 通用组件
│ ├── pages/ # 页面文件
│ │ ├── index/ # 首页
│ │ ├── login/ # 登录页
│ │ ├── mine/ # 个人中心
│ │ └── workbench/ # 工作台
│ ├── static/ # 静态资源
│ ├── utils/ # 工具函数
│ ├── App.vue # 应用入口
│ ├── config.js # 配置文件
│ └── main.js # 主入口文件
├── pages.json # 页面配置
├── manifest.json # 应用配置
└── uni.scss # 全局样式
```
## 3. 开发规范
### 页面开发规范
- **页面命名**: 使用小写字母和连字符 (如: user-list)
- **组件命名**: 使用PascalCase (如: UserCard)
- **API调用**: 统一使用封装的request工具
- **样式规范**: 使用uView UI组件和样式变量
### 页面模板
```vue
<template>
<view class="page-container">
<u-navbar title="页面标题" @leftClick="handleBack"></u-navbar>
<!-- 页面内容 -->
</view>
</template>
<script>
export default {
data() {
return {
// 页面数据
}
},
onLoad() {
// 页面加载逻辑
},
methods: {
handleBack() {
uni.navigateBack();
}
}
}
</script>
<style lang="scss" scoped>
.page-container {
// 页面样式
}
</style>
```
## 4. 与后端API对接规范
### 请求封装
```javascript
// utils/request.js
const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
url: getApp().globalData.baseUrl + options.url,
method: options.method || 'GET',
data: options.data || {},
header: {
'Authorization': uni.getStorageSync('token'),
'Content-Type': 'application/json'
},
success: (res) => {
if (res.data.code === 200) {
resolve(res.data);
} else {
reject(res.data);
}
},
fail: (err) => {
reject(err);
}
});
});
};
```
---
# 通用开发原则
## 1. 代码质量保证
### 编码规范
- 遵循各技术栈的官方编码规范
- 使用统一的代码格式化工具
- 添加适当的注释和文档
- 进行代码审查
### 测试要求
- 单元测试覆盖核心业务逻辑
- 集成测试验证API接口
- UI测试确保界面交互正常
- 性能测试保证系统响应速度
## 2. 安全规范
### 数据安全
- 敏感数据脱敏处理
- API接口权限控制
- 输入参数严格校验
- SQL注入防护
### 系统安全
- HTTPS协议传输
- JWT token认证
- 密码加密存储
- 定期安全检查
## 3. 性能优化
### 前端优化
- 代码分割和懒加载
- 图片压缩和CDN
- 缓存策略优化
- 首屏加载优化
### 后端优化
- 数据库查询优化
- Redis缓存策略
- 异步处理耗时操作
- JVM参数调优
## 4. 文档维护
### 同步更新
- 代码变更必须同步更新文档
- API文档自动生成和维护
- 数据库变更记录追踪
- 部署文档及时更新
### 版本管理
- 文档版本与代码版本保持一致
- 重要变更记录详细说明
- 保持向后兼容性考虑
- 定期文档审查和整理
---
## 🚨 重要提醒和强制要求
1. **📝 文档同步更新**:每次代码调整都必须同步更新相关文档,这是强制性要求
2. **🔴 API文档管理**:API接口变更必须立即更新 `docs/开发文档/API.md` 文档
3. **📋 变更记录**:每次调整都必须在 `docs/变更管理/code-adjust-record.md` 中记录
4. **🎯 业务上下文**:充分利用 `docs/业务模块/` 下的文档为AI提供完整业务上下文
5. **📚 模板使用**:使用标准文档模板,确保格式一致性
6. **🔍 质量控制**:确保文档内容与代码实现完全一致
7. **⚡ 实时性**:文档更新不得延后,必须与代码变更同步进行
## 参考资源
- **项目文档体系**:`docs/` 目录下的完整文档
- **业务模块文档**:`docs/业务模块/` 各模块的详细文档
- **开发文档**:`docs/开发文档/` 技术规范和API文档
- **变更记录**:`docs/变更管理/code-adjust-record.md`
- **标准模板**:各目录下的模板文件
**🎯 目标**:通过完善的文档管理体系,为Cursor AI提供准确的开发上下文,确保高质量的代码生成和文档同步更新!
---
# 第五部分: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-WItuWtpumZoiIsImRlcHRDYXRlZ29yeSI6IiIsIm5pY2tOYW1lIjoi55av54uC55qE54uu5a2QTGkifQ.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;
}
```
## 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调用
- ✅ 用户权限验证通过
- ✅ 加密解密机制正常
```
## 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管理
---
**🎉 成功状态**: 登录获取Token功能已完全实现并正常工作,可以稳定用于API开发和测试。