feat: add mica-smdm-scaffold proposal and rollback files; create unit testing specifications and SKILL documentation

This commit is contained in:
杨轩
2026-08-04 18:04:01 +08:00
parent fcb30e1c69
commit ba03f5d4db
16 changed files with 2035 additions and 7 deletions
+191 -4
View File
@@ -149,7 +149,6 @@ public interface WorkshopApi {
- 请求入口:`log.info("物料查询请求:itemCode={}", dto.getItemCode())`
- 异常捕获:`log.error("物料查询失败", e)`
- 关键业务节点:`log.info("物料创建成功:itemCode={}", result.getItemCode())`
- Feign 调用:`log.debug("Feign 调用 - 创建物料,入参:{}", JsonUtils.toJson(dto))`
**示例**:
```java
@@ -169,7 +168,31 @@ public class ItemController {
}
```
### 4. 字段注释
### 4. Feign 调用日志规范
**正确示例**:
```java
@Override
public ResponseModel insertItem(ItemFormDTO dto) {
log.debug("Feign 调用 - 创建物料,入参:{}", JSON.toJSONString(dto));
long start = System.currentTimeMillis();
Map<String, Object> itemMap = Convert.convert(Map.class, dto);
ResponseModel response = itemApi.insertItem(itemMap);
log.debug("Feign 调用 - 创建物料完成,耗时:{}ms",
System.currentTimeMillis() - start);
return response;
}
```
**规范**:
- 日志级别:`debug`
- 记录内容:入参 + 耗时
- **禁止记录返回值**(避免日志过大)
- 使用 `JSON.toJSONString()` (fastjson) 序列化对象
### 5. 字段注释
单行注释即可:
@@ -183,7 +206,7 @@ private String itemName;
---
## 🐛 已修正的问题清单 (1-12)
## 🐛 已修正的问题清单 (1-15)
以下问题在开发过程中发现并已修正,**后续开发必须遵守**:
@@ -192,7 +215,7 @@ private String itemName;
| 1 | **ResponseModel 静态引用错误** | 使用 `ResponseModel.succeed(data)` 静态方法 | `ItemController.java`, `ItemServiceImpl.java` |
| 2 | **分页 XML / 详情 MP 混合使用** | 分页查询用原生 XML,详情查询用 `BaseMapper.selectById` | `ItemMapper.xml`, `ItemServiceImpl.java` |
| 3 | **移除编码查询条件** | 从 DTO 和 XML 移除 `itemCode` 模糊搜索 | `ItemQueryDTO.java`, `ItemMapper.xml` |
| 4 | **Feign 调用添加日志** | debug 级别:入参 + 耗时 + 返回 | `ItemServiceImpl.java` |
| 4 | **Feign 调用添加日志** | debug 级别:入参 + 耗时 | `ItemServiceImpl.java` |
| 5 | **Controller 层 ecid 处理** | `GlobalUtils.getEcid()` 在 Controller 层获取并传递给 Service | `ItemController.java` |
| 6 | **恢复分页 XML 查询** | 保留完整的分页查询 SQL | `ItemMapper.xml` |
| 7 | **使用 PageDomain (非 PageHelper)** | 手动分页:先 count 查询总数,再 LIMIT 查询数据 | `ItemServiceImpl.java` |
@@ -201,6 +224,9 @@ private String itemName;
| 10 | **Map 类型转换警告** | 使用 `Convert.convert(Map.class, dto)` 或 `@SuppressWarnings` | `ItemController.java`, `ItemServiceImpl.java` |
| 11 | **XML 使用 `<sql>` + `<include>` 片段** | 公共列定义和查询条件使用 SQL 片段复用 | `ItemMapper.xml` |
| 12 | **ItemApi ResponseModel 泛型** | Feign 接口返回 `ResponseModel<Void>` | `ItemApi.java` |
| 13 | **ResponseModel 使用裸类型** | 与项目其他 Feign 接口一致,使用裸类型 `ResponseModel` | `ItemApi.java`, `ItemService.java`, `ItemServiceImpl.java`, `ItemController.java` |
| 14 | **日志禁止记录返回值** | 只记录耗时,不记录返回值(避免日志过大) | `ItemServiceImpl.java` |
| 15 | **JsonUtils.toJson() 方法不存在** | 使用 `JSON.toJSONString()` (fastjson) 替代 | `ItemServiceImpl.java` |
---
@@ -240,6 +266,32 @@ ItemInfo item = itemMapper.selectById(id);
---
### 问题 4 详解:Feign 调用日志
**正确示例**:
```java
@Override
public ResponseModel insertItem(ItemFormDTO dto) {
log.debug("Feign 调用 - 创建物料,入参:{}", JSON.toJSONString(dto));
long start = System.currentTimeMillis();
Map<String, Object> itemMap = Convert.convert(Map.class, dto);
ResponseModel response = itemApi.insertItem(itemMap);
log.debug("Feign 调用 - 创建物料完成,耗时:{}ms",
System.currentTimeMillis() - start);
return response;
}
```
**规范**:
- 日志级别:`debug`
- 记录内容:入参 + 耗时
- **禁止记录返回值**(避免日志过大)
- 使用 `JSON.toJSONString()` (fastjson) 序列化对象
---
### 问题 5 详解:Controller 层 ecid 处理
**Controller**:
@@ -345,6 +397,53 @@ public PageDomain<ItemVO> queryPageList(ItemQueryDTO dto) {
---
### 问题 13 详解:ResponseModel 裸类型
**错误**:
```java
public ResponseModel<Map<String, Object>> insertItem(ItemFormDTO dto) { // ❌ 泛型参数
// ...
}
```
**正确** (与项目其他 Feign 接口一致):
```java
public ResponseModel insertItem(ItemFormDTO dto) { // ✅ 裸类型
// ...
}
```
**参考项目其他 Feign 接口**:
```java
// WorkshopApi.java
ResponseModel queryWorkshopPageList(@RequestBody Map<String, Object> workshop);
ResponseModel insertWorkshop(@RequestBody Map<String, Object> workshop);
// FactoryApi.java
ResponseModel getWorkShops(@RequestParam("ecid") String ecid);
ResponseModel getProdLineList(@RequestParam String workshopCode, @RequestParam String ecid);
```
---
### 问题 15 详解:JsonUtils 替代方案
**错误**:
```java
log.debug("入参:{}", JsonUtils.toJson(dto)); // ❌ JsonUtils.toJson() 方法不存在
```
**正确** (使用 fastjson):
```java
import com.alibaba.fastjson.JSON;
log.debug("入参:{}", JSON.toJSONString(dto)); // ✅ 使用 fastjson
```
**原因**: `common-utils` 依赖中的 `JsonUtils` 类没有 `toJson()` 方法,项目已引入 `fastjson` 依赖。
---
## 📁 后端完整文件清单 (10 个)
| # | 文件 | 路径 | 状态 |
@@ -362,6 +461,88 @@ public PageDomain<ItemVO> queryPageList(ItemQueryDTO dto) {
---
## 数据字典模块开发 (2026-08-04 下午)
### 🔴 数据字典模块强制性红线
| # | 红线 | 正确做法 |
|---|------|----------|
| 1 | **不需要 Controller** | 纯内部工具服务 |
| 2 | **不需要 Feign API** | 不暴露外部接口 |
| 3 | **不需要缓存实现** | 后续可调用 Feign 接口缓存 |
| 4 | **不需要继承 BaseDomain** | 配置项不是业务实体 |
### 📋 数据字典核心功能
1. **单个字典类型查询**: `Map<String, String> getDictionaryMap(String typeCode)`
2. **批量字典类型查询**: `Map<String, Map<String, String>> getDictionaryMaps(List<String> typeCodes)`
3. **输出格式**: `Map<String, String>` (en_code → full_name)
4. **重复处理**: 同一 typeCode 下 en_code 重复时取第一条 (按 sort_code + id 排序)
5. **多租户支持**: 自动获取 ecid 过滤
6. **软删除过滤**: delete_mark = 0
### 📁 数据字典已生成文件 (5 个)
| # | 文件 | 路径 | 状态 |
|---|------|------|------|
| 1 | `DictionaryMapper.java` | `smd/mapper/` | ✅ 已写入 |
| 2 | `DictionaryMapper.xml` | `resources/mapper/smd/` | ✅ 已写入 |
| 3 | `DictionaryItem.java` | `smd/dto/` | ✅ 已写入 |
| 4 | `DictionaryService.java` | `smd/service/` | ✅ 已写入 |
| 5 | `DictionaryServiceImpl.java` | `smd/service/impl/` | ✅ 已写入 |
### 📁 已生成枚举类 (2 个)
| # | 文件 | 说明 |
|---|------|------|
| 1 | `StatusEnum.java` | 状态枚举 (Y=启用,N=禁用) |
| 2 | `YesNoEnum.java` | 是否枚举 (Y=是,N=否) |
### 🔧 字典填充规范
#### VO 设计
- 添加 `xxxName` 字段存储字典翻译后的中文名称
- 示例:`itemType` (en_code) + `itemTypeName` (中文名称)
#### Service 层填充
- **批量查询字典**: 一次查询多个字典类型,避免 N+1 问题
- **通用填充方法**: `fillDictionaryData(ItemVO itemVO, Map<String, Map<String, String>> dictMaps)`
- **性能要求**: 列表查询只查 1 次字典,批量填充
#### 物料信息字典映射
| VO 字段 | 字典类型 | 说明 |
|--------|---------|------|
| `itemTypeName` | `materialsType` | 物料类型名称 |
| `propertiesName` | `itemProperties` | 物料属性名称 |
| `pickingPropertyName` | `pickingProperty` | 领料属性名称 |
| `statusName` | `StatusEnum` | 状态名称 (枚举) |
### 📊 性能优化
| 优化点 | 说明 | 效果 |
|--------|------|------|
| **批量查询字典** | 一次查询多个字典类型 | 避免多次数据库查询 |
| **字典 Map 传入** | `fillDictionaryData()` 接收外部传入的 dictMaps | 避免重复查询 |
| **列表查询优化** | 100 条数据从 101 次查询降低到 2 次 | 性能提升 50 倍 |
| **枚举静态方法** | 枚举翻译使用静态方法 | 无运行时开销 |
### 🧪 单元测试
- 测试文件:`src/test/java/com/witsoft/mica/smd/service/DictionaryServiceTest.java`
- 测试方法:英文命名(避免中文字符)
- Mock 处理:`GlobalUtils.getEcid()` 改为可 mock 的实例方法
- 测试结果:✅ 5 个测试全部通过
### 🐛 数据字典开发修正问题
| # | 问题 | 修正方案 |
|---|------|----------|
| 16 | **fillDictionaryData 重复查询** | 修改方法签名接收 dictMaps 参数,避免 N+1 问题 |
| 17 | **planner 越权生成代码** | 明确 planner 禁止生成代码,由 backend agent 执行 |
---
## 📝 待办事项
### Backend (mica-server)
@@ -375,6 +556,12 @@ public PageDomain<ItemVO> queryPageList(ItemQueryDTO dto) {
- [x] 创建 `smd/dto/ItemQueryDTO.java`
- [x] 创建 `smd/dto/ItemFormDTO.java`
- [x] 创建 `smd/vo/ItemVO.java`
- [x] 修正 15 个编译错误
- [x] Maven 编译验证通过
- [x] 数据字典模块开发 (5 个文件 + 2 个枚举类)
- [x] 字典填充逻辑实现
- [x] 单元测试通过
- [ ] 集成测试
### Frontend (mica-web)
- [ ] 创建物料管理 API 封装 (`app/composables/smd/useItemApi.ts`)