ai-engineering-init 1.3.3 → 1.4.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 (228) hide show
  1. package/.claude/hooks/skill-forced-eval.js +4 -1
  2. package/.claude/settings.json +3 -3
  3. package/.claude/skills/add-skill/SKILL.md +252 -116
  4. package/.claude/skills/api-development/SKILL.md +83 -377
  5. package/.claude/skills/architecture-design/SKILL.md +138 -632
  6. package/.claude/skills/backend-annotations/SKILL.md +134 -506
  7. package/.claude/skills/banana-image/SKILL.md +10 -3
  8. package/.claude/skills/brainstorm/SKILL.md +103 -535
  9. package/.claude/skills/bug-detective/SKILL.md +147 -1097
  10. package/.claude/skills/bug-detective/references/error-patterns.md +242 -0
  11. package/.claude/skills/code-patterns/SKILL.md +116 -426
  12. package/.claude/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  13. package/.claude/skills/crud-development/SKILL.md +64 -304
  14. package/.claude/skills/data-permission/SKILL.md +105 -412
  15. package/.claude/skills/data-permission/references/custom-data-scope.md +90 -0
  16. package/.claude/skills/file-oss-management/SKILL.md +106 -714
  17. package/.claude/skills/file-oss-management/references/entities.md +105 -0
  18. package/.claude/skills/file-oss-management/references/service-impl.md +104 -0
  19. package/.claude/skills/leniu-api-development/SKILL.md +142 -626
  20. package/.claude/skills/leniu-api-development/references/real-examples.md +273 -0
  21. package/.claude/skills/leniu-architecture-design/SKILL.md +176 -391
  22. package/.claude/skills/leniu-backend-annotations/SKILL.md +132 -519
  23. package/.claude/skills/leniu-brainstorm/SKILL.md +132 -541
  24. package/.claude/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  25. package/.claude/skills/leniu-crud-development/SKILL.md +232 -938
  26. package/.claude/skills/leniu-crud-development/references/templates.md +597 -0
  27. package/.claude/skills/leniu-customization-location/SKILL.md +410 -0
  28. package/.claude/skills/leniu-data-permission/SKILL.md +70 -0
  29. package/.claude/skills/leniu-java-entity/SKILL.md +76 -590
  30. package/.claude/skills/leniu-java-entity/references/templates.md +237 -0
  31. package/.claude/skills/leniu-java-export/SKILL.md +94 -379
  32. package/.claude/skills/leniu-java-logging/SKILL.md +106 -709
  33. package/.claude/skills/leniu-java-logging/references/data-mask.md +46 -0
  34. package/.claude/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  35. package/.claude/skills/leniu-java-mybatis/SKILL.md +73 -446
  36. package/.claude/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  37. package/.claude/skills/leniu-report-customization/SKILL.md +111 -325
  38. package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
  39. package/.claude/skills/leniu-report-standard-customization/SKILL.md +328 -0
  40. package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  41. package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  42. package/.claude/skills/leniu-security-guard/SKILL.md +133 -347
  43. package/.claude/skills/mysql-debug/SKILL.md +364 -0
  44. package/.claude/skills/openspec-apply-change/SKILL.md +10 -1
  45. package/.claude/skills/openspec-archive-change/SKILL.md +9 -1
  46. package/.claude/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  47. package/.claude/skills/openspec-continue-change/SKILL.md +9 -1
  48. package/.claude/skills/openspec-explore/SKILL.md +10 -1
  49. package/.claude/skills/openspec-ff-change/SKILL.md +9 -1
  50. package/.claude/skills/openspec-new-change/SKILL.md +9 -1
  51. package/.claude/skills/openspec-onboard/SKILL.md +15 -130
  52. package/.claude/skills/openspec-sync-specs/SKILL.md +9 -1
  53. package/.claude/skills/openspec-verify-change/SKILL.md +9 -1
  54. package/.claude/skills/performance-doctor/SKILL.md +110 -434
  55. package/.claude/skills/redis-cache/SKILL.md +89 -595
  56. package/.claude/skills/redis-cache/references/listeners.md +23 -0
  57. package/.claude/skills/scheduled-jobs/SKILL.md +88 -407
  58. package/.claude/skills/security-guard/SKILL.md +137 -532
  59. package/.claude/skills/security-guard/references/encrypt-config.md +103 -0
  60. package/.claude/skills/security-guard/references/sensitive-strategies.md +42 -0
  61. package/.claude/skills/sms-mail/SKILL.md +116 -574
  62. package/.claude/skills/sms-mail/references/mail-config.md +88 -0
  63. package/.claude/skills/sms-mail/references/sms-config.md +74 -0
  64. package/.claude/skills/social-login/SKILL.md +112 -514
  65. package/.claude/skills/social-login/references/provider-configs.md +118 -0
  66. package/.claude/skills/tenant-management/SKILL.md +129 -444
  67. package/.claude/skills/tenant-management/references/tenant-scenarios.md +91 -0
  68. package/.claude/skills/test-development/SKILL.md +86 -540
  69. package/.claude/skills/test-development/references/parameterized-examples.md +119 -0
  70. package/.claude/skills/utils-toolkit/SKILL.md +52 -305
  71. package/.claude/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  72. package/.claude/skills/websocket-sse/SKILL.md +105 -550
  73. package/.claude/skills/workflow-engine/SKILL.md +147 -502
  74. package/.codex/skills/add-skill/SKILL.md +252 -116
  75. package/.codex/skills/api-development/SKILL.md +172 -599
  76. package/.codex/skills/architecture-design/SKILL.md +138 -504
  77. package/.codex/skills/backend-annotations/SKILL.md +134 -496
  78. package/.codex/skills/banana-image/SKILL.md +10 -3
  79. package/.codex/skills/brainstorm/SKILL.md +103 -535
  80. package/.codex/skills/bug-detective/SKILL.md +147 -1097
  81. package/.codex/skills/bug-detective/references/error-patterns.md +242 -0
  82. package/.codex/skills/code-patterns/SKILL.md +120 -282
  83. package/.codex/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  84. package/.codex/skills/crud-development/SKILL.md +64 -292
  85. package/.codex/skills/data-permission/SKILL.md +108 -407
  86. package/.codex/skills/data-permission/references/custom-data-scope.md +90 -0
  87. package/.codex/skills/database-ops/SKILL.md +8 -154
  88. package/.codex/skills/error-handler/SKILL.md +10 -0
  89. package/.codex/skills/file-oss-management/SKILL.md +106 -714
  90. package/.codex/skills/file-oss-management/references/entities.md +105 -0
  91. package/.codex/skills/file-oss-management/references/service-impl.md +104 -0
  92. package/.codex/skills/git-workflow/SKILL.md +27 -5
  93. package/.codex/skills/leniu-api-development/SKILL.md +142 -626
  94. package/.codex/skills/leniu-api-development/references/real-examples.md +273 -0
  95. package/.codex/skills/leniu-architecture-design/SKILL.md +176 -391
  96. package/.codex/skills/leniu-backend-annotations/SKILL.md +132 -519
  97. package/.codex/skills/leniu-brainstorm/SKILL.md +132 -541
  98. package/.codex/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  99. package/.codex/skills/leniu-crud-development/SKILL.md +232 -938
  100. package/.codex/skills/leniu-crud-development/references/templates.md +597 -0
  101. package/.codex/skills/leniu-customization-location/SKILL.md +410 -0
  102. package/.codex/skills/leniu-data-permission/SKILL.md +70 -0
  103. package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
  104. package/.codex/skills/leniu-java-entity/SKILL.md +76 -590
  105. package/.codex/skills/leniu-java-entity/references/templates.md +237 -0
  106. package/.codex/skills/leniu-java-export/SKILL.md +94 -379
  107. package/.codex/skills/leniu-java-logging/SKILL.md +106 -709
  108. package/.codex/skills/leniu-java-logging/references/data-mask.md +46 -0
  109. package/.codex/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  110. package/.codex/skills/leniu-java-mybatis/SKILL.md +73 -446
  111. package/.codex/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  112. package/.codex/skills/leniu-report-customization/SKILL.md +111 -325
  113. package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
  114. package/.codex/skills/leniu-report-standard-customization/SKILL.md +328 -0
  115. package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  116. package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  117. package/.codex/skills/leniu-security-guard/SKILL.md +133 -347
  118. package/.codex/skills/mysql-debug/SKILL.md +364 -0
  119. package/.codex/skills/openspec-apply-change/SKILL.md +10 -1
  120. package/.codex/skills/openspec-archive-change/SKILL.md +9 -1
  121. package/.codex/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  122. package/.codex/skills/openspec-continue-change/SKILL.md +9 -1
  123. package/.codex/skills/openspec-explore/SKILL.md +10 -1
  124. package/.codex/skills/openspec-ff-change/SKILL.md +9 -1
  125. package/.codex/skills/openspec-new-change/SKILL.md +9 -1
  126. package/.codex/skills/openspec-onboard/SKILL.md +15 -130
  127. package/.codex/skills/openspec-sync-specs/SKILL.md +9 -1
  128. package/.codex/skills/openspec-verify-change/SKILL.md +9 -1
  129. package/.codex/skills/performance-doctor/SKILL.md +110 -434
  130. package/.codex/skills/project-navigator/SKILL.md +20 -1
  131. package/.codex/skills/redis-cache/SKILL.md +93 -589
  132. package/.codex/skills/redis-cache/references/listeners.md +23 -0
  133. package/.codex/skills/scheduled-jobs/SKILL.md +88 -407
  134. package/.codex/skills/security-guard/SKILL.md +141 -527
  135. package/.codex/skills/security-guard/references/encrypt-config.md +103 -0
  136. package/.codex/skills/security-guard/references/sensitive-strategies.md +42 -0
  137. package/.codex/skills/sms-mail/SKILL.md +116 -574
  138. package/.codex/skills/sms-mail/references/mail-config.md +88 -0
  139. package/.codex/skills/sms-mail/references/sms-config.md +74 -0
  140. package/.codex/skills/social-login/SKILL.md +112 -514
  141. package/.codex/skills/social-login/references/provider-configs.md +118 -0
  142. package/.codex/skills/store-pc/SKILL.md +258 -383
  143. package/.codex/skills/tenant-management/SKILL.md +129 -444
  144. package/.codex/skills/tenant-management/references/tenant-scenarios.md +91 -0
  145. package/.codex/skills/test-development/SKILL.md +86 -540
  146. package/.codex/skills/test-development/references/parameterized-examples.md +119 -0
  147. package/.codex/skills/ui-pc/SKILL.md +350 -387
  148. package/.codex/skills/utils-toolkit/SKILL.md +52 -283
  149. package/.codex/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  150. package/.codex/skills/websocket-sse/SKILL.md +105 -550
  151. package/.codex/skills/workflow-engine/SKILL.md +147 -502
  152. package/.cursor/hooks.json +3 -3
  153. package/.cursor/rules/skill-activation.mdc +2 -0
  154. package/.cursor/skills/add-skill/SKILL.md +252 -116
  155. package/.cursor/skills/api-development/SKILL.md +83 -377
  156. package/.cursor/skills/architecture-design/SKILL.md +138 -632
  157. package/.cursor/skills/backend-annotations/SKILL.md +134 -506
  158. package/.cursor/skills/banana-image/SKILL.md +10 -3
  159. package/.cursor/skills/brainstorm/SKILL.md +103 -535
  160. package/.cursor/skills/bug-detective/SKILL.md +147 -1097
  161. package/.cursor/skills/bug-detective/references/error-patterns.md +242 -0
  162. package/.cursor/skills/code-patterns/SKILL.md +116 -426
  163. package/.cursor/skills/code-patterns/references/leniu-code-patterns.md +87 -0
  164. package/.cursor/skills/crud-development/SKILL.md +64 -304
  165. package/.cursor/skills/data-permission/SKILL.md +105 -412
  166. package/.cursor/skills/data-permission/references/custom-data-scope.md +90 -0
  167. package/.cursor/skills/file-oss-management/SKILL.md +106 -714
  168. package/.cursor/skills/file-oss-management/references/entities.md +105 -0
  169. package/.cursor/skills/file-oss-management/references/service-impl.md +104 -0
  170. package/.cursor/skills/git-workflow/SKILL.md +27 -5
  171. package/.cursor/skills/leniu-api-development/SKILL.md +142 -626
  172. package/.cursor/skills/leniu-api-development/references/real-examples.md +273 -0
  173. package/.cursor/skills/leniu-architecture-design/SKILL.md +176 -391
  174. package/.cursor/skills/leniu-backend-annotations/SKILL.md +132 -519
  175. package/.cursor/skills/leniu-brainstorm/SKILL.md +132 -541
  176. package/.cursor/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
  177. package/.cursor/skills/leniu-crud-development/SKILL.md +232 -938
  178. package/.cursor/skills/leniu-crud-development/references/templates.md +597 -0
  179. package/.cursor/skills/leniu-customization-location/SKILL.md +410 -0
  180. package/.cursor/skills/leniu-data-permission/SKILL.md +70 -0
  181. package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
  182. package/.cursor/skills/leniu-java-entity/SKILL.md +76 -590
  183. package/.cursor/skills/leniu-java-entity/references/templates.md +237 -0
  184. package/.cursor/skills/leniu-java-export/SKILL.md +94 -379
  185. package/.cursor/skills/leniu-java-logging/SKILL.md +106 -709
  186. package/.cursor/skills/leniu-java-logging/references/data-mask.md +46 -0
  187. package/.cursor/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
  188. package/.cursor/skills/leniu-java-mybatis/SKILL.md +73 -446
  189. package/.cursor/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
  190. package/.cursor/skills/leniu-report-customization/SKILL.md +111 -325
  191. package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
  192. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +328 -0
  193. package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
  194. package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
  195. package/.cursor/skills/leniu-security-guard/SKILL.md +133 -347
  196. package/.cursor/skills/mysql-debug/SKILL.md +364 -0
  197. package/.cursor/skills/openspec-apply-change/SKILL.md +10 -1
  198. package/.cursor/skills/openspec-archive-change/SKILL.md +9 -1
  199. package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +9 -1
  200. package/.cursor/skills/openspec-continue-change/SKILL.md +9 -1
  201. package/.cursor/skills/openspec-explore/SKILL.md +10 -1
  202. package/.cursor/skills/openspec-ff-change/SKILL.md +9 -1
  203. package/.cursor/skills/openspec-new-change/SKILL.md +9 -1
  204. package/.cursor/skills/openspec-onboard/SKILL.md +15 -130
  205. package/.cursor/skills/openspec-sync-specs/SKILL.md +9 -1
  206. package/.cursor/skills/openspec-verify-change/SKILL.md +9 -1
  207. package/.cursor/skills/performance-doctor/SKILL.md +110 -434
  208. package/.cursor/skills/redis-cache/SKILL.md +89 -595
  209. package/.cursor/skills/redis-cache/references/listeners.md +23 -0
  210. package/.cursor/skills/scheduled-jobs/SKILL.md +88 -407
  211. package/.cursor/skills/security-guard/SKILL.md +137 -532
  212. package/.cursor/skills/security-guard/references/encrypt-config.md +103 -0
  213. package/.cursor/skills/security-guard/references/sensitive-strategies.md +42 -0
  214. package/.cursor/skills/sms-mail/SKILL.md +116 -574
  215. package/.cursor/skills/sms-mail/references/mail-config.md +88 -0
  216. package/.cursor/skills/sms-mail/references/sms-config.md +74 -0
  217. package/.cursor/skills/social-login/SKILL.md +112 -514
  218. package/.cursor/skills/social-login/references/provider-configs.md +118 -0
  219. package/.cursor/skills/tenant-management/SKILL.md +129 -444
  220. package/.cursor/skills/tenant-management/references/tenant-scenarios.md +91 -0
  221. package/.cursor/skills/test-development/SKILL.md +86 -540
  222. package/.cursor/skills/test-development/references/parameterized-examples.md +119 -0
  223. package/.cursor/skills/utils-toolkit/SKILL.md +52 -305
  224. package/.cursor/skills/utils-toolkit/references/redis-utils-api.md +56 -0
  225. package/.cursor/skills/websocket-sse/SKILL.md +105 -550
  226. package/.cursor/skills/workflow-engine/SKILL.md +147 -502
  227. package/AGENTS.md +1 -0
  228. package/package.json +1 -1
@@ -8,81 +8,65 @@ description: |
8
8
  - 实现异步导出(数据量大时)
9
9
  - 实现分页导出(防内存溢出)
10
10
  - 导出API接口设计(@PostMapping("/export"))
11
+ - 实现同步导出(EasyExcelUtil)
11
12
 
12
13
  适用项目:
13
14
  - leniu-tengyun-core:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun-core
14
15
  - leniu-yunshitang:/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun/leniu-yunshitang
15
16
 
16
- 触发词:导出、Excel导出、异步导出、分页导出、@ExcelProperty、exportApi、数据导出
17
+ 触发词:导出、Excel导出、异步导出、分页导出、@ExcelProperty、exportApi、数据导出、EasyExcelUtil、导出列
17
18
  ---
18
19
 
19
- # leniu-tengyun-core 数据导出规范
20
-
21
- ## 项目特征
22
-
23
- | 特征 | 说明 |
24
- |------|------|
25
- | 包名 | `net.xnzn.*` |
26
- | 异常类 | `LeException` |
27
- | 导出工具 | `ExportApi.startExcelExportTaskByPage()` |
28
- | 国际化 | `I18n.getMessage()` |
29
- | 工具类 | Hutool(CollUtil、BeanUtil 等) |
30
- | 请求包装 | `LeRequest<T>` |
20
+ # leniu 数据导出规范
31
21
 
32
22
  ## 核心组件
33
23
 
34
- - **ExportApi**: 导出API接口
35
- - **EasyExcelUtil**: 同步导出工具(报表 Controller 直接使用)
36
- - **I18n**: 国际化工具
37
- - **PageDTO**: 分页参数
38
- - **ReportConstant**: 报表常量(工作表名称等)
24
+ | 组件 | 用途 |
25
+ |------|------|
26
+ | `ExportApi` | 异步分页导出 |
27
+ | `EasyExcelUtil` | 同步导出(直接返回文件流) |
28
+ | `I18n.getMessage()` | 文件名国际化 |
29
+ | `ReportBaseParam` | 基类(含 exportCols、page) |
30
+ | `ReportConstant` | 报表常量(工作表名称等) |
39
31
 
40
32
  ## 两种导出模式
41
33
 
42
34
  | 模式 | 工具 | 适用场景 |
43
35
  |------|------|---------|
44
- | **同步导出** | `EasyExcelUtil.writeExcelByDownLoadIncludeWrite()` | 报表 Controller 直接返回文件流,数据量不大 |
36
+ | **同步导出** | `EasyExcelUtil.writeExcelByDownLoadIncludeWrite()` | 数据量不大,直接返回文件流 |
45
37
  | **异步分页导出** | `exportApi.startExcelExportTaskByPage()` | 大数据量,任务队列方式 |
46
- | **异步分页导出(Feign)** | `orderClients.export().startExcelExportTaskByPage()` | 跨模块导出,通过 Feign 客户端 |
38
+ | **异步(Feign)** | `orderClients.export().startExcelExportTaskByPage()` | 跨模块导出 |
47
39
 
48
- ## 同步导出(EasyExcelUtil)
40
+ ---
41
+
42
+ ## 同步导出模板
49
43
 
50
44
  ```java
51
45
  @ApiOperation(value = "流水汇总-同步导出")
52
46
  @PostMapping("/export")
53
- @SneakyThrows
47
+ @SneakyThrows // 必须加,EasyExcelUtil 抛受检异常
54
48
  public void export(@RequestBody LeRequest<ReportAnalysisTurnoverParam> request,
55
49
  HttpServletResponse response) {
56
50
  ReportAnalysisTurnoverParam param = request.getContent();
57
-
58
- // 1. 查询数据
59
51
  ReportBaseTotalVO<TurnoverVO> result = reportService.pageSummary(param);
60
52
 
61
- // 2. 将列表 + 合计行合并(合计行追加到列表末尾)
62
53
  List<TurnoverVO> records = result.getResultPage().getRecords();
63
- CollUtil.addAll(records, result.getTotalLine()); // 合计行是单个 VO 或 List
54
+ CollUtil.addAll(records, result.getTotalLine()); // 合计行追加到末尾
64
55
 
65
- // 3. 直接写出文件流
66
56
  EasyExcelUtil.writeExcelByDownLoadIncludeWrite(
67
57
  response,
68
- I18n.getMessage("report.turnover.title"), // 文件名(国际化)
69
- TurnoverVO.class, // VO 类型
70
- I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS), // 工作表名
71
- records, // 数据列表(含合计行)
72
- param.getExportCols() // 导出列
58
+ I18n.getMessage("report.turnover.title"),
59
+ TurnoverVO.class,
60
+ I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS),
61
+ records,
62
+ param.getExportCols()
73
63
  );
74
64
  }
75
65
  ```
76
66
 
77
- **注意事项**:
78
- - 方法签名必须加 `@SneakyThrows`(`EasyExcelUtil` 抛出受检异常)
79
- - `HttpServletResponse response` 作为方法参数接收
80
- - 合计行用 `CollUtil.addAll(records, totalLine)` 追加到列表末尾
81
- - 若合计行是单个 VO:`records.add(totalLine)` 即可
82
-
83
- ## 异步分页导出
67
+ ---
84
68
 
85
- ### 基础导出模板
69
+ ## 异步分页导出模板
86
70
 
87
71
  ```java
88
72
  @ApiOperation(value = "xxx导出")
@@ -90,101 +74,62 @@ public void export(@RequestBody LeRequest<ReportAnalysisTurnoverParam> request,
90
74
  public void export(@RequestBody LeRequest<XxxPageParam> request) {
91
75
  XxxPageParam param = request.getContent();
92
76
 
93
- // 获取合计行(可选)
77
+ // 合计行(可选)
94
78
  XxxVO totalLine = xxxService.getSummaryTotal(param);
95
79
 
96
- // 启动异步导出任务
97
- exportApi.startExcelExportTaskByPage(
98
- I18n.getMessage("report.xxx.title"), // 文件名(国际化)
99
- I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS), // 工作表名
100
- XxxVO.class, // 数据类型
101
- param.getExportCols(), // 导出列
102
- param.getPage(), // 分页参数
103
- totalLine, // 合计行(可为null)
104
- () -> xxxService.pageList(param).getResultPage() // 数据提供者
105
- );
106
- }
107
- ```
108
-
109
- ### 实际项目示例
110
-
111
- ```java
112
- @PostMapping("/purchase/order/export")
113
- @ApiOperation(value = "采购-采购订单汇总-导出")
114
- public void exportPurchaseOrder(@RequestBody LeRequest<MonitorPageParam> param) {
115
- MonitorPageParam content = param.getContent();
116
-
117
- // 1. 获取合计行
118
- PurchaseOrderSummaryVO totalLine = monitorSafetyPurchaseService.getPurchaseOrderSummaryTotal(content);
119
-
120
- // 2. 启动导出任务
121
80
  exportApi.startExcelExportTaskByPage(
122
- I18n.getMessage("school.purchase-order-summary"), // 文件名(国际化)
123
- I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS), // 工作表名
124
- PurchaseOrderSummaryVO.class, // VO类型
125
- content.getExportCols(), // 导出列
126
- content.getPage(), // 分页参数
127
- totalLine, // 合计行
128
- () -> monitorSafetyPurchaseService.getPurchaseOrderSummary(content).getResultPage()
81
+ I18n.getMessage("report.xxx.title"), // 文件名(国际化)
82
+ I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS), // 工作表名
83
+ XxxVO.class, // 数据类型
84
+ param.getExportCols(), // 导出列
85
+ param.getPage(), // 分页参数
86
+ totalLine, // 合计行(可为null)
87
+ () -> xxxService.pageList(param).getResultPage() // 数据提供者
129
88
  );
130
89
  }
131
90
  ```
132
91
 
133
- ## 异步分页导出(Feign 客户端模式)
92
+ ---
134
93
 
135
- 跨模块导出时,通过 Feign 客户端调用目标模块的导出接口。订单模块导出是典型示例:
94
+ ## 跨模块导出(Feign 客户端)
136
95
 
137
96
  ```java
138
- /**
139
- * 订单导出 Controller(独立拆分,避免与主 Controller 耦合)
140
- */
141
97
  @Slf4j
142
98
  @Api(tags = "订单导出")
143
99
  @RestController
144
100
  @RequestMapping("/web/order/export")
145
101
  public class OrderInfoExportWebController {
146
102
 
147
- // ✅ 跨模块依赖:通过 Feign 客户端调用,@Lazy 避免循环依赖
148
- @Autowired
149
- @Lazy
103
+ @Autowired @Lazy // @Lazy 防循环依赖
150
104
  private OrderClients orderClients;
151
105
 
152
106
  @ApiOperation(value = "订单导出")
153
107
  @PostMapping("/start")
154
108
  public void export(@RequestBody LeRequest<OrderDetailWebDTO> request) {
155
109
  OrderDetailWebDTO dto = request.getContent();
156
-
157
- // 转换为内部查询参数
158
110
  OrderSearchParam searchParam = dto.convertToOrderSearchParam();
159
111
 
160
- // 通过 Feign 客户端启动异步导出任务
161
112
  orderClients.export().startExcelExportTaskByPage(
162
- I18n.getMessage("order.export.title"), // 文件名
163
- I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS), // 工作表名
164
- OrderDetailVO.class, // VO 类型
165
- dto.getExportCols(), // 导出列
166
- dto.getPage(), // 分页参数
167
- null, // 无合计行
168
- () -> orderClients.order().pageOrder(searchParam) // Lambda 提供数据
113
+ I18n.getMessage("order.export.title"),
114
+ I18n.getMessage(ReportConstant.REPORT_TITLE_DETAILS),
115
+ OrderDetailVO.class,
116
+ dto.getExportCols(),
117
+ dto.getPage(),
118
+ null,
119
+ () -> orderClients.order().pageOrder(searchParam)
169
120
  );
170
121
  }
171
122
  }
172
123
  ```
173
124
 
174
- **独立 Export Controller 的优点**:
175
- - 将导出逻辑与查询逻辑解耦
176
- - 避免单个 Controller 过于庞大
177
- - `@Autowired @Lazy` 防止 Spring 循环依赖
178
-
179
- ## VO类导出注解
125
+ ---
180
126
 
181
- ### 使用@ExcelProperty
127
+ ## VO 类导出注解
182
128
 
183
129
  ```java
184
130
  @Data
185
131
  @ApiModel("xxx导出VO")
186
132
  public class XxxVO {
187
-
188
133
  @ExcelProperty(value = "ID", index = 0)
189
134
  @ApiModelProperty("ID")
190
135
  private Long id;
@@ -193,369 +138,139 @@ public class XxxVO {
193
138
  @ApiModelProperty("名称")
194
139
  private String name;
195
140
 
196
- @ExcelProperty(value = "状态", index = 2)
197
- @ApiModelProperty("状态")
198
- private String statusDesc;
199
-
200
- @ExcelProperty(value = "金额(元)", index = 3)
201
- @ApiModelProperty("金额(元)")
141
+ @ExcelProperty(value = "金额(元)", index = 2)
202
142
  @NumberFormat("#,##0.00")
203
143
  private BigDecimal amount;
204
144
 
205
- @ExcelProperty(value = "创建时间", index = 4)
206
- @ApiModelProperty("创建时间")
145
+ @ExcelProperty(value = "创建时间", index = 3)
207
146
  @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
208
147
  private LocalDateTime createTime;
209
148
  }
210
149
  ```
211
150
 
212
- ## 导出参数类
213
-
214
- ### PageParam包含导出列
215
-
216
- ```java
217
- @Data
218
- @ApiModel("xxx分页查询参数")
219
- public class XxxPageParam extends ReportBaseParam {
220
-
221
- @ApiModelProperty(value = "查询条件")
222
- private String keyword;
223
-
224
- // 其他查询条件...
225
- // 导出列 exportCols 和分页 page 已在 ReportBaseParam 基类中定义
226
- }
227
- ```
228
-
229
- ## Service层导出逻辑
151
+ ---
230
152
 
231
- ### 导出时不分页
153
+ ## Service 层:导出时不分页
232
154
 
233
155
  ```java
234
156
  public PageVO<XxxVO> pageList(XxxPageParam param) {
235
- // 导出时不分页,查询全部数据
236
157
  if (CollUtil.isNotEmpty(param.getExportCols())) {
237
- // 不调用 PageMethod.startPage()
158
+ // 导出时不分页,不调用 PageMethod.startPage()
238
159
  List<XxxEntity> records = mapper.selectList(param);
239
- List<XxxVO> voList = BeanUtil.copyToList(records, XxxVO.class);
240
- return PageVO.of(voList);
160
+ return PageVO.of(BeanUtil.copyToList(records, XxxVO.class));
241
161
  }
242
-
243
- // 正常分页查询
162
+ // 正常分页
244
163
  PageMethod.startPage(param);
245
164
  List<XxxEntity> records = mapper.pageList(param);
246
- List<XxxVO> voList = BeanUtil.copyToList(records, XxxVO.class);
247
- return PageVO.of(voList);
165
+ return PageVO.of(BeanUtil.copyToList(records, XxxVO.class));
248
166
  }
249
167
  ```
250
168
 
251
- ### 带合计行的导出
169
+ ## 带合计行的导出 Service
252
170
 
253
171
  ```java
254
- // ⚠️ 系统默认在商户库执行,业务查询无需 Executors.readInSystem()
255
- // Executors.readInSystem() 仅用于需要访问系统库的场景(如全局配置、商户管理)
256
-
257
172
  public ReportBaseTotalVO<XxxVO> pageWithTotal(XxxPageParam param) {
258
173
  ReportBaseTotalVO<XxxVO> result = new ReportBaseTotalVO<>();
259
174
 
260
- // 1. 导出时不查询合计行(避免不必要的性能开销)
175
+ // 导出时不查合计行(避免性能开销)
261
176
  if (CollUtil.isEmpty(param.getExportCols())) {
262
- XxxVO totalLine = mapper.getSummaryTotal(param);
263
- result.setTotalLine(totalLine);
177
+ result.setTotalLine(mapper.getSummaryTotal(param));
264
178
  }
265
179
 
266
- // 2. 导出时不分页
267
180
  if (CollUtil.isNotEmpty(param.getExportCols())) {
268
- List<XxxVO> list = mapper.getSummaryList(param);
269
- result.setResultPage(PageVO.of(list));
181
+ result.setResultPage(PageVO.of(mapper.getSummaryList(param)));
270
182
  } else {
271
- // 正常分页查询
272
183
  PageMethod.startPage(param);
273
- List<XxxVO> list = mapper.getSummaryList(param);
274
- result.setResultPage(PageVO.of(list));
184
+ result.setResultPage(PageVO.of(mapper.getSummaryList(param)));
275
185
  }
276
-
277
186
  return result;
278
187
  }
279
188
  ```
280
189
 
281
- ## 导出文件名国际化
190
+ ---
282
191
 
283
- ### 使用I18n
192
+ ## 导出文件名国际化
284
193
 
285
- ```java
286
- // resources/message_zh.properties 中定义
194
+ ```properties
195
+ # resources/message_zh.properties
287
196
  report.order.title=订单报表
288
- report.order.sheet=订单明细
289
-
290
- // 在 resources/message_en.properties 中定义
197
+ # resources/message_en.properties
291
198
  report.order.title=Order Report
292
- report.order.sheet=Order Details
293
-
294
- // 在代码中使用
295
- exportApi.startExcelExportTaskByPage(
296
- I18n.getMessage("report.order.title"), // 订单报表
297
- I18n.getMessage("report.order.sheet"), // 订单明细
298
- OrderVO.class,
299
- param.getExportCols(),
300
- param.getPage(),
301
- totalLine,
302
- () -> orderService.pageList(param).getResultPage()
303
- );
304
- ```
305
-
306
- ## 导出列控制
307
-
308
- ### 前端传递导出列
309
-
310
- ```json
311
- {
312
- "page": {
313
- "current": 1,
314
- "size": 10
315
- },
316
- "exportCols": ["id", "name", "status", "amount", "createTime"],
317
- "keyword": "test"
318
- }
319
199
  ```
320
200
 
321
- ### 后端处理导出列
322
-
323
201
  ```java
324
- @PostMapping("/export")
325
- public void export(@RequestBody LeRequest<XxxPageParam> request) {
326
- XxxPageParam param = request.getContent();
327
-
328
- // 校验导出列
329
- if (CollUtil.isEmpty(param.getExportCols())) {
330
- throw new LeException("导出列不能为空");
331
- }
332
-
333
- // 启动导出任务
334
- exportApi.startExcelExportTaskByPage(
335
- I18n.getMessage("report.xxx.title"),
336
- I18n.getMessage("report.xxx.sheet"),
337
- XxxVO.class,
338
- param.getExportCols(), // 传递导出列
339
- param.getPage(),
340
- null,
341
- () -> xxxService.pageList(param).getResultPage()
342
- );
343
- }
202
+ I18n.getMessage("report.order.title") // 根据当前语言自动返回
344
203
  ```
345
204
 
346
- ## 导出数据转换
347
-
348
- ### 状态码转换为描述(使用BeanUtil)
349
-
350
- ```java
351
- public PageVO<XxxVO> pageList(XxxPageParam param) {
352
- PageMethod.startPage(param);
353
- List<XxxEntity> records = mapper.pageList(param);
354
-
355
- // 转换为VO并处理状态描述(leniu 使用 BeanUtil,不用 MapstructUtils)
356
- List<XxxVO> voList = records.stream()
357
- .map(entity -> {
358
- XxxVO vo = new XxxVO();
359
- BeanUtil.copyProperties(entity, vo);
360
-
361
- // 状态码转换为描述
362
- vo.setStatusDesc(StatusEnum.getByCode(entity.getStatus()).getDesc());
205
+ ---
363
206
 
364
- return vo;
365
- })
366
- .collect(Collectors.toList());
207
+ ## 导出列控制
367
208
 
368
- return PageVO.of(voList);
369
- }
209
+ 前端传递:
210
+ ```json
211
+ { "exportCols": ["id", "name", "status", "amount"], "page": { "current": 1, "size": 10 } }
370
212
  ```
371
213
 
372
- ## 常见场景
373
-
374
- ### 场景1:订单导出
375
-
214
+ 后端校验:
376
215
  ```java
377
- @ApiOperation(value = "订单导出")
378
- @PostMapping("/export")
379
- public void export(@RequestBody LeRequest<OrderPageParam> request) {
380
- OrderPageParam param = request.getContent();
381
-
382
- log.info("【导出】订单导出,条件:{}", param);
383
-
384
- // 获取合计行
385
- OrderVO totalLine = orderService.getSummaryTotal(param);
386
-
387
- // 启动导出任务
388
- exportApi.startExcelExportTaskByPage(
389
- I18n.getMessage("report.order.title"),
390
- I18n.getMessage("report.order.sheet"),
391
- OrderVO.class,
392
- param.getExportCols(),
393
- param.getPage(),
394
- totalLine,
395
- () -> orderService.pageList(param).getResultPage()
396
- );
216
+ if (CollUtil.isEmpty(param.getExportCols())) {
217
+ throw new LeException("导出列不能为空");
397
218
  }
398
219
  ```
399
220
 
400
- ### 场景2:报表导出
401
-
402
- ```java
403
- @ApiOperation(value = "销售报表导出")
404
- @PostMapping("/export")
405
- public void export(@RequestBody LeRequest<SalesReportParam> request) {
406
- SalesReportParam param = request.getContent();
407
-
408
- log.info("【导出】销售报表导出,日期范围:{} - {}",
409
- param.getStartDate(), param.getEndDate());
410
-
411
- // 获取合计行
412
- SalesReportVO totalLine = reportService.getSummaryTotal(param);
413
-
414
- // 启动导出任务
415
- exportApi.startExcelExportTaskByPage(
416
- I18n.getMessage("report.sales.title"),
417
- I18n.getMessage("report.sales.sheet"),
418
- SalesReportVO.class,
419
- param.getExportCols(),
420
- param.getPage(),
421
- totalLine,
422
- () -> reportService.getSummary(param).getResultPage()
423
- );
424
- }
425
- ```
221
+ ---
426
222
 
427
- ### 场景3:带权限过滤的导出
223
+ ## 带权限过滤的导出
428
224
 
429
225
  ```java
430
- @ApiOperation(value = "数据导出")
431
226
  @PostMapping("/export")
432
227
  public void export(@RequestBody LeRequest<DataPageParam> request) {
433
228
  DataPageParam param = request.getContent();
434
-
435
- // 获取用户权限
436
229
  MgrUserAuthPO authPO = mgrAuthApi.getUserAuthPO();
437
230
  ReportDataPermissionParam dataPermission =
438
231
  reportDataPermissionService.getDataPermission(authPO);
439
232
 
440
- log.info("【导出】数据导出,用户:{}, 权限范围:{}",
441
- authPO.getUserId(), dataPermission.getCanteenIds());
442
-
443
- // 启动导出任务(权限过滤在Service层处理)
444
233
  exportApi.startExcelExportTaskByPage(
445
234
  I18n.getMessage("report.data.title"),
446
235
  I18n.getMessage("report.data.sheet"),
447
- DataVO.class,
448
- param.getExportCols(),
449
- param.getPage(),
450
- null,
236
+ DataVO.class, param.getExportCols(), param.getPage(), null,
451
237
  () -> dataService.pageList(param).getResultPage()
452
238
  );
453
239
  }
454
240
  ```
455
241
 
456
- ## 导出性能优化
457
-
458
- ### 1. 限制导出数量
459
-
460
- ```java
461
- @PostMapping("/export")
462
- public void export(@RequestBody LeRequest<XxxPageParam> request) {
463
- XxxPageParam param = request.getContent();
464
-
465
- // 查询总数
466
- long total = xxxService.count(param);
467
-
468
- // 限制导出数量
469
- if (total > 100000) {
470
- throw new LeException("导出数据量过大,请缩小查询范围");
471
- }
472
-
473
- // 启动导出任务
474
- exportApi.startExcelExportTaskByPage(
475
- I18n.getMessage("report.xxx.title"),
476
- I18n.getMessage("report.xxx.sheet"),
477
- XxxVO.class,
478
- param.getExportCols(),
479
- param.getPage(),
480
- null,
481
- () -> xxxService.pageList(param).getResultPage()
482
- );
483
- }
484
- ```
242
+ ---
485
243
 
486
- ### 2. 导出数据脱敏
244
+ ## 导出数据脱敏
487
245
 
488
246
  ```java
489
- public PageVO<UserVO> pageList(UserPageParam param) {
490
- PageMethod.startPage(param);
491
- List<User> records = mapper.pageList(param);
492
-
493
- List<UserVO> voList = records.stream()
494
- .map(user -> {
495
- UserVO vo = new UserVO();
496
- BeanUtil.copyProperties(user, vo);
497
-
498
- // 导出时脱敏
499
- if (CollUtil.isNotEmpty(param.getExportCols())) {
500
- vo.setMobile(maskMobile(user.getMobile()));
501
- vo.setIdCard(maskIdCard(user.getIdCard()));
502
- }
503
-
504
- return vo;
505
- })
506
- .collect(Collectors.toList());
507
-
508
- return PageVO.of(voList);
247
+ // VO 转换时处理
248
+ if (CollUtil.isNotEmpty(param.getExportCols())) {
249
+ vo.setMobile(maskMobile(user.getMobile()));
250
+ vo.setIdCard(maskIdCard(user.getIdCard()));
509
251
  }
510
252
  ```
511
253
 
512
- ## 最佳实践
254
+ ---
513
255
 
514
- ### 1. 导出日志
256
+ ## 导出数量限制
515
257
 
516
258
  ```java
517
- @PostMapping("/export")
518
- public void export(@RequestBody LeRequest<XxxPageParam> request) {
519
- XxxPageParam param = request.getContent();
520
-
521
- log.info("【导出】开始导出,文件名:{}, 条件:{}",
522
- I18n.getMessage("report.xxx.title"), param);
523
-
524
- exportApi.startExcelExportTaskByPage(
525
- I18n.getMessage("report.xxx.title"),
526
- I18n.getMessage("report.xxx.sheet"),
527
- XxxVO.class,
528
- param.getExportCols(),
529
- param.getPage(),
530
- null,
531
- () -> xxxService.pageList(param).getResultPage()
532
- );
533
-
534
- log.info("【导出】导出任务已启动");
259
+ long total = xxxService.count(param);
260
+ if (total > 100000) {
261
+ throw new LeException("导出数据量过大,请缩小查询范围");
535
262
  }
536
263
  ```
537
264
 
538
- ### 2. 导出权限校验
539
-
540
- ```java
541
- @PostMapping("/export")
542
- public void export(@RequestBody LeRequest<XxxPageParam> request) {
543
- // 校验导出权限
544
- if (!hasExportPermission()) {
545
- throw new LeException("无导出权限");
546
- }
547
-
548
- // 启动导出任务
549
- exportApi.startExcelExportTaskByPage(...);
550
- }
551
- ```
265
+ ---
552
266
 
553
267
  ## 常见错误
554
268
 
555
- | 错误写法 | 正确写法 | 说明 |
556
- |---------|---------|------|
557
- | `throw new ServiceException("msg")` | `throw new LeException("msg")` | leniu 项目异常类 |
558
- | `MapstructUtils.convert(a, B.class)` | `BeanUtil.copyProperties(a, b)` | leniu 使用 Hutool |
559
- | `@RequestParam` 接收请求 | `@RequestBody LeRequest<T>` | leniu 接口使用 LeRequest 包装 |
560
- | `import javax.validation.*` | `import jakarta.validation.*` | JDK 21 + Spring Boot 3.x |
561
- | 不写导出日志 | log.info 记录导出参数 | 便于排查导出问题 |
269
+ | 错误写法 | 正确写法 |
270
+ |---------|---------|
271
+ | `throw new ServiceException("msg")` | `throw new LeException("msg")` |
272
+ | `MapstructUtils.convert(a, B.class)` | `BeanUtil.copyProperties(a, b)` |
273
+ | `@RequestParam` 接收请求 | `@RequestBody LeRequest<T>` |
274
+ | `import javax.validation.*` | `import jakarta.validation.*` |
275
+ | 不写导出日志 | `log.info("【导出】开始导出...")` |
276
+ | 同步导出不加 `@SneakyThrows` | 必须加(受检异常) |