ai-engineering-init 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/code-reviewer.md +139 -0
- package/.claude/agents/project-manager.md +159 -0
- package/.claude/audio/completed.wav +0 -0
- package/.claude/commands/add-todo.md +255 -0
- package/.claude/commands/check.md +210 -0
- package/.claude/commands/crud.md +454 -0
- package/.claude/commands/dev.md +503 -0
- package/.claude/commands/init-docs.md +681 -0
- package/.claude/commands/next.md +251 -0
- package/.claude/commands/progress.md +242 -0
- package/.claude/commands/start.md +199 -0
- package/.claude/commands/sync.md +307 -0
- package/.claude/commands/update-status.md +428 -0
- package/.claude/docs/Mixin/344/275/277/347/224/250/346/214/207/345/215/227.md +299 -0
- package/.claude/docs/README.md +167 -0
- package/.claude/docs//345/211/215/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +599 -0
- package/.claude/docs//345/220/216/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +726 -0
- package/.claude/docs//345/267/245/344/275/234/346/265/201/345/274/200/345/217/221/346/214/207/345/215/227.md +714 -0
- package/.claude/docs//345/267/245/345/205/267/347/261/273/344/275/277/347/224/250/346/214/207/345/215/227.md +463 -0
- package/.claude/docs//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/350/247/204/350/214/203.md +390 -0
- package/.claude/docs//346/226/260/345/212/237/350/203/275/345/274/200/345/217/221/346/265/201/347/250/213/350/247/204/350/214/203.md +688 -0
- package/.claude/docs//346/226/260/351/241/271/347/233/256/345/274/200/345/217/221/346/265/201/347/250/213.md +365 -0
- package/.claude/docs//346/241/206/346/236/266/350/257/264/346/230/216.md +393 -0
- package/.claude/docs//350/267/257/347/224/261/351/205/215/347/275/256/346/214/207/345/215/227.md +246 -0
- package/.claude/framework-config.json +73 -0
- package/.claude/hooks/pre-tool-use.js +117 -0
- package/.claude/hooks/skill-forced-eval.js +167 -0
- package/.claude/hooks/stop.js +58 -0
- package/.claude/settings.json +41 -0
- package/.claude/skills/add-skill/SKILL.md +352 -0
- package/.claude/skills/api-development/SKILL.md +560 -0
- package/.claude/skills/architecture-design/SKILL.md +756 -0
- package/.claude/skills/backend-annotations/SKILL.md +674 -0
- package/.claude/skills/banana-image/CHANGELOG.md +37 -0
- package/.claude/skills/banana-image/README.md +146 -0
- package/.claude/skills/banana-image/SKILL.md +164 -0
- package/.claude/skills/banana-image/assets/logo.png +0 -0
- package/.claude/skills/banana-image/references/advanced-usage.md +189 -0
- package/.claude/skills/banana-image/scripts/apply_template.py +125 -0
- package/.claude/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.claude/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.claude/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.claude/skills/banana-image/scripts/package.json +18 -0
- package/.claude/skills/banana-image/scripts/requirements.txt +10 -0
- package/.claude/skills/banana-image/templates/poster.json +22 -0
- package/.claude/skills/banana-image/templates/product.json +17 -0
- package/.claude/skills/banana-image/templates/social.json +22 -0
- package/.claude/skills/banana-image/templates/thumbnail.json +17 -0
- package/.claude/skills/brainstorm/SKILL.md +648 -0
- package/.claude/skills/bug-detective/SKILL.md +1206 -0
- package/.claude/skills/code-patterns/SKILL.md +590 -0
- package/.claude/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.claude/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.claude/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.claude/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.claude/skills/crud-development/SKILL.md +649 -0
- package/.claude/skills/data-permission/SKILL.md +599 -0
- package/.claude/skills/database-ops/SKILL.md +407 -0
- package/.claude/skills/error-handler/SKILL.md +371 -0
- package/.claude/skills/file-oss-management/SKILL.md +863 -0
- package/.claude/skills/git-workflow/SKILL.md +375 -0
- package/.claude/skills/json-serialization/SKILL.md +357 -0
- package/.claude/skills/leniu-api-development/SKILL.md +803 -0
- package/.claude/skills/leniu-architecture-design/SKILL.md +598 -0
- package/.claude/skills/leniu-backend-annotations/SKILL.md +664 -0
- package/.claude/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.claude/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.claude/skills/leniu-data-permission/SKILL.md +256 -0
- package/.claude/skills/leniu-database-ops/SKILL.md +426 -0
- package/.claude/skills/leniu-error-handler/SKILL.md +462 -0
- package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.claude/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.claude/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.claude/skills/leniu-java-entity/SKILL.md +751 -0
- package/.claude/skills/leniu-java-export/SKILL.md +560 -0
- package/.claude/skills/leniu-java-logging/SKILL.md +832 -0
- package/.claude/skills/leniu-java-mq/SKILL.md +338 -0
- package/.claude/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.claude/skills/leniu-java-task/SKILL.md +367 -0
- package/.claude/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
- package/.claude/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.claude/skills/leniu-security-guard/SKILL.md +520 -0
- package/.claude/skills/leniu-utils-toolkit/SKILL.md +380 -0
- package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
- package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
- package/.claude/skills/openspec-explore/SKILL.md +290 -0
- package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
- package/.claude/skills/openspec-new-change/SKILL.md +74 -0
- package/.claude/skills/openspec-onboard/SKILL.md +529 -0
- package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
- package/.claude/skills/performance-doctor/SKILL.md +627 -0
- package/.claude/skills/project-navigator/SKILL.md +305 -0
- package/.claude/skills/redis-cache/SKILL.md +839 -0
- package/.claude/skills/scheduled-jobs/SKILL.md +633 -0
- package/.claude/skills/security-guard/SKILL.md +748 -0
- package/.claude/skills/sms-mail/SKILL.md +766 -0
- package/.claude/skills/social-login/SKILL.md +668 -0
- package/.claude/skills/store-pc/SKILL.md +366 -0
- package/.claude/skills/task-tracker/SKILL.md +307 -0
- package/.claude/skills/tech-decision/SKILL.md +393 -0
- package/.claude/skills/tenant-management/SKILL.md +603 -0
- package/.claude/skills/test-development/SKILL.md +755 -0
- package/.claude/skills/ui-pc/SKILL.md +438 -0
- package/.claude/skills/utils-toolkit/SKILL.md +615 -0
- package/.claude/skills/websocket-sse/SKILL.md +716 -0
- package/.claude/skills/workflow-engine/SKILL.md +676 -0
- package/.claude/templates//345/276/205/345/212/236/346/270/205/345/215/225/346/250/241/346/235/277.md +56 -0
- package/.claude/templates//351/234/200/346/261/202/346/226/207/346/241/243/346/250/241/346/235/277.md +85 -0
- package/.claude/templates//351/241/271/347/233/256/347/212/266/346/200/201/346/250/241/346/235/277.md +43 -0
- package/.codex/skills/add-skill/SKILL.md +352 -0
- package/.codex/skills/add-todo/SKILL.md +269 -0
- package/.codex/skills/api-development/SKILL.md +693 -0
- package/.codex/skills/architecture-design/SKILL.md +628 -0
- package/.codex/skills/backend-annotations/SKILL.md +664 -0
- package/.codex/skills/banana-image/CHANGELOG.md +37 -0
- package/.codex/skills/banana-image/README.md +146 -0
- package/.codex/skills/banana-image/SKILL.md +164 -0
- package/.codex/skills/banana-image/assets/logo.png +0 -0
- package/.codex/skills/banana-image/references/advanced-usage.md +189 -0
- package/.codex/skills/banana-image/scripts/apply_template.py +125 -0
- package/.codex/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.codex/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.codex/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.codex/skills/banana-image/scripts/package.json +18 -0
- package/.codex/skills/banana-image/scripts/requirements.txt +10 -0
- package/.codex/skills/banana-image/templates/poster.json +22 -0
- package/.codex/skills/banana-image/templates/product.json +17 -0
- package/.codex/skills/banana-image/templates/social.json +22 -0
- package/.codex/skills/banana-image/templates/thumbnail.json +17 -0
- package/.codex/skills/brainstorm/SKILL.md +648 -0
- package/.codex/skills/bug-detective/SKILL.md +1206 -0
- package/.codex/skills/check/SKILL.md +367 -0
- package/.codex/skills/code-patterns/SKILL.md +442 -0
- package/.codex/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.codex/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.codex/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.codex/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.codex/skills/crud/SKILL.md +265 -0
- package/.codex/skills/crud-development/SKILL.md +637 -0
- package/.codex/skills/data-permission/SKILL.md +591 -0
- package/.codex/skills/database-ops/SKILL.md +553 -0
- package/.codex/skills/dev/SKILL.md +187 -0
- package/.codex/skills/error-handler/SKILL.md +361 -0
- package/.codex/skills/file-oss-management/SKILL.md +863 -0
- package/.codex/skills/git-workflow/SKILL.md +375 -0
- package/.codex/skills/init-docs/SKILL.md +194 -0
- package/.codex/skills/json-serialization/SKILL.md +357 -0
- package/.codex/skills/leniu-api-development/SKILL.md +803 -0
- package/.codex/skills/leniu-architecture-design/SKILL.md +594 -0
- package/.codex/skills/leniu-backend-annotations/SKILL.md +662 -0
- package/.codex/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.codex/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.codex/skills/leniu-data-permission/SKILL.md +256 -0
- package/.codex/skills/leniu-database-ops/SKILL.md +426 -0
- package/.codex/skills/leniu-error-handler/SKILL.md +462 -0
- package/.codex/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.codex/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.codex/skills/leniu-java-entity/SKILL.md +751 -0
- package/.codex/skills/leniu-java-export/SKILL.md +560 -0
- package/.codex/skills/leniu-java-logging/SKILL.md +832 -0
- package/.codex/skills/leniu-java-mq/SKILL.md +338 -0
- package/.codex/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.codex/skills/leniu-java-task/SKILL.md +367 -0
- package/.codex/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
- package/.codex/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.codex/skills/leniu-security-guard/SKILL.md +520 -0
- package/.codex/skills/leniu-utils-toolkit/SKILL.md +378 -0
- package/.codex/skills/next/SKILL.md +137 -0
- package/.codex/skills/openspec-apply-change/SKILL.md +156 -0
- package/.codex/skills/openspec-archive-change/SKILL.md +114 -0
- package/.codex/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.codex/skills/openspec-continue-change/SKILL.md +118 -0
- package/.codex/skills/openspec-explore/SKILL.md +290 -0
- package/.codex/skills/openspec-ff-change/SKILL.md +101 -0
- package/.codex/skills/openspec-new-change/SKILL.md +74 -0
- package/.codex/skills/openspec-onboard/SKILL.md +529 -0
- package/.codex/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.codex/skills/openspec-verify-change/SKILL.md +168 -0
- package/.codex/skills/performance-doctor/SKILL.md +627 -0
- package/.codex/skills/progress/SKILL.md +193 -0
- package/.codex/skills/project-navigator/SKILL.md +286 -0
- package/.codex/skills/redis-cache/SKILL.md +829 -0
- package/.codex/skills/scheduled-jobs/SKILL.md +633 -0
- package/.codex/skills/security-guard/SKILL.md +739 -0
- package/.codex/skills/sms-mail/SKILL.md +766 -0
- package/.codex/skills/social-login/SKILL.md +668 -0
- package/.codex/skills/start/SKILL.md +154 -0
- package/.codex/skills/store-pc/SKILL.md +491 -0
- package/.codex/skills/sync/SKILL.md +149 -0
- package/.codex/skills/task-tracker/SKILL.md +307 -0
- package/.codex/skills/tech-decision/SKILL.md +393 -0
- package/.codex/skills/tenant-management/SKILL.md +603 -0
- package/.codex/skills/test-development/SKILL.md +755 -0
- package/.codex/skills/ui-pc/SKILL.md +475 -0
- package/.codex/skills/update-status/SKILL.md +159 -0
- package/.codex/skills/utils-toolkit/SKILL.md +593 -0
- package/.codex/skills/websocket-sse/SKILL.md +716 -0
- package/.codex/skills/workflow-engine/SKILL.md +676 -0
- package/.cursor/agents/code-reviewer.md +139 -0
- package/.cursor/agents/project-manager.md +159 -0
- package/.cursor/commands/opsx-apply.md +152 -0
- package/.cursor/commands/opsx-archive.md +157 -0
- package/.cursor/commands/opsx-bulk-archive.md +242 -0
- package/.cursor/commands/opsx-continue.md +114 -0
- package/.cursor/commands/opsx-explore.md +174 -0
- package/.cursor/commands/opsx-ff.md +94 -0
- package/.cursor/commands/opsx-new.md +69 -0
- package/.cursor/commands/opsx-onboard.md +525 -0
- package/.cursor/commands/opsx-sync.md +134 -0
- package/.cursor/commands/opsx-verify.md +164 -0
- package/.cursor/mcp.json +22 -0
- package/.cursor/skills/add-skill/SKILL.md +352 -0
- package/.cursor/skills/api-development/SKILL.md +560 -0
- package/.cursor/skills/architecture-design/SKILL.md +756 -0
- package/.cursor/skills/backend-annotations/SKILL.md +674 -0
- package/.cursor/skills/banana-image/CHANGELOG.md +37 -0
- package/.cursor/skills/banana-image/README.md +146 -0
- package/.cursor/skills/banana-image/SKILL.md +164 -0
- package/.cursor/skills/banana-image/assets/logo.png +0 -0
- package/.cursor/skills/banana-image/references/advanced-usage.md +189 -0
- package/.cursor/skills/banana-image/scripts/apply_template.py +125 -0
- package/.cursor/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.cursor/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.cursor/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.cursor/skills/banana-image/scripts/package.json +18 -0
- package/.cursor/skills/banana-image/scripts/requirements.txt +10 -0
- package/.cursor/skills/banana-image/templates/poster.json +22 -0
- package/.cursor/skills/banana-image/templates/product.json +17 -0
- package/.cursor/skills/banana-image/templates/social.json +22 -0
- package/.cursor/skills/banana-image/templates/thumbnail.json +17 -0
- package/.cursor/skills/brainstorm/SKILL.md +648 -0
- package/.cursor/skills/bug-detective/SKILL.md +1206 -0
- package/.cursor/skills/code-patterns/SKILL.md +590 -0
- package/.cursor/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.cursor/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.cursor/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.cursor/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.cursor/skills/crud-development/SKILL.md +649 -0
- package/.cursor/skills/data-permission/SKILL.md +599 -0
- package/.cursor/skills/database-ops/SKILL.md +407 -0
- package/.cursor/skills/error-handler/SKILL.md +371 -0
- package/.cursor/skills/file-oss-management/SKILL.md +863 -0
- package/.cursor/skills/git-workflow/SKILL.md +375 -0
- package/.cursor/skills/json-serialization/SKILL.md +357 -0
- package/.cursor/skills/leniu-api-development/SKILL.md +803 -0
- package/.cursor/skills/leniu-architecture-design/SKILL.md +598 -0
- package/.cursor/skills/leniu-backend-annotations/SKILL.md +664 -0
- package/.cursor/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.cursor/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.cursor/skills/leniu-data-permission/SKILL.md +256 -0
- package/.cursor/skills/leniu-database-ops/SKILL.md +426 -0
- package/.cursor/skills/leniu-error-handler/SKILL.md +462 -0
- package/.cursor/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.cursor/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.cursor/skills/leniu-java-entity/SKILL.md +751 -0
- package/.cursor/skills/leniu-java-export/SKILL.md +560 -0
- package/.cursor/skills/leniu-java-logging/SKILL.md +832 -0
- package/.cursor/skills/leniu-java-mq/SKILL.md +338 -0
- package/.cursor/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.cursor/skills/leniu-java-task/SKILL.md +367 -0
- package/.cursor/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
- package/.cursor/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.cursor/skills/leniu-security-guard/SKILL.md +520 -0
- package/.cursor/skills/leniu-utils-toolkit/SKILL.md +380 -0
- package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
- package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
- package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.cursor/skills/openspec-continue-change/SKILL.md +118 -0
- package/.cursor/skills/openspec-explore/SKILL.md +290 -0
- package/.cursor/skills/openspec-ff-change/SKILL.md +101 -0
- package/.cursor/skills/openspec-new-change/SKILL.md +74 -0
- package/.cursor/skills/openspec-onboard/SKILL.md +529 -0
- package/.cursor/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.cursor/skills/openspec-verify-change/SKILL.md +168 -0
- package/.cursor/skills/performance-doctor/SKILL.md +627 -0
- package/.cursor/skills/project-navigator/SKILL.md +305 -0
- package/.cursor/skills/redis-cache/SKILL.md +839 -0
- package/.cursor/skills/scheduled-jobs/SKILL.md +633 -0
- package/.cursor/skills/security-guard/SKILL.md +748 -0
- package/.cursor/skills/sms-mail/SKILL.md +766 -0
- package/.cursor/skills/social-login/SKILL.md +668 -0
- package/.cursor/skills/store-pc/SKILL.md +366 -0
- package/.cursor/skills/task-tracker/SKILL.md +307 -0
- package/.cursor/skills/tech-decision/SKILL.md +393 -0
- package/.cursor/skills/tenant-management/SKILL.md +603 -0
- package/.cursor/skills/test-development/SKILL.md +755 -0
- package/.cursor/skills/ui-pc/SKILL.md +438 -0
- package/.cursor/skills/utils-toolkit/SKILL.md +615 -0
- package/.cursor/skills/websocket-sse/SKILL.md +716 -0
- package/.cursor/skills/workflow-engine/SKILL.md +676 -0
- package/AGENTS.md +669 -0
- package/CLAUDE.md +205 -0
- package/README.md +205 -0
- package/bin/index.js +179 -0
- package/init.sh +178 -0
- package/package.json +27 -0
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
# 新功能开发流程规范
|
|
2
|
+
|
|
3
|
+
> **重要提示**: 本文档规定了从零开发新功能的完整流程。
|
|
4
|
+
> **注意**: 本项目是 RuoYi-Vue-Plus **纯后端项目**,采用**三层架构**(无 DAO 层)。
|
|
5
|
+
|
|
6
|
+
最后更新: 2026-02-09
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 📋 开发流程总览
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
第一步: 需求分析与设计
|
|
14
|
+
↓
|
|
15
|
+
第二步: 设计数据库表结构
|
|
16
|
+
↓
|
|
17
|
+
第三步: 生成菜单 SQL
|
|
18
|
+
↓
|
|
19
|
+
第四步: 生成后端代码(三层架构)
|
|
20
|
+
↓
|
|
21
|
+
第五步: 开发业务逻辑
|
|
22
|
+
↓
|
|
23
|
+
第六步: 测试与验证
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🏗️ 核心架构(必须牢记)
|
|
29
|
+
|
|
30
|
+
| 项目 | 规范 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| **包名** | `org.dromara.*`(禁止 `com.ruoyi.*`、`plus.ruoyi.*`) |
|
|
33
|
+
| **架构** | 三层:Controller → Service → Mapper(**无 DAO 层**) |
|
|
34
|
+
| **查询构建** | Service 层 `buildQueryWrapper()` |
|
|
35
|
+
| **Mapper 继承** | `BaseMapperPlus<Entity, VO>` |
|
|
36
|
+
| **对象转换** | `MapstructUtils.convert()` |
|
|
37
|
+
| **Entity 基类** | `TenantEntity`(多租户) |
|
|
38
|
+
| **BO 映射** | `@AutoMapper` 注解(单数,不是 `@AutoMappers`) |
|
|
39
|
+
| **主键策略** | 雪花 ID(不用 AUTO_INCREMENT) |
|
|
40
|
+
| **API 路径** | 标准 RESTful:`/list`、`/{id}` |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 📐 第一步: 需求分析与设计
|
|
45
|
+
|
|
46
|
+
### 1.1 明确功能需求
|
|
47
|
+
|
|
48
|
+
在开始开发前,明确以下内容:
|
|
49
|
+
- 功能名称和用途
|
|
50
|
+
- 需要哪些字段
|
|
51
|
+
- 业务规则和校验
|
|
52
|
+
- 权限控制要求
|
|
53
|
+
|
|
54
|
+
### 1.2 确定模块位置
|
|
55
|
+
|
|
56
|
+
| 业务领域 | 模块目录 | 包路径 | 表前缀 |
|
|
57
|
+
|---------|---------|--------|--------|
|
|
58
|
+
| 系统管理 | `ruoyi-modules/ruoyi-system/` | `org.dromara.system` | `sys_` |
|
|
59
|
+
| 演示模块 | `ruoyi-modules/ruoyi-demo/` | `org.dromara.demo` | `test_` |
|
|
60
|
+
| 工作流 | `ruoyi-modules/ruoyi-workflow/` | `org.dromara.workflow` | `flow_` |
|
|
61
|
+
| 商城业务 | `ruoyi-modules/ruoyi-mall/` | `org.dromara.mall` | `m_` |
|
|
62
|
+
| 自定义 | `ruoyi-modules/ruoyi-xxx/` | `org.dromara.xxx` | `xxx_` |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 📐 第二步: 设计数据库表结构
|
|
67
|
+
|
|
68
|
+
### 2.1 表设计规范
|
|
69
|
+
|
|
70
|
+
#### ✅ 命名规范
|
|
71
|
+
|
|
72
|
+
| 项目 | 规范 | 示例 |
|
|
73
|
+
|------|------|------|
|
|
74
|
+
| **表名** | 前缀 + 业务名称 | `m_goods`(商城商品) |
|
|
75
|
+
| **主键** | `id`(雪花 ID) | `id BIGINT(20) NOT NULL` |
|
|
76
|
+
| **外键** | `关联表_id` | `user_id`, `goods_id` |
|
|
77
|
+
| **状态字段** | `status` | `status CHAR(1) DEFAULT '1'` |
|
|
78
|
+
| **删除标记** | `del_flag` | `del_flag CHAR(1) DEFAULT '0'` |
|
|
79
|
+
|
|
80
|
+
#### ✅ 建表模板(必须包含的字段)
|
|
81
|
+
|
|
82
|
+
```sql
|
|
83
|
+
CREATE TABLE xxx_table (
|
|
84
|
+
-- 主键(雪花 ID,不用 AUTO_INCREMENT)
|
|
85
|
+
id BIGINT(20) NOT NULL COMMENT '主键ID',
|
|
86
|
+
|
|
87
|
+
-- 多租户字段(必须)
|
|
88
|
+
tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户ID',
|
|
89
|
+
|
|
90
|
+
-- 业务字段
|
|
91
|
+
xxx_name VARCHAR(100) NOT NULL COMMENT '名称',
|
|
92
|
+
status CHAR(1) DEFAULT '1' COMMENT '状态(0停用 1正常)',
|
|
93
|
+
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
|
94
|
+
|
|
95
|
+
-- 审计字段(必须,继承自 TenantEntity)
|
|
96
|
+
create_dept BIGINT(20) DEFAULT NULL COMMENT '创建部门',
|
|
97
|
+
create_by BIGINT(20) DEFAULT NULL COMMENT '创建人',
|
|
98
|
+
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
99
|
+
update_by BIGINT(20) DEFAULT NULL COMMENT '更新人',
|
|
100
|
+
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
101
|
+
|
|
102
|
+
-- 逻辑删除(必须)
|
|
103
|
+
del_flag CHAR(1) DEFAULT '0' COMMENT '删除标志(0正常 1已删除)',
|
|
104
|
+
|
|
105
|
+
PRIMARY KEY (id),
|
|
106
|
+
INDEX idx_tenant_id (tenant_id),
|
|
107
|
+
INDEX idx_status (status)
|
|
108
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='xxx表';
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2.2 SQL 文件存放位置
|
|
112
|
+
|
|
113
|
+
| 类型 | 位置 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| 系统表 | `script/sql/ry_vue_5.X.sql` |
|
|
116
|
+
| 业务表 | `script/sql/` 目录下新建文件 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 🎯 第三步: 生成菜单 SQL
|
|
121
|
+
|
|
122
|
+
### 3.1 菜单表结构
|
|
123
|
+
|
|
124
|
+
```sql
|
|
125
|
+
INSERT INTO sys_menu VALUES (
|
|
126
|
+
menu_id, -- 菜单ID(唯一,从已有最大ID+10开始)
|
|
127
|
+
'menu_name', -- 菜单名称(中文)
|
|
128
|
+
parent_id, -- 父菜单ID(一级目录为0)
|
|
129
|
+
order_num, -- 排序值
|
|
130
|
+
'path', -- 路由地址
|
|
131
|
+
'component', -- 组件路径
|
|
132
|
+
NULL, -- 路由参数
|
|
133
|
+
'0', -- 是否外链
|
|
134
|
+
'1', -- 菜单状态
|
|
135
|
+
'menu_type', -- 菜单类型(M目录 C菜单 F按钮)
|
|
136
|
+
'1', -- 显示状态
|
|
137
|
+
'1', -- 状态
|
|
138
|
+
'permission', -- 权限标识符
|
|
139
|
+
'icon', -- 菜单图标
|
|
140
|
+
103, -- 创建部门
|
|
141
|
+
1, -- 创建人
|
|
142
|
+
sysdate(), -- 创建时间
|
|
143
|
+
NULL, -- 更新人
|
|
144
|
+
NULL, -- 更新时间
|
|
145
|
+
'remark' -- 备注
|
|
146
|
+
);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 3.2 权限标识符命名规范
|
|
150
|
+
|
|
151
|
+
| 操作 | 权限标识符 | 说明 |
|
|
152
|
+
|------|-----------|------|
|
|
153
|
+
| **列表** | `模块:功能:list` | `demo:xxx:list` |
|
|
154
|
+
| **查询** | `模块:功能:query` | `demo:xxx:query` |
|
|
155
|
+
| **新增** | `模块:功能:add` | `demo:xxx:add` |
|
|
156
|
+
| **修改** | `模块:功能:edit` | `demo:xxx:edit` |
|
|
157
|
+
| **删除** | `模块:功能:remove` | `demo:xxx:remove` |
|
|
158
|
+
| **导出** | `模块:功能:export` | `demo:xxx:export` |
|
|
159
|
+
|
|
160
|
+
### 3.3 完整菜单 SQL 示例
|
|
161
|
+
|
|
162
|
+
```sql
|
|
163
|
+
-- 功能菜单(二级菜单)
|
|
164
|
+
INSERT INTO sys_menu VALUES (
|
|
165
|
+
3010, 'XXX管理', 2000, 10, 'xxx', 'demo/xxx/index',
|
|
166
|
+
NULL, '0', '1', 'C', '1', '1', 'demo:xxx:list', 'list',
|
|
167
|
+
103, 1, sysdate(), NULL, NULL, 'XXX管理菜单'
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
-- 按钮权限
|
|
171
|
+
INSERT INTO sys_menu VALUES (3011, 'XXX查询', 3010, 1, '#', '', NULL, '0', '1', 'F', '1', '1', 'demo:xxx:query', '#', 103, 1, sysdate(), NULL, NULL, '');
|
|
172
|
+
INSERT INTO sys_menu VALUES (3012, 'XXX新增', 3010, 2, '#', '', NULL, '0', '1', 'F', '1', '1', 'demo:xxx:add', '#', 103, 1, sysdate(), NULL, NULL, '');
|
|
173
|
+
INSERT INTO sys_menu VALUES (3013, 'XXX修改', 3010, 3, '#', '', NULL, '0', '1', 'F', '1', '1', 'demo:xxx:edit', '#', 103, 1, sysdate(), NULL, NULL, '');
|
|
174
|
+
INSERT INTO sys_menu VALUES (3014, 'XXX删除', 3010, 4, '#', '', NULL, '0', '1', 'F', '1', '1', 'demo:xxx:remove', '#', 103, 1, sysdate(), NULL, NULL, '');
|
|
175
|
+
INSERT INTO sys_menu VALUES (3015, 'XXX导出', 3010, 5, '#', '', NULL, '0', '1', 'F', '1', '1', 'demo:xxx:export', '#', 103, 1, sysdate(), NULL, NULL, '');
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 🔧 第四步: 生成后端代码(三层架构)
|
|
181
|
+
|
|
182
|
+
### 4.1 代码生成顺序
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
1. Entity (实体类) → extends TenantEntity
|
|
186
|
+
↓
|
|
187
|
+
2. BO (业务对象) → @AutoMapper(target = Entity.class)
|
|
188
|
+
↓
|
|
189
|
+
3. VO (视图对象) → @AutoMapper(target = Entity.class)
|
|
190
|
+
↓
|
|
191
|
+
4. Mapper (接口) → extends BaseMapperPlus<Entity, Vo>
|
|
192
|
+
↓
|
|
193
|
+
5. Service 接口 → IXxxService
|
|
194
|
+
↓
|
|
195
|
+
6. Service 实现 → 包含 buildQueryWrapper()
|
|
196
|
+
↓
|
|
197
|
+
7. Controller → extends BaseController
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 4.2 后端包结构
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
ruoyi-modules/ruoyi-xxx/src/main/java/org/dromara/xxx/
|
|
204
|
+
├── controller/
|
|
205
|
+
│ └── XxxController.java # @RestController
|
|
206
|
+
├── service/
|
|
207
|
+
│ ├── IXxxService.java # 服务接口
|
|
208
|
+
│ └── impl/
|
|
209
|
+
│ └── XxxServiceImpl.java # 服务实现(包含 buildQueryWrapper)
|
|
210
|
+
├── mapper/
|
|
211
|
+
│ └── XxxMapper.java # extends BaseMapperPlus<Xxx, XxxVo>
|
|
212
|
+
└── domain/
|
|
213
|
+
├── Xxx.java # Entity(extends TenantEntity)
|
|
214
|
+
├── bo/
|
|
215
|
+
│ └── XxxBo.java # 业务对象(@AutoMapper)
|
|
216
|
+
└── vo/
|
|
217
|
+
└── XxxVo.java # 视图对象
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 4.3 代码模板
|
|
221
|
+
|
|
222
|
+
#### Entity(实体类)
|
|
223
|
+
|
|
224
|
+
```java
|
|
225
|
+
package org.dromara.xxx.domain;
|
|
226
|
+
|
|
227
|
+
import com.baomidou.mybatisplus.annotation.*;
|
|
228
|
+
import lombok.Data;
|
|
229
|
+
import lombok.EqualsAndHashCode;
|
|
230
|
+
import org.dromara.common.tenant.core.TenantEntity;
|
|
231
|
+
|
|
232
|
+
@Data
|
|
233
|
+
@EqualsAndHashCode(callSuper = true)
|
|
234
|
+
@TableName("xxx_table")
|
|
235
|
+
public class Xxx extends TenantEntity {
|
|
236
|
+
|
|
237
|
+
@TableId(value = "id")
|
|
238
|
+
private Long id;
|
|
239
|
+
|
|
240
|
+
private String xxxName;
|
|
241
|
+
private String status;
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
#### BO(业务对象)
|
|
246
|
+
|
|
247
|
+
```java
|
|
248
|
+
package org.dromara.xxx.domain.bo;
|
|
249
|
+
|
|
250
|
+
import io.github.linpeilie.annotations.AutoMapper;
|
|
251
|
+
import jakarta.validation.constraints.*;
|
|
252
|
+
import lombok.Data;
|
|
253
|
+
import lombok.EqualsAndHashCode;
|
|
254
|
+
import org.dromara.common.core.validate.AddGroup;
|
|
255
|
+
import org.dromara.common.core.validate.EditGroup;
|
|
256
|
+
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
|
257
|
+
import org.dromara.xxx.domain.Xxx;
|
|
258
|
+
|
|
259
|
+
@Data
|
|
260
|
+
@EqualsAndHashCode(callSuper = true)
|
|
261
|
+
@AutoMapper(target = Xxx.class, reverseConvertGenerate = false) // ✅ 单数
|
|
262
|
+
public class XxxBo extends BaseEntity {
|
|
263
|
+
|
|
264
|
+
@NotNull(message = "ID不能为空", groups = {EditGroup.class})
|
|
265
|
+
private Long id;
|
|
266
|
+
|
|
267
|
+
@NotBlank(message = "名称不能为空", groups = {AddGroup.class, EditGroup.class})
|
|
268
|
+
private String xxxName;
|
|
269
|
+
|
|
270
|
+
private String status;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### VO(视图对象)
|
|
275
|
+
|
|
276
|
+
```java
|
|
277
|
+
package org.dromara.xxx.domain.vo;
|
|
278
|
+
|
|
279
|
+
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
|
280
|
+
import cn.idev.excel.annotation.ExcelProperty;
|
|
281
|
+
import io.github.linpeilie.annotations.AutoMapper;
|
|
282
|
+
import lombok.Data;
|
|
283
|
+
import org.dromara.xxx.domain.Xxx;
|
|
284
|
+
import java.io.Serializable;
|
|
285
|
+
import java.util.Date;
|
|
286
|
+
|
|
287
|
+
@Data
|
|
288
|
+
@ExcelIgnoreUnannotated
|
|
289
|
+
@AutoMapper(target = Xxx.class)
|
|
290
|
+
public class XxxVo implements Serializable {
|
|
291
|
+
|
|
292
|
+
@ExcelProperty(value = "ID")
|
|
293
|
+
private Long id;
|
|
294
|
+
|
|
295
|
+
@ExcelProperty(value = "名称")
|
|
296
|
+
private String xxxName;
|
|
297
|
+
|
|
298
|
+
@ExcelProperty(value = "状态")
|
|
299
|
+
private String status;
|
|
300
|
+
|
|
301
|
+
@ExcelProperty(value = "创建时间")
|
|
302
|
+
private Date createTime;
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Mapper(接口)
|
|
307
|
+
|
|
308
|
+
```java
|
|
309
|
+
package org.dromara.xxx.mapper;
|
|
310
|
+
|
|
311
|
+
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
|
312
|
+
import org.dromara.xxx.domain.Xxx;
|
|
313
|
+
import org.dromara.xxx.domain.vo.XxxVo;
|
|
314
|
+
|
|
315
|
+
public interface XxxMapper extends BaseMapperPlus<Xxx, XxxVo> {
|
|
316
|
+
// 继承 BaseMapperPlus,已提供 selectVoById、selectVoPage 等方法
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Service 接口
|
|
321
|
+
|
|
322
|
+
```java
|
|
323
|
+
package org.dromara.xxx.service;
|
|
324
|
+
|
|
325
|
+
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
326
|
+
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
327
|
+
import org.dromara.xxx.domain.bo.XxxBo;
|
|
328
|
+
import org.dromara.xxx.domain.vo.XxxVo;
|
|
329
|
+
import java.util.Collection;
|
|
330
|
+
import java.util.List;
|
|
331
|
+
|
|
332
|
+
public interface IXxxService {
|
|
333
|
+
|
|
334
|
+
XxxVo queryById(Long id);
|
|
335
|
+
|
|
336
|
+
TableDataInfo<XxxVo> queryPageList(XxxBo bo, PageQuery pageQuery);
|
|
337
|
+
|
|
338
|
+
List<XxxVo> queryList(XxxBo bo);
|
|
339
|
+
|
|
340
|
+
Boolean insertByBo(XxxBo bo);
|
|
341
|
+
|
|
342
|
+
Boolean updateByBo(XxxBo bo);
|
|
343
|
+
|
|
344
|
+
Boolean deleteByIds(Collection<Long> ids);
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### Service 实现(⭐ 核心:无 DAO 层)
|
|
349
|
+
|
|
350
|
+
```java
|
|
351
|
+
package org.dromara.xxx.service.impl;
|
|
352
|
+
|
|
353
|
+
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
354
|
+
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
355
|
+
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
356
|
+
import lombok.RequiredArgsConstructor;
|
|
357
|
+
import org.springframework.stereotype.Service;
|
|
358
|
+
import org.dromara.common.core.utils.MapstructUtils;
|
|
359
|
+
import org.dromara.common.core.utils.StringUtils;
|
|
360
|
+
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
361
|
+
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
362
|
+
import org.dromara.xxx.domain.Xxx;
|
|
363
|
+
import org.dromara.xxx.domain.bo.XxxBo;
|
|
364
|
+
import org.dromara.xxx.domain.vo.XxxVo;
|
|
365
|
+
import org.dromara.xxx.mapper.XxxMapper;
|
|
366
|
+
import org.dromara.xxx.service.IXxxService;
|
|
367
|
+
import java.util.Collection;
|
|
368
|
+
import java.util.List;
|
|
369
|
+
import java.util.Map;
|
|
370
|
+
|
|
371
|
+
@Service
|
|
372
|
+
@RequiredArgsConstructor
|
|
373
|
+
public class XxxServiceImpl implements IXxxService {
|
|
374
|
+
|
|
375
|
+
private final XxxMapper baseMapper; // ✅ 直接注入 Mapper(无 DAO 层)
|
|
376
|
+
|
|
377
|
+
@Override
|
|
378
|
+
public XxxVo queryById(Long id) {
|
|
379
|
+
return baseMapper.selectVoById(id);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@Override
|
|
383
|
+
public TableDataInfo<XxxVo> queryPageList(XxxBo bo, PageQuery pageQuery) {
|
|
384
|
+
LambdaQueryWrapper<Xxx> lqw = buildQueryWrapper(bo);
|
|
385
|
+
Page<XxxVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
|
386
|
+
return TableDataInfo.build(result);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@Override
|
|
390
|
+
public List<XxxVo> queryList(XxxBo bo) {
|
|
391
|
+
return baseMapper.selectVoList(buildQueryWrapper(bo));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
@Override
|
|
395
|
+
public Boolean insertByBo(XxxBo bo) {
|
|
396
|
+
Xxx add = MapstructUtils.convert(bo, Xxx.class); // ✅ MapstructUtils 转换
|
|
397
|
+
return baseMapper.insert(add) > 0;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@Override
|
|
401
|
+
public Boolean updateByBo(XxxBo bo) {
|
|
402
|
+
Xxx update = MapstructUtils.convert(bo, Xxx.class);
|
|
403
|
+
return baseMapper.updateById(update) > 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
@Override
|
|
407
|
+
public Boolean deleteByIds(Collection<Long> ids) {
|
|
408
|
+
return baseMapper.deleteByIds(ids) > 0;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* 构建查询条件(在 Service 层)
|
|
413
|
+
*/
|
|
414
|
+
private LambdaQueryWrapper<Xxx> buildQueryWrapper(XxxBo bo) {
|
|
415
|
+
Map<String, Object> params = bo.getParams();
|
|
416
|
+
LambdaQueryWrapper<Xxx> lqw = Wrappers.lambdaQuery();
|
|
417
|
+
lqw.like(StringUtils.isNotBlank(bo.getXxxName()), Xxx::getXxxName, bo.getXxxName());
|
|
418
|
+
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Xxx::getStatus, bo.getStatus());
|
|
419
|
+
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
|
420
|
+
Xxx::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
|
421
|
+
return lqw;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
#### Controller
|
|
427
|
+
|
|
428
|
+
```java
|
|
429
|
+
package org.dromara.xxx.controller;
|
|
430
|
+
|
|
431
|
+
import cn.dev33.satoken.annotation.SaCheckPermission;
|
|
432
|
+
import jakarta.servlet.http.HttpServletResponse;
|
|
433
|
+
import jakarta.validation.constraints.NotEmpty;
|
|
434
|
+
import jakarta.validation.constraints.NotNull;
|
|
435
|
+
import lombok.RequiredArgsConstructor;
|
|
436
|
+
import org.dromara.common.core.domain.R;
|
|
437
|
+
import org.dromara.common.core.validate.AddGroup;
|
|
438
|
+
import org.dromara.common.core.validate.EditGroup;
|
|
439
|
+
import org.dromara.common.excel.utils.ExcelUtil;
|
|
440
|
+
import org.dromara.common.log.annotation.Log;
|
|
441
|
+
import org.dromara.common.log.enums.BusinessType;
|
|
442
|
+
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
443
|
+
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
444
|
+
import org.dromara.common.web.core.BaseController;
|
|
445
|
+
import org.dromara.xxx.domain.bo.XxxBo;
|
|
446
|
+
import org.dromara.xxx.domain.vo.XxxVo;
|
|
447
|
+
import org.dromara.xxx.service.IXxxService;
|
|
448
|
+
import org.springframework.validation.annotation.Validated;
|
|
449
|
+
import org.springframework.web.bind.annotation.*;
|
|
450
|
+
import java.util.List;
|
|
451
|
+
|
|
452
|
+
@Validated
|
|
453
|
+
@RequiredArgsConstructor
|
|
454
|
+
@RestController
|
|
455
|
+
@RequestMapping("/xxx/xxx")
|
|
456
|
+
public class XxxController extends BaseController {
|
|
457
|
+
|
|
458
|
+
private final IXxxService xxxService;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* 查询列表
|
|
462
|
+
*/
|
|
463
|
+
@SaCheckPermission("xxx:xxx:list")
|
|
464
|
+
@GetMapping("/list")
|
|
465
|
+
public TableDataInfo<XxxVo> list(XxxBo bo, PageQuery pageQuery) {
|
|
466
|
+
return xxxService.queryPageList(bo, pageQuery);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* 获取详情
|
|
471
|
+
*/
|
|
472
|
+
@SaCheckPermission("xxx:xxx:query")
|
|
473
|
+
@GetMapping("/{id}")
|
|
474
|
+
public R<XxxVo> getInfo(@NotNull(message = "ID不能为空") @PathVariable Long id) {
|
|
475
|
+
return R.ok(xxxService.queryById(id));
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* 新增
|
|
480
|
+
*/
|
|
481
|
+
@SaCheckPermission("xxx:xxx:add")
|
|
482
|
+
@Log(title = "XXX管理", businessType = BusinessType.INSERT)
|
|
483
|
+
@PostMapping
|
|
484
|
+
public R<Void> add(@Validated(AddGroup.class) @RequestBody XxxBo bo) {
|
|
485
|
+
return toAjax(xxxService.insertByBo(bo));
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* 修改
|
|
490
|
+
*/
|
|
491
|
+
@SaCheckPermission("xxx:xxx:edit")
|
|
492
|
+
@Log(title = "XXX管理", businessType = BusinessType.UPDATE)
|
|
493
|
+
@PutMapping
|
|
494
|
+
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XxxBo bo) {
|
|
495
|
+
return toAjax(xxxService.updateByBo(bo));
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 删除
|
|
500
|
+
*/
|
|
501
|
+
@SaCheckPermission("xxx:xxx:remove")
|
|
502
|
+
@Log(title = "XXX管理", businessType = BusinessType.DELETE)
|
|
503
|
+
@DeleteMapping("/{ids}")
|
|
504
|
+
public R<Void> remove(@NotEmpty(message = "ID不能为空") @PathVariable Long[] ids) {
|
|
505
|
+
return toAjax(xxxService.deleteByIds(List.of(ids)));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* 导出
|
|
510
|
+
*/
|
|
511
|
+
@SaCheckPermission("xxx:xxx:export")
|
|
512
|
+
@Log(title = "XXX管理", businessType = BusinessType.EXPORT)
|
|
513
|
+
@PostMapping("/export")
|
|
514
|
+
public void export(XxxBo bo, HttpServletResponse response) {
|
|
515
|
+
List<XxxVo> list = xxxService.queryList(bo);
|
|
516
|
+
ExcelUtil.exportExcel(list, "XXX数据", XxxVo.class, response);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 🎯 第五步: 开发业务逻辑
|
|
524
|
+
|
|
525
|
+
### 5.1 添加业务校验
|
|
526
|
+
|
|
527
|
+
```java
|
|
528
|
+
@Override
|
|
529
|
+
public Boolean insertByBo(XxxBo bo) {
|
|
530
|
+
// 业务校验
|
|
531
|
+
if (isNameExists(bo.getXxxName())) {
|
|
532
|
+
throw new ServiceException("名称已存在");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
Xxx add = MapstructUtils.convert(bo, Xxx.class);
|
|
536
|
+
return baseMapper.insert(add) > 0;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private boolean isNameExists(String name) {
|
|
540
|
+
return baseMapper.exists(Wrappers.<Xxx>lambdaQuery()
|
|
541
|
+
.eq(Xxx::getXxxName, name));
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### 5.2 添加事务管理
|
|
546
|
+
|
|
547
|
+
```java
|
|
548
|
+
@Transactional(rollbackFor = Exception.class)
|
|
549
|
+
@Override
|
|
550
|
+
public Boolean insertByBo(XxxBo bo) {
|
|
551
|
+
// 多表操作使用事务
|
|
552
|
+
Xxx add = MapstructUtils.convert(bo, Xxx.class);
|
|
553
|
+
boolean result = baseMapper.insert(add) > 0;
|
|
554
|
+
|
|
555
|
+
// 其他关联操作...
|
|
556
|
+
|
|
557
|
+
return result;
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## 📋 开发流程检查清单
|
|
564
|
+
|
|
565
|
+
### ✅ 表设计检查
|
|
566
|
+
|
|
567
|
+
- [ ] 表前缀与模块对应
|
|
568
|
+
- [ ] 主键使用雪花 ID(不用 AUTO_INCREMENT)
|
|
569
|
+
- [ ] 包含 `tenant_id` 字段
|
|
570
|
+
- [ ] 包含审计字段(create_dept、create_by、create_time、update_by、update_time)
|
|
571
|
+
- [ ] 包含逻辑删除字段(del_flag)
|
|
572
|
+
- [ ] 添加必要的索引
|
|
573
|
+
|
|
574
|
+
### ✅ 后端代码检查
|
|
575
|
+
|
|
576
|
+
- [ ] 包名是 `org.dromara.*`
|
|
577
|
+
- [ ] Entity 继承 `TenantEntity`
|
|
578
|
+
- [ ] BO 使用 `@AutoMapper`(单数)
|
|
579
|
+
- [ ] Service 不继承任何基类
|
|
580
|
+
- [ ] Service 直接注入 Mapper(无 DAO 层)
|
|
581
|
+
- [ ] `buildQueryWrapper()` 在 Service 实现类中
|
|
582
|
+
- [ ] 使用 `MapstructUtils.convert()` 转换对象
|
|
583
|
+
- [ ] Mapper 继承 `BaseMapperPlus<Entity, VO>`
|
|
584
|
+
- [ ] Controller 使用标准 RESTful 路径(/list、/{id})
|
|
585
|
+
- [ ] 使用 `@SaCheckPermission` 权限注解
|
|
586
|
+
|
|
587
|
+
### ✅ 菜单 SQL 检查
|
|
588
|
+
|
|
589
|
+
- [ ] 菜单 ID 不冲突
|
|
590
|
+
- [ ] 权限标识符符合规范
|
|
591
|
+
- [ ] 包含完整的权限按钮(list、query、add、edit、remove、export)
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## ❌ 常见错误
|
|
596
|
+
|
|
597
|
+
### 禁止的写法
|
|
598
|
+
|
|
599
|
+
```java
|
|
600
|
+
// ❌ 错误1: 注入 DAO(本项目没有 DAO 层)
|
|
601
|
+
private final IXxxDao xxxDao;
|
|
602
|
+
|
|
603
|
+
// ❌ 错误2: 使用 BeanUtils
|
|
604
|
+
BeanUtil.copyProperties(bo, entity);
|
|
605
|
+
|
|
606
|
+
// ❌ 错误3: Service 继承基类
|
|
607
|
+
public class XxxServiceImpl extends ServiceImpl<XxxMapper, Xxx> { }
|
|
608
|
+
|
|
609
|
+
// ❌ 错误4: 使用 @AutoMappers(复数)
|
|
610
|
+
@AutoMappers({@AutoMapper(target = Xxx.class)})
|
|
611
|
+
|
|
612
|
+
// ❌ 错误5: 错误的包名
|
|
613
|
+
package com.ruoyi.xxx;
|
|
614
|
+
package plus.ruoyi.xxx;
|
|
615
|
+
|
|
616
|
+
// ❌ 错误6: 使用 AUTO_INCREMENT
|
|
617
|
+
id BIGINT(20) AUTO_INCREMENT
|
|
618
|
+
|
|
619
|
+
// ❌ 错误7: 错误的 API 路径
|
|
620
|
+
@GetMapping("/pageXxxs")
|
|
621
|
+
@GetMapping("/getXxx/{id}")
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### 正确的写法
|
|
625
|
+
|
|
626
|
+
```java
|
|
627
|
+
// ✅ 正确1: 直接注入 Mapper
|
|
628
|
+
private final XxxMapper baseMapper;
|
|
629
|
+
|
|
630
|
+
// ✅ 正确2: 使用 MapstructUtils
|
|
631
|
+
MapstructUtils.convert(bo, Xxx.class);
|
|
632
|
+
|
|
633
|
+
// ✅ 正确3: Service 只实现接口
|
|
634
|
+
public class XxxServiceImpl implements IXxxService { }
|
|
635
|
+
|
|
636
|
+
// ✅ 正确4: 使用 @AutoMapper(单数)
|
|
637
|
+
@AutoMapper(target = Xxx.class)
|
|
638
|
+
|
|
639
|
+
// ✅ 正确5: 正确的包名
|
|
640
|
+
package org.dromara.xxx;
|
|
641
|
+
|
|
642
|
+
// ✅ 正确6: 使用雪花 ID
|
|
643
|
+
id BIGINT(20) NOT NULL
|
|
644
|
+
|
|
645
|
+
// ✅ 正确7: 标准 RESTful 路径
|
|
646
|
+
@GetMapping("/list")
|
|
647
|
+
@GetMapping("/{id}")
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## 📚 参考实现
|
|
653
|
+
|
|
654
|
+
查看已有的完整实现:
|
|
655
|
+
|
|
656
|
+
| 类型 | 参考文件 |
|
|
657
|
+
|------|---------|
|
|
658
|
+
| Entity | `org.dromara.demo.domain.TestDemo` |
|
|
659
|
+
| BO | `org.dromara.demo.domain.bo.TestDemoBo` |
|
|
660
|
+
| VO | `org.dromara.demo.domain.vo.TestDemoVo` |
|
|
661
|
+
| Service | `org.dromara.demo.service.impl.TestDemoServiceImpl` |
|
|
662
|
+
| Mapper | `org.dromara.demo.mapper.TestDemoMapper` |
|
|
663
|
+
| Controller | `org.dromara.demo.controller.TestDemoController` |
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
## 🎯 总结
|
|
668
|
+
|
|
669
|
+
**开发流程**:
|
|
670
|
+
|
|
671
|
+
```
|
|
672
|
+
1️⃣ 需求分析 → 明确功能、确定模块位置
|
|
673
|
+
2️⃣ 表设计 → 雪花ID、租户ID、审计字段、逻辑删除
|
|
674
|
+
3️⃣ 菜单SQL → 权限标识符规范
|
|
675
|
+
4️⃣ 后端代码 → 三层架构(Controller → Service → Mapper)
|
|
676
|
+
5️⃣ 业务逻辑 → 校验、事务、异常处理
|
|
677
|
+
6️⃣ 测试验证 → 接口测试、功能测试
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**核心原则**:
|
|
681
|
+
|
|
682
|
+
- ✅ **包名是 `org.dromara.*`**
|
|
683
|
+
- ✅ **三层架构,无 DAO 层**
|
|
684
|
+
- ✅ **Service 直接注入 Mapper**
|
|
685
|
+
- ✅ **buildQueryWrapper() 在 Service 层**
|
|
686
|
+
- ✅ **使用 MapstructUtils.convert() 转换对象**
|
|
687
|
+
- ✅ **主键使用雪花 ID**
|
|
688
|
+
- ✅ **RESTful API 路径规范**
|