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,1206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bug-detective
|
|
3
|
+
description: |
|
|
4
|
+
后端 Bug 排查指南。包含错误诊断决策树、日志分析、分层定位、数据库排查、本项目特有问题库。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 接口返回 4xx/5xx 错误
|
|
8
|
+
- NullPointerException、SQLException 等异常排查
|
|
9
|
+
- 数据查不到、对象转换失败
|
|
10
|
+
- R.ok() 返回值陷阱、雪花 ID 精度丢失
|
|
11
|
+
- 日志文件分析(./logs/sys-console.log)
|
|
12
|
+
|
|
13
|
+
触发词:Bug、报错、异常、不工作、500错误、NullPointerException、SQLException、数据查不到、日志分析、排查、调试、debug、错误排查
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Bug 排查指南(RuoYi-Vue-Plus 三层架构版)
|
|
17
|
+
|
|
18
|
+
> **⚠️ 重要声明**:本项目是 **RuoYi-Vue-Plus 纯后端项目**,采用三层架构(Controller → Service → Mapper),无独立 DAO 层!
|
|
19
|
+
> 本文档用于**排查已发生的问题**。如需设计异常处理机制(try-catch、全局异常、错误码),请使用 error-handler Skill。
|
|
20
|
+
|
|
21
|
+
## 问题类型速查表
|
|
22
|
+
|
|
23
|
+
| 问题类型 | 表现现象 | 排查方式 | 涉及层级 | 相关 Skill |
|
|
24
|
+
|---------|--------|--------|--------|----------|
|
|
25
|
+
| **接口 5xx 错误** | 服务端返回 500 | 读日志、打断点 | 后端全层 | bug-detective |
|
|
26
|
+
| **接口 4xx 错误** | 参数/路径/权限错误 | 检查请求格式、权限配置 | Controller 层 | security-guard, api-development |
|
|
27
|
+
| **数据查不到** | 查询条件错误、租户隔离 | 执行 SQL 验证 | Service/Mapper 层 | bug-detective, database-ops |
|
|
28
|
+
| **对象转换失败** | MapstructUtils 返回 null | 检查 @AutoMapper 配置 | Service 层 | code-patterns, crud-development |
|
|
29
|
+
| **R.ok() 返回格式错误** | data 为 null,msg 有值 | R.ok(String) 陷阱,改用 R.ok(null, value) | Controller 层 | bug-detective(本项目特有) |
|
|
30
|
+
| **数据精度丢失** | ID 最后几位变成 0 | 雪花 ID 大数问题,Long 改 String | 前后端交互 | bug-detective(本项目特有) |
|
|
31
|
+
| **权限不足** | 接口 403,用户无权限 | 检查角色权限、菜单配置 | Service 层 | security-guard, data-permission |
|
|
32
|
+
| **前端页面不显示** | 空白、组件未渲染、JS 错误 | 浏览器开发工具、Vue Devtools | 前端层 | ui-pc |
|
|
33
|
+
| **SQL 执行报错** | PostgreSQL 类型错误、语法错误 | 检查字段类型与查询方法匹配 | Mapper 层 | database-ops, code-patterns |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 快速诊断入口
|
|
38
|
+
|
|
39
|
+
> **描述你的问题,根据关键词快速定位**
|
|
40
|
+
|
|
41
|
+
### 错误关键词索引
|
|
42
|
+
|
|
43
|
+
| 关键词/现象 | 可能原因 | 跳转章节 |
|
|
44
|
+
|------------|---------|---------|
|
|
45
|
+
| `NullPointerException` | 对象为空 | [#NPE 排查](#1-nullpointerexception) |
|
|
46
|
+
| `SQLException` / `SQL 语法` | SQL 错误 | [#SQL 异常](#2-sql-异常) |
|
|
47
|
+
| `401` / `未认证` | Token 问题 | [#权限问题](#3-权限问题) |
|
|
48
|
+
| `403` / `无权限` | 权限配置 | [#权限问题](#3-权限问题) |
|
|
49
|
+
| `404` / `接口不存在` | URL 路径错误 | [#接口调用失败](#1-接口调用失败) |
|
|
50
|
+
| `500` / `服务器错误` | 后端异常 | [#日志分析](#日志分析) |
|
|
51
|
+
| **`data 为 null`** / **`msg 有值 data 没值`** | **R.ok(String) 陷阱** | [#R.ok() 陷阱](#1-rok-返回-string-类型的陷阱极易踩坑) |
|
|
52
|
+
| `MapstructUtils 返回 null` | @AutoMappers 配置 | [#对象转换问题](#3-对象转换问题) |
|
|
53
|
+
| `查询无结果` / `数据查不到` | 租户/条件问题 | [#租户数据问题](#4-租户数据问题) |
|
|
54
|
+
| `like 报错` / `PostgreSQL 类型错误` | like 仅限 String 类型 | [#like 方法类型限制](#5-like-方法类型限制) |
|
|
55
|
+
| `前端取不到数据` | API 调用格式 | [#API 调用格式](#6-api-调用格式错误) |
|
|
56
|
+
| `页面空白` / `组件不显示` | 响应式/v-if | [#页面渲染问题](#2-页面渲染问题) |
|
|
57
|
+
| `样式错乱` | CSS 优先级/单位 | [#样式问题](#3-样式问题) |
|
|
58
|
+
| `精度丢失` / `ID 不对` | 雪花 ID 大数问题 | [#雪花 ID 精度问题](#6-雪花-id-精度丢失) |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 问题诊断决策树
|
|
63
|
+
|
|
64
|
+
### 接口返回错误
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
接口返回错误
|
|
68
|
+
├─ 状态码 4xx
|
|
69
|
+
│ ├─ 400 → 请求参数格式/类型错误
|
|
70
|
+
│ │ 检查:@RequestBody/@RequestParam、参数名称、类型
|
|
71
|
+
│ ├─ 401 → Token 过期/未登录
|
|
72
|
+
│ │ 检查:Authorization 头、Token 是否有效、是否传递
|
|
73
|
+
│ ├─ 403 → 无权限访问
|
|
74
|
+
│ │ 检查:@SaCheckPermission 配置、用户角色、菜单权限
|
|
75
|
+
│ └─ 404 → 接口路径不存在
|
|
76
|
+
│ 检查:@RequestMapping 路径、Controller 是否扫描到
|
|
77
|
+
│
|
|
78
|
+
├─ 状态码 500
|
|
79
|
+
│ ├─ 控制台有堆栈 → 根据异常类型定位
|
|
80
|
+
│ │ ├─ NullPointerException → 对象未初始化/查询返回 null
|
|
81
|
+
│ │ ├─ SQLException → SQL 语法/字段名错误
|
|
82
|
+
│ │ ├─ ServiceException → 业务逻辑主动抛出
|
|
83
|
+
│ │ └─ 其他异常 → 查看具体异常信息
|
|
84
|
+
│ └─ 无堆栈信息 → 检查全局异常处理器是否吞掉了异常
|
|
85
|
+
│
|
|
86
|
+
└─ 状态码 200 但数据不对
|
|
87
|
+
├─ data 为 null,msg 有值
|
|
88
|
+
│ └─ ⭐ R.ok(String) 陷阱!用 R.ok(null, str) 替代
|
|
89
|
+
├─ data 为 null,msg 也为 null
|
|
90
|
+
│ ├─ 查询条件错误 → 检查 buildQueryWrapper
|
|
91
|
+
│ ├─ 租户 ID 不匹配 → 检查 tenant_id
|
|
92
|
+
│ └─ 数据被逻辑删除 → 检查 del_flag
|
|
93
|
+
├─ data 部分字段缺失
|
|
94
|
+
│ └─ @AutoMappers 配置问题
|
|
95
|
+
└─ data 格式不对(如 ID 精度丢失)
|
|
96
|
+
└─ 雪花 ID 大数问题,需要 String 化
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 页面不显示/报错
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
页面问题
|
|
103
|
+
├─ 控制台有 JS 错误
|
|
104
|
+
│ ├─ TypeError → 类型错误,检查变量定义
|
|
105
|
+
│ ├─ ReferenceError → 引用错误,检查导入
|
|
106
|
+
│ └─ 组件报错 → 检查组件属性/插槽
|
|
107
|
+
│
|
|
108
|
+
├─ Network 有红色请求
|
|
109
|
+
│ └─ 接口问题 → 转到"接口返回错误"决策树
|
|
110
|
+
│
|
|
111
|
+
├─ 无错误但不显示
|
|
112
|
+
│ ├─ v-if 条件为 false → 检查条件逻辑
|
|
113
|
+
│ ├─ 数据未赋值 → 检查 .value 是否正确使用
|
|
114
|
+
│ ├─ 组件未注册 → 检查 import 和 components
|
|
115
|
+
│ └─ CSS display:none → 检查样式
|
|
116
|
+
│
|
|
117
|
+
└─ 样式问题
|
|
118
|
+
└─ PC 端 → 检查是否误用 el-* 组件
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 分层定位指南
|
|
124
|
+
|
|
125
|
+
### 快速判断问题在哪一层
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
步骤 1:用 Postman/curl 直接调接口
|
|
129
|
+
├─ 返回正确数据 → 问题在【前端】
|
|
130
|
+
└─ 返回错误 → 问题在【后端】
|
|
131
|
+
|
|
132
|
+
步骤 2(后端问题):打断点或加日志
|
|
133
|
+
├─ Controller 收到请求 → 问题在 Service/Mapper
|
|
134
|
+
├─ Controller 没收到 → URL 路径/扫描问题
|
|
135
|
+
└─ Controller 参数为空 → 请求参数传递问题
|
|
136
|
+
|
|
137
|
+
步骤 3(后端问题):在数据库直接执行 SQL
|
|
138
|
+
├─ 有数据 → 查询条件构建问题(Service 层 buildQueryWrapper)
|
|
139
|
+
└─ 无数据 → 数据本身不存在/租户问题
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 各层常见问题速查
|
|
143
|
+
|
|
144
|
+
| 层级 | 常见问题 | 排查重点 |
|
|
145
|
+
|------|---------|---------|
|
|
146
|
+
| **Controller** | 参数绑定失败、路径 404 | `@RequestMapping`、`@RequestBody`、`@PathVariable` |
|
|
147
|
+
| **Service** | 业务逻辑错误、事务回滚、查询条件不对 | `@Transactional`、`buildQueryWrapper`、业务校验逻辑 |
|
|
148
|
+
| **Mapper** | SQL 语法、字段映射、类型转换 | `@TableName`、`@TableField`、XML SQL、字段类型匹配 |
|
|
149
|
+
| **前端 API** | 请求配置、参数格式 | `http.get/post`、Content-Type |
|
|
150
|
+
| **前端组件** | 响应式、生命周期 | `ref/reactive`、`onMounted` |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 后端问题排查
|
|
155
|
+
|
|
156
|
+
### 常见错误类型
|
|
157
|
+
|
|
158
|
+
#### 1. NullPointerException
|
|
159
|
+
|
|
160
|
+
**原因**: 对象为 null 时调用方法或属性
|
|
161
|
+
|
|
162
|
+
**排查**:
|
|
163
|
+
```java
|
|
164
|
+
// 检查可能为 null 的位置
|
|
165
|
+
User user = baseMapper.selectById(id); // 可能返回 null
|
|
166
|
+
user.getName(); // 如果 user 为 null 则报错
|
|
167
|
+
|
|
168
|
+
// 修复
|
|
169
|
+
if (user == null) {
|
|
170
|
+
throw new ServiceException("用户不存在");
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**本项目常见场景**:
|
|
175
|
+
- `baseMapper.selectById(id)` 返回 null
|
|
176
|
+
- `MapstructUtils.convert()` 源对象为 null
|
|
177
|
+
- 链式调用中间某环节为 null
|
|
178
|
+
|
|
179
|
+
#### 2. SQL 异常
|
|
180
|
+
|
|
181
|
+
**常见原因**:
|
|
182
|
+
- 字段名/表名错误
|
|
183
|
+
- SQL 语法错误
|
|
184
|
+
- 数据类型不匹配
|
|
185
|
+
- 唯一键冲突
|
|
186
|
+
|
|
187
|
+
**排查**:
|
|
188
|
+
```sql
|
|
189
|
+
-- 检查表是否存在
|
|
190
|
+
SHOW TABLES LIKE 'b_xxx';
|
|
191
|
+
|
|
192
|
+
-- 检查字段是否存在
|
|
193
|
+
DESC b_xxx;
|
|
194
|
+
|
|
195
|
+
-- 直接执行 SQL 查看错误
|
|
196
|
+
SELECT * FROM b_xxx WHERE id = 1;
|
|
197
|
+
|
|
198
|
+
-- 检查唯一键冲突
|
|
199
|
+
SELECT * FROM b_xxx WHERE unique_field = 'value';
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### 3. 权限问题
|
|
203
|
+
|
|
204
|
+
**表现**: 接口返回 401/403
|
|
205
|
+
|
|
206
|
+
**排查**:
|
|
207
|
+
```java
|
|
208
|
+
// 1. 检查是否添加了权限注解
|
|
209
|
+
@SaCheckPermission("base:ad:query")
|
|
210
|
+
|
|
211
|
+
// 2. 检查权限字符串是否正确(必须与菜单配置一致)
|
|
212
|
+
// 查询数据库
|
|
213
|
+
SELECT * FROM sys_menu WHERE perms = 'base:ad:query';
|
|
214
|
+
|
|
215
|
+
// 3. 检查用户是否有该角色
|
|
216
|
+
SELECT r.* FROM sys_role r
|
|
217
|
+
JOIN sys_user_role ur ON r.role_id = ur.role_id
|
|
218
|
+
WHERE ur.user_id = {userId};
|
|
219
|
+
|
|
220
|
+
// 4. 检查角色是否有该菜单权限
|
|
221
|
+
SELECT m.* FROM sys_menu m
|
|
222
|
+
JOIN sys_role_menu rm ON m.menu_id = rm.menu_id
|
|
223
|
+
WHERE rm.role_id = {roleId} AND m.perms = 'base:ad:query';
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### 4. 事务问题
|
|
227
|
+
|
|
228
|
+
**表现**: 数据不一致、部分成功
|
|
229
|
+
|
|
230
|
+
**排查**:
|
|
231
|
+
```java
|
|
232
|
+
// 1. 检查是否添加事务注解
|
|
233
|
+
@Transactional(rollbackFor = Exception.class)
|
|
234
|
+
|
|
235
|
+
// 2. 检查是否有嵌套事务(默认 REQUIRED 传播)
|
|
236
|
+
// 3. 检查异常是否被 try-catch 吞掉
|
|
237
|
+
try {
|
|
238
|
+
// 操作
|
|
239
|
+
} catch (Exception e) {
|
|
240
|
+
log.error("错误", e); // ❌ 异常被吞掉,事务不回滚
|
|
241
|
+
throw e; // ✅ 需要重新抛出
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// 4. 检查是否在非 public 方法上使用(不生效)
|
|
245
|
+
@Transactional // ❌ private 方法不生效
|
|
246
|
+
private void doSomething() {}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 日志分析
|
|
250
|
+
|
|
251
|
+
**日志位置**: 控制台输出 / 日志文件
|
|
252
|
+
|
|
253
|
+
**关键信息**:
|
|
254
|
+
```
|
|
255
|
+
1. 异常类型: NullPointerException, SQLException...
|
|
256
|
+
2. 异常信息: 具体错误描述
|
|
257
|
+
3. 堆栈信息: 定位到具体代码行(at org.dromara.xxx.XxxService:123)
|
|
258
|
+
4. 请求参数: 检查入参是否正确
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**添加调试日志**:
|
|
262
|
+
```java
|
|
263
|
+
import lombok.extern.slf4j.Slf4j;
|
|
264
|
+
|
|
265
|
+
@Slf4j
|
|
266
|
+
@Service
|
|
267
|
+
public class XxxServiceImpl implements IXxxService {
|
|
268
|
+
public void doSomething(Long id) {
|
|
269
|
+
log.info("开始处理, id: {}", id);
|
|
270
|
+
// ...
|
|
271
|
+
log.debug("中间状态: {}", state);
|
|
272
|
+
log.info("处理完成, 结果: {}", result);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 日志文件分析(开发环境 - 重点!)
|
|
278
|
+
|
|
279
|
+
> **⭐ 新增能力**:开发环境现已配置日志文件,AI 可以直接读取分析!
|
|
280
|
+
|
|
281
|
+
#### 日志文件位置
|
|
282
|
+
|
|
283
|
+
**开发环境(非 prod)**:
|
|
284
|
+
- `./logs/sys-console.log` - 本次启动的完整日志(控制台输出)
|
|
285
|
+
- 包含:INFO、WARN、ERROR 所有级别日志
|
|
286
|
+
- 包含:SQL 日志(p6spy)、业务日志、系统日志
|
|
287
|
+
- 格式:`日期 [线程] 级别 Logger名称 - 消息内容`
|
|
288
|
+
|
|
289
|
+
**生产环境(prod)**:
|
|
290
|
+
- `./logs/sys-console.log` - 控制台日志(保留 7 天)
|
|
291
|
+
- `./logs/sys-info.log` - INFO 日志(保留 60 天)
|
|
292
|
+
- `./logs/sys-error.log` - ERROR 日志(保留 60 天)
|
|
293
|
+
- `./logs/sys-sql.log` - SQL 日志(保留 7 天)
|
|
294
|
+
|
|
295
|
+
#### AI 自动读取日志流程(必须执行)
|
|
296
|
+
|
|
297
|
+
**触发条件**(满足任一即读取日志):
|
|
298
|
+
1. 用户报告问题但未提供错误堆栈
|
|
299
|
+
2. 需要分析 SQL 执行情况
|
|
300
|
+
3. 需要查看业务流程日志
|
|
301
|
+
4. 需要定位异常发生的时间点
|
|
302
|
+
5. 用户说"看日志"、"分析日志"、"日志里有什么"
|
|
303
|
+
|
|
304
|
+
**执行步骤**:
|
|
305
|
+
```bash
|
|
306
|
+
# 步骤 1:读取最新日志(开发环境)
|
|
307
|
+
Read ./logs/sys-console.log
|
|
308
|
+
|
|
309
|
+
# 步骤 2:分析日志内容
|
|
310
|
+
# - 查找 ERROR/WARN 级别日志
|
|
311
|
+
# - 定位异常堆栈信息
|
|
312
|
+
# - 分析 SQL 执行耗时
|
|
313
|
+
# - 检查业务逻辑流程
|
|
314
|
+
|
|
315
|
+
# 步骤 3:给出诊断结果和解决方案
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### 日志内容识别规则
|
|
319
|
+
|
|
320
|
+
**日志格式**:
|
|
321
|
+
```
|
|
322
|
+
2026-01-08 22:12:10 [xxx] [http-nio-8080-exec-1] INFO org.dromara.xxx.XxxService - 业务日志
|
|
323
|
+
2026-01-08 22:12:10 [xxx] [http-nio-8080-exec-1] INFO p6spy - Execute SQL: SELECT ... | Cost: 5 ms
|
|
324
|
+
2026-01-08 22:12:10 [xxx] [http-nio-8080-exec-1] ERROR org.dromara.xxx.XxxService - 错误信息
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**关键信息提取**:
|
|
328
|
+
| 信息类型 | 提取规则 | 用途 |
|
|
329
|
+
|---------|---------|------|
|
|
330
|
+
| **异常堆栈** | `ERROR` + 多行异常信息 | 定位错误原因 |
|
|
331
|
+
| **SQL 日志** | `INFO p6spy` | 分析查询性能、SQL 语法 |
|
|
332
|
+
| **业务流程** | `INFO/WARN` + 业务 Logger | 理解执行流程 |
|
|
333
|
+
| **执行耗时** | `Cost: X ms` | 性能分析 |
|
|
334
|
+
| **请求参数** | 日志中的参数输出 | 检查输入数据 |
|
|
335
|
+
|
|
336
|
+
#### 常见日志分析场景
|
|
337
|
+
|
|
338
|
+
**场景 1:接口报 500 错误**
|
|
339
|
+
```bash
|
|
340
|
+
# 1. 读取日志
|
|
341
|
+
Read ./logs/sys-console.log
|
|
342
|
+
|
|
343
|
+
# 2. 搜索 ERROR 关键字
|
|
344
|
+
grep "ERROR" ./logs/sys-console.log | tail -20
|
|
345
|
+
|
|
346
|
+
# 3. 定位异常类型(NullPointerException/SQLException等)
|
|
347
|
+
# 4. 查看堆栈信息,定位到具体代码行
|
|
348
|
+
# 5. 给出解决方案
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**场景 2:查询慢/性能问题**
|
|
352
|
+
```bash
|
|
353
|
+
# 1. 读取日志
|
|
354
|
+
Read ./logs/sys-console.log
|
|
355
|
+
|
|
356
|
+
# 2. 查找 SQL 日志
|
|
357
|
+
grep "p6spy" ./logs/sys-console.log | tail -50
|
|
358
|
+
|
|
359
|
+
# 3. 分析 Cost 耗时
|
|
360
|
+
# - Cost < 50ms → 正常
|
|
361
|
+
# - Cost 50-200ms → 需要关注
|
|
362
|
+
# - Cost > 200ms → 需要优化
|
|
363
|
+
|
|
364
|
+
# 4. 检查是否有 N+1 查询
|
|
365
|
+
# 5. 给出优化建议(添加索引/使用批量查询)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**场景 3:功能不工作/无报错**
|
|
369
|
+
```bash
|
|
370
|
+
# 1. 读取完整日志
|
|
371
|
+
Read ./logs/sys-console.log
|
|
372
|
+
|
|
373
|
+
# 2. 按时间顺序查看业务流程日志
|
|
374
|
+
# 3. 定位哪一步没有执行或逻辑分支错误
|
|
375
|
+
# 4. 检查是否有 WARN 级别的警告
|
|
376
|
+
# 5. 分析可能的原因
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**场景 4:租户数据问题**
|
|
380
|
+
```bash
|
|
381
|
+
# 1. 读取日志中的 SQL
|
|
382
|
+
grep "p6spy.*SELECT" ./logs/sys-console.log | tail -10
|
|
383
|
+
|
|
384
|
+
# 2. 检查 SQL 中的 tenant_id 条件
|
|
385
|
+
# 3. 对比数据库实际数据
|
|
386
|
+
# 4. 给出解决方案
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### 日志分析最佳实践
|
|
390
|
+
|
|
391
|
+
1. **优先读取日志文件**
|
|
392
|
+
- ✅ 日志文件包含完整上下文(SQL + 业务逻辑)
|
|
393
|
+
- ✅ 可以看到时间顺序和执行流程
|
|
394
|
+
- ✅ 比用户描述更准确
|
|
395
|
+
|
|
396
|
+
2. **结合代码分析**
|
|
397
|
+
- 从日志找到出错代码行号
|
|
398
|
+
- Read 对应的代码文件
|
|
399
|
+
- 分析代码逻辑
|
|
400
|
+
|
|
401
|
+
3. **时间线分析**
|
|
402
|
+
- 按时间顺序查看日志
|
|
403
|
+
- 理解请求的完整生命周期
|
|
404
|
+
- 定位哪一步出现问题
|
|
405
|
+
|
|
406
|
+
4. **SQL 性能分析**
|
|
407
|
+
- 关注 Cost 超过 200ms 的 SQL
|
|
408
|
+
- 检查是否有重复查询
|
|
409
|
+
- 建议添加索引或优化查询
|
|
410
|
+
|
|
411
|
+
#### 示例:完整的日志分析流程
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
用户问题:接口返回 500,但不知道原因
|
|
415
|
+
|
|
416
|
+
AI 执行:
|
|
417
|
+
1. Read ./logs/sys-console.log
|
|
418
|
+
→ 发现最后一个 ERROR:NullPointerException at XxxService.java:45
|
|
419
|
+
|
|
420
|
+
2. Read ruoyi-business/src/main/java/org/dromara/business/xxx/service/impl/XxxServiceImpl.java:45
|
|
421
|
+
→ 代码:user.getName()
|
|
422
|
+
|
|
423
|
+
3. 分析日志中的 SQL
|
|
424
|
+
→ 发现 SELECT * FROM sys_user WHERE id = 999 返回空
|
|
425
|
+
|
|
426
|
+
4. Bash 连接数据库验证
|
|
427
|
+
→ 确认 ID 999 的用户不存在
|
|
428
|
+
|
|
429
|
+
5. 给出诊断结果:
|
|
430
|
+
- 原因:用户不存在时,代码未判空
|
|
431
|
+
- 解决方案:添加 null 检查或改用 Optional
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
#### 日志文件维护说明
|
|
435
|
+
|
|
436
|
+
**自动清空机制**:
|
|
437
|
+
- 开发环境日志保留 1 天(`sys-console.log`)
|
|
438
|
+
- 保证日志只包含本次运行的内容
|
|
439
|
+
- 方便 AI 分析,无历史干扰
|
|
440
|
+
|
|
441
|
+
**如需保留历史日志**:
|
|
442
|
+
```bash
|
|
443
|
+
# 重启前备份日志
|
|
444
|
+
cp ./logs/sys-console.log ./logs/console-backup-$(date +%Y%m%d-%H%M%S).log
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**日志过大处理**:
|
|
448
|
+
```bash
|
|
449
|
+
# 只查看最后 1000 行
|
|
450
|
+
Read ./logs/sys-console.log (offset: -1000)
|
|
451
|
+
|
|
452
|
+
# 或使用 tail 命令
|
|
453
|
+
tail -n 1000 ./logs/sys-console.log
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 本项目特有问题库(重点!)
|
|
459
|
+
|
|
460
|
+
### 1. R.ok() 返回 String 类型的陷阱(极易踩坑!)
|
|
461
|
+
|
|
462
|
+
当控制器返回类型为 `R<String>` 时,使用 `R.ok(stringValue)` 会导致数据放错位置!
|
|
463
|
+
|
|
464
|
+
```java
|
|
465
|
+
// ❌ 错误:R.ok(String) 会匹配到 ok(String msg) 方法
|
|
466
|
+
// 结果:stringValue 被放入 msg 字段,data 为 null
|
|
467
|
+
@GetMapping("/getCode")
|
|
468
|
+
public R<String> getCode() {
|
|
469
|
+
String code = "ABC123";
|
|
470
|
+
return R.ok(code); // ❌ 前端收到 { code: 200, msg: "ABC123", data: null }
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// ✅ 正确:使用 ok(String msg, T data) 方法,明确指定 data
|
|
474
|
+
@GetMapping("/getCode")
|
|
475
|
+
public R<String> getCode() {
|
|
476
|
+
String code = "ABC123";
|
|
477
|
+
return R.ok(null, code); // ✅ 前端收到 { code: 200, msg: null, data: "ABC123" }
|
|
478
|
+
// 或者
|
|
479
|
+
return R.ok("获取成功", code); // ✅ { code: 200, msg: "获取成功", data: "ABC123" }
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**原因分析**:R 类有多个重载方法:
|
|
484
|
+
- `R.ok(T data)` - 泛型方法,将数据放入 data 字段
|
|
485
|
+
- `R.ok(String msg)` - 字符串方法,将字符串放入 msg 字段
|
|
486
|
+
|
|
487
|
+
当 `T` 也是 `String` 时,Java 优先匹配更具体的 `ok(String msg)` 方法,而不是泛型的 `ok(T data)`。
|
|
488
|
+
|
|
489
|
+
**排查场景**:
|
|
490
|
+
- 前端调用接口后 `data` 为 `null`,但响应 `msg` 中有数据
|
|
491
|
+
- 返回验证码、Token、URL 等字符串值时出现问题
|
|
492
|
+
- 接口返回 200 成功但前端取不到数据
|
|
493
|
+
|
|
494
|
+
### 2. 查询条件不生效
|
|
495
|
+
|
|
496
|
+
```java
|
|
497
|
+
// ❌ 错误:忘记添加条件判断(null/空字符串时也拼接条件)
|
|
498
|
+
private LambdaQueryWrapper<Xxx> buildQueryWrapper(XxxBo bo) {
|
|
499
|
+
LambdaQueryWrapper<Xxx> lqw = Wrappers.lambdaQuery();
|
|
500
|
+
lqw.eq(Xxx::getStatus, bo.getStatus()); // ❌ status 为 null 时会报错或查不到数据
|
|
501
|
+
lqw.like(Xxx::getName, bo.getName()); // ❌ name 为空时会拼接 LIKE '%%'
|
|
502
|
+
return lqw;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// ✅ 正确:在 Service 实现类的 buildQueryWrapper 中添加条件判断
|
|
506
|
+
@Service
|
|
507
|
+
@RequiredArgsConstructor
|
|
508
|
+
public class XxxServiceImpl implements IXxxService {
|
|
509
|
+
private final XxxMapper baseMapper;
|
|
510
|
+
|
|
511
|
+
private LambdaQueryWrapper<Xxx> buildQueryWrapper(XxxBo bo) {
|
|
512
|
+
LambdaQueryWrapper<Xxx> lqw = Wrappers.lambdaQuery();
|
|
513
|
+
lqw.eq(bo.getStatus() != null, Xxx::getStatus, bo.getStatus());
|
|
514
|
+
lqw.like(StringUtils.isNotBlank(bo.getName()), Xxx::getName, bo.getName());
|
|
515
|
+
return lqw;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
@Override
|
|
519
|
+
public List<XxxVo> list(XxxBo bo) {
|
|
520
|
+
LambdaQueryWrapper<Xxx> wrapper = buildQueryWrapper(bo);
|
|
521
|
+
return baseMapper.selectVoList(wrapper);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**排查场景**:
|
|
527
|
+
- 查询条件不生效(缺少条件判断)
|
|
528
|
+
- 分页查询结果不对(条件构建错误)
|
|
529
|
+
- 搜索功能不工作(like 条件处理错误)
|
|
530
|
+
|
|
531
|
+
### 3. 对象转换问题
|
|
532
|
+
|
|
533
|
+
```java
|
|
534
|
+
// ❌ 错误:MapstructUtils.convert() 返回 null
|
|
535
|
+
XxxVo vo = MapstructUtils.convert(entity, XxxVo.class); // 返回 null
|
|
536
|
+
|
|
537
|
+
// 原因:BO/VO 类未配置 @AutoMapper 注解
|
|
538
|
+
// ✅ 正确:检查 XxxBo 类(使用单数 @AutoMapper)
|
|
539
|
+
@Data
|
|
540
|
+
@AutoMapper(target = Xxx.class, reverseConvertGenerate = false)
|
|
541
|
+
public class XxxBo extends BaseEntity {
|
|
542
|
+
// 字段...
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// ✅ XxxVo 类(通常不需要 @AutoMapper,由 BO 反向生成)
|
|
546
|
+
@Data
|
|
547
|
+
public class XxxVo implements Serializable {
|
|
548
|
+
// 字段...
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
**排查步骤**:
|
|
553
|
+
1. 检查源对象是否为 null
|
|
554
|
+
2. 检查目标类是否有 `@AutoMappers` 注解
|
|
555
|
+
3. 检查 `@AutoMapper` 的 target 是否正确
|
|
556
|
+
4. 重新编译项目(Mapstruct 在编译时生成代码)
|
|
557
|
+
|
|
558
|
+
### 4. 租户数据问题
|
|
559
|
+
|
|
560
|
+
```sql
|
|
561
|
+
-- 检查数据是否在当前租户下
|
|
562
|
+
SELECT * FROM b_ad WHERE id = 1 AND tenant_id = '000000';
|
|
563
|
+
|
|
564
|
+
-- 检查请求头中的 tenant-id 是否正确传递
|
|
565
|
+
-- 前端需要在请求头中添加:
|
|
566
|
+
-- tenant-id: 000000
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
```java
|
|
570
|
+
// 检查 Entity 是否继承 TenantEntity
|
|
571
|
+
// ❌ 错误:继承 BaseEntity(无租户隔离)
|
|
572
|
+
public class Xxx extends BaseEntity { ... }
|
|
573
|
+
|
|
574
|
+
// ✅ 正确:继承 TenantEntity(有租户隔离)
|
|
575
|
+
public class Xxx extends TenantEntity { ... }
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**排查场景**:
|
|
579
|
+
- 数据明明存在但查询不到
|
|
580
|
+
- 不同租户数据串了
|
|
581
|
+
- 新增数据没有 tenant_id
|
|
582
|
+
|
|
583
|
+
### 5. like 方法类型限制
|
|
584
|
+
|
|
585
|
+
> ⚠️ **like() 方法应仅用于 String 类型字段!非 String 类型应使用精确匹配方法。**
|
|
586
|
+
|
|
587
|
+
```java
|
|
588
|
+
// ❌ 错误:对非 String 类型使用 like
|
|
589
|
+
lqw.like(Xxx::getId, searchValue); // ❌ Long 类型不适合模糊匹配
|
|
590
|
+
lqw.like(Xxx::getCreateTime, searchValue); // ❌ Date 类型不适合模糊匹配
|
|
591
|
+
|
|
592
|
+
// ✅ 正确:like 仅用于 String 类型字段
|
|
593
|
+
lqw.like(StringUtils.isNotBlank(bo.getName()), Xxx::getName, bo.getName()); // ✅ String
|
|
594
|
+
|
|
595
|
+
// ✅ 非 String 类型使用 eq/in/between 等精确匹配
|
|
596
|
+
lqw.eq(bo.getId() != null, Xxx::getId, bo.getId()); // ✅ Long → eq
|
|
597
|
+
lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
|
|
598
|
+
Xxx::getCreateTime, params.get("beginTime"), params.get("endTime")); // ✅ Date → between
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**规则**:
|
|
602
|
+
| 字段类型 | 推荐方法 | 说明 |
|
|
603
|
+
|---------|---------|------|
|
|
604
|
+
| `String` | `like()` | 模糊匹配 |
|
|
605
|
+
| `Long/Integer` | `eq()`/`in()` | 精确匹配 |
|
|
606
|
+
| `Date/LocalDateTime` | `between()`/`ge()`/`le()` | 范围查询 |
|
|
607
|
+
|
|
608
|
+
**框架示例**(参考 `SysUserServiceImpl.java`):
|
|
609
|
+
```java
|
|
610
|
+
.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName())
|
|
611
|
+
.like(StringUtils.isNotBlank(user.getNickName()), SysUser::getNickName, user.getNickName())
|
|
612
|
+
.like(StringUtils.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### 6. 雪花 ID 精度丢失
|
|
616
|
+
|
|
617
|
+
```java
|
|
618
|
+
// 问题:前端接收到的 ID 最后几位变成 0
|
|
619
|
+
// 后端返回:1234567890123456789
|
|
620
|
+
// 前端收到:1234567890123456000
|
|
621
|
+
|
|
622
|
+
// 原因:JavaScript Number 最大安全整数是 2^53-1 = 9007199254740991
|
|
623
|
+
// 雪花 ID 是 Long 类型,超出了 JS 精度范围
|
|
624
|
+
|
|
625
|
+
// ✅ 解决方案 1:VO 中使用 String 类型
|
|
626
|
+
public class XxxVo {
|
|
627
|
+
private String id; // 改为 String
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// ✅ 解决方案 2:使用 @JsonSerialize 序列化为字符串
|
|
631
|
+
@JsonSerialize(using = ToStringSerializer.class)
|
|
632
|
+
private Long id;
|
|
633
|
+
|
|
634
|
+
// ✅ 解决方案 3:全局配置(本项目已配置)
|
|
635
|
+
// 检查 JacksonConfig 是否生效
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### 7. API 调用格式错误
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
// ❌ 错误:使用 try-catch
|
|
642
|
+
try {
|
|
643
|
+
const data = await pageXxxs(params)
|
|
644
|
+
} catch (error) {
|
|
645
|
+
console.error(error)
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// ✅ 正确:使用 [err, data] 格式
|
|
649
|
+
const [err, data] = await pageXxxs(params)
|
|
650
|
+
if (!err) {
|
|
651
|
+
dataList.value = data.records
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
**本项目规范**:API 调用统一使用 `[err, data]` 格式,不使用 try-catch。
|
|
656
|
+
|
|
657
|
+
### 8. Service 继承基类问题
|
|
658
|
+
|
|
659
|
+
```java
|
|
660
|
+
// ❌ 错误:继承 ServiceImpl(违反项目规范)
|
|
661
|
+
public class XxxServiceImpl extends ServiceImpl<XxxMapper, Xxx> implements IXxxService {
|
|
662
|
+
// 本项目是三层架构,不使用 ServiceImpl 基类
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// ✅ 正确:不继承任何基类,直接注入 Mapper
|
|
666
|
+
@Service
|
|
667
|
+
@RequiredArgsConstructor
|
|
668
|
+
public class XxxServiceImpl implements IXxxService {
|
|
669
|
+
private final XxxMapper baseMapper; // 直接注入 Mapper(三层架构无 DAO 层)
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### 9. 逻辑删除数据仍能查到
|
|
674
|
+
|
|
675
|
+
```java
|
|
676
|
+
// 检查 Entity 是否有 @TableLogic 注解
|
|
677
|
+
// 注意:逻辑删除字段在各 Entity 中自行定义,不在 BaseEntity/TenantEntity 中
|
|
678
|
+
@TableLogic
|
|
679
|
+
private Long delFlag; // TestDemo 等用 Long 类型
|
|
680
|
+
|
|
681
|
+
// 或
|
|
682
|
+
@TableLogic
|
|
683
|
+
private String delFlag; // SysUser 等用 String 类型
|
|
684
|
+
|
|
685
|
+
// 检查表中 del_flag 字段值
|
|
686
|
+
// 0 = 未删除(正常)
|
|
687
|
+
// 非0 = 已删除(框架使用雪花 ID 作为删除标记值)
|
|
688
|
+
|
|
689
|
+
// 如果需要查询已删除数据,使用:
|
|
690
|
+
// mapper.selectList(Wrappers.<Xxx>query().ne("del_flag", 0));
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### 10. Bean 注入失败
|
|
694
|
+
|
|
695
|
+
```java
|
|
696
|
+
// NoSuchBeanDefinitionException: No qualifying bean of type 'xxx'
|
|
697
|
+
|
|
698
|
+
// 排查步骤:
|
|
699
|
+
// 1. 检查是否添加了 @Service/@Repository/@Component
|
|
700
|
+
@Service
|
|
701
|
+
public class XxxServiceImpl implements IXxxService { ... }
|
|
702
|
+
|
|
703
|
+
// 2. 检查包路径是否在扫描范围内
|
|
704
|
+
// 必须在 org.dromara.* 包下
|
|
705
|
+
|
|
706
|
+
// 3. 检查是否有循环依赖
|
|
707
|
+
// A 依赖 B,B 又依赖 A
|
|
708
|
+
|
|
709
|
+
// 4. 检查接口和实现类是否匹配
|
|
710
|
+
// IXxxService 接口
|
|
711
|
+
// XxxServiceImpl 实现
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## 前端问题排查
|
|
717
|
+
|
|
718
|
+
### 常见错误类型
|
|
719
|
+
|
|
720
|
+
#### 1. 接口调用失败
|
|
721
|
+
|
|
722
|
+
**排查步骤**:
|
|
723
|
+
1. 打开浏览器开发者工具 (F12)
|
|
724
|
+
2. 切换到 Network 标签
|
|
725
|
+
3. 查看请求状态码和响应内容
|
|
726
|
+
|
|
727
|
+
**常见状态码**:
|
|
728
|
+
| 状态码 | 含义 | 解决方案 |
|
|
729
|
+
|--------|------|---------|
|
|
730
|
+
| 400 | 请求参数错误 | 检查请求参数类型、格式 |
|
|
731
|
+
| 401 | 未认证 | 检查 Token 是否有效、是否传递 |
|
|
732
|
+
| 403 | 无权限 | 检查权限配置、角色分配 |
|
|
733
|
+
| 404 | 接口不存在 | 检查 URL 路径、后端是否启动 |
|
|
734
|
+
| 500 | 服务端错误 | 查看后端控制台日志 |
|
|
735
|
+
|
|
736
|
+
#### 2. 页面渲染问题
|
|
737
|
+
|
|
738
|
+
**排查**:
|
|
739
|
+
```typescript
|
|
740
|
+
// 检查数据是否正确获取
|
|
741
|
+
console.log('API 返回:', data)
|
|
742
|
+
|
|
743
|
+
// 检查响应式数据是否正确赋值
|
|
744
|
+
console.log('ref value:', someRef.value)
|
|
745
|
+
|
|
746
|
+
// 使用 Vue Devtools 查看组件状态
|
|
747
|
+
// Chrome 扩展:Vue.js devtools
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
#### 3. 状态不更新
|
|
751
|
+
|
|
752
|
+
**常见原因**:
|
|
753
|
+
- 直接修改 reactive 对象的引用
|
|
754
|
+
- 数组操作未触发响应式
|
|
755
|
+
- 深层对象属性变化未检测
|
|
756
|
+
|
|
757
|
+
**修复**:
|
|
758
|
+
```typescript
|
|
759
|
+
// ❌ 错误:直接替换引用
|
|
760
|
+
list = newList
|
|
761
|
+
|
|
762
|
+
// ✅ 正确:修改 .value
|
|
763
|
+
list.value = newList
|
|
764
|
+
list.value.push(item)
|
|
765
|
+
list.value.splice(index, 1)
|
|
766
|
+
|
|
767
|
+
// ❌ 错误:直接修改 reactive 对象属性
|
|
768
|
+
Object.assign(form, newData)
|
|
769
|
+
|
|
770
|
+
// ✅ 正确:逐个赋值或使用展开
|
|
771
|
+
Object.keys(newData).forEach(key => {
|
|
772
|
+
form[key] = newData[key]
|
|
773
|
+
})
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
#### 4. 组件使用错误
|
|
777
|
+
|
|
778
|
+
```vue
|
|
779
|
+
<!-- ❌ 错误:使用原生 Element Plus 组件 -->
|
|
780
|
+
<el-input v-model="form.name" />
|
|
781
|
+
<el-dialog v-model="visible" />
|
|
782
|
+
|
|
783
|
+
<!-- ✅ 正确:使用项目封装的 A* 组件 -->
|
|
784
|
+
<AFormInput v-model="form.name" label="名称" prop="name" />
|
|
785
|
+
<AModal v-model="visible" />
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### 调试技巧
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
// 打断点
|
|
792
|
+
debugger
|
|
793
|
+
|
|
794
|
+
// 控制台日志
|
|
795
|
+
console.log('变量值:', value)
|
|
796
|
+
console.table(arrayData) // 表格形式显示数组
|
|
797
|
+
console.dir(object) // 展开对象结构
|
|
798
|
+
|
|
799
|
+
// Vue Devtools
|
|
800
|
+
// 安装 Chrome 扩展,查看组件树、状态、事件
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
---
|
|
804
|
+
|
|
805
|
+
## 数据库问题排查
|
|
806
|
+
|
|
807
|
+
### 主动排查流程(AI 自动执行)
|
|
808
|
+
|
|
809
|
+
> **重要**:当排查涉及数据问题时,AI 应主动连接数据库进行验证,而不只是给出 SQL 让用户执行。
|
|
810
|
+
|
|
811
|
+
#### 步骤 1:读取数据库配置
|
|
812
|
+
|
|
813
|
+
```bash
|
|
814
|
+
# 首先读取配置文件,获取数据库连接信息
|
|
815
|
+
Read ruoyi-admin/src/main/resources/application-dev.yml
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
从配置中解析:
|
|
819
|
+
- 数据库类型(MySQL/Oracle/PostgreSQL/SQL Server)
|
|
820
|
+
- 主机地址(`${DB_HOST:127.0.0.1}`)
|
|
821
|
+
- 端口(`${DB_PORT:3306}`)
|
|
822
|
+
- 数据库名(`${DB_NAME:xxx}`)
|
|
823
|
+
- 用户名/密码
|
|
824
|
+
|
|
825
|
+
#### 步骤 2:连接数据库执行查询
|
|
826
|
+
|
|
827
|
+
根据数据库类型选择连接命令:
|
|
828
|
+
|
|
829
|
+
```bash
|
|
830
|
+
# MySQL(最常用)
|
|
831
|
+
mysql -h127.0.0.1 -P3306 -uroot -p密码 数据库名 -e "SELECT * FROM b_xxx WHERE id = 1"
|
|
832
|
+
|
|
833
|
+
# PostgreSQL
|
|
834
|
+
PGPASSWORD=密码 psql -h 127.0.0.1 -p 5432 -U root -d 数据库名 -c "SELECT * FROM b_xxx WHERE id = 1"
|
|
835
|
+
|
|
836
|
+
# SQL Server
|
|
837
|
+
sqlcmd -S 127.0.0.1,1433 -U sa -P 密码 -d 数据库名 -Q "SELECT * FROM b_xxx WHERE id = 1"
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
#### 步骤 3:根据结果分析问题
|
|
841
|
+
|
|
842
|
+
```
|
|
843
|
+
查询结果分析决策树:
|
|
844
|
+
├─ 返回数据
|
|
845
|
+
│ ├─ 数据正确 → 问题不在数据库,转查代码
|
|
846
|
+
│ ├─ 数据不对 → 分析哪个字段有问题
|
|
847
|
+
│ └─ 数据被删除(del_flag='1')→ 数据已逻辑删除
|
|
848
|
+
├─ 无数据返回
|
|
849
|
+
│ ├─ 检查 tenant_id → 是否租户不匹配
|
|
850
|
+
│ ├─ 检查 del_flag → 是否被删除
|
|
851
|
+
│ └─ 检查 ID 值 → 是否 ID 错误
|
|
852
|
+
└─ 执行报错
|
|
853
|
+
├─ 表不存在 → 检查表名/数据库
|
|
854
|
+
├─ 字段不存在 → 检查字段名
|
|
855
|
+
└─ 语法错误 → 检查 SQL 语法
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
### 常用排查 SQL 模板
|
|
859
|
+
|
|
860
|
+
#### 数据存在性检查
|
|
861
|
+
|
|
862
|
+
```sql
|
|
863
|
+
-- 基础检查
|
|
864
|
+
SELECT * FROM [表名] WHERE id = [ID值];
|
|
865
|
+
|
|
866
|
+
-- 含租户和逻辑删除检查
|
|
867
|
+
SELECT * FROM [表名] WHERE id = [ID值] AND tenant_id = '000000' AND del_flag = '0';
|
|
868
|
+
|
|
869
|
+
-- 检查最近的数据
|
|
870
|
+
SELECT * FROM [表名] ORDER BY create_time DESC LIMIT 10;
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
#### 数据关联检查
|
|
874
|
+
|
|
875
|
+
```sql
|
|
876
|
+
-- 检查关联数据
|
|
877
|
+
SELECT a.*, b.*
|
|
878
|
+
FROM table_a a
|
|
879
|
+
LEFT JOIN table_b b ON a.id = b.a_id
|
|
880
|
+
WHERE a.id = [ID值];
|
|
881
|
+
|
|
882
|
+
-- 检查外键引用
|
|
883
|
+
SELECT * FROM [子表] WHERE [外键字段] = [主表ID];
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
#### 权限数据检查
|
|
887
|
+
|
|
888
|
+
```sql
|
|
889
|
+
-- 检查用户权限
|
|
890
|
+
SELECT DISTINCT m.perms
|
|
891
|
+
FROM sys_menu m
|
|
892
|
+
JOIN sys_role_menu rm ON m.menu_id = rm.menu_id
|
|
893
|
+
JOIN sys_user_role ur ON rm.role_id = ur.role_id
|
|
894
|
+
WHERE ur.user_id = [用户ID] AND m.perms IS NOT NULL;
|
|
895
|
+
|
|
896
|
+
-- 检查菜单是否存在
|
|
897
|
+
SELECT * FROM sys_menu WHERE perms = '[权限字符串]';
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
#### 字典数据检查
|
|
901
|
+
|
|
902
|
+
```sql
|
|
903
|
+
-- 检查字典类型
|
|
904
|
+
SELECT * FROM sys_dict_type WHERE dict_type = '[字典类型]';
|
|
905
|
+
|
|
906
|
+
-- 检查字典数据
|
|
907
|
+
SELECT * FROM sys_dict_data WHERE dict_type = '[字典类型]' ORDER BY dict_sort;
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
#### 性能问题检查
|
|
911
|
+
|
|
912
|
+
```sql
|
|
913
|
+
-- 查看执行计划
|
|
914
|
+
EXPLAIN SELECT * FROM [表名] WHERE [条件];
|
|
915
|
+
|
|
916
|
+
-- type 字段说明:
|
|
917
|
+
-- ALL = 全表扫描(需要优化)
|
|
918
|
+
-- index = 索引扫描
|
|
919
|
+
-- range = 范围扫描
|
|
920
|
+
-- ref = 使用索引
|
|
921
|
+
-- const = 常量查询(最优)
|
|
922
|
+
|
|
923
|
+
-- 检查索引
|
|
924
|
+
SHOW INDEX FROM [表名];
|
|
925
|
+
|
|
926
|
+
-- 检查表结构
|
|
927
|
+
DESC [表名];
|
|
928
|
+
SHOW CREATE TABLE [表名];
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
### 场景化排查指南
|
|
932
|
+
|
|
933
|
+
| 问题场景 | 排查 SQL | 说明 |
|
|
934
|
+
|---------|---------|------|
|
|
935
|
+
| 数据查不到 | `SELECT * FROM 表 WHERE id=? AND tenant_id='000000' AND del_flag='0'` | 检查三要素 |
|
|
936
|
+
| 权限不足 | `SELECT perms FROM sys_menu WHERE menu_id IN (SELECT menu_id FROM sys_role_menu WHERE role_id=?)` | 检查角色权限 |
|
|
937
|
+
| 字典不显示 | `SELECT * FROM sys_dict_data WHERE dict_type=?` | 检查字典数据 |
|
|
938
|
+
| ID 重复 | `SELECT id, COUNT(*) FROM 表 GROUP BY id HAVING COUNT(*) > 1` | 检查重复数据 |
|
|
939
|
+
| 关联数据丢失 | `SELECT a.id FROM 主表 a LEFT JOIN 子表 b ON a.id=b.主表id WHERE b.id IS NULL` | 检查孤立数据 |
|
|
940
|
+
|
|
941
|
+
### 多数据库注意事项
|
|
942
|
+
|
|
943
|
+
| 功能 | MySQL | PostgreSQL | Oracle | SQL Server |
|
|
944
|
+
|------|-------|------------|--------|------------|
|
|
945
|
+
| 分页 | `LIMIT 10` | `LIMIT 10` | `ROWNUM <= 10` | `TOP 10` |
|
|
946
|
+
| 字符串连接 | `CONCAT()` | `||` | `||` | `+` |
|
|
947
|
+
| 当前时间 | `NOW()` | `NOW()` | `SYSDATE` | `GETDATE()` |
|
|
948
|
+
| 类型转换 | `CAST()` | `CAST()` / `::` | `TO_CHAR()` | `CONVERT()` |
|
|
949
|
+
|
|
950
|
+
> **提示**:`like()` 方法仅适用于 String 类型字段。非 String 类型(Long/Date 等)应使用 `eq()`/`in()`/`between()` 等精确匹配方法。
|
|
951
|
+
|
|
952
|
+
---
|
|
953
|
+
|
|
954
|
+
## 常见问题速查表
|
|
955
|
+
|
|
956
|
+
| 问题 | 可能原因 | 解决方案 |
|
|
957
|
+
|------|---------|---------|
|
|
958
|
+
| 接口 404 | URL 错误 / 后端未启动 | 检查 URL,重启后端 |
|
|
959
|
+
| 接口 500 | 后端代码异常 | 查看后端控制台日志 |
|
|
960
|
+
| 数据为空 | 条件错误 / 数据不存在 | 检查 SQL 条件 |
|
|
961
|
+
| **R\<String\> data 为 null** | **R.ok(str) 匹配到 ok(String msg)** | **用 R.ok(null, str) 或 R.ok(msg, str)** |
|
|
962
|
+
| 对象转换失败 | @AutoMappers 未配置 | 检查 BO/VO 注解 |
|
|
963
|
+
| 租户数据查不到 | tenant_id 不匹配 | 检查请求头 tenant-id |
|
|
964
|
+
| like 报错 | 非 String 类型 | 改用 eq/in/between |
|
|
965
|
+
| ID 精度丢失 | JS 大数问题 | Long 改 String 或加序列化 |
|
|
966
|
+
| 页面空白 | JS 错误 / 路由错误 | 查看控制台错误 |
|
|
967
|
+
| 样式错乱 | CSS 冲突 / 单位问题 | 检查样式优先级 |
|
|
968
|
+
| 表单不提交 | 校验失败 / 方法错误 | 检查校验规则 |
|
|
969
|
+
| 权限不足 | 角色未配置 / Token 过期 | 检查权限配置 |
|
|
970
|
+
| 事务不回滚 | 异常被吞 / 非 public 方法 | 检查 @Transactional 使用 |
|
|
971
|
+
| Bean 注入失败 | 未加注解 / 包路径错误 | 检查 @Service 和包路径 |
|
|
972
|
+
|
|
973
|
+
---
|
|
974
|
+
|
|
975
|
+
## 调试建议
|
|
976
|
+
|
|
977
|
+
1. **保持冷静**: 不要急于修改代码
|
|
978
|
+
2. **复现问题**: 确保问题可以稳定复现
|
|
979
|
+
3. **二分法**: 逐步缩小问题范围
|
|
980
|
+
4. **看日志**: 日志是最重要的线索
|
|
981
|
+
5. **查文档**: 确认 API 用法是否正确
|
|
982
|
+
6. **搜索**: 错误信息通常能搜到解决方案
|
|
983
|
+
7. **最小复现**: 创建最小示例复现问题
|
|
984
|
+
|
|
985
|
+
---
|
|
986
|
+
|
|
987
|
+
## Skill 联动建议
|
|
988
|
+
|
|
989
|
+
| 排查发现 | 推荐激活 | 说明 |
|
|
990
|
+
|---------|---------|------|
|
|
991
|
+
| 查询性能慢 | `performance-doctor` | 需要优化索引或缓存 |
|
|
992
|
+
| 权限配置问题 | `security-guard` | 需要调整权限设计 |
|
|
993
|
+
| SQL 语法错误 | `database-ops` | 需要检查表结构或建表 |
|
|
994
|
+
| PC 组件使用错误 | `ui-pc` | 需要了解 A* 组件用法 |
|
|
995
|
+
| 对象转换失败 | `crud-development` | 需要检查 BO/VO 配置 |
|
|
996
|
+
| 异常处理缺失 | `error-handler` | 需要设计异常机制 |
|
|
997
|
+
| API 设计问题 | `api-development` | 需要了解接口规范 |
|
|
998
|
+
|
|
999
|
+
### 数据库直连排查(内置能力,无需激活其他技能)
|
|
1000
|
+
|
|
1001
|
+
> **配置文件位置**:`ruoyi-admin/src/main/resources/application-dev.yml`
|
|
1002
|
+
|
|
1003
|
+
当遇到以下情况时,**直接读取配置并连接数据库**:
|
|
1004
|
+
|
|
1005
|
+
| 问题类型 | 排查 SQL |
|
|
1006
|
+
|---------|---------|
|
|
1007
|
+
| 数据查不到 | `SELECT * FROM 表名 WHERE id = ? AND tenant_id = '000000' AND del_flag = '0'` |
|
|
1008
|
+
| 数据不一致 | `SELECT * FROM 关联表 WHERE 外键 = ?` |
|
|
1009
|
+
| 权限报错 | `SELECT * FROM sys_menu WHERE menu_id = ?` |
|
|
1010
|
+
| 字典不显示 | `SELECT * FROM sys_dict_data WHERE dict_type = '?'` |
|
|
1011
|
+
| 性能问题 | `EXPLAIN SELECT ...` |
|
|
1012
|
+
|
|
1013
|
+
**执行流程(3 步)**:
|
|
1014
|
+
```
|
|
1015
|
+
1. Read ruoyi-admin/src/main/resources/application-dev.yml → 获取连接信息
|
|
1016
|
+
2. Bash 连接数据库 → mysql -h127.0.0.1 -P3306 -uroot -proot 数据库名
|
|
1017
|
+
3. 执行诊断 SQL → 分析结果给出方案
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
**连接命令速查**:
|
|
1021
|
+
```bash
|
|
1022
|
+
# MySQL(默认)
|
|
1023
|
+
mysql -h127.0.0.1 -P3306 -u用户名 -p密码 数据库名 -e "SQL语句"
|
|
1024
|
+
|
|
1025
|
+
# PostgreSQL
|
|
1026
|
+
PGPASSWORD=密码 psql -h 127.0.0.1 -p 5432 -U 用户名 -d 数据库名 -c "SQL语句"
|
|
1027
|
+
|
|
1028
|
+
# SQL Server
|
|
1029
|
+
sqlcmd -S 127.0.0.1,1433 -U 用户名 -P 密码 -d 数据库名 -Q "SQL语句"
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
---
|
|
1033
|
+
|
|
1034
|
+
## 排查流程决策树(完整版)
|
|
1035
|
+
|
|
1036
|
+
### 判断问题在哪一层
|
|
1037
|
+
|
|
1038
|
+
```
|
|
1039
|
+
现象:功能不工作、数据不正确、接口返回错误
|
|
1040
|
+
↓
|
|
1041
|
+
第 1 步:用 Postman 或浏览器直接调接口
|
|
1042
|
+
├─ 返回正确数据 → 问题在【前端层】
|
|
1043
|
+
│ └─ 检查:@RestController 路径、@Validated、参数绑定
|
|
1044
|
+
│
|
|
1045
|
+
└─ 返回错误(4xx/5xx) → 问题在【后端层】
|
|
1046
|
+
└─ 进入"后端问题排查流程"(见下)
|
|
1047
|
+
|
|
1048
|
+
后端问题排查流程:
|
|
1049
|
+
↓
|
|
1050
|
+
第 2 步:读取 ./logs/sys-console.log(开发环境)
|
|
1051
|
+
├─ 有 ERROR 日志 → 查看堆栈信息
|
|
1052
|
+
│ ├─ NullPointerException → 对象未初始化或查询返回 null
|
|
1053
|
+
│ ├─ SQLException → SQL 字段/表名/语法错误
|
|
1054
|
+
│ ├─ ServiceException → 业务逻辑主动抛出异常
|
|
1055
|
+
│ └─ 其他异常 → 根据具体异常信息定位
|
|
1056
|
+
│
|
|
1057
|
+
└─ 无 ERROR 日志或日志看不出问题 → 进入"分层定位"
|
|
1058
|
+
└─ 第 3 步:打断点或加日志(按调用链向下)
|
|
1059
|
+
├─ Controller 收到请求,参数正确 → 问题在 Service/Mapper
|
|
1060
|
+
├─ Controller 没收到请求 → URL 路径/扫描问题
|
|
1061
|
+
└─ Controller 参数为空 → 请求参数传递问题
|
|
1062
|
+
|
|
1063
|
+
分层定位(从上到下):
|
|
1064
|
+
Controller 层:检查 @RequestMapping、@RequestBody、参数类型
|
|
1065
|
+
↓ 参数正确
|
|
1066
|
+
Service 层:检查业务逻辑、@Transactional、数据转换
|
|
1067
|
+
↓ 逻辑正确
|
|
1068
|
+
Mapper 层(查询构建):检查 buildQueryWrapper、查询条件、字段类型匹配
|
|
1069
|
+
↓ 条件正确
|
|
1070
|
+
Mapper 层:检查 SQL 语句、字段映射、表名
|
|
1071
|
+
↓ SQL 正确
|
|
1072
|
+
数据库:直接执行 SQL 验证数据
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
---
|
|
1076
|
+
|
|
1077
|
+
## 排查清单
|
|
1078
|
+
|
|
1079
|
+
### 后端排查清单
|
|
1080
|
+
|
|
1081
|
+
- [ ] **是否读取了日志文件?** (`./logs/sys-console.log`)
|
|
1082
|
+
- [ ] **异常堆栈中的类名包名是否为 `org.dromara.*`?**
|
|
1083
|
+
- [ ] **是否检查了 Controller 的 @RequestMapping 路径?**
|
|
1084
|
+
- [ ] **参数绑定是否使用了 @RequestBody/@RequestParam?**
|
|
1085
|
+
- [ ] **Service 是否继承了 ServiceImpl(不应该)?**
|
|
1086
|
+
- [ ] **Service 的 buildQueryWrapper 中是否正确构建查询条件?**
|
|
1087
|
+
- [ ] **非字符串字段是否使用了 eq/in/between 而不是 like?**
|
|
1088
|
+
- [ ] **Entity 是否继承了 TenantEntity(多租户)?**
|
|
1089
|
+
- [ ] **MapstructUtils.convert() 是否正确配置了 @AutoMapper?**
|
|
1090
|
+
- [ ] **R.ok(String) 是否改用了 R.ok(null, value) 或 R.ok(msg, value)?**
|
|
1091
|
+
- [ ] **返回值类型是否符合规范?(LIST→TableDataInfo, GET→R<T>, EXPORT→void)**
|
|
1092
|
+
- [ ] **数据库中是否真的存在需要的数据?(SQL 验证)**
|
|
1093
|
+
|
|
1094
|
+
### 前端排查清单
|
|
1095
|
+
|
|
1096
|
+
- [ ] **是否打开了浏览器开发者工具 (F12)?**
|
|
1097
|
+
- [ ] **Network 中接口状态码是多少?(400/401/403/404/500)**
|
|
1098
|
+
- [ ] **响应数据中 code/msg/data 字段是否有值?**
|
|
1099
|
+
- [ ] **是否使用了 [err, data] 格式而不是 try-catch?**
|
|
1100
|
+
- [ ] **数据是否正确赋值给了响应式变量?(.value)**
|
|
1101
|
+
- [ ] **组件是否使用了封装的 A* 组件而不是原生 Element Plus?**
|
|
1102
|
+
- [ ] **v-if 条件是否为 true?**
|
|
1103
|
+
- [ ] **CSS 是否隐藏了元素?(display:none)**
|
|
1104
|
+
|
|
1105
|
+
---
|
|
1106
|
+
|
|
1107
|
+
## 最佳实践
|
|
1108
|
+
|
|
1109
|
+
### 1. 日志优先原则
|
|
1110
|
+
|
|
1111
|
+
```
|
|
1112
|
+
问题出现 → 【立即读取日志】→ 95% 的问题能在日志中找到根本原因
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
**为什么日志最重要**:
|
|
1116
|
+
- ✅ 包含完整的执行上下文(时间、线程、SQL)
|
|
1117
|
+
- ✅ 不依赖用户的口头描述
|
|
1118
|
+
- ✅ 可以看到时间顺序和流程
|
|
1119
|
+
- ✅ SQL 日志显示实际执行的 SQL 和耗时
|
|
1120
|
+
|
|
1121
|
+
### 2. 分层排查原则
|
|
1122
|
+
|
|
1123
|
+
不要一上来就改代码,要按这个顺序排查:
|
|
1124
|
+
1. **外部因素**:数据库连接、请求参数、权限配置
|
|
1125
|
+
2. **日志分析**:找堆栈、定位异常类型
|
|
1126
|
+
3. **代码路径**:从 Controller 开始向下逐层检查
|
|
1127
|
+
4. **数据库验证**:直接执行 SQL 对比实际数据
|
|
1128
|
+
|
|
1129
|
+
### 3. 重现问题原则
|
|
1130
|
+
|
|
1131
|
+
不能稳定重现的问题很难排查,所以:
|
|
1132
|
+
- ✅ 找到稳定复现的步骤
|
|
1133
|
+
- ✅ 记录每一步的输入和输出
|
|
1134
|
+
- ✅ 隔离变量(先排除前端,再排除中间件)
|
|
1135
|
+
|
|
1136
|
+
### 4. 代码版本原则
|
|
1137
|
+
|
|
1138
|
+
修改代码前:
|
|
1139
|
+
- ✅ 理解问题的根本原因
|
|
1140
|
+
- ✅ 制定解决方案
|
|
1141
|
+
- ✅ 再进行修改
|
|
1142
|
+
|
|
1143
|
+
不要:
|
|
1144
|
+
- ❌ 盲目改代码希望能解决问题
|
|
1145
|
+
- ❌ 加一堆 try-catch 来"压制"错误
|
|
1146
|
+
- ❌ 重复修改同一个地方
|
|
1147
|
+
|
|
1148
|
+
---
|
|
1149
|
+
|
|
1150
|
+
## 常见误区
|
|
1151
|
+
|
|
1152
|
+
| 误区 | 错误做法 | 正确做法 |
|
|
1153
|
+
|------|--------|--------|
|
|
1154
|
+
| 日志没看 | 直接改代码 | 先读日志找原因 |
|
|
1155
|
+
| 包名错 | 使用 `org.dromara.*` | 必须 `org.dromara.*` |
|
|
1156
|
+
| R.ok() 陷阱 | `return R.ok(str)` 返回字符串 | `return R.ok(null, str)` |
|
|
1157
|
+
| Service 架构 | `extends ServiceImpl<>` | `implements IXxxService` 不继承 |
|
|
1158
|
+
| 查询构建 | new LambdaQueryWrapper 直接用 | Service 层 buildQueryWrapper 方法 |
|
|
1159
|
+
| like 方法 | Long/Date 字段用 `.like()` | 必须用 `.eq()`/`.between()` |
|
|
1160
|
+
| 对象转换 | `BeanUtil.copyProperties()` | `MapstructUtils.convert()` |
|
|
1161
|
+
| 前端 API | `try-catch` 调用 API | `const [err, data] = await api()` |
|
|
1162
|
+
| Bean 扫描 | 其他包路径 | 必须 `org.dromara.*` |
|
|
1163
|
+
|
|
1164
|
+
---
|
|
1165
|
+
|
|
1166
|
+
## 快速参考
|
|
1167
|
+
|
|
1168
|
+
### 常见错误速查
|
|
1169
|
+
|
|
1170
|
+
```
|
|
1171
|
+
NullPointerException → 对象为空,加 null 检查
|
|
1172
|
+
SQLException → SQL 错误,检查字段/表名
|
|
1173
|
+
ClassNotFoundException → 类未找到,检查包路径
|
|
1174
|
+
403 Forbidden → 权限不足,检查 @SaCheckPermission
|
|
1175
|
+
404 Not Found → 路径错误,检查 @RequestMapping
|
|
1176
|
+
500 Internal Server Error → 服务异常,读日志
|
|
1177
|
+
data 为 null,msg 有值 → R.ok(String) 陷阱,改 R.ok(null, value)
|
|
1178
|
+
ID 精度丢失 → 雪花 ID 大数,Long 改 String
|
|
1179
|
+
like 报错 → 非字符串用 eq/in/between
|
|
1180
|
+
```
|
|
1181
|
+
|
|
1182
|
+
### 排查工具速查
|
|
1183
|
+
|
|
1184
|
+
| 问题类型 | 使用工具 | 命令/方法 |
|
|
1185
|
+
|---------|--------|---------|
|
|
1186
|
+
| 后端异常 | 日志文件 | `Read ./logs/sys-console.log` |
|
|
1187
|
+
| 前端错误 | 浏览器 DevTools | F12 → Console/Network |
|
|
1188
|
+
| SQL 执行 | 数据库客户端 | `mysql -h... -u... -p...` |
|
|
1189
|
+
| 代码定位 | IDE 调试器 | 打断点 → F5 单步执行 |
|
|
1190
|
+
| 性能分析 | 日志中的 Cost | 关注 `Cost: XXms` |
|
|
1191
|
+
| 权限问题 | 数据库查询 | `SELECT * FROM sys_menu WHERE perms='...'` |
|
|
1192
|
+
|
|
1193
|
+
---
|
|
1194
|
+
|
|
1195
|
+
## Skill 联动
|
|
1196
|
+
|
|
1197
|
+
| 排查发现 | 推荐激活 | 用途 |
|
|
1198
|
+
|---------|--------|------|
|
|
1199
|
+
| 需要优化 SQL 性能 | `performance-doctor` | SQL 索引优化、缓存策略 |
|
|
1200
|
+
| 权限配置问题 | `security-guard` | Sa-Token、权限设计 |
|
|
1201
|
+
| 代码规范违反 | `code-patterns` | 快速查看禁止项和规范 |
|
|
1202
|
+
| API 设计问题 | `api-development` | RESTful 规范、注解用法 |
|
|
1203
|
+
| 前端组件用法 | `ui-pc` | Element Plus 组件 |
|
|
1204
|
+
| BO/VO 映射错误 | `crud-development` | @AutoMappers、对象转换 |
|
|
1205
|
+
| 数据库表设计 | `database-ops` | 建表、字段定义、索引 |
|
|
1206
|
+
| 需要设计异常机制 | `error-handler` | 全局异常处理、错误码系统 |
|