ai-engineering-init 1.7.0 → 1.8.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 (118) hide show
  1. package/.claude/hooks/skill-forced-eval.js +46 -62
  2. package/.claude/settings.json +10 -1
  3. package/.claude/skills/api-development/SKILL.md +179 -130
  4. package/.claude/skills/architecture-design/SKILL.md +102 -212
  5. package/.claude/skills/backend-annotations/SKILL.md +166 -220
  6. package/.claude/skills/bug-detective/SKILL.md +225 -186
  7. package/.claude/skills/code-patterns/SKILL.md +127 -244
  8. package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
  9. package/.claude/skills/crud-development/SKILL.md +226 -307
  10. package/.claude/skills/data-permission/SKILL.md +131 -202
  11. package/.claude/skills/database-ops/SKILL.md +158 -355
  12. package/.claude/skills/error-handler/SKILL.md +224 -285
  13. package/.claude/skills/file-oss-management/SKILL.md +174 -169
  14. package/.claude/skills/git-workflow/SKILL.md +123 -341
  15. package/.claude/skills/json-serialization/SKILL.md +121 -137
  16. package/.claude/skills/performance-doctor/SKILL.md +83 -89
  17. package/.claude/skills/redis-cache/SKILL.md +134 -185
  18. package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
  19. package/.claude/skills/security-guard/SKILL.md +168 -276
  20. package/.claude/skills/sms-mail/SKILL.md +266 -228
  21. package/.claude/skills/social-login/SKILL.md +257 -195
  22. package/.claude/skills/tenant-management/SKILL.md +172 -188
  23. package/.claude/skills/utils-toolkit/SKILL.md +214 -222
  24. package/.claude/skills/websocket-sse/SKILL.md +251 -172
  25. package/.claude/skills/workflow-engine/SKILL.md +178 -250
  26. package/.codex/skills/api-development/SKILL.md +179 -130
  27. package/.codex/skills/architecture-design/SKILL.md +102 -212
  28. package/.codex/skills/backend-annotations/SKILL.md +166 -220
  29. package/.codex/skills/bug-detective/SKILL.md +225 -186
  30. package/.codex/skills/code-patterns/SKILL.md +127 -244
  31. package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
  32. package/.codex/skills/crud-development/SKILL.md +226 -307
  33. package/.codex/skills/data-permission/SKILL.md +131 -202
  34. package/.codex/skills/database-ops/SKILL.md +158 -355
  35. package/.codex/skills/error-handler/SKILL.md +224 -285
  36. package/.codex/skills/file-oss-management/SKILL.md +174 -169
  37. package/.codex/skills/git-workflow/SKILL.md +123 -341
  38. package/.codex/skills/json-serialization/SKILL.md +121 -137
  39. package/.codex/skills/performance-doctor/SKILL.md +83 -89
  40. package/.codex/skills/redis-cache/SKILL.md +134 -185
  41. package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
  42. package/.codex/skills/security-guard/SKILL.md +168 -276
  43. package/.codex/skills/sms-mail/SKILL.md +266 -228
  44. package/.codex/skills/social-login/SKILL.md +257 -195
  45. package/.codex/skills/tenant-management/SKILL.md +172 -188
  46. package/.codex/skills/utils-toolkit/SKILL.md +214 -222
  47. package/.codex/skills/websocket-sse/SKILL.md +251 -172
  48. package/.codex/skills/workflow-engine/SKILL.md +178 -250
  49. package/.cursor/hooks/cursor-skill-eval.js +66 -6
  50. package/.cursor/skills/api-development/SKILL.md +179 -130
  51. package/.cursor/skills/architecture-design/SKILL.md +102 -212
  52. package/.cursor/skills/backend-annotations/SKILL.md +166 -220
  53. package/.cursor/skills/bug-detective/SKILL.md +225 -186
  54. package/.cursor/skills/code-patterns/SKILL.md +127 -244
  55. package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
  56. package/.cursor/skills/crud-development/SKILL.md +226 -307
  57. package/.cursor/skills/data-permission/SKILL.md +131 -202
  58. package/.cursor/skills/database-ops/SKILL.md +158 -355
  59. package/.cursor/skills/error-handler/SKILL.md +224 -285
  60. package/.cursor/skills/file-oss-management/SKILL.md +174 -169
  61. package/.cursor/skills/git-workflow/SKILL.md +123 -341
  62. package/.cursor/skills/json-serialization/SKILL.md +121 -137
  63. package/.cursor/skills/performance-doctor/SKILL.md +83 -89
  64. package/.cursor/skills/redis-cache/SKILL.md +134 -185
  65. package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
  66. package/.cursor/skills/security-guard/SKILL.md +168 -276
  67. package/.cursor/skills/sms-mail/SKILL.md +266 -228
  68. package/.cursor/skills/social-login/SKILL.md +257 -195
  69. package/.cursor/skills/tenant-management/SKILL.md +172 -188
  70. package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
  71. package/.cursor/skills/websocket-sse/SKILL.md +251 -172
  72. package/.cursor/skills/workflow-engine/SKILL.md +178 -250
  73. package/AGENTS.md +49 -540
  74. package/CLAUDE.md +73 -119
  75. package/README.md +37 -6
  76. package/bin/index.js +5 -1
  77. package/package.json +1 -1
  78. package/src/skills/api-development/SKILL.md +179 -130
  79. package/src/skills/architecture-design/SKILL.md +102 -212
  80. package/src/skills/backend-annotations/SKILL.md +166 -220
  81. package/src/skills/bug-detective/SKILL.md +225 -186
  82. package/src/skills/code-patterns/SKILL.md +127 -244
  83. package/src/skills/collaborating-with-codex/SKILL.md +96 -113
  84. package/src/skills/crud-development/SKILL.md +226 -307
  85. package/src/skills/data-permission/SKILL.md +131 -202
  86. package/src/skills/database-ops/SKILL.md +158 -355
  87. package/src/skills/error-handler/SKILL.md +224 -285
  88. package/src/skills/file-oss-management/SKILL.md +174 -169
  89. package/src/skills/git-workflow/SKILL.md +123 -341
  90. package/src/skills/json-serialization/SKILL.md +121 -137
  91. package/src/skills/performance-doctor/SKILL.md +83 -89
  92. package/src/skills/redis-cache/SKILL.md +134 -185
  93. package/src/skills/scheduled-jobs/SKILL.md +187 -224
  94. package/src/skills/security-guard/SKILL.md +168 -276
  95. package/src/skills/sms-mail/SKILL.md +266 -228
  96. package/src/skills/social-login/SKILL.md +257 -195
  97. package/src/skills/tenant-management/SKILL.md +172 -188
  98. package/src/skills/utils-toolkit/SKILL.md +214 -222
  99. package/src/skills/websocket-sse/SKILL.md +251 -172
  100. package/src/skills/workflow-engine/SKILL.md +178 -250
  101. package/.claude/skills/skill-creator/LICENSE.txt +0 -202
  102. package/.claude/skills/skill-creator/SKILL.md +0 -479
  103. package/.claude/skills/skill-creator/agents/analyzer.md +0 -274
  104. package/.claude/skills/skill-creator/agents/comparator.md +0 -202
  105. package/.claude/skills/skill-creator/agents/grader.md +0 -223
  106. package/.claude/skills/skill-creator/assets/eval_review.html +0 -146
  107. package/.claude/skills/skill-creator/eval-viewer/generate_review.py +0 -471
  108. package/.claude/skills/skill-creator/eval-viewer/viewer.html +0 -1325
  109. package/.claude/skills/skill-creator/references/schemas.md +0 -430
  110. package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
  111. package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
  112. package/.claude/skills/skill-creator/scripts/generate_report.py +0 -326
  113. package/.claude/skills/skill-creator/scripts/improve_description.py +0 -248
  114. package/.claude/skills/skill-creator/scripts/package_skill.py +0 -136
  115. package/.claude/skills/skill-creator/scripts/quick_validate.py +0 -103
  116. package/.claude/skills/skill-creator/scripts/run_eval.py +0 -310
  117. package/.claude/skills/skill-creator/scripts/run_loop.py +0 -332
  118. 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 或使用事件机制解耦 |