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.
Files changed (313) hide show
  1. package/.claude/agents/code-reviewer.md +139 -0
  2. package/.claude/agents/project-manager.md +159 -0
  3. package/.claude/audio/completed.wav +0 -0
  4. package/.claude/commands/add-todo.md +255 -0
  5. package/.claude/commands/check.md +210 -0
  6. package/.claude/commands/crud.md +454 -0
  7. package/.claude/commands/dev.md +503 -0
  8. package/.claude/commands/init-docs.md +681 -0
  9. package/.claude/commands/next.md +251 -0
  10. package/.claude/commands/progress.md +242 -0
  11. package/.claude/commands/start.md +199 -0
  12. package/.claude/commands/sync.md +307 -0
  13. package/.claude/commands/update-status.md +428 -0
  14. package/.claude/docs/Mixin/344/275/277/347/224/250/346/214/207/345/215/227.md +299 -0
  15. package/.claude/docs/README.md +167 -0
  16. package/.claude/docs//345/211/215/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +599 -0
  17. package/.claude/docs//345/220/216/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +726 -0
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. package/.claude/docs//346/241/206/346/236/266/350/257/264/346/230/216.md +393 -0
  24. package/.claude/docs//350/267/257/347/224/261/351/205/215/347/275/256/346/214/207/345/215/227.md +246 -0
  25. package/.claude/framework-config.json +73 -0
  26. package/.claude/hooks/pre-tool-use.js +117 -0
  27. package/.claude/hooks/skill-forced-eval.js +167 -0
  28. package/.claude/hooks/stop.js +58 -0
  29. package/.claude/settings.json +41 -0
  30. package/.claude/skills/add-skill/SKILL.md +352 -0
  31. package/.claude/skills/api-development/SKILL.md +560 -0
  32. package/.claude/skills/architecture-design/SKILL.md +756 -0
  33. package/.claude/skills/backend-annotations/SKILL.md +674 -0
  34. package/.claude/skills/banana-image/CHANGELOG.md +37 -0
  35. package/.claude/skills/banana-image/README.md +146 -0
  36. package/.claude/skills/banana-image/SKILL.md +164 -0
  37. package/.claude/skills/banana-image/assets/logo.png +0 -0
  38. package/.claude/skills/banana-image/references/advanced-usage.md +189 -0
  39. package/.claude/skills/banana-image/scripts/apply_template.py +125 -0
  40. package/.claude/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  41. package/.claude/skills/banana-image/scripts/batch_prep.py +82 -0
  42. package/.claude/skills/banana-image/scripts/package-lock.json +1437 -0
  43. package/.claude/skills/banana-image/scripts/package.json +18 -0
  44. package/.claude/skills/banana-image/scripts/requirements.txt +10 -0
  45. package/.claude/skills/banana-image/templates/poster.json +22 -0
  46. package/.claude/skills/banana-image/templates/product.json +17 -0
  47. package/.claude/skills/banana-image/templates/social.json +22 -0
  48. package/.claude/skills/banana-image/templates/thumbnail.json +17 -0
  49. package/.claude/skills/brainstorm/SKILL.md +648 -0
  50. package/.claude/skills/bug-detective/SKILL.md +1206 -0
  51. package/.claude/skills/code-patterns/SKILL.md +590 -0
  52. package/.claude/skills/collaborating-with-codex/SKILL.md +174 -0
  53. package/.claude/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  54. package/.claude/skills/collaborating-with-gemini/SKILL.md +194 -0
  55. package/.claude/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  56. package/.claude/skills/crud-development/SKILL.md +649 -0
  57. package/.claude/skills/data-permission/SKILL.md +599 -0
  58. package/.claude/skills/database-ops/SKILL.md +407 -0
  59. package/.claude/skills/error-handler/SKILL.md +371 -0
  60. package/.claude/skills/file-oss-management/SKILL.md +863 -0
  61. package/.claude/skills/git-workflow/SKILL.md +375 -0
  62. package/.claude/skills/json-serialization/SKILL.md +357 -0
  63. package/.claude/skills/leniu-api-development/SKILL.md +803 -0
  64. package/.claude/skills/leniu-architecture-design/SKILL.md +598 -0
  65. package/.claude/skills/leniu-backend-annotations/SKILL.md +664 -0
  66. package/.claude/skills/leniu-code-patterns/SKILL.md +365 -0
  67. package/.claude/skills/leniu-crud-development/SKILL.md +1110 -0
  68. package/.claude/skills/leniu-data-permission/SKILL.md +256 -0
  69. package/.claude/skills/leniu-database-ops/SKILL.md +426 -0
  70. package/.claude/skills/leniu-error-handler/SKILL.md +462 -0
  71. package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
  72. package/.claude/skills/leniu-java-code-style/SKILL.md +510 -0
  73. package/.claude/skills/leniu-java-concurrent/SKILL.md +400 -0
  74. package/.claude/skills/leniu-java-entity/SKILL.md +751 -0
  75. package/.claude/skills/leniu-java-export/SKILL.md +560 -0
  76. package/.claude/skills/leniu-java-logging/SKILL.md +832 -0
  77. package/.claude/skills/leniu-java-mq/SKILL.md +338 -0
  78. package/.claude/skills/leniu-java-mybatis/SKILL.md +640 -0
  79. package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
  80. package/.claude/skills/leniu-java-task/SKILL.md +367 -0
  81. package/.claude/skills/leniu-java-total-line/SKILL.md +195 -0
  82. package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  83. package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  84. package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
  85. package/.claude/skills/leniu-redis-cache/SKILL.md +316 -0
  86. package/.claude/skills/leniu-security-guard/SKILL.md +520 -0
  87. package/.claude/skills/leniu-utils-toolkit/SKILL.md +380 -0
  88. package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
  89. package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
  90. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  91. package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
  92. package/.claude/skills/openspec-explore/SKILL.md +290 -0
  93. package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
  94. package/.claude/skills/openspec-new-change/SKILL.md +74 -0
  95. package/.claude/skills/openspec-onboard/SKILL.md +529 -0
  96. package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
  97. package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
  98. package/.claude/skills/performance-doctor/SKILL.md +627 -0
  99. package/.claude/skills/project-navigator/SKILL.md +305 -0
  100. package/.claude/skills/redis-cache/SKILL.md +839 -0
  101. package/.claude/skills/scheduled-jobs/SKILL.md +633 -0
  102. package/.claude/skills/security-guard/SKILL.md +748 -0
  103. package/.claude/skills/sms-mail/SKILL.md +766 -0
  104. package/.claude/skills/social-login/SKILL.md +668 -0
  105. package/.claude/skills/store-pc/SKILL.md +366 -0
  106. package/.claude/skills/task-tracker/SKILL.md +307 -0
  107. package/.claude/skills/tech-decision/SKILL.md +393 -0
  108. package/.claude/skills/tenant-management/SKILL.md +603 -0
  109. package/.claude/skills/test-development/SKILL.md +755 -0
  110. package/.claude/skills/ui-pc/SKILL.md +438 -0
  111. package/.claude/skills/utils-toolkit/SKILL.md +615 -0
  112. package/.claude/skills/websocket-sse/SKILL.md +716 -0
  113. package/.claude/skills/workflow-engine/SKILL.md +676 -0
  114. package/.claude/templates//345/276/205/345/212/236/346/270/205/345/215/225/346/250/241/346/235/277.md +56 -0
  115. package/.claude/templates//351/234/200/346/261/202/346/226/207/346/241/243/346/250/241/346/235/277.md +85 -0
  116. package/.claude/templates//351/241/271/347/233/256/347/212/266/346/200/201/346/250/241/346/235/277.md +43 -0
  117. package/.codex/skills/add-skill/SKILL.md +352 -0
  118. package/.codex/skills/add-todo/SKILL.md +269 -0
  119. package/.codex/skills/api-development/SKILL.md +693 -0
  120. package/.codex/skills/architecture-design/SKILL.md +628 -0
  121. package/.codex/skills/backend-annotations/SKILL.md +664 -0
  122. package/.codex/skills/banana-image/CHANGELOG.md +37 -0
  123. package/.codex/skills/banana-image/README.md +146 -0
  124. package/.codex/skills/banana-image/SKILL.md +164 -0
  125. package/.codex/skills/banana-image/assets/logo.png +0 -0
  126. package/.codex/skills/banana-image/references/advanced-usage.md +189 -0
  127. package/.codex/skills/banana-image/scripts/apply_template.py +125 -0
  128. package/.codex/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  129. package/.codex/skills/banana-image/scripts/batch_prep.py +82 -0
  130. package/.codex/skills/banana-image/scripts/package-lock.json +1437 -0
  131. package/.codex/skills/banana-image/scripts/package.json +18 -0
  132. package/.codex/skills/banana-image/scripts/requirements.txt +10 -0
  133. package/.codex/skills/banana-image/templates/poster.json +22 -0
  134. package/.codex/skills/banana-image/templates/product.json +17 -0
  135. package/.codex/skills/banana-image/templates/social.json +22 -0
  136. package/.codex/skills/banana-image/templates/thumbnail.json +17 -0
  137. package/.codex/skills/brainstorm/SKILL.md +648 -0
  138. package/.codex/skills/bug-detective/SKILL.md +1206 -0
  139. package/.codex/skills/check/SKILL.md +367 -0
  140. package/.codex/skills/code-patterns/SKILL.md +442 -0
  141. package/.codex/skills/collaborating-with-codex/SKILL.md +174 -0
  142. package/.codex/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  143. package/.codex/skills/collaborating-with-gemini/SKILL.md +194 -0
  144. package/.codex/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  145. package/.codex/skills/crud/SKILL.md +265 -0
  146. package/.codex/skills/crud-development/SKILL.md +637 -0
  147. package/.codex/skills/data-permission/SKILL.md +591 -0
  148. package/.codex/skills/database-ops/SKILL.md +553 -0
  149. package/.codex/skills/dev/SKILL.md +187 -0
  150. package/.codex/skills/error-handler/SKILL.md +361 -0
  151. package/.codex/skills/file-oss-management/SKILL.md +863 -0
  152. package/.codex/skills/git-workflow/SKILL.md +375 -0
  153. package/.codex/skills/init-docs/SKILL.md +194 -0
  154. package/.codex/skills/json-serialization/SKILL.md +357 -0
  155. package/.codex/skills/leniu-api-development/SKILL.md +803 -0
  156. package/.codex/skills/leniu-architecture-design/SKILL.md +594 -0
  157. package/.codex/skills/leniu-backend-annotations/SKILL.md +662 -0
  158. package/.codex/skills/leniu-code-patterns/SKILL.md +365 -0
  159. package/.codex/skills/leniu-crud-development/SKILL.md +1110 -0
  160. package/.codex/skills/leniu-data-permission/SKILL.md +256 -0
  161. package/.codex/skills/leniu-database-ops/SKILL.md +426 -0
  162. package/.codex/skills/leniu-error-handler/SKILL.md +462 -0
  163. package/.codex/skills/leniu-java-amount-handling/SKILL.md +461 -0
  164. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  165. package/.codex/skills/leniu-java-concurrent/SKILL.md +400 -0
  166. package/.codex/skills/leniu-java-entity/SKILL.md +751 -0
  167. package/.codex/skills/leniu-java-export/SKILL.md +560 -0
  168. package/.codex/skills/leniu-java-logging/SKILL.md +832 -0
  169. package/.codex/skills/leniu-java-mq/SKILL.md +338 -0
  170. package/.codex/skills/leniu-java-mybatis/SKILL.md +640 -0
  171. package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
  172. package/.codex/skills/leniu-java-task/SKILL.md +367 -0
  173. package/.codex/skills/leniu-java-total-line/SKILL.md +195 -0
  174. package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  175. package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  176. package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
  177. package/.codex/skills/leniu-redis-cache/SKILL.md +316 -0
  178. package/.codex/skills/leniu-security-guard/SKILL.md +520 -0
  179. package/.codex/skills/leniu-utils-toolkit/SKILL.md +378 -0
  180. package/.codex/skills/next/SKILL.md +137 -0
  181. package/.codex/skills/openspec-apply-change/SKILL.md +156 -0
  182. package/.codex/skills/openspec-archive-change/SKILL.md +114 -0
  183. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  184. package/.codex/skills/openspec-continue-change/SKILL.md +118 -0
  185. package/.codex/skills/openspec-explore/SKILL.md +290 -0
  186. package/.codex/skills/openspec-ff-change/SKILL.md +101 -0
  187. package/.codex/skills/openspec-new-change/SKILL.md +74 -0
  188. package/.codex/skills/openspec-onboard/SKILL.md +529 -0
  189. package/.codex/skills/openspec-sync-specs/SKILL.md +138 -0
  190. package/.codex/skills/openspec-verify-change/SKILL.md +168 -0
  191. package/.codex/skills/performance-doctor/SKILL.md +627 -0
  192. package/.codex/skills/progress/SKILL.md +193 -0
  193. package/.codex/skills/project-navigator/SKILL.md +286 -0
  194. package/.codex/skills/redis-cache/SKILL.md +829 -0
  195. package/.codex/skills/scheduled-jobs/SKILL.md +633 -0
  196. package/.codex/skills/security-guard/SKILL.md +739 -0
  197. package/.codex/skills/sms-mail/SKILL.md +766 -0
  198. package/.codex/skills/social-login/SKILL.md +668 -0
  199. package/.codex/skills/start/SKILL.md +154 -0
  200. package/.codex/skills/store-pc/SKILL.md +491 -0
  201. package/.codex/skills/sync/SKILL.md +149 -0
  202. package/.codex/skills/task-tracker/SKILL.md +307 -0
  203. package/.codex/skills/tech-decision/SKILL.md +393 -0
  204. package/.codex/skills/tenant-management/SKILL.md +603 -0
  205. package/.codex/skills/test-development/SKILL.md +755 -0
  206. package/.codex/skills/ui-pc/SKILL.md +475 -0
  207. package/.codex/skills/update-status/SKILL.md +159 -0
  208. package/.codex/skills/utils-toolkit/SKILL.md +593 -0
  209. package/.codex/skills/websocket-sse/SKILL.md +716 -0
  210. package/.codex/skills/workflow-engine/SKILL.md +676 -0
  211. package/.cursor/agents/code-reviewer.md +139 -0
  212. package/.cursor/agents/project-manager.md +159 -0
  213. package/.cursor/commands/opsx-apply.md +152 -0
  214. package/.cursor/commands/opsx-archive.md +157 -0
  215. package/.cursor/commands/opsx-bulk-archive.md +242 -0
  216. package/.cursor/commands/opsx-continue.md +114 -0
  217. package/.cursor/commands/opsx-explore.md +174 -0
  218. package/.cursor/commands/opsx-ff.md +94 -0
  219. package/.cursor/commands/opsx-new.md +69 -0
  220. package/.cursor/commands/opsx-onboard.md +525 -0
  221. package/.cursor/commands/opsx-sync.md +134 -0
  222. package/.cursor/commands/opsx-verify.md +164 -0
  223. package/.cursor/mcp.json +22 -0
  224. package/.cursor/skills/add-skill/SKILL.md +352 -0
  225. package/.cursor/skills/api-development/SKILL.md +560 -0
  226. package/.cursor/skills/architecture-design/SKILL.md +756 -0
  227. package/.cursor/skills/backend-annotations/SKILL.md +674 -0
  228. package/.cursor/skills/banana-image/CHANGELOG.md +37 -0
  229. package/.cursor/skills/banana-image/README.md +146 -0
  230. package/.cursor/skills/banana-image/SKILL.md +164 -0
  231. package/.cursor/skills/banana-image/assets/logo.png +0 -0
  232. package/.cursor/skills/banana-image/references/advanced-usage.md +189 -0
  233. package/.cursor/skills/banana-image/scripts/apply_template.py +125 -0
  234. package/.cursor/skills/banana-image/scripts/banana_image_exec.ts +412 -0
  235. package/.cursor/skills/banana-image/scripts/batch_prep.py +82 -0
  236. package/.cursor/skills/banana-image/scripts/package-lock.json +1437 -0
  237. package/.cursor/skills/banana-image/scripts/package.json +18 -0
  238. package/.cursor/skills/banana-image/scripts/requirements.txt +10 -0
  239. package/.cursor/skills/banana-image/templates/poster.json +22 -0
  240. package/.cursor/skills/banana-image/templates/product.json +17 -0
  241. package/.cursor/skills/banana-image/templates/social.json +22 -0
  242. package/.cursor/skills/banana-image/templates/thumbnail.json +17 -0
  243. package/.cursor/skills/brainstorm/SKILL.md +648 -0
  244. package/.cursor/skills/bug-detective/SKILL.md +1206 -0
  245. package/.cursor/skills/code-patterns/SKILL.md +590 -0
  246. package/.cursor/skills/collaborating-with-codex/SKILL.md +174 -0
  247. package/.cursor/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
  248. package/.cursor/skills/collaborating-with-gemini/SKILL.md +194 -0
  249. package/.cursor/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
  250. package/.cursor/skills/crud-development/SKILL.md +649 -0
  251. package/.cursor/skills/data-permission/SKILL.md +599 -0
  252. package/.cursor/skills/database-ops/SKILL.md +407 -0
  253. package/.cursor/skills/error-handler/SKILL.md +371 -0
  254. package/.cursor/skills/file-oss-management/SKILL.md +863 -0
  255. package/.cursor/skills/git-workflow/SKILL.md +375 -0
  256. package/.cursor/skills/json-serialization/SKILL.md +357 -0
  257. package/.cursor/skills/leniu-api-development/SKILL.md +803 -0
  258. package/.cursor/skills/leniu-architecture-design/SKILL.md +598 -0
  259. package/.cursor/skills/leniu-backend-annotations/SKILL.md +664 -0
  260. package/.cursor/skills/leniu-code-patterns/SKILL.md +365 -0
  261. package/.cursor/skills/leniu-crud-development/SKILL.md +1110 -0
  262. package/.cursor/skills/leniu-data-permission/SKILL.md +256 -0
  263. package/.cursor/skills/leniu-database-ops/SKILL.md +426 -0
  264. package/.cursor/skills/leniu-error-handler/SKILL.md +462 -0
  265. package/.cursor/skills/leniu-java-amount-handling/SKILL.md +461 -0
  266. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  267. package/.cursor/skills/leniu-java-concurrent/SKILL.md +400 -0
  268. package/.cursor/skills/leniu-java-entity/SKILL.md +751 -0
  269. package/.cursor/skills/leniu-java-export/SKILL.md +560 -0
  270. package/.cursor/skills/leniu-java-logging/SKILL.md +832 -0
  271. package/.cursor/skills/leniu-java-mq/SKILL.md +338 -0
  272. package/.cursor/skills/leniu-java-mybatis/SKILL.md +640 -0
  273. package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
  274. package/.cursor/skills/leniu-java-task/SKILL.md +367 -0
  275. package/.cursor/skills/leniu-java-total-line/SKILL.md +195 -0
  276. package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
  277. package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
  278. package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
  279. package/.cursor/skills/leniu-redis-cache/SKILL.md +316 -0
  280. package/.cursor/skills/leniu-security-guard/SKILL.md +520 -0
  281. package/.cursor/skills/leniu-utils-toolkit/SKILL.md +380 -0
  282. package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
  283. package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
  284. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +246 -0
  285. package/.cursor/skills/openspec-continue-change/SKILL.md +118 -0
  286. package/.cursor/skills/openspec-explore/SKILL.md +290 -0
  287. package/.cursor/skills/openspec-ff-change/SKILL.md +101 -0
  288. package/.cursor/skills/openspec-new-change/SKILL.md +74 -0
  289. package/.cursor/skills/openspec-onboard/SKILL.md +529 -0
  290. package/.cursor/skills/openspec-sync-specs/SKILL.md +138 -0
  291. package/.cursor/skills/openspec-verify-change/SKILL.md +168 -0
  292. package/.cursor/skills/performance-doctor/SKILL.md +627 -0
  293. package/.cursor/skills/project-navigator/SKILL.md +305 -0
  294. package/.cursor/skills/redis-cache/SKILL.md +839 -0
  295. package/.cursor/skills/scheduled-jobs/SKILL.md +633 -0
  296. package/.cursor/skills/security-guard/SKILL.md +748 -0
  297. package/.cursor/skills/sms-mail/SKILL.md +766 -0
  298. package/.cursor/skills/social-login/SKILL.md +668 -0
  299. package/.cursor/skills/store-pc/SKILL.md +366 -0
  300. package/.cursor/skills/task-tracker/SKILL.md +307 -0
  301. package/.cursor/skills/tech-decision/SKILL.md +393 -0
  302. package/.cursor/skills/tenant-management/SKILL.md +603 -0
  303. package/.cursor/skills/test-development/SKILL.md +755 -0
  304. package/.cursor/skills/ui-pc/SKILL.md +438 -0
  305. package/.cursor/skills/utils-toolkit/SKILL.md +615 -0
  306. package/.cursor/skills/websocket-sse/SKILL.md +716 -0
  307. package/.cursor/skills/workflow-engine/SKILL.md +676 -0
  308. package/AGENTS.md +669 -0
  309. package/CLAUDE.md +205 -0
  310. package/README.md +205 -0
  311. package/bin/index.js +179 -0
  312. package/init.sh +178 -0
  313. package/package.json +27 -0
@@ -0,0 +1,603 @@
1
+ ---
2
+ name: tenant-management
3
+ description: |
4
+ 当需要实现多租户数据隔离、租户管理、跨租户查询时自动使用此 Skill。
5
+
6
+ 触发场景:
7
+ - 需要为业务表添加租户隔离
8
+ - 需要临时忽略租户过滤查询全量数据
9
+ - 需要切换到其他租户执行操作
10
+ - 需要配置排除租户过滤的表
11
+ - 需要理解多租户数据隔离原理
12
+
13
+ 触发词:多租户、租户隔离、TenantEntity、TenantHelper、租户ID、tenantId、跨租户、ignore租户、动态租户、租户切换、SaaS、数据隔离
14
+ ---
15
+
16
+ # 多租户开发指南
17
+
18
+ > **适用模块**:`ruoyi-common-tenant`
19
+
20
+ ## 概述
21
+
22
+ 本框架基于 **MyBatis-Plus 租户插件** 实现多租户数据隔离,支持 SaaS 多租户架构。
23
+
24
+ **核心特性**:
25
+ - ✅ 自动 SQL 过滤(无需手动添加 tenant_id 条件)
26
+ - ✅ Redis 缓存自动隔离(Key 前缀自动添加租户)
27
+ - ✅ Spring Cache 租户隔离
28
+ - ✅ Sa-Token 会话租户隔离
29
+ - ✅ 支持临时忽略租户、动态切换租户
30
+
31
+ ---
32
+
33
+ ## 一、多租户架构原理
34
+
35
+ ### 1.1 数据隔离流程
36
+
37
+ ```
38
+ ┌─────────────┐ 请求头携带租户ID ┌─────────────┐
39
+ │ 前端请求 │ ───────────────────────→ │ 后端服务 │
40
+ └─────────────┘ └─────────────┘
41
+
42
+ ┌────────────┴────────────┐
43
+ │ TenantHelper │
44
+ │ 获取当前租户ID │
45
+ └────────────┬────────────┘
46
+
47
+ ┌──────────────────────────────────┼──────────────────────────────────┐
48
+ │ │ │
49
+ ▼ ▼ ▼
50
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
51
+ │ MyBatis-Plus │ │ Redis 缓存 │ │ Spring Cache │
52
+ │ 自动追加条件 │ │ Key 前缀隔离 │ │ 缓存名隔离 │
53
+ │ WHERE tenant_id │ │ {tenantId}:key │ │ {tenantId}::xxx │
54
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
55
+ ```
56
+
57
+ ### 1.2 自动 SQL 改写
58
+
59
+ 原始 SQL:
60
+ ```sql
61
+ SELECT * FROM sys_user WHERE status = '1'
62
+ ```
63
+
64
+ 自动改写后:
65
+ ```sql
66
+ SELECT * FROM sys_user WHERE status = '1' AND tenant_id = '000000'
67
+ ```
68
+
69
+ ---
70
+
71
+ ## 二、Entity 继承规范
72
+
73
+ ### 2.1 TenantEntity 基类
74
+
75
+ **位置**:`org.dromara.common.tenant.core.TenantEntity`
76
+
77
+ ```java
78
+ /**
79
+ * 租户基类
80
+ */
81
+ @Data
82
+ @EqualsAndHashCode(callSuper = true)
83
+ public class TenantEntity extends BaseEntity {
84
+
85
+ /**
86
+ * 租户编号
87
+ */
88
+ private String tenantId;
89
+
90
+ }
91
+ ```
92
+
93
+ ### 2.2 继承关系
94
+
95
+ ```
96
+ TenantEntity
97
+ └── BaseEntity
98
+ ├── createDept // 创建部门
99
+ ├── createBy // 创建者
100
+ ├── createTime // 创建时间
101
+ ├── updateBy // 更新者
102
+ ├── updateTime // 更新时间
103
+ └── params // 请求参数
104
+ ```
105
+
106
+ ### 2.3 Entity 示例
107
+
108
+ ```java
109
+ import org.dromara.common.tenant.core.TenantEntity;
110
+ import com.baomidou.mybatisplus.annotation.TableId;
111
+ import com.baomidou.mybatisplus.annotation.TableName;
112
+ import lombok.Data;
113
+ import lombok.EqualsAndHashCode;
114
+
115
+ /**
116
+ * 业务实体(需要租户隔离)
117
+ */
118
+ @Data
119
+ @EqualsAndHashCode(callSuper = true)
120
+ @TableName("biz_order")
121
+ public class BizOrder extends TenantEntity {
122
+
123
+ @TableId(value = "id")
124
+ private Long id;
125
+
126
+ private String orderNo;
127
+
128
+ private String status;
129
+ }
130
+ ```
131
+
132
+ ### 2.4 数据库表设计
133
+
134
+ ```sql
135
+ CREATE TABLE biz_order (
136
+ id BIGINT(20) NOT NULL COMMENT '主键ID',
137
+ tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户ID', -- 必须有此字段
138
+ order_no VARCHAR(64) NOT NULL COMMENT '订单号',
139
+ status CHAR(1) DEFAULT '0' COMMENT '状态',
140
+ create_dept BIGINT(20) DEFAULT NULL COMMENT '创建部门',
141
+ create_by BIGINT(20) DEFAULT NULL COMMENT '创建人',
142
+ create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
143
+ update_by BIGINT(20) DEFAULT NULL COMMENT '更新人',
144
+ update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
145
+ del_flag CHAR(1) DEFAULT '0' COMMENT '删除标志',
146
+ PRIMARY KEY (id),
147
+ KEY idx_tenant_id (tenant_id) -- 建议加索引
148
+ ) ENGINE=InnoDB COMMENT='业务订单表';
149
+ ```
150
+
151
+ ---
152
+
153
+ ## 三、TenantHelper 工具类
154
+
155
+ **位置**:`org.dromara.common.tenant.helper.TenantHelper`
156
+
157
+ ### 3.1 核心方法
158
+
159
+ ```java
160
+ import org.dromara.common.tenant.helper.TenantHelper;
161
+
162
+ // ========== 基础方法 ==========
163
+
164
+ // 1. 检查租户功能是否启用
165
+ boolean enabled = TenantHelper.isEnable();
166
+
167
+ // 2. 获取当前租户ID(优先返回动态租户,其次返回登录用户租户)
168
+ String tenantId = TenantHelper.getTenantId();
169
+
170
+ // ========== 忽略租户(查询全量数据) ==========
171
+
172
+ // 3. 在忽略租户中执行(无返回值)
173
+ TenantHelper.ignore(() -> {
174
+ // 此代码块内的 SQL 不会追加 tenant_id 条件
175
+ List<SysUser> allUsers = userMapper.selectList(null);
176
+ });
177
+
178
+ // 4. 在忽略租户中执行(有返回值)
179
+ List<SysUser> allUsers = TenantHelper.ignore(() -> {
180
+ return userMapper.selectList(null);
181
+ });
182
+
183
+ // ========== 动态租户(切换到其他租户) ==========
184
+
185
+ // 5. 在指定租户中执行(无返回值)
186
+ TenantHelper.dynamic("000001", () -> {
187
+ // 此代码块内使用租户 000001 的数据
188
+ userMapper.insert(user);
189
+ });
190
+
191
+ // 6. 在指定租户中执行(有返回值)
192
+ List<SysUser> tenant001Users = TenantHelper.dynamic("000001", () -> {
193
+ return userMapper.selectList(null);
194
+ });
195
+
196
+ // ========== 手动管理动态租户 ==========
197
+
198
+ // 7. 设置动态租户(需手动清理)
199
+ TenantHelper.setDynamic("000001");
200
+ // ... 执行操作 ...
201
+ TenantHelper.clearDynamic(); // 必须清理
202
+
203
+ // 8. 设置全局动态租户(跨请求生效,存入 Redis)
204
+ TenantHelper.setDynamic("000001", true);
205
+ // ... 多次请求都使用该租户 ...
206
+ TenantHelper.clearDynamic();
207
+ ```
208
+
209
+ ### 3.2 方法速查表
210
+
211
+ | 方法 | 说明 | 使用场景 |
212
+ |------|------|---------|
213
+ | `isEnable()` | 检查租户是否启用 | 条件判断 |
214
+ | `getTenantId()` | 获取当前租户ID | 业务逻辑 |
215
+ | `ignore(Runnable)` | 忽略租户执行(无返回值) | 查询全量数据 |
216
+ | `ignore(Supplier<T>)` | 忽略租户执行(有返回值) | 查询全量数据 |
217
+ | `dynamic(tenantId, Runnable)` | 切换租户执行(无返回值) | 跨租户操作 |
218
+ | `dynamic(tenantId, Supplier<T>)` | 切换租户执行(有返回值) | 跨租户查询 |
219
+ | `setDynamic(tenantId)` | 手动设置动态租户 | 复杂场景 |
220
+ | `setDynamic(tenantId, true)` | 设置全局动态租户 | 跨请求场景 |
221
+ | `getDynamic()` | 获取动态租户 | 调试/检查 |
222
+ | `clearDynamic()` | 清除动态租户 | 配合 setDynamic |
223
+
224
+ ---
225
+
226
+ ## 四、配置说明
227
+
228
+ ### 4.1 启用多租户
229
+
230
+ ```yaml
231
+ # application.yml
232
+ tenant:
233
+ # 是否开启多租户
234
+ enable: true
235
+ # 排除表(这些表不追加 tenant_id 条件)
236
+ excludes:
237
+ - sys_menu # 菜单表(所有租户共享)
238
+ - sys_dict_type # 字典类型(所有租户共享)
239
+ - sys_dict_data # 字典数据(所有租户共享)
240
+ ```
241
+
242
+ ### 4.2 排除表说明
243
+
244
+ 以下类型的表通常需要排除:
245
+ - **系统配置表**:所有租户共享的配置
246
+ - **字典表**:公共字典数据
247
+ - **地区表**:省市区数据
248
+ - **代码生成表**:gen_table、gen_table_column(框架自动排除)
249
+
250
+ ### 4.3 自动配置的组件
251
+
252
+ 当 `tenant.enable=true` 时,框架自动配置:
253
+
254
+ | 组件 | 类名 | 功能 |
255
+ |------|------|------|
256
+ | MyBatis 租户插件 | `TenantLineInnerInterceptor` | SQL 自动追加租户条件 |
257
+ | Redis Key 前缀 | `TenantKeyPrefixHandler` | Redis Key 自动添加租户前缀 |
258
+ | 缓存管理器 | `TenantSpringCacheManager` | Spring Cache 租户隔离 |
259
+ | Sa-Token DAO | `TenantSaTokenDao` | 会话数据租户隔离 |
260
+
261
+ ---
262
+
263
+ ## 五、常见场景
264
+
265
+ ### 5.1 场景:管理员查看所有租户数据
266
+
267
+ ```java
268
+ @Service
269
+ @RequiredArgsConstructor
270
+ public class AdminUserServiceImpl implements IAdminUserService {
271
+
272
+ private final SysUserMapper userMapper;
273
+
274
+ /**
275
+ * 管理员查看所有租户的用户(需要超级管理员权限)
276
+ */
277
+ @SaCheckRole("superadmin")
278
+ public List<SysUserVo> listAllTenantUsers() {
279
+ // 忽略租户过滤,查询所有数据
280
+ return TenantHelper.ignore(() -> {
281
+ return userMapper.selectVoList(null);
282
+ });
283
+ }
284
+ }
285
+ ```
286
+
287
+ ### 5.2 场景:跨租户数据同步
288
+
289
+ ```java
290
+ @Service
291
+ @RequiredArgsConstructor
292
+ public class DataSyncServiceImpl implements IDataSyncService {
293
+
294
+ private final SysConfigMapper configMapper;
295
+
296
+ /**
297
+ * 将配置同步到所有租户
298
+ */
299
+ public void syncConfigToAllTenants(SysConfig config) {
300
+ // 1. 获取所有租户ID
301
+ List<String> tenantIds = TenantHelper.ignore(() -> {
302
+ return tenantMapper.selectList(null)
303
+ .stream()
304
+ .map(SysTenant::getTenantId)
305
+ .collect(Collectors.toList());
306
+ });
307
+
308
+ // 2. 逐个租户同步
309
+ for (String tenantId : tenantIds) {
310
+ TenantHelper.dynamic(tenantId, () -> {
311
+ // 检查是否已存在
312
+ SysConfig existing = configMapper.selectByKey(config.getConfigKey());
313
+ if (existing == null) {
314
+ configMapper.insert(config);
315
+ } else {
316
+ configMapper.updateById(config);
317
+ }
318
+ });
319
+ }
320
+ }
321
+ }
322
+ ```
323
+
324
+ ### 5.3 场景:定时任务处理所有租户
325
+
326
+ ```java
327
+ @Service
328
+ @RequiredArgsConstructor
329
+ public class OrderCleanupJob {
330
+
331
+ private final OrderMapper orderMapper;
332
+ private final SysTenantMapper tenantMapper;
333
+
334
+ /**
335
+ * 清理所有租户的过期订单
336
+ */
337
+ @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点
338
+ public void cleanupExpiredOrders() {
339
+ // 1. 获取所有启用的租户
340
+ List<SysTenant> tenants = TenantHelper.ignore(() -> {
341
+ return tenantMapper.selectList(
342
+ Wrappers.<SysTenant>lambdaQuery()
343
+ .eq(SysTenant::getStatus, "0")
344
+ );
345
+ });
346
+
347
+ // 2. 逐个租户处理
348
+ for (SysTenant tenant : tenants) {
349
+ try {
350
+ TenantHelper.dynamic(tenant.getTenantId(), () -> {
351
+ // 删除30天前的已取消订单
352
+ orderMapper.delete(
353
+ Wrappers.<Order>lambdaQuery()
354
+ .eq(Order::getStatus, "CANCELLED")
355
+ .lt(Order::getCreateTime, DateUtils.addDays(new Date(), -30))
356
+ );
357
+ });
358
+ } catch (Exception e) {
359
+ log.error("清理租户 {} 订单失败: {}", tenant.getTenantId(), e.getMessage());
360
+ }
361
+ }
362
+ }
363
+ }
364
+ ```
365
+
366
+ ### 5.4 场景:统计所有租户数据
367
+
368
+ ```java
369
+ @Service
370
+ @RequiredArgsConstructor
371
+ public class StatisticsServiceImpl implements IStatisticsService {
372
+
373
+ private final OrderMapper orderMapper;
374
+
375
+ /**
376
+ * 统计各租户订单数量
377
+ */
378
+ public List<TenantOrderStats> getTenantOrderStats() {
379
+ // 忽略租户,使用 GROUP BY 统计
380
+ return TenantHelper.ignore(() -> {
381
+ return orderMapper.selectMaps(
382
+ new QueryWrapper<Order>()
383
+ .select("tenant_id", "COUNT(*) as order_count", "SUM(amount) as total_amount")
384
+ .groupBy("tenant_id")
385
+ ).stream().map(map -> {
386
+ TenantOrderStats stats = new TenantOrderStats();
387
+ stats.setTenantId((String) map.get("tenant_id"));
388
+ stats.setOrderCount(((Number) map.get("order_count")).longValue());
389
+ stats.setTotalAmount((BigDecimal) map.get("total_amount"));
390
+ return stats;
391
+ }).collect(Collectors.toList());
392
+ });
393
+ }
394
+ }
395
+ ```
396
+
397
+ ---
398
+
399
+ ## 六、Redis 缓存隔离
400
+
401
+ ### 6.1 自动隔离原理
402
+
403
+ 框架通过 `TenantKeyPrefixHandler` 自动为 Redis Key 添加租户前缀:
404
+
405
+ ```
406
+ 原始 Key: user:info:1001
407
+ 实际 Key: 000000:user:info:1001 (租户 000000)
408
+ 实际 Key: 000001:user:info:1001 (租户 000001)
409
+ ```
410
+
411
+ ### 6.2 全局 Key(不隔离)
412
+
413
+ 使用 `GlobalConstants.GLOBAL_REDIS_KEY` 前缀的 Key 不会添加租户前缀:
414
+
415
+ ```java
416
+ import org.dromara.common.core.constant.GlobalConstants;
417
+
418
+ // 全局缓存(所有租户共享)
419
+ String globalKey = GlobalConstants.GLOBAL_REDIS_KEY + "config:site_name";
420
+ RedisUtils.setCacheObject(globalKey, "网站名称");
421
+
422
+ // 租户隔离缓存
423
+ String tenantKey = "user:info:" + userId; // 自动添加租户前缀
424
+ RedisUtils.setCacheObject(tenantKey, userInfo);
425
+ ```
426
+
427
+ ### 6.3 忽略租户时的缓存
428
+
429
+ 在 `TenantHelper.ignore()` 中操作的缓存不会添加租户前缀:
430
+
431
+ ```java
432
+ TenantHelper.ignore(() -> {
433
+ // 此处的 Redis 操作不添加租户前缀
434
+ RedisUtils.setCacheObject("global:data", data);
435
+ });
436
+ ```
437
+
438
+ ---
439
+
440
+ ## 七、常见错误与最佳实践
441
+
442
+ ### ❌ 错误1:忘记继承 TenantEntity
443
+
444
+ ```java
445
+ // ❌ 错误:继承 BaseEntity,没有 tenantId 字段
446
+ @Data
447
+ @EqualsAndHashCode(callSuper = true)
448
+ public class BizOrder extends BaseEntity {
449
+ // 没有 tenantId,数据无法隔离!
450
+ }
451
+
452
+ // ✅ 正确:继承 TenantEntity
453
+ @Data
454
+ @EqualsAndHashCode(callSuper = true)
455
+ public class BizOrder extends TenantEntity {
456
+ // 自动包含 tenantId 字段
457
+ }
458
+ ```
459
+
460
+ ### ❌ 错误2:数据库表缺少 tenant_id 字段
461
+
462
+ ```sql
463
+ -- ❌ 错误:表没有 tenant_id 字段
464
+ CREATE TABLE biz_order (
465
+ id BIGINT(20) NOT NULL,
466
+ order_no VARCHAR(64)
467
+ );
468
+
469
+ -- ✅ 正确:添加 tenant_id 字段
470
+ CREATE TABLE biz_order (
471
+ id BIGINT(20) NOT NULL,
472
+ tenant_id VARCHAR(20) DEFAULT '000000', -- 必须有
473
+ order_no VARCHAR(64)
474
+ );
475
+ ```
476
+
477
+ ### ❌ 错误3:setDynamic 后忘记 clearDynamic
478
+
479
+ ```java
480
+ // ❌ 错误:设置后没有清理,后续请求使用错误的租户
481
+ TenantHelper.setDynamic("000001");
482
+ userMapper.insert(user);
483
+ // 忘记 clearDynamic(),租户ID泄漏到其他请求!
484
+
485
+ // ✅ 正确方式1:使用 try-finally
486
+ TenantHelper.setDynamic("000001");
487
+ try {
488
+ userMapper.insert(user);
489
+ } finally {
490
+ TenantHelper.clearDynamic();
491
+ }
492
+
493
+ // ✅ 正确方式2:使用 dynamic() 方法(推荐)
494
+ TenantHelper.dynamic("000001", () -> {
495
+ userMapper.insert(user);
496
+ });
497
+ ```
498
+
499
+ ### ❌ 错误4:在事务中切换租户
500
+
501
+ ```java
502
+ // ❌ 错误:事务内切换租户可能导致数据错乱
503
+ @Transactional
504
+ public void wrongMethod() {
505
+ orderMapper.insert(order); // 使用当前租户
506
+ TenantHelper.dynamic("000001", () -> {
507
+ logMapper.insert(log); // 使用租户 000001
508
+ });
509
+ // 事务提交时可能出现问题!
510
+ }
511
+
512
+ // ✅ 正确:避免在事务中切换租户,或使用独立事务
513
+ public void correctMethod() {
514
+ // 先处理当前租户
515
+ saveOrder(order);
516
+
517
+ // 再处理其他租户(独立事务)
518
+ saveLogToOtherTenant("000001", log);
519
+ }
520
+
521
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
522
+ public void saveLogToOtherTenant(String tenantId, Log log) {
523
+ TenantHelper.dynamic(tenantId, () -> {
524
+ logMapper.insert(log);
525
+ });
526
+ }
527
+ ```
528
+
529
+ ### ❌ 错误5:排除表配置不当
530
+
531
+ ```yaml
532
+ # ❌ 错误:把业务表加入排除列表
533
+ tenant:
534
+ excludes:
535
+ - biz_order # 业务表不应该排除!
536
+
537
+ # ✅ 正确:只排除真正需要共享的系统表
538
+ tenant:
539
+ excludes:
540
+ - sys_menu # 菜单配置(共享)
541
+ - sys_dict_type # 字典类型(共享)
542
+ - sys_config # 系统配置(共享)
543
+ ```
544
+
545
+ ---
546
+
547
+ ## 八、API 速查表
548
+
549
+ ### TenantHelper 方法
550
+
551
+ | 方法 | 说明 | 返回值 |
552
+ |------|------|--------|
553
+ | `isEnable()` | 租户功能是否启用 | boolean |
554
+ | `getTenantId()` | 获取当前租户ID | String |
555
+ | `ignore(Runnable)` | 忽略租户执行 | void |
556
+ | `ignore(Supplier<T>)` | 忽略租户执行 | T |
557
+ | `dynamic(tenantId, Runnable)` | 动态租户执行 | void |
558
+ | `dynamic(tenantId, Supplier<T>)` | 动态租户执行 | T |
559
+ | `setDynamic(tenantId)` | 设置动态租户 | void |
560
+ | `setDynamic(tenantId, global)` | 设置全局动态租户 | void |
561
+ | `getDynamic()` | 获取动态租户 | String |
562
+ | `clearDynamic()` | 清除动态租户 | void |
563
+
564
+ ### Entity 继承
565
+
566
+ | 基类 | 说明 | 包含字段 |
567
+ |------|------|---------|
568
+ | `BaseEntity` | 基础实体 | createDept, createBy, createTime, updateBy, updateTime |
569
+ | `TenantEntity` | 租户实体 | tenantId + BaseEntity 所有字段 |
570
+
571
+ ---
572
+
573
+ ## 九、配置参考
574
+
575
+ ### 完整配置示例
576
+
577
+ ```yaml
578
+ # application.yml
579
+ tenant:
580
+ # 是否开启多租户
581
+ enable: true
582
+ # 排除表(不追加租户条件的表)
583
+ excludes:
584
+ - sys_menu # 菜单表
585
+ - sys_dict_type # 字典类型
586
+ - sys_dict_data # 字典数据
587
+ - sys_oss_config # OSS 配置
588
+ - sys_config # 系统配置
589
+ ```
590
+
591
+ ---
592
+
593
+ ## 十、参考代码位置
594
+
595
+ | 类型 | 位置 |
596
+ |------|------|
597
+ | 租户基类 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/core/TenantEntity.java` |
598
+ | 租户助手 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java` |
599
+ | 租户处理器 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java` |
600
+ | Redis Key 处理 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java` |
601
+ | 租户配置类 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java` |
602
+ | 租户属性 | `ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/properties/TenantProperties.java` |
603
+ | 配置文件 | `ruoyi-admin/src/main/resources/application.yml` |