Files
openclaw-config/workspace-planner/memory/2026-08-04.md
T
2026-08-04 14:56:20 +08:00

393 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-08-04 工作日志
## mica 项目 - SMDM 物料管理模块开发规范
### 🔴 强制性红线 (违反即停止)
| # | 红线 | 违规示例 | 正确做法 |
|------|---------|----------|----------|
| 1 | **表前缀必须过滤** | `DmpMdItemInfo` | `ItemInfo` |
| 2 | **API 必须放在 apis.smdm 包** | `smd.api.ItemApi` | `apis.smdm.ItemApi` |
| 3 | **查询只能用 Mapper** | 使用 MyBatis-Plus | 原生 MyBatis XML |
| 4 | **改删必须 Feign 远程调用** | 本地直接 UPDATE/DELETE | 调用 SMDM 服务 API |
| 5 | **实体必须继承 BaseDomain** | 独立定义审计字段 | `extends BaseDomain` |
| 6 | **只使用指定 13 个业务字段** | 添加表中其他字段 | 仅用规范内字段 |
| 7 | **代码必须生成到 smd 目录** | `com.witsoft.mica.item.*` | `com.witsoft.mica.smd.*` |
---
### 📋 已确认的开发规范
#### 1. 包路径规范
- **代码生成目录**: `/root/projects/wit/mica-server/src/main/java/com/witsoft/mica/smd/`
- **包前缀**: `com.witsoft.mica.smd`
- **API 包路径**: `com.witsoft.mica.apis.smdm`
- **子包结构**:
```
smd/
├── controller/ # 控制器层
├── service/ # 服务层接口
├── service/impl/ # 服务层实现
├── mapper/ # MyBatis Mapper 接口
├── entity/ # 数据库实体类
├── dto/ # 数据传输对象
└── vo/ # 视图对象
```
#### 2. 表名前缀过滤规则
- **过滤前缀**: `dmp_md_`
- **示例**:
- `dmp_md_item_info` → `ItemInfo`
- `dmp_md_xxx` → `Xxx`
#### 3. 实体类规范
- **基础字段** (业务必需):
| 字段说明 | 数据库字段 | Java 字段 |
|---------|-----------|----------|
| 物料编码 | `item_code` | `itemCode` |
| 物料名称 | `item_name` | `itemName` |
| 规格型号 | `item_spec` | `itemSpec` |
| 物料类型 | `item_type` | `itemType` |
| 物料分类 | `item_categorys_code` | `itemCategorysCode` |
| 物料属性 | `properties` | `properties` |
| 主单位 | `unit_code` | `unitCode` |
| 辅单位 | `assist_unit_code` | `assistUnitCode` |
| 物料描述 | `item_desc` | `itemDesc` |
| 供应商 | `vendor_code` | `vendorCode` |
| 默认仓库 | `good_warehouse` | `goodWarehouse` |
| 批次控制 | `batch_control` | `batchControl` (默认 0/关) |
| 领料属性 | `picking_property` | `pickingProperty` (默认 AD/按单领料) |
| 状态 | `status` | `status` |
- **审计字段** (继承 `BaseDomain`):
```java
import com.witsoft.gen.base.BaseDomain;
public class ItemInfo extends BaseDomain {
// 业务字段...
}
```
- `id`, `ecid`, `createdBy`, `createTime`, `updatedBy`, `updateTime`
#### 4. 数据访问规范
- **查询权限**: 仅有数据库查询权限
- **查询方式**: 使用原生 MyBatis Mapper**不使用 MyBatis-Plus**
- **修改/删除**: 通过 Feign 远程调用 SMDM 服务
#### 5. 架构模式
```
mica-server (本地) smdm (远程服务)
│ │
├── Controller │
├── Service │
├── Mapper ──(查询)──→ 数据库
└── Feign Api ──(改删)──→ WorkshopApi 模式
```
#### 6. Feign 远程调用模式
**API 包路径**: `com.witsoft.mica.apis.smdm`
参考现有 `WorkshopApi`:
```java
@FeignClient(name = "smdm", path = "/smdm/smd/web/workshop")
public interface WorkshopApi {
@PostMapping("/getListPage")
ResponseModel queryWorkshopPageList(@RequestBody Map<String, Object> workshop);
@PostMapping("/create")
ResponseModel insertWorkshop(@RequestBody Map<String, Object> workshop);
}
```
---
## 📝 注释与日志规范
### 1. 类注释 (Javadoc 风格)
参考现有 `WorkshopController.java`:
```java
/**
* @Description : 物料信息管理
* @ModifyBrief :
* @Author : yangxuan
* @Date : 2026/8/4
* @Version : 1.0
*/
```
**规范**:
- `@Author` 固定为 `yangxuan`
- `@Date` 精确到日 (`2026/8/4`)
- `@ModifyBrief` 留空,后续修改时补充
### 2. 方法注释
```java
/**
* @Description : 物料信息列表分页查询
* @ModifyBrief :
* @Author : yangxuan
* @Date : 2026/8/4
* @Version : 1.0
* @Param : itemQueryDTO
* @Return : PageDomain<ItemVO>
*/
```
**规范**:
- 公共接口方法必须添加方法注释
- 私有方法可选添加
- `@Author` 固定为 `yangxuan`
### 3. 日志规范
**框架**: SLF4J + Lombok `@Slf4j`
**使用场景**:
- 请求入口:`log.info("物料查询请求:itemCode={}", dto.getItemCode())`
- 异常捕获:`log.error("物料查询失败", e)`
- 关键业务节点:`log.info("物料创建成功:itemCode={}", result.getItemCode())`
- Feign 调用:`log.debug("Feign 调用 - 创建物料,入参:{}", JsonUtils.toJson(dto))`
**示例**:
```java
@Slf4j
@RestController
public class ItemController {
public ResponseModel<PageDomain<ItemVO>> queryPageList(@RequestBody ItemQueryDTO dto) {
log.info("物料查询请求:ecid={}", dto.getEcid());
try {
return itemService.queryPageList(dto);
} catch (Exception e) {
log.error("物料查询失败", e);
return ResponseModel.failed("查询失败");
}
}
}
```
### 4. 字段注释
单行注释即可:
```java
/** 物料编码 */
private String itemCode;
/** 物料名称 */
private String itemName;
```
---
## 🐛 已修正的问题清单 (1-12)
以下问题在开发过程中发现并已修正,**后续开发必须遵守**:
| # | 问题 | 修正方案 | 涉及文件 |
|---|------|----------|----------|
| 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` |
| 5 | **Controller 层 ecid 处理** | `GlobalUtils.getEcid()` 在 Controller 层获取并传递给 Service | `ItemController.java` |
| 6 | **恢复分页 XML 查询** | 保留完整的分页查询 SQL | `ItemMapper.xml` |
| 7 | **使用 PageDomain (非 PageHelper)** | 手动分页:先 count 查询总数,再 LIMIT 查询数据 | `ItemServiceImpl.java` |
| 8 | **删除 queryByCode 方法** | 删除所有 `queryByCode` 相关代码 | `ItemMapper.java`, `ItemService.java`, `ItemController.java` |
| 9 | **ResponseModel 泛型参数化** | 所有返回类型使用 `ResponseModel<T>` | `ItemController.java`, `ItemServiceImpl.java` |
| 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` |
---
### 问题 1 详解:ResponseModel 静态引用
**错误**:
```java
return ResponseModel.success(result); // ❌ success 不是静态方法
```
**正确**:
```java
return ResponseModel.succeed(result); // ✅ 使用静态方法 succeed
```
---
### 问题 2 详解:分页 XML / 详情 MP
**分页查询** (原生 XML):
```java
// ItemMapper.xml
<select id="queryPageList" resultType="com.witsoft.mica.smd.vo.ItemVO">
SELECT <include refid="selectItemColumns"/>
FROM dmp_md_item_info t
<include refid="queryConditions"/>
ORDER BY t.create_time DESC
LIMIT #{dto.pageNo}, #{dto.pageSize}
</select>
```
**详情查询** (MyBatis-Plus):
```java
// ItemServiceImpl.java
ItemInfo item = itemMapper.selectById(id);
```
---
### 问题 5 详解:Controller 层 ecid 处理
**Controller**:
```java
@PostMapping("/getPageList")
public ResponseModel<PageDomain<ItemVO>> queryPageList(@RequestBody ItemQueryDTO dto) {
String ecid = GlobalUtils.getEcid();
dto.setEcid(ecid);
log.info("物料查询请求:ecid={}", ecid);
return itemService.queryPageList(dto);
}
```
**Service** (直接使用传入的 ecid):
```java
@Override
public PageDomain<ItemVO> queryPageList(ItemQueryDTO dto) {
// 直接使用 dto.getEcid(),不再自己获取
List<ItemVO> list = itemMapper.queryPageList(dto);
// ...
}
```
---
### 问题 7 详解:使用 PageDomain
**Service 手动分页**:
```java
@Override
public PageDomain<ItemVO> queryPageList(ItemQueryDTO dto) {
int pageNo = dto.getPageNo() != null ? dto.getPageNo() : 1;
int pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
// 查询总数
long total = itemMapper.queryPageCount(dto);
// 查询分页数据
List<ItemVO> list = itemMapper.queryPageList(dto);
// 构建 PageDomain
PageDomain<ItemVO> page = new PageDomain<>(pageNo, pageSize, total);
page.setList(list);
return page;
}
```
---
### 问题 11 详解:XML SQL 片段
**ItemMapper.xml**:
```xml
<mapper namespace="com.witsoft.mica.smd.mapper.ItemMapper">
<!-- 公共列定义 -->
<sql id="selectItemColumns">
t.id, t.ecid, t.item_code, t.item_name, t.item_spec, t.item_type,
t.item_categorys_code, t.properties, t.unit_code, t.assist_unit_code,
t.item_desc, t.vendor_code, t.good_warehouse, t.batch_control,
t.picking_property, t.status, t.create_time, t.created_by,
t.update_time, t.updated_by
</sql>
<!-- 公共查询条件 -->
<sql id="queryConditions">
<where>
<if test="dto.ecid != null and dto.ecid != ''">
AND t.ecid = #{dto.ecid}
</if>
<if test="dto.itemName != null and dto.itemName != ''">
AND t.item_name LIKE CONCAT('%', #{dto.itemName}, '%')
</if>
<if test="dto.itemType != null and dto.itemType != ''">
AND t.item_type = #{dto.itemType}
</if>
<if test="dto.status != null and dto.status != ''">
AND t.status = #{dto.status}
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="queryPageList" resultType="com.witsoft.mica.smd.vo.ItemVO">
SELECT
<include refid="selectItemColumns"/>
FROM dmp_md_item_info t
<include refid="queryConditions"/>
ORDER BY t.create_time DESC
LIMIT #{dto.pageNo}, #{dto.pageSize}
</select>
<!-- 总数查询 -->
<select id="queryPageCount" resultType="long">
SELECT COUNT(*)
FROM dmp_md_item_info t
<include refid="queryConditions"/>
</select>
</mapper>
```
---
## 📁 后端完整文件清单 (10 个)
| # | 文件 | 路径 | 状态 |
|---|------|------|------|
| 1 | `ItemApi.java` | `apis/smdm/` | ✅ 已写入 |
| 2 | `ItemInfo.java` | `smd/entity/` | ✅ 已写入 |
| 3 | `ItemMapper.java` | `smd/mapper/` | ✅ 已写入 |
| 4 | `ItemMapper.xml` | `resources/mapper/smd/` | ✅ 已写入 |
| 5 | `ItemService.java` | `smd/service/` | ✅ 已写入 |
| 6 | `ItemServiceImpl.java` | `smd/service/impl/` | ✅ 已写入 |
| 7 | `ItemController.java` | `smd/controller/` | ✅ 已写入 |
| 8 | `ItemQueryDTO.java` | `smd/dto/` | ✅ 已写入 |
| 9 | `ItemFormDTO.java` | `smd/dto/` | ✅ 已写入 |
| 10 | `ItemVO.java` | `smd/vo/` | ✅ 已写入 |
---
## 📝 待办事项
### Backend (mica-server)
- [x] 创建 `apis/smdm/ItemApi.java` (Feign 接口)
- [x] 创建 `smd/entity/ItemInfo.java`
- [x] 创建 `smd/mapper/ItemMapper.java`
- [x] 创建 `smd/mapper/ItemMapper.xml`
- [x] 创建 `smd/service/ItemService.java`
- [x] 创建 `smd/service/impl/ItemServiceImpl.java`
- [x] 创建 `smd/controller/ItemController.java`
- [x] 创建 `smd/dto/ItemQueryDTO.java`
- [x] 创建 `smd/dto/ItemFormDTO.java`
- [x] 创建 `smd/vo/ItemVO.java`
### Frontend (mica-web)
- [ ] 创建物料管理 API 封装 (`app/composables/smd/useItemApi.ts`)
- [ ] 创建物料列表页面 (`app/pages/smd/item/index.vue`)
- [ ] 创建物料详情/编辑表单 (`app/pages/smd/item/form.vue`)
- [ ] 创建物料详情页面 (`app/pages/smd/item/detail.vue`)
- [ ] 更新路由配置
---
## 🔗 相关资源
- 数据库:`dmp_smdm.dmp_md_item_info`
- 连接:`mysql -h 47.99.209.185 -P 50036 -u witsoftd -p mica`
- 项目路径:`/root/projects/wit/`
- 规范文档:`/root/.openclaw/workspace-planner/memory/2026-08-04.md`