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,560 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-development
|
|
3
|
+
description: |
|
|
4
|
+
后端 API 接口设计规范。基于三层架构的 RESTful API 开发指南。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 设计 RESTful API 接口
|
|
8
|
+
- 编写 Controller 层代码
|
|
9
|
+
- 配置接口权限、日志、防重复提交注解
|
|
10
|
+
- 接口返回值类型选择
|
|
11
|
+
- 数据验证和参数校验
|
|
12
|
+
|
|
13
|
+
触发词:API、接口、RESTful、Controller、GetMapping、PostMapping、权限注解、日志注解、分页查询、接口规范
|
|
14
|
+
|
|
15
|
+
注意:
|
|
16
|
+
- 本项目是三层架构:Controller → Service → Mapper
|
|
17
|
+
- 参考 java-controller 技能获取更详细的 Controller 层规范
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# API 接口设计规范
|
|
21
|
+
|
|
22
|
+
## 核心规范
|
|
23
|
+
|
|
24
|
+
### 1. 接口定义原则
|
|
25
|
+
|
|
26
|
+
| 原则 | 说明 |
|
|
27
|
+
|------|------|
|
|
28
|
+
| **统一入口** | 所有接口使用 POST 或 RESTful 风格 |
|
|
29
|
+
| **认证保护** | 所有业务接口必须添加认证注解 |
|
|
30
|
+
| **参数校验** | 使用分组校验区分新增/修改场景 |
|
|
31
|
+
| **统一响应** | 使用统一的响应格式包装返回数据 |
|
|
32
|
+
|
|
33
|
+
### 2. HTTP 方法规范
|
|
34
|
+
|
|
35
|
+
| 操作 | HTTP 方法 | 路径 | 说明 |
|
|
36
|
+
|------|---------|------|------|
|
|
37
|
+
| **列表查询** | POST/GET | `/query` 或 `/list` | 分页查询列表 |
|
|
38
|
+
| **获取详情** | POST/GET | `/{id}` 或 `/detail` | 根据 ID 查询 |
|
|
39
|
+
| **新增** | POST | `/add` | 创建新数据 |
|
|
40
|
+
| **修改** | POST/PUT | `/update` | 更新数据 |
|
|
41
|
+
| **删除** | POST/DELETE | `/delete` 或 `/batch/delete` | 删除数据 |
|
|
42
|
+
| **导出** | POST | `/export` | 导出数据到 Excel |
|
|
43
|
+
| **导入** | POST | `/import-excel` | 从 Excel 导入数据 |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Controller 类模板
|
|
48
|
+
|
|
49
|
+
### 标准模板
|
|
50
|
+
|
|
51
|
+
```java
|
|
52
|
+
@Slf4j
|
|
53
|
+
@RestController
|
|
54
|
+
@RequiresAuthentication // 认证注解
|
|
55
|
+
@RequestMapping("/module/feature")
|
|
56
|
+
@Api(value = "模块/功能", tags = "模块/功能")
|
|
57
|
+
public class XxxController {
|
|
58
|
+
|
|
59
|
+
@Resource
|
|
60
|
+
@Lazy
|
|
61
|
+
private XxxService xxxService;
|
|
62
|
+
|
|
63
|
+
@PostMapping("/add")
|
|
64
|
+
@ApiOperation(value = "功能描述-新增")
|
|
65
|
+
public Long add(@Validated(InsertGroup.class) @RequestBody LeRequest<XxxDTO> request) {
|
|
66
|
+
return xxxService.add(request.getContent());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@PostMapping("/update")
|
|
70
|
+
@ApiOperation(value = "功能描述-修改")
|
|
71
|
+
public void update(@Validated(UpdateGroup.class) @RequestBody LeRequest<XxxDTO> request) {
|
|
72
|
+
xxxService.update(request.getContent());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@PostMapping("/query")
|
|
76
|
+
@ApiOperation(value = "功能描述-分页查询")
|
|
77
|
+
public Page<XxxVO> query(@Validated @RequestBody LeRequest<XxxQueryParam> request) {
|
|
78
|
+
return xxxService.pageList(request.getContent());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@PostMapping("/delete")
|
|
82
|
+
@ApiOperation(value = "功能描述-删除")
|
|
83
|
+
public void delete(@RequestBody LeRequest<Long> request) {
|
|
84
|
+
xxxService.delete(request.getContent());
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 参数封装规范
|
|
92
|
+
|
|
93
|
+
### 1. 请求参数封装
|
|
94
|
+
|
|
95
|
+
使用统一的请求包装类 `LeRequest<T>`:
|
|
96
|
+
|
|
97
|
+
```java
|
|
98
|
+
@PostMapping("/query")
|
|
99
|
+
public Page<XxxVO> query(@RequestBody LeRequest<XxxQueryParam> request) {
|
|
100
|
+
XxxQueryParam param = request.getContent(); // 获取实际参数
|
|
101
|
+
return xxxService.pageList(param);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. 分页参数
|
|
106
|
+
|
|
107
|
+
```java
|
|
108
|
+
@Data
|
|
109
|
+
public class XxxPageParam implements Serializable {
|
|
110
|
+
|
|
111
|
+
@ApiModelProperty(value = "分页参数", required = true)
|
|
112
|
+
@NotNull(message = "分页参数不能为空")
|
|
113
|
+
private PageDTO page;
|
|
114
|
+
|
|
115
|
+
@ApiModelProperty("关键字")
|
|
116
|
+
private String keyword;
|
|
117
|
+
|
|
118
|
+
@ApiModelProperty("状态")
|
|
119
|
+
private Integer status;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 3. 分组校验
|
|
124
|
+
|
|
125
|
+
```java
|
|
126
|
+
// 定义校验分组
|
|
127
|
+
public interface InsertGroup {}
|
|
128
|
+
public interface UpdateGroup {}
|
|
129
|
+
|
|
130
|
+
// DTO 中使用分组
|
|
131
|
+
@Data
|
|
132
|
+
public class XxxDTO {
|
|
133
|
+
|
|
134
|
+
@NotNull(message = "ID不能为空", groups = {UpdateGroup.class})
|
|
135
|
+
private Long id;
|
|
136
|
+
|
|
137
|
+
@NotBlank(message = "名称不能为空", groups = {InsertGroup.class, UpdateGroup.class})
|
|
138
|
+
private String name;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Controller 中应用分组
|
|
142
|
+
@PostMapping("/add")
|
|
143
|
+
public Long add(@Validated(InsertGroup.class) @RequestBody LeRequest<XxxDTO> request)
|
|
144
|
+
|
|
145
|
+
@PostMapping("/update")
|
|
146
|
+
public void update(@Validated(UpdateGroup.class) @RequestBody LeRequest<XxxDTO> request)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 响应格式规范
|
|
152
|
+
|
|
153
|
+
### 1. 分页响应
|
|
154
|
+
|
|
155
|
+
```java
|
|
156
|
+
// 使用 MyBatis-Plus 的 Page 对象
|
|
157
|
+
@PostMapping("/query")
|
|
158
|
+
public Page<XxxVO> query(@RequestBody LeRequest<XxxQueryParam> request) {
|
|
159
|
+
return xxxService.pageList(request.getContent());
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 或使用自定义分页对象
|
|
163
|
+
public class PageVO<T> {
|
|
164
|
+
private List<T> records; // 数据列表
|
|
165
|
+
private Long total; // 总条数
|
|
166
|
+
private Integer pageNum; // 当前页
|
|
167
|
+
private Integer pageSize; // 每页条数
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 2. 单条数据响应
|
|
172
|
+
|
|
173
|
+
```java
|
|
174
|
+
// 直接返回 VO 对象
|
|
175
|
+
@GetMapping("/{id}")
|
|
176
|
+
public XxxVO getById(@PathVariable Long id) {
|
|
177
|
+
return xxxService.getById(id);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// 或使用统一响应对象
|
|
181
|
+
@GetMapping("/{id}")
|
|
182
|
+
public R<XxxVO> getById(@PathVariable Long id) {
|
|
183
|
+
return R.ok(xxxService.getById(id));
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 3. 无返回值操作
|
|
188
|
+
|
|
189
|
+
```java
|
|
190
|
+
// 新增/修改/删除可以直接返回 void
|
|
191
|
+
@PostMapping("/add")
|
|
192
|
+
public void add(@RequestBody LeRequest<XxxDTO> request) {
|
|
193
|
+
xxxService.add(request.getContent());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 或返回 ID
|
|
197
|
+
@PostMapping("/add")
|
|
198
|
+
public Long add(@RequestBody LeRequest<XxxDTO> request) {
|
|
199
|
+
return xxxService.add(request.getContent());
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 参数校验规范
|
|
206
|
+
|
|
207
|
+
### 1. Jakarta Validation 注解
|
|
208
|
+
|
|
209
|
+
**重要**: 项目使用 JDK 21,必须使用 `jakarta.validation.constraints.*` 包
|
|
210
|
+
|
|
211
|
+
```java
|
|
212
|
+
import jakarta.validation.Valid;
|
|
213
|
+
import jakarta.validation.constraints.NotNull;
|
|
214
|
+
import jakarta.validation.constraints.NotBlank;
|
|
215
|
+
import jakarta.validation.constraints.NotEmpty;
|
|
216
|
+
import jakarta.validation.constraints.Size;
|
|
217
|
+
import jakarta.validation.constraints.Pattern;
|
|
218
|
+
import jakarta.validation.constraints.Min;
|
|
219
|
+
import jakarta.validation.constraints.Max;
|
|
220
|
+
|
|
221
|
+
@Data
|
|
222
|
+
public class XxxDTO {
|
|
223
|
+
|
|
224
|
+
@NotNull(message = "ID不能为空", groups = {UpdateGroup.class})
|
|
225
|
+
private Long id;
|
|
226
|
+
|
|
227
|
+
@NotBlank(message = "名称不能为空", groups = {InsertGroup.class, UpdateGroup.class})
|
|
228
|
+
@Size(max = 100, message = "名称长度不能超过100个字符")
|
|
229
|
+
private String name;
|
|
230
|
+
|
|
231
|
+
@Min(value = 0, message = "数量不能小于0")
|
|
232
|
+
@Max(value = 9999, message = "数量不能大于9999")
|
|
233
|
+
private Integer count;
|
|
234
|
+
|
|
235
|
+
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
|
236
|
+
private String phone;
|
|
237
|
+
|
|
238
|
+
@Email(message = "邮箱格式不正确")
|
|
239
|
+
private String email;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 2. 校验注解速查表
|
|
244
|
+
|
|
245
|
+
| 注解 | 用途 | 示例 |
|
|
246
|
+
|------|------|------|
|
|
247
|
+
| `@NotNull` | 不能为 null | `@NotNull(message = "ID不能为空")` |
|
|
248
|
+
| `@NotBlank` | 字符串不能为空或空白 | `@NotBlank(message = "名称不能为空")` |
|
|
249
|
+
| `@NotEmpty` | 集合/数组不能为空 | `@NotEmpty(message = "ID列表不能为空")` |
|
|
250
|
+
| `@Size` | 集合/字符串长度 | `@Size(min = 1, max = 100)` |
|
|
251
|
+
| `@Min` | 最小值 | `@Min(value = 0, message = "不能小于0")` |
|
|
252
|
+
| `@Max` | 最大值 | `@Max(value = 100, message = "不能大于100")` |
|
|
253
|
+
| `@Pattern` | 正则表达式 | `@Pattern(regexp = "^[0-9]+$")` |
|
|
254
|
+
| `@Email` | 邮箱格式 | `@Email(message = "邮箱格式错误")` |
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## API 文档注解
|
|
259
|
+
|
|
260
|
+
### Swagger 注解使用
|
|
261
|
+
|
|
262
|
+
```java
|
|
263
|
+
import io.swagger.annotations.Api;
|
|
264
|
+
import io.swagger.annotations.ApiOperation;
|
|
265
|
+
import io.swagger.annotations.ApiModel;
|
|
266
|
+
import io.swagger.annotations.ApiModelProperty;
|
|
267
|
+
|
|
268
|
+
// Controller 类级别
|
|
269
|
+
@Api(value = "模块/功能", tags = "模块/功能")
|
|
270
|
+
@RestController
|
|
271
|
+
public class XxxController {
|
|
272
|
+
|
|
273
|
+
// 方法级别
|
|
274
|
+
@ApiOperation(value = "功能描述-新增")
|
|
275
|
+
@PostMapping("/add")
|
|
276
|
+
public Long add(@RequestBody LeRequest<XxxDTO> request) {
|
|
277
|
+
// ...
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// DTO/VO 类级别
|
|
282
|
+
@Data
|
|
283
|
+
@ApiModel("功能描述DTO")
|
|
284
|
+
public class XxxDTO {
|
|
285
|
+
|
|
286
|
+
@ApiModelProperty(value = "主键ID", required = true)
|
|
287
|
+
private Long id;
|
|
288
|
+
|
|
289
|
+
@ApiModelProperty("名称")
|
|
290
|
+
private String name;
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## 常见场景示例
|
|
297
|
+
|
|
298
|
+
### 1. 带 Redisson 分布式锁的导入
|
|
299
|
+
|
|
300
|
+
```java
|
|
301
|
+
@PostMapping("/import-excel")
|
|
302
|
+
@ApiOperation(value = "Excel导入")
|
|
303
|
+
public void importExcel(@RequestParam(value = "file") MultipartFile file) {
|
|
304
|
+
if (Objects.isNull(file) || file.isEmpty()) {
|
|
305
|
+
throw new LeException("文件不能为空");
|
|
306
|
+
}
|
|
307
|
+
RLock lock = redissonClient.getLock("import:lock:" + TenantContextHolder.getTenantId());
|
|
308
|
+
if (!lock.tryLock(5, 60, TimeUnit.SECONDS)) {
|
|
309
|
+
throw new LeException("正在处理中,请稍后再试");
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
xxxService.importExcel(file);
|
|
313
|
+
} finally {
|
|
314
|
+
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
|
|
315
|
+
lock.unlock();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### 2. 批量删除
|
|
322
|
+
|
|
323
|
+
```java
|
|
324
|
+
@RequestMapping(value = "/batch/delete", method = {RequestMethod.POST, RequestMethod.PUT})
|
|
325
|
+
@ApiOperation(value = "批量删除")
|
|
326
|
+
public void batchDelete(@RequestBody LeRequest<List<Long>> request) {
|
|
327
|
+
if (CollUtil.isEmpty(request.getContent())) {
|
|
328
|
+
throw new LeException("ID列表不能为空");
|
|
329
|
+
}
|
|
330
|
+
xxxService.batchDelete(request.getContent());
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 3. 带合计行的分页查询
|
|
335
|
+
|
|
336
|
+
```java
|
|
337
|
+
@PostMapping("/query")
|
|
338
|
+
@ApiOperation(value = "分页查询(带合计)")
|
|
339
|
+
public ReportBaseTotalVO<XxxVO> query(@RequestBody LeRequest<XxxQueryParam> request) {
|
|
340
|
+
ReportBaseTotalVO<XxxVO> result = new ReportBaseTotalVO<>();
|
|
341
|
+
|
|
342
|
+
// 查询合计行
|
|
343
|
+
XxxVO totalLine = xxxService.getSummaryTotal(request.getContent());
|
|
344
|
+
result.setTotalLine(totalLine);
|
|
345
|
+
|
|
346
|
+
// 分页查询
|
|
347
|
+
Page<XxxVO> page = xxxService.pageList(request.getContent());
|
|
348
|
+
result.setResultPage(PageVO.of(page));
|
|
349
|
+
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 检查清单
|
|
357
|
+
|
|
358
|
+
生成 API 代码前必须检查:
|
|
359
|
+
|
|
360
|
+
- [ ] **认证注解是否添加**?(`@RequiresAuthentication` 或类似)
|
|
361
|
+
- [ ] **API 文档注解是否添加**?(`@ApiOperation`)
|
|
362
|
+
- [ ] **参数校验是否正确**?(`@Validated` + 分组)
|
|
363
|
+
- [ ] **返回值类型是否正确**?(分页用 `Page<VO>`,单条用 VO 或 `R<VO>`)
|
|
364
|
+
- [ ] **HTTP 方法是否正确**?(查询 POST/GET,新增 POST,修改 POST/PUT)
|
|
365
|
+
- [ ] **路径命名是否规范**?(`/add`, `/update`, `/query`, `/delete`)
|
|
366
|
+
- [ ] **是否使用了 `LeRequest<T>` 封装请求**?
|
|
367
|
+
- [ ] **是否使用中文注释和错误提示**?
|
|
368
|
+
- [ ] **敏感操作是否加了分布式锁**?
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 错误对比
|
|
373
|
+
|
|
374
|
+
### ❌ 不要做
|
|
375
|
+
|
|
376
|
+
```java
|
|
377
|
+
// 错误 1: 缺少认证注解
|
|
378
|
+
@RestController
|
|
379
|
+
public class XxxController { }
|
|
380
|
+
|
|
381
|
+
// 错误 2: 不使用参数封装
|
|
382
|
+
@PostMapping("/add")
|
|
383
|
+
public Long add(@RequestBody XxxDTO dto) { } // 应该用 LeRequest<XxxDTO>
|
|
384
|
+
|
|
385
|
+
// 错误 3: 不使用分组校验
|
|
386
|
+
@PostMapping("/add")
|
|
387
|
+
public Long add(@Valid @RequestBody LeRequest<XxxDTO> request) { } // 应该用 @Validated(InsertGroup.class)
|
|
388
|
+
|
|
389
|
+
// 错误 4: 使用 javax.validation(JDK 21 应用 jakarta.validation)
|
|
390
|
+
import javax.validation.constraints.NotNull; // ❌ 错误
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### ✅ 正确做法
|
|
394
|
+
|
|
395
|
+
```java
|
|
396
|
+
// 正确 1: 添加认证注解
|
|
397
|
+
@RestController
|
|
398
|
+
@RequiresAuthentication
|
|
399
|
+
public class XxxController { }
|
|
400
|
+
|
|
401
|
+
// 正确 2: 使用参数封装
|
|
402
|
+
@PostMapping("/add")
|
|
403
|
+
public Long add(@Validated(InsertGroup.class) @RequestBody LeRequest<XxxDTO> request) {
|
|
404
|
+
return xxxService.add(request.getContent());
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// 正确 3: 使用分组校验
|
|
408
|
+
@Validated(InsertGroup.class)
|
|
409
|
+
|
|
410
|
+
// 正确 4: 使用 Jakarta Validation
|
|
411
|
+
import jakarta.validation.constraints.NotNull; // ✅ 正确
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 相关技能
|
|
417
|
+
|
|
418
|
+
| 需要了解 | 激活 Skill |
|
|
419
|
+
|---------|-----------|
|
|
420
|
+
| Service 层规范 | `java-service` |
|
|
421
|
+
| Controller 详细规范 | `java-controller` |
|
|
422
|
+
| 异常处理 | `java-exception` / `error-handler` |
|
|
423
|
+
| 参数校验详细 | `java-entity` |
|
|
424
|
+
| 数据库设计 | `java-database` / `database-ops` |
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 多项目深度对比
|
|
429
|
+
|
|
430
|
+
### 项目架构差异详解
|
|
431
|
+
|
|
432
|
+
| 特征 | RuoYi-Vue-Plus | leniu-tengyun-core |
|
|
433
|
+
|-----|----------------|-------------------|
|
|
434
|
+
| **JDK 版本** | 17 | 21 |
|
|
435
|
+
| **包名前缀** | `org.dromara.*` | `net.xnzn.core.*` |
|
|
436
|
+
| **请求封装** | 直接使用 BO | `LeRequest<T>` 包装 |
|
|
437
|
+
| **响应封装** | `R<T>`, `TableDataInfo<T>` | `Page<T>`, `void` |
|
|
438
|
+
| **分组校验** | `AddGroup`, `EditGroup` | `InsertGroup`, `UpdateGroup` |
|
|
439
|
+
| **认证注解** | `@SaCheckPermission` | `@RequiresAuthentication` |
|
|
440
|
+
| **异常类** | `ServiceException` | `LeException` |
|
|
441
|
+
| **国际化** | `MessageUtils.message()` | `I18n.getMessage()` |
|
|
442
|
+
|
|
443
|
+
### leniu-tengyun-core Controller 完整示例
|
|
444
|
+
|
|
445
|
+
```java
|
|
446
|
+
@RequiresAuthentication
|
|
447
|
+
@RestController
|
|
448
|
+
@RequestMapping("/back/attendance/leave-info")
|
|
449
|
+
@Api(value = "考勤/请假信息", tags = "考勤/请假信息")
|
|
450
|
+
public class LeaveInfoController {
|
|
451
|
+
|
|
452
|
+
@Resource
|
|
453
|
+
@Lazy
|
|
454
|
+
private LeaveInfoService leaveInfoService;
|
|
455
|
+
|
|
456
|
+
@PostMapping("/add")
|
|
457
|
+
@ApiOperation(value = "请假信息-新增")
|
|
458
|
+
public Long add(@Validated(InsertGroup.class) @RequestBody LeRequest<LeaveInfoDTO> request) {
|
|
459
|
+
return leaveInfoService.add(request.getContent());
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
@PostMapping("/update")
|
|
463
|
+
@ApiOperation(value = "请假信息-修改")
|
|
464
|
+
public void update(@Validated(UpdateGroup.class) @RequestBody LeRequest<LeaveInfoDTO> request) {
|
|
465
|
+
leaveInfoService.update(request.getContent());
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
@PostMapping("/query")
|
|
469
|
+
@ApiOperation(value = "请假信息-分页查询")
|
|
470
|
+
public Page<LeaveInfoVO> query(@Validated @RequestBody LeRequest<LeaveInfoQueryParam> request) {
|
|
471
|
+
return leaveInfoService.pageList(request.getContent());
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
@PostMapping("/delete")
|
|
475
|
+
@ApiOperation(value = "请假信息-删除")
|
|
476
|
+
public void delete(@RequestBody LeRequest<Long> request) {
|
|
477
|
+
leaveInfoService.delete(request.getContent());
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Redisson 分布式锁完整示例
|
|
483
|
+
|
|
484
|
+
```java
|
|
485
|
+
import org.redisson.api.RLock;
|
|
486
|
+
import org.redisson.api.RedissonClient;
|
|
487
|
+
import java.util.concurrent.TimeUnit;
|
|
488
|
+
|
|
489
|
+
@Resource
|
|
490
|
+
private RedissonClient redissonClient;
|
|
491
|
+
|
|
492
|
+
@PostMapping("/import-excel")
|
|
493
|
+
@ApiOperation(value = "Excel导入")
|
|
494
|
+
public void importExcel(@RequestParam(value = "file") MultipartFile file) {
|
|
495
|
+
if (Objects.isNull(file) || file.isEmpty()) {
|
|
496
|
+
throw new LeException("文件不能为空");
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// 获取分布式锁
|
|
500
|
+
RLock lock = redissonClient.getLock("import:lock:" + TenantContextHolder.getTenantId());
|
|
501
|
+
|
|
502
|
+
// 尝试获取锁:等待5秒,锁定60秒后自动释放
|
|
503
|
+
if (!lock.tryLock(5, 60, TimeUnit.SECONDS)) {
|
|
504
|
+
throw new LeException("正在处理中,请稍后再试");
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
try {
|
|
508
|
+
xxxService.importExcel(file);
|
|
509
|
+
} finally {
|
|
510
|
+
// 释放锁前检查当前线程是否持有锁
|
|
511
|
+
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
|
|
512
|
+
lock.unlock();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### 批量操作示例
|
|
519
|
+
|
|
520
|
+
```java
|
|
521
|
+
@RequestMapping(value = "/batch/delete", method = {RequestMethod.POST, RequestMethod.PUT})
|
|
522
|
+
@ApiOperation(value = "批量删除")
|
|
523
|
+
public void batchDelete(@RequestBody LeRequest<List<Long>> request) {
|
|
524
|
+
// 使用 Hutool 的 CollUtil 进行判空
|
|
525
|
+
if (CollUtil.isEmpty(request.getContent())) {
|
|
526
|
+
throw new LeException("ID列表不能为空");
|
|
527
|
+
}
|
|
528
|
+
xxxService.batchDelete(request.getContent());
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
@PostMapping("/batch/update-status")
|
|
532
|
+
@ApiOperation(value = "批量更新状态")
|
|
533
|
+
public void batchUpdateStatus(@RequestBody LeRequest<BatchUpdateDTO> request) {
|
|
534
|
+
BatchUpdateDTO dto = request.getContent();
|
|
535
|
+
if (CollUtil.isEmpty(dto.getIds())) {
|
|
536
|
+
throw new LeException("ID列表不能为空");
|
|
537
|
+
}
|
|
538
|
+
xxxService.batchUpdateStatus(dto.getIds(), dto.getStatus());
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 带合计行的分页查询
|
|
543
|
+
|
|
544
|
+
```java
|
|
545
|
+
@PostMapping("/query")
|
|
546
|
+
@ApiOperation(value = "分页查询(带合计)")
|
|
547
|
+
public ReportBaseTotalVO<XxxVO> query(@RequestBody LeRequest<XxxQueryParam> request) {
|
|
548
|
+
ReportBaseTotalVO<XxxVO> result = new ReportBaseTotalVO<>();
|
|
549
|
+
|
|
550
|
+
// 1. 查询合计行
|
|
551
|
+
XxxVO totalLine = xxxService.getSummaryTotal(request.getContent());
|
|
552
|
+
result.setTotalLine(totalLine);
|
|
553
|
+
|
|
554
|
+
// 2. 分页查询
|
|
555
|
+
Page<XxxVO> page = xxxService.pageList(request.getContent());
|
|
556
|
+
result.setResultPage(PageVO.of(page));
|
|
557
|
+
|
|
558
|
+
return result;
|
|
559
|
+
}
|
|
560
|
+
```
|