# 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 ``` ### 页面开发规范 #### 列表页面标准模板 ```vue ``` ## 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 => { 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 list(UserBo bo, PageQuery pageQuery) { TableDataInfo result = userService.queryPageList(bo, pageQuery); return result; } // ✅ 正确 - 非分页接口使用R类型包装 @GetMapping("/options") public R> options() { List list = userService.selectUserOptions(); return R.ok(list); } // ❌ 错误 - 分页接口使用R类型包装 @GetMapping("/list") public R> list(UserBo bo, PageQuery pageQuery) { TableDataInfo result = userService.queryPageList(bo, pageQuery); return R.ok(result); // 这会产生多层嵌套 } ``` **2. 分页接口规范** ```java // 分页查询直接返回 TableDataInfo 数据 @GetMapping("/list") public TableDataInfo list(UserBo bo, PageQuery pageQuery) { TableDataInfo result = userService.queryPageList(bo, pageQuery); return result; } // 返回格式: // { // "total": 100, // "rows": [...], // "code": 200, // "msg": "查询成功" // } ``` **3. 非分页列表接口** ```java // 非分页列表查询(下拉选项等) @GetMapping("/options") public R> options() { List list = userService.selectUserOptions(); return R.ok(list); } // 返回格式: // { // "code": 200, // "msg": "查询成功", // "data": [...] // } ``` **4. 单条数据接口** ```java // 单条数据查询 @GetMapping("/{id}") public R getInfo(@PathVariable Long id) { UserVo user = userService.queryById(id); return R.ok(user); } // 返回格式: // { // "code": 200, // "msg": "操作成功", // "data": {...} // } ``` **5. 操作类接口** ```java // 新增/修改/删除操作 @PostMapping public R 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> list(UserBo bo, PageQuery pageQuery) { // 接口实现 } ``` #### 📝 参数验证规范 ```java // 使用Bean Validation进行参数校验 @PostMapping public R 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 list(PmRepairOrderBo bo, PageQuery pageQuery) { return repairOrderService.queryPageList(bo, pageQuery); } // 详情查询 - 对应按钮权限 @SaCheckPermission("pm:repairOrder:query") @GetMapping("/{id}") @Operation(summary = "获取报修工单详细信息") public R getInfo(@PathVariable Long id) { return R.ok(repairOrderService.queryById(id)); } // 新增功能 - 对应按钮权限 @SaCheckPermission("pm:repairOrder:add") @PostMapping @Operation(summary = "新增报修工单") public R add(@RequestBody PmRepairOrderBo bo) { return toAjax(repairOrderService.insertByBo(bo)); } // 修改功能 - 对应按钮权限 @SaCheckPermission("pm:repairOrder:edit") @PutMapping @Operation(summary = "修改报修工单") public R edit(@RequestBody PmRepairOrderBo bo) { return toAjax(repairOrderService.updateByBo(bo)); } // 删除功能 - 对应按钮权限 @SaCheckPermission("pm:repairOrder:remove") @DeleteMapping("/{ids}") @Operation(summary = "删除报修工单") public R remove(@PathVariable Long[] ids) { return toAjax(repairOrderService.deleteWithValidByIds(List.of(ids))); } // 统计数据 - 对应功能权限 @SaCheckPermission("pm:repairOrder:statistics") @GetMapping("/statistics") @Operation(summary = "获取报修统计数据") public R> statistics() { return R.ok(repairOrderService.getStatistics()); } // 下拉选项 - 对应功能权限 @SaCheckPermission("pm:repairOrder:generateOrderNo") @PostMapping("/generateOrderNo") @Operation(summary = "生成工单编号") public R generateOrderNo() { return R.ok(repairOrderService.generateOrderNo()); } } ``` #### 权限注解检查清单 - [ ] 每个Controller方法都有@SaCheckPermission注解 - [ ] 权限标识与sys_menu表中的perms字段一致 - [ ] 权限标识命名符合[模块]:[功能]:[操作]规范 - [ ] 所有权限标识都已在sys_menu表中配置 ### 🖥️ 前端权限控制规范 #### Vue页面权限控制 ```vue ``` #### 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 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 queryPageList(SysUserBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page 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 ``` ## 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开发和测试。