ai-engineering-init 1.7.0 → 1.10.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 (139) hide show
  1. package/.claude/agents/bug-analyzer.md +103 -0
  2. package/.claude/agents/code-reviewer.md +115 -5
  3. package/.claude/agents/image-reader.md +154 -0
  4. package/.claude/agents/loki-runner.md +80 -0
  5. package/.claude/agents/mysql-runner.md +81 -0
  6. package/.claude/agents/requirements-analyzer.md +162 -0
  7. package/.claude/agents/task-fetcher.md +75 -0
  8. package/.claude/commands/dev.md +29 -0
  9. package/.claude/commands/next.md +31 -1
  10. package/.claude/commands/progress.md +23 -1
  11. package/.claude/hooks/skill-forced-eval.js +46 -62
  12. package/.claude/settings.json +10 -1
  13. package/.claude/skills/api-development/SKILL.md +179 -130
  14. package/.claude/skills/architecture-design/SKILL.md +102 -212
  15. package/.claude/skills/backend-annotations/SKILL.md +166 -220
  16. package/.claude/skills/bug-detective/SKILL.md +225 -186
  17. package/.claude/skills/code-patterns/SKILL.md +127 -244
  18. package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
  19. package/.claude/skills/crud-development/SKILL.md +226 -307
  20. package/.claude/skills/data-permission/SKILL.md +131 -202
  21. package/.claude/skills/database-ops/SKILL.md +158 -355
  22. package/.claude/skills/error-handler/SKILL.md +224 -285
  23. package/.claude/skills/file-oss-management/SKILL.md +174 -169
  24. package/.claude/skills/git-workflow/SKILL.md +123 -341
  25. package/.claude/skills/json-serialization/SKILL.md +121 -137
  26. package/.claude/skills/performance-doctor/SKILL.md +83 -89
  27. package/.claude/skills/redis-cache/SKILL.md +134 -185
  28. package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
  29. package/.claude/skills/security-guard/SKILL.md +168 -276
  30. package/.claude/skills/sms-mail/SKILL.md +266 -228
  31. package/.claude/skills/social-login/SKILL.md +257 -195
  32. package/.claude/skills/tenant-management/SKILL.md +172 -188
  33. package/.claude/skills/utils-toolkit/SKILL.md +214 -222
  34. package/.claude/skills/websocket-sse/SKILL.md +251 -172
  35. package/.claude/skills/workflow-engine/SKILL.md +178 -250
  36. package/.codex/skills/api-development/SKILL.md +179 -130
  37. package/.codex/skills/architecture-design/SKILL.md +102 -212
  38. package/.codex/skills/backend-annotations/SKILL.md +166 -220
  39. package/.codex/skills/bug-detective/SKILL.md +225 -186
  40. package/.codex/skills/code-patterns/SKILL.md +127 -244
  41. package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
  42. package/.codex/skills/crud-development/SKILL.md +226 -307
  43. package/.codex/skills/data-permission/SKILL.md +131 -202
  44. package/.codex/skills/database-ops/SKILL.md +158 -355
  45. package/.codex/skills/dev/SKILL.md +476 -131
  46. package/.codex/skills/error-handler/SKILL.md +224 -285
  47. package/.codex/skills/file-oss-management/SKILL.md +174 -169
  48. package/.codex/skills/git-workflow/SKILL.md +123 -341
  49. package/.codex/skills/json-serialization/SKILL.md +121 -137
  50. package/.codex/skills/next/SKILL.md +186 -42
  51. package/.codex/skills/performance-doctor/SKILL.md +83 -89
  52. package/.codex/skills/progress/SKILL.md +147 -76
  53. package/.codex/skills/redis-cache/SKILL.md +134 -185
  54. package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
  55. package/.codex/skills/security-guard/SKILL.md +168 -276
  56. package/.codex/skills/sms-mail/SKILL.md +266 -228
  57. package/.codex/skills/social-login/SKILL.md +257 -195
  58. package/.codex/skills/tenant-management/SKILL.md +172 -188
  59. package/.codex/skills/utils-toolkit/SKILL.md +214 -222
  60. package/.codex/skills/websocket-sse/SKILL.md +251 -172
  61. package/.codex/skills/workflow-engine/SKILL.md +178 -250
  62. package/.cursor/agents/bug-analyzer.md +102 -0
  63. package/.cursor/agents/code-reviewer.md +80 -97
  64. package/.cursor/agents/image-reader.md +154 -0
  65. package/.cursor/agents/loki-runner.md +80 -0
  66. package/.cursor/agents/mysql-runner.md +81 -0
  67. package/.cursor/agents/project-manager.md +1 -1
  68. package/.cursor/agents/requirements-analyzer.md +141 -0
  69. package/.cursor/agents/task-fetcher.md +75 -0
  70. package/.cursor/hooks/cursor-skill-eval.js +66 -6
  71. package/.cursor/skills/api-development/SKILL.md +179 -130
  72. package/.cursor/skills/architecture-design/SKILL.md +102 -212
  73. package/.cursor/skills/backend-annotations/SKILL.md +166 -220
  74. package/.cursor/skills/bug-detective/SKILL.md +225 -186
  75. package/.cursor/skills/code-patterns/SKILL.md +127 -244
  76. package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
  77. package/.cursor/skills/crud-development/SKILL.md +226 -307
  78. package/.cursor/skills/data-permission/SKILL.md +131 -202
  79. package/.cursor/skills/database-ops/SKILL.md +158 -355
  80. package/.cursor/skills/error-handler/SKILL.md +224 -285
  81. package/.cursor/skills/file-oss-management/SKILL.md +174 -169
  82. package/.cursor/skills/git-workflow/SKILL.md +123 -341
  83. package/.cursor/skills/json-serialization/SKILL.md +121 -137
  84. package/.cursor/skills/performance-doctor/SKILL.md +83 -89
  85. package/.cursor/skills/redis-cache/SKILL.md +134 -185
  86. package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
  87. package/.cursor/skills/security-guard/SKILL.md +168 -276
  88. package/.cursor/skills/sms-mail/SKILL.md +266 -228
  89. package/.cursor/skills/social-login/SKILL.md +257 -195
  90. package/.cursor/skills/tenant-management/SKILL.md +172 -188
  91. package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
  92. package/.cursor/skills/websocket-sse/SKILL.md +251 -172
  93. package/.cursor/skills/workflow-engine/SKILL.md +178 -250
  94. package/AGENTS.md +117 -540
  95. package/CLAUDE.md +105 -117
  96. package/README.md +37 -6
  97. package/bin/index.js +5 -1
  98. package/package.json +1 -1
  99. package/src/skills/api-development/SKILL.md +179 -130
  100. package/src/skills/architecture-design/SKILL.md +102 -212
  101. package/src/skills/backend-annotations/SKILL.md +166 -220
  102. package/src/skills/bug-detective/SKILL.md +225 -186
  103. package/src/skills/code-patterns/SKILL.md +127 -244
  104. package/src/skills/collaborating-with-codex/SKILL.md +96 -113
  105. package/src/skills/crud-development/SKILL.md +226 -307
  106. package/src/skills/data-permission/SKILL.md +131 -202
  107. package/src/skills/database-ops/SKILL.md +158 -355
  108. package/src/skills/error-handler/SKILL.md +224 -285
  109. package/src/skills/file-oss-management/SKILL.md +174 -169
  110. package/src/skills/git-workflow/SKILL.md +123 -341
  111. package/src/skills/json-serialization/SKILL.md +121 -137
  112. package/src/skills/performance-doctor/SKILL.md +83 -89
  113. package/src/skills/redis-cache/SKILL.md +134 -185
  114. package/src/skills/scheduled-jobs/SKILL.md +187 -224
  115. package/src/skills/security-guard/SKILL.md +168 -276
  116. package/src/skills/sms-mail/SKILL.md +266 -228
  117. package/src/skills/social-login/SKILL.md +257 -195
  118. package/src/skills/tenant-management/SKILL.md +172 -188
  119. package/src/skills/utils-toolkit/SKILL.md +214 -222
  120. package/src/skills/websocket-sse/SKILL.md +251 -172
  121. package/src/skills/workflow-engine/SKILL.md +178 -250
  122. package/.claude/skills/skill-creator/LICENSE.txt +0 -202
  123. package/.claude/skills/skill-creator/SKILL.md +0 -479
  124. package/.claude/skills/skill-creator/agents/analyzer.md +0 -274
  125. package/.claude/skills/skill-creator/agents/comparator.md +0 -202
  126. package/.claude/skills/skill-creator/agents/grader.md +0 -223
  127. package/.claude/skills/skill-creator/assets/eval_review.html +0 -146
  128. package/.claude/skills/skill-creator/eval-viewer/generate_review.py +0 -471
  129. package/.claude/skills/skill-creator/eval-viewer/viewer.html +0 -1325
  130. package/.claude/skills/skill-creator/references/schemas.md +0 -430
  131. package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
  132. package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
  133. package/.claude/skills/skill-creator/scripts/generate_report.py +0 -326
  134. package/.claude/skills/skill-creator/scripts/improve_description.py +0 -248
  135. package/.claude/skills/skill-creator/scripts/package_skill.py +0 -136
  136. package/.claude/skills/skill-creator/scripts/quick_validate.py +0 -103
  137. package/.claude/skills/skill-creator/scripts/run_eval.py +0 -310
  138. package/.claude/skills/skill-creator/scripts/run_loop.py +0 -332
  139. package/.claude/skills/skill-creator/scripts/utils.py +0 -47
@@ -1,409 +1,328 @@
1
1
  ---
2
2
  name: crud-development
3
3
  description: |
4
- 后端 CRUD 开发规范。基于 RuoYi-Vue-Plus 三层架构(Controller -> Service -> Mapper),无独立 DAO 层。
4
+ 通用 CRUD 开发指南。基于 Spring Boot 三层架构(Controller -> Service -> Mapper),
5
+ 提供 Entity、DTO、VO、Service、Controller 的标准模板。
6
+ 触发场景:新增业务模块、增删改查开发、快速生成 CRUD 代码。
7
+ 触发词:CRUD、增删改查、新增模块、生成代码。
8
+ 注意:如果项目有专属技能(如 `leniu-crud`),优先使用专属版本。
9
+ ---
5
10
 
6
- 触发场景:
7
- - 新建业务模块的 CRUD 功能
8
- - 创建 Entity、BO、VO、Service、Mapper、Controller
9
- - 分页查询、新增、修改、删除、导出
10
- - 查询条件构建(buildQueryWrapper)
11
+ # CRUD 开发指南
11
12
 
12
- 触发词:CRUD、增删改查、新建模块、Entity、BO、VO、Service、Mapper、Controller、分页查询、buildQueryWrapper、@AutoMapper、BaseMapperPlus、TenantEntity
13
+ > 通用模板。如果项目有专属技能(如 `leniu-crud`),优先使用。
13
14
 
14
- 注意:
15
- - 三层架构,Service 直接注入 Mapper,无 DAO 层。
16
- - 查询条件在 Service 层构建(buildQueryWrapper)。
17
- - 使用 @AutoMapper(单数)而非 @AutoMappers。
18
- - API 路径使用标准 RESTful 格式(/list、/{id})。
19
- ---
15
+ ## 核心规范
20
16
 
21
- # CRUD 开发规范(RuoYi-Vue-Plus 三层架构)
17
+ ### 三层架构
22
18
 
23
- ## 核心架构特征
19
+ | 层 | 职责 | 命名示例 |
20
+ |----|------|---------|
21
+ | Controller | 接收请求、参数校验、路由分发 | `OrderController` |
22
+ | Service | 业务逻辑、事务管理 | `OrderService` / `OrderServiceImpl` |
23
+ | Mapper | 数据访问(ORM 映射) | `OrderMapper` |
24
24
 
25
- | 项 | 规范 |
26
- |----|------|
27
- | **包名前缀** | `org.dromara.*` |
28
- | **架构** | Controller -> Service -> Mapper(无 DAO 层) |
29
- | **查询构建** | Service 层 `buildQueryWrapper()` |
30
- | **Mapper** | 继承 `BaseMapperPlus<Entity, VO>` |
31
- | **对象转换** | `MapstructUtils.convert()` |
32
- | **Entity 基类** | `TenantEntity`(多租户) |
33
- | **BO 映射** | `@AutoMapper`(单数) |
34
- | **API 路径** | RESTful:`/list`、`/{id}` |
25
+ ### 标准包结构
35
26
 
36
- ---
27
+ ```
28
+ [你的包名]/
29
+ ├── controller/ # 控制器
30
+ ├── service/
31
+ │ └── impl/ # 服务实现
32
+ ├── mapper/ # 数据访问层
33
+ ├── entity/ # 实体类
34
+ ├── dto/ # 请求参数对象
35
+ ├── vo/ # 响应视图对象
36
+ ├── enums/ # 枚举常量
37
+ └── config/ # 模块配置
38
+ ```
39
+
40
+ ## 代码示例
37
41
 
38
- ## 1. Entity
42
+ ### 1. Entity(实体类)
39
43
 
40
44
  ```java
41
- package org.dromara.demo.domain;
45
+ package [你的包名].entity;
42
46
 
43
- import org.dromara.common.tenant.core.TenantEntity;
44
47
  import com.baomidou.mybatisplus.annotation.*;
45
48
  import lombok.Data;
46
- import lombok.EqualsAndHashCode;
47
- import java.io.Serial;
49
+ import java.time.LocalDateTime;
48
50
 
49
51
  @Data
50
- @EqualsAndHashCode(callSuper = true)
51
- @TableName("test_xxx")
52
- public class Xxx extends TenantEntity {
52
+ @TableName("t_order")
53
+ public class Order {
53
54
 
54
- @Serial
55
- private static final long serialVersionUID = 1L;
56
-
57
- @TableId(value = "id")
55
+ @TableId(type = IdType.ASSIGN_ID)
58
56
  private Long id;
59
57
 
60
- private String xxxName;
58
+ private String orderNo;
59
+
60
+ private Integer status;
61
+
62
+ private Long amount;
63
+
64
+ @TableField(fill = FieldFill.INSERT)
65
+ private String createBy;
66
+
67
+ @TableField(fill = FieldFill.INSERT)
68
+ private LocalDateTime createTime;
61
69
 
62
- private String status;
70
+ @TableField(fill = FieldFill.INSERT_UPDATE)
71
+ private String updateBy;
63
72
 
64
- @TableLogic
65
- private Long delFlag;
73
+ @TableField(fill = FieldFill.INSERT_UPDATE)
74
+ private LocalDateTime updateTime;
75
+
76
+ @TableLogic(value = "0", delval = "1")
77
+ private Integer deleted;
66
78
  }
67
79
  ```
68
80
 
69
- ## 2. BO
81
+ ### 2. DTO(请求参数)
70
82
 
71
83
  ```java
72
- package org.dromara.demo.domain.bo;
84
+ package [你的包名].dto;
73
85
 
74
- import io.github.linpeilie.annotations.AutoMapper;
75
- import org.dromara.demo.domain.Xxx;
76
- import org.dromara.common.core.validate.AddGroup;
77
- import org.dromara.common.core.validate.EditGroup;
78
- import org.dromara.common.mybatis.core.domain.BaseEntity;
79
- import lombok.Data;
80
- import lombok.EqualsAndHashCode;
81
86
  import jakarta.validation.constraints.*;
87
+ import lombok.Data;
82
88
 
83
89
  @Data
84
- @EqualsAndHashCode(callSuper = true)
85
- @AutoMapper(target = Xxx.class, reverseConvertGenerate = false)
86
- public class XxxBo extends BaseEntity {
90
+ public class OrderCreateDTO {
87
91
 
88
- @NotNull(message = "主键不能为空", groups = {EditGroup.class})
89
- private Long id;
92
+ @NotBlank(message = "订单号不能为空")
93
+ private String orderNo;
90
94
 
91
- @NotBlank(message = "名称不能为空", groups = {AddGroup.class, EditGroup.class})
92
- private String xxxName;
95
+ @NotNull(message = "金额不能为空")
96
+ @Min(value = 1, message = "金额必须大于0")
97
+ private Long amount;
98
+ }
99
+ ```
93
100
 
94
- private String status;
101
+ ```java
102
+ package [你的包名].dto;
103
+
104
+ import lombok.Data;
105
+
106
+ @Data
107
+ public class OrderQueryDTO {
108
+
109
+ private String orderNo;
110
+
111
+ private Integer status;
112
+
113
+ private Integer pageNum = 1;
114
+
115
+ private Integer pageSize = 10;
95
116
  }
96
117
  ```
97
118
 
98
- ## 3. VO
119
+ ### 3. VO(响应对象)
99
120
 
100
121
  ```java
101
- package org.dromara.demo.domain.vo;
122
+ package [你的包名].vo;
102
123
 
103
- import io.github.linpeilie.annotations.AutoMapper;
104
- import org.dromara.demo.domain.Xxx;
105
- import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
106
- import cn.idev.excel.annotation.ExcelProperty;
107
124
  import lombok.Data;
108
- import java.io.Serial;
109
- import java.io.Serializable;
110
- import java.util.Date;
125
+ import java.time.LocalDateTime;
111
126
 
112
127
  @Data
113
- @ExcelIgnoreUnannotated
114
- @AutoMapper(target = Xxx.class)
115
- public class XxxVo implements Serializable {
116
-
117
- @Serial
118
- private static final long serialVersionUID = 1L;
128
+ public class OrderVO {
119
129
 
120
- @ExcelProperty(value = "主键")
121
130
  private Long id;
122
131
 
123
- @ExcelProperty(value = "名称")
124
- private String xxxName;
132
+ private String orderNo;
133
+
134
+ private Integer status;
125
135
 
126
- @ExcelProperty(value = "状态")
127
- private String status;
136
+ private Long amount;
128
137
 
129
- @ExcelProperty(value = "创建时间")
130
- private Date createTime;
138
+ private LocalDateTime createTime;
131
139
  }
132
140
  ```
133
141
 
134
- ## 4. Service 接口
142
+ ### 4. Mapper
135
143
 
136
144
  ```java
137
- package org.dromara.demo.service;
138
-
139
- import org.dromara.demo.domain.bo.XxxBo;
140
- import org.dromara.demo.domain.vo.XxxVo;
141
- import org.dromara.common.mybatis.core.page.PageQuery;
142
- import org.dromara.common.mybatis.core.page.TableDataInfo;
143
- import java.util.Collection;
144
- import java.util.List;
145
-
146
- public interface IXxxService {
147
- XxxVo queryById(Long id);
148
- List<XxxVo> queryList(XxxBo bo);
149
- TableDataInfo<XxxVo> queryPageList(XxxBo bo, PageQuery pageQuery);
150
- Boolean insertByBo(XxxBo bo);
151
- Boolean updateByBo(XxxBo bo);
152
- Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
145
+ package [你的包名].mapper;
146
+
147
+ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
148
+ import [你的包名].entity.Order;
149
+ import org.apache.ibatis.annotations.Mapper;
150
+
151
+ @Mapper
152
+ public interface OrderMapper extends BaseMapper<Order> {
153
153
  }
154
154
  ```
155
155
 
156
- ## 5. Service 实现(核心)
156
+ ### 5. Service
157
157
 
158
158
  ```java
159
- package org.dromara.demo.service.impl;
159
+ package [你的包名].service;
160
+
161
+ import com.baomidou.mybatisplus.extension.service.IService;
162
+ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
163
+ import [你的包名].entity.Order;
164
+ import [你的包名].dto.OrderCreateDTO;
165
+ import [你的包名].dto.OrderQueryDTO;
166
+ import [你的包名].vo.OrderVO;
167
+
168
+ public interface IOrderService extends IService<Order> {
169
+
170
+ Long createOrder(OrderCreateDTO dto);
171
+
172
+ void updateOrder(Long id, OrderCreateDTO dto);
173
+
174
+ OrderVO getOrderDetail(Long id);
175
+
176
+ Page<OrderVO> pageQuery(OrderQueryDTO query);
177
+ }
178
+ ```
179
+
180
+ ```java
181
+ package [你的包名].service.impl;
160
182
 
161
183
  import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
162
- import com.baomidou.mybatisplus.core.toolkit.Wrappers;
163
184
  import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
185
+ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
186
+ import [你的包名].dto.OrderCreateDTO;
187
+ import [你的包名].dto.OrderQueryDTO;
188
+ import [你的包名].entity.Order;
189
+ import [你的包名].mapper.OrderMapper;
190
+ import [你的包名].service.IOrderService;
191
+ import [你的包名].vo.OrderVO;
164
192
  import lombok.RequiredArgsConstructor;
165
193
  import org.springframework.stereotype.Service;
166
- import org.dromara.common.core.exception.ServiceException;
167
- import org.dromara.common.core.utils.MapstructUtils;
168
- import org.dromara.common.core.utils.StringUtils;
169
- import org.dromara.common.mybatis.core.page.PageQuery;
170
- import org.dromara.common.mybatis.core.page.TableDataInfo;
171
- import org.dromara.demo.domain.Xxx;
172
- import org.dromara.demo.domain.bo.XxxBo;
173
- import org.dromara.demo.domain.vo.XxxVo;
174
- import org.dromara.demo.mapper.XxxMapper;
175
- import org.dromara.demo.service.IXxxService;
176
- import java.util.Collection;
177
- import java.util.List;
178
- import java.util.Map;
194
+ import org.springframework.transaction.annotation.Transactional;
195
+ import org.springframework.util.StringUtils;
179
196
 
180
197
  @Service
181
198
  @RequiredArgsConstructor
182
- public class XxxServiceImpl implements IXxxService {
183
-
184
- private final XxxMapper baseMapper; // 直接注入 Mapper(无 DAO 层)
199
+ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
185
200
 
186
201
  @Override
187
- public XxxVo queryById(Long id) {
188
- return baseMapper.selectVoById(id);
202
+ @Transactional(rollbackFor = Exception.class)
203
+ public Long createOrder(OrderCreateDTO dto) {
204
+ Order order = new Order();
205
+ // 使用 [你的对象转换工具] 或手动赋值
206
+ order.setOrderNo(dto.getOrderNo());
207
+ order.setAmount(dto.getAmount());
208
+ order.setStatus(0);
209
+ this.save(order);
210
+ return order.getId();
189
211
  }
190
212
 
191
213
  @Override
192
- public List<XxxVo> queryList(XxxBo bo) {
193
- return baseMapper.selectVoList(buildQueryWrapper(bo));
194
- }
195
-
196
- @Override
197
- public TableDataInfo<XxxVo> queryPageList(XxxBo bo, PageQuery pageQuery) {
198
- LambdaQueryWrapper<Xxx> lqw = buildQueryWrapper(bo);
199
- Page<XxxVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
200
- return TableDataInfo.build(result);
201
- }
202
-
203
- @Override
204
- public Boolean insertByBo(XxxBo bo) {
205
- Xxx add = MapstructUtils.convert(bo, Xxx.class);
206
- validEntityBeforeSave(add);
207
- return baseMapper.insert(add) > 0;
208
- }
209
-
210
- @Override
211
- public Boolean updateByBo(XxxBo bo) {
212
- Xxx update = MapstructUtils.convert(bo, Xxx.class);
213
- validEntityBeforeSave(update);
214
- return baseMapper.updateById(update) > 0;
214
+ @Transactional(rollbackFor = Exception.class)
215
+ public void updateOrder(Long id, OrderCreateDTO dto) {
216
+ Order order = this.getById(id);
217
+ if (order == null) {
218
+ throw new [你的业务异常类]("订单不存在");
219
+ }
220
+ order.setOrderNo(dto.getOrderNo());
221
+ order.setAmount(dto.getAmount());
222
+ this.updateById(order);
215
223
  }
216
224
 
217
225
  @Override
218
- public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
219
- if (isValid) {
220
- List<Xxx> list = baseMapper.selectByIds(ids);
221
- if (list.size() != ids.size()) {
222
- throw new ServiceException("您没有删除权限!");
223
- }
226
+ public OrderVO getOrderDetail(Long id) {
227
+ Order order = this.getById(id);
228
+ if (order == null) {
229
+ throw new [你的业务异常类]("订单不存在");
224
230
  }
225
- return baseMapper.deleteByIds(ids) > 0;
226
- }
227
-
228
- private LambdaQueryWrapper<Xxx> buildQueryWrapper(XxxBo bo) {
229
- Map<String, Object> params = bo.getParams();
230
- LambdaQueryWrapper<Xxx> lqw = Wrappers.lambdaQuery();
231
- lqw.eq(bo.getId() != null, Xxx::getId, bo.getId());
232
- lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Xxx::getStatus, bo.getStatus());
233
- lqw.like(StringUtils.isNotBlank(bo.getXxxName()), Xxx::getXxxName, bo.getXxxName());
234
- lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
235
- Xxx::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
236
- lqw.orderByAsc(Xxx::getId);
237
- return lqw;
231
+ OrderVO vo = new OrderVO();
232
+ // 使用 [你的对象转换工具] 或手动赋值
233
+ vo.setId(order.getId());
234
+ vo.setOrderNo(order.getOrderNo());
235
+ vo.setStatus(order.getStatus());
236
+ vo.setAmount(order.getAmount());
237
+ vo.setCreateTime(order.getCreateTime());
238
+ return vo;
238
239
  }
239
240
 
240
- private void validEntityBeforeSave(Xxx entity) {
241
- // TODO 做一些数据校验,如唯一约束
241
+ @Override
242
+ public Page<OrderVO> pageQuery(OrderQueryDTO query) {
243
+ Page<Order> page = new Page<>(query.getPageNum(), query.getPageSize());
244
+ LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>()
245
+ .like(StringUtils.hasText(query.getOrderNo()), Order::getOrderNo, query.getOrderNo())
246
+ .eq(query.getStatus() != null, Order::getStatus, query.getStatus())
247
+ .orderByDesc(Order::getCreateTime);
248
+ Page<Order> result = this.page(page, wrapper);
249
+
250
+ // 转换为 VO
251
+ Page<OrderVO> voPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
252
+ voPage.setRecords(result.getRecords().stream().map(order -> {
253
+ OrderVO vo = new OrderVO();
254
+ vo.setId(order.getId());
255
+ vo.setOrderNo(order.getOrderNo());
256
+ vo.setStatus(order.getStatus());
257
+ vo.setAmount(order.getAmount());
258
+ vo.setCreateTime(order.getCreateTime());
259
+ return vo;
260
+ }).toList());
261
+ return voPage;
242
262
  }
243
263
  }
244
264
  ```
245
265
 
246
- ## 6. Mapper
247
-
248
- ```java
249
- package org.dromara.demo.mapper;
250
-
251
- import org.dromara.demo.domain.Xxx;
252
- import org.dromara.demo.domain.vo.XxxVo;
253
- import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
254
-
255
- public interface XxxMapper extends BaseMapperPlus<Xxx, XxxVo> {
256
- // 已提供 selectVoById、selectVoPage、selectVoList 等方法
257
- }
258
- ```
259
-
260
- ## 7. Controller
266
+ ### 6. Controller
261
267
 
262
268
  ```java
263
- package org.dromara.demo.controller;
269
+ package [你的包名].controller;
264
270
 
265
- import java.util.Arrays;
266
- import java.util.List;
271
+ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
272
+ import [你的包名].dto.OrderCreateDTO;
273
+ import [你的包名].dto.OrderQueryDTO;
274
+ import [你的包名].service.IOrderService;
275
+ import [你的包名].vo.OrderVO;
276
+ import jakarta.validation.Valid;
267
277
  import lombok.RequiredArgsConstructor;
268
- import jakarta.servlet.http.HttpServletResponse;
269
- import jakarta.validation.constraints.*;
270
- import cn.dev33.satoken.annotation.SaCheckPermission;
278
+ import org.springframework.http.ResponseEntity;
271
279
  import org.springframework.web.bind.annotation.*;
272
- import org.springframework.validation.annotation.Validated;
273
- import org.dromara.common.idempotent.annotation.RepeatSubmit;
274
- import org.dromara.common.log.annotation.Log;
275
- import org.dromara.common.log.enums.BusinessType;
276
- import org.dromara.common.mybatis.core.page.PageQuery;
277
- import org.dromara.common.mybatis.core.page.TableDataInfo;
278
- import org.dromara.common.web.core.BaseController;
279
- import org.dromara.common.core.domain.R;
280
- import org.dromara.common.core.validate.AddGroup;
281
- import org.dromara.common.core.validate.EditGroup;
282
- import org.dromara.common.excel.utils.ExcelUtil;
283
- import org.dromara.demo.domain.vo.XxxVo;
284
- import org.dromara.demo.domain.bo.XxxBo;
285
- import org.dromara.demo.service.IXxxService;
286
-
287
- @Validated
288
- @RequiredArgsConstructor
289
- @RestController
290
- @RequestMapping("/demo/xxx")
291
- public class XxxController extends BaseController {
292
280
 
293
- private final IXxxService xxxService;
281
+ @RestController
282
+ @RequestMapping("/api/v1/orders")
283
+ @RequiredArgsConstructor
284
+ public class OrderController {
294
285
 
295
- @SaCheckPermission("demo:xxx:list")
296
- @GetMapping("/list")
297
- public TableDataInfo<XxxVo> list(XxxBo bo, PageQuery pageQuery) {
298
- return xxxService.queryPageList(bo, pageQuery);
299
- }
286
+ private final IOrderService orderService;
300
287
 
301
- @SaCheckPermission("demo:xxx:query")
302
- @GetMapping("/{id}")
303
- public R<XxxVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
304
- return R.ok(xxxService.queryById(id));
288
+ @PostMapping
289
+ public ResponseEntity<Long> create(@Valid @RequestBody OrderCreateDTO dto) {
290
+ return ResponseEntity.ok(orderService.createOrder(dto));
305
291
  }
306
292
 
307
- @SaCheckPermission("demo:xxx:add")
308
- @Log(title = "XXX管理", businessType = BusinessType.INSERT)
309
- @RepeatSubmit()
310
- @PostMapping()
311
- public R<Void> add(@Validated(AddGroup.class) @RequestBody XxxBo bo) {
312
- return toAjax(xxxService.insertByBo(bo));
293
+ @PutMapping("/{id}")
294
+ public ResponseEntity<Void> update(@PathVariable Long id,
295
+ @Valid @RequestBody OrderCreateDTO dto) {
296
+ orderService.updateOrder(id, dto);
297
+ return ResponseEntity.ok().build();
313
298
  }
314
299
 
315
- @SaCheckPermission("demo:xxx:edit")
316
- @Log(title = "XXX管理", businessType = BusinessType.UPDATE)
317
- @RepeatSubmit()
318
- @PutMapping()
319
- public R<Void> edit(@Validated(EditGroup.class) @RequestBody XxxBo bo) {
320
- return toAjax(xxxService.updateByBo(bo));
300
+ @GetMapping("/{id}")
301
+ public ResponseEntity<OrderVO> detail(@PathVariable Long id) {
302
+ return ResponseEntity.ok(orderService.getOrderDetail(id));
321
303
  }
322
304
 
323
- @SaCheckPermission("demo:xxx:remove")
324
- @Log(title = "XXX管理", businessType = BusinessType.DELETE)
325
- @DeleteMapping("/{ids}")
326
- public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
327
- return toAjax(xxxService.deleteWithValidByIds(Arrays.asList(ids), true));
305
+ @GetMapping
306
+ public ResponseEntity<Page<OrderVO>> page(OrderQueryDTO query) {
307
+ return ResponseEntity.ok(orderService.pageQuery(query));
328
308
  }
329
309
 
330
- @SaCheckPermission("demo:xxx:export")
331
- @Log(title = "XXX管理", businessType = BusinessType.EXPORT)
332
- @PostMapping("/export")
333
- public void export(@Validated XxxBo bo, HttpServletResponse response) {
334
- List<XxxVo> list = xxxService.queryList(bo);
335
- ExcelUtil.exportExcel(list, "XXX数据", XxxVo.class, response);
310
+ @DeleteMapping("/{id}")
311
+ public ResponseEntity<Void> delete(@PathVariable Long id) {
312
+ orderService.removeById(id);
313
+ return ResponseEntity.ok().build();
336
314
  }
337
315
  }
338
316
  ```
339
317
 
340
- ## 8. 建表 SQL
341
-
342
- ```sql
343
- CREATE TABLE demo_xxx (
344
- id BIGINT(20) NOT NULL COMMENT '主键(雪花ID,不用AUTO_INCREMENT)',
345
- tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户ID',
346
- xxx_name VARCHAR(100) NOT NULL COMMENT '名称',
347
- status CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
348
- create_dept BIGINT(20) DEFAULT NULL COMMENT '创建部门',
349
- create_by BIGINT(20) DEFAULT NULL COMMENT '创建人',
350
- create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
351
- update_by BIGINT(20) DEFAULT NULL COMMENT '更新人',
352
- update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
353
- remark VARCHAR(255) DEFAULT NULL COMMENT '备注',
354
- del_flag BIGINT(20) DEFAULT 0 COMMENT '删除标志(0正常 1已删除)',
355
- PRIMARY KEY (id)
356
- ) ENGINE=InnoDB COMMENT='XXX表';
357
- ```
358
-
359
- ---
360
-
361
- ## 常见错误速查
362
-
363
- ```java
364
- // ---- 错误写法 ----
365
- private final IXxxDao xxxDao; // 本项目没有 DAO 层
366
- BeanUtil.copyProperties(bo, entity); // 必须用 MapstructUtils.convert()
367
- class XxxServiceImpl extends ServiceImpl<...> {} // Service 不继承基类
368
- @AutoMappers({@AutoMapper(...)}) // 用单数 @AutoMapper
369
- @GetMapping("/pageXxxs") // 应该是 /list
370
- @GetMapping("/getXxx/{id}") // 应该是 /{id}
371
-
372
- // ---- 正确写法 ----
373
- private final XxxMapper baseMapper; // 直接注入 Mapper
374
- MapstructUtils.convert(bo, Xxx.class); // MapstructUtils 转换
375
- class XxxServiceImpl implements IXxxService {} // 只实现接口
376
- @AutoMapper(target = Xxx.class) // 单数注解
377
- @GetMapping("/list") // RESTful 路径
378
- @GetMapping("/{id}") // RESTful 路径
379
- ```
380
-
381
- ---
382
-
383
- ## 检查清单
384
-
385
- - [ ] 包名是 `org.dromara.*`?
386
- - [ ] Service 只实现接口,不继承基类?
387
- - [ ] Service 直接注入 Mapper(无 DAO)?
388
- - [ ] `buildQueryWrapper()` 在 Service 层?
389
- - [ ] Entity 继承 `TenantEntity`?
390
- - [ ] BO 使用 `@AutoMapper`(单数)?
391
- - [ ] 使用 `MapstructUtils.convert()` 转换?
392
- - [ ] Mapper 继承 `BaseMapperPlus<Entity, VO>`?
393
- - [ ] Controller 使用 RESTful 路径?
394
- - [ ] SQL 使用 `del_flag`(0正常 1删除)?
395
- - [ ] 主键使用雪花 ID(无 AUTO_INCREMENT)?
396
- - [ ] 代码注释和 SQL COMMENT 使用中文?
397
-
398
- ---
399
-
400
- ## 参考实现
401
-
402
- | 类型 | 类名 |
403
- |------|------|
404
- | Entity | `org.dromara.demo.domain.TestDemo` |
405
- | BO | `org.dromara.demo.domain.bo.TestDemoBo` |
406
- | VO | `org.dromara.demo.domain.vo.TestDemoVo` |
407
- | Service | `org.dromara.demo.service.impl.TestDemoServiceImpl` |
408
- | Mapper | `org.dromara.demo.mapper.TestDemoMapper` |
409
- | Controller | `org.dromara.demo.controller.TestDemoController` |
318
+ ## 常见错误
319
+
320
+ | 错误 | 正确做法 |
321
+ |------|---------|
322
+ | Controller 里写业务逻辑 | 业务逻辑放 Service 层 |
323
+ | 直接返回 Entity 给前端 | 使用 VO 封装响应数据 |
324
+ | Map 传递业务数据 | 使用 DTO/VO 强类型对象 |
325
+ | 忘记加 `@Transactional` | 写操作方法加事务注解 |
326
+ | 逻辑删除字段值搞反 | 确认项目约定(通用:0=正常, 1=删除) |
327
+ | 分页参数未设默认值 | DTO 中给 pageNum/pageSize 默认值 |
328
+ | Service 之间循环依赖 | 提取公共 Service 或使用事件机制解耦 |