docs(business): 生成业务契约文档并重构MES客户端代码

- 创建案例.md文档,包含业务场景清单、业务流程、案例和回归测试三份完整文档
- WMS库房管理系统涵盖入库、出库、库存、检验、盘点等24个业务场景
- MES产线控制系统包含工单、排产、BOM、备料、质检、追溯等23个业务场景
- 工位终端系统支持上线、报工、下线、领料、巡检等15个现场作业场景
- 主链路从合同到成品入库,异常链路处理不合格、数量不符、退料等情况
- 删除MES客户端中的ScanRecord相关代码,精简客户端结构
- 更新客户端初始化逻辑,移除扫描记录相关的依赖注入配置
This commit is contained in:
SunYF
2026-09-20 18:25:44 +08:00
parent 5f68e77d5f
commit 8e6e8e1d20
46 changed files with 1052 additions and 3954 deletions
+60 -4
View File
@@ -463,11 +463,13 @@ type zoneBatchGenReq struct {
LayerEnd int `json:"layerEnd"`
PosStart int `json:"posStart"`
PosEnd int `json:"posEnd"`
Level int `json:"level"` // 3=批量生成层(level3) 4=批量生成位置号(level4,默认,同时确保层存在)
Preview bool `json:"preview"`
}
// batchGenerateHandler 批量生成位置号:选区域→货架→层范围→位置范围,先预览后提交。
// 自动确保层节点(level3)存在;已存在的位置号跳过不重复建
// batchGenerateHandler 批量生成库位节点:选区域→货架→范围,先预览后提交。
// level=3:只生成「层」节点(按层范围);level=4(默认):生成「位置号」节点(层×位置),并自动确保层节点存在
// 已存在的节点跳过不重复建。
func batchGenerateHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req zoneBatchGenReq
@@ -481,8 +483,16 @@ func batchGenerateHandler(ctx *svc.ServiceContext) http.HandlerFunc {
fail(w, http.StatusBadRequest, "请选择区域与货架")
return
}
if req.LayerStart < 0 || req.LayerEnd < req.LayerStart || req.PosStart < 0 || req.PosEnd < req.PosStart {
fail(w, http.StatusBadRequest, "层/位置起止不合法(起始需 ≤ 结束,且 ≥ 0)")
level := req.Level
if level != 3 {
level = 4
}
if req.LayerStart < 0 || req.LayerEnd < req.LayerStart {
fail(w, http.StatusBadRequest, "层起止不合法(起始需 ≤ 结束,且 ≥ 0)")
return
}
if level == 4 && (req.PosStart < 0 || req.PosEnd < req.PosStart) {
fail(w, http.StatusBadRequest, "位置起止不合法(起始需 ≤ 结束,且 ≥ 0)")
return
}
sh, err := ctx.EntClient.Zone.Query().Where(zone.LevelEQ(2), zone.ZoneCodeEQ(req.ZoneCode), zone.CodeEQ(req.ShelfNo)).Only(ctx0())
@@ -496,6 +506,52 @@ func batchGenerateHandler(ctx *svc.ServiceContext) http.HandlerFunc {
for l := req.LayerStart; l <= req.LayerEnd; l++ {
layers = append(layers, l)
}
// ---------- level=3:批量生成层节点 ----------
if level == 3 {
if len(layers) > 2000 {
fail(w, http.StatusBadRequest, "一次最多生成 2000 个层,请缩小范围")
return
}
type genLayer struct {
LayerNo string `json:"layerNo"`
LayerName string `json:"layerName"`
Exists bool `json:"exists"`
}
layerList := make([]genLayer, 0, len(layers))
for _, l := range layers {
ls := strconv.Itoa(l)
exists, _ := ctx.EntClient.Zone.Query().
Where(zone.LevelEQ(3), zone.ZoneCodeEQ(zoneCode), zone.ShelfNoEQ(req.ShelfNo), zone.CodeEQ(ls)).Exist(ctx0())
layerList = append(layerList, genLayer{LayerNo: ls, LayerName: req.ShelfNo + "架" + ls + "层", Exists: exists})
}
if req.Preview {
ok(w, map[string]any{"preview": true, "level": 3, "list": layerList, "total": len(layerList)})
return
}
createdL, skippedL := 0, 0
for _, it := range layerList {
if it.Exists {
skippedL++
continue
}
if _, err := ctx.EntClient.Zone.Create().
SetLevel(3).SetCode(it.LayerNo).SetParentCode(req.ShelfNo).
SetZoneCode(zoneCode).SetShelfNo(req.ShelfNo).SetLayerNo(it.LayerNo).
SetName(it.LayerName).SetStatus("启用").Save(ctx0()); err != nil {
fail(w, http.StatusInternalServerError, "创建层失败: "+err.Error())
return
}
createdL++
}
ctx.EventLog.Write(ctx0(), "zone.batch", r.Header.Get("X-Username"), "zone", req.ShelfNo,
"批量生成层 "+req.ZoneCode+"/"+req.ShelfNo+" 层"+strconv.Itoa(req.LayerStart)+"-"+strconv.Itoa(req.LayerEnd)+
":新建"+strconv.Itoa(createdL)+" 跳过"+strconv.Itoa(skippedL), nil)
ok(w, map[string]any{"preview": false, "level": 3, "created": createdL, "skipped": skippedL, "total": len(layers)})
return
}
// ---------- level=4:批量生成位置号 ----------
poss := make([]int, 0)
for p := req.PosStart; p <= req.PosEnd; p++ {
poss = append(poss, p)