📝 主要改进: • Cursor配置模块化:拆分为前端、后端、移动端、文档、API测试5个专门规范文件 • API文档重新组织:按业务模块拆分到docs/开发文档/API/目录下 • 新增维修分类功能完整测试方案和自动化测试脚本 • 后端热启动脚本完善,支持Linux/Windows双平台 • 强化文档同步更新规范,确保代码与文档一致性 🔧 技术改进: • 优化Cursor AI工作流程和代码生成质量 • 完善API测试规范(AES+RSA双重加密登录方法) • 提升开发效率和代码质量标准化程度 �� 测试覆盖: • 维修分类管理功能端到端测试验证通过 • 包含页面加载、CRUD操作、搜索功能等核心测试用例 更新时间:2025-07-01
2359 lines
77 KiB
Plaintext
2359 lines
77 KiB
Plaintext
# 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开发和测试。
|
||
|