refactor: 统一术语BOM为物料清单并补充工位扩展能力
主要变更: 1. 后端:重构工位管理逻辑,新增工位自定义扩展能力,将工位号上限调整为999并支持14+虚拟工位 2. 前后端:全量替换"BOM"术语为"物料清单",包括提示语、注释和文档 3. WMS模块:新增AGV任务取消接口与前端页面,对接海康RCS取消任务逻辑 4. 权限与种子数据:新增工位新增权限并更新权限配置 5. 修复错误校验逻辑,优化AGV客户端签名与请求处理
This commit is contained in:
@@ -200,6 +200,73 @@ func mapHikStatus(s string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// cancelAgvHandler 取消 AGV 任务(软取消)。
|
||||
// 已下发(DISPATCHED/DELIVERING)的调海康 RCS task/cancel;本地任务置 CANCELLED,
|
||||
// 并把关联的 MES 备料单行从 DELIVERING 退回待发料状态。
|
||||
func cancelAgvHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
TaskNo string `json:"taskNo"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if err := parseJSON(r, &req); err != nil {
|
||||
fail(w, http.StatusBadRequest, "参数错误: "+err.Error())
|
||||
return
|
||||
}
|
||||
if req.TaskNo == "" {
|
||||
fail(w, http.StatusBadRequest, "缺少任务号")
|
||||
return
|
||||
}
|
||||
t, err := ctx.EntClient.AgvTask.Query().Where(agvtask.TaskNo(req.TaskNo)).First(ctx0())
|
||||
if err != nil {
|
||||
fail(w, http.StatusNotFound, "AGV 任务不存在")
|
||||
return
|
||||
}
|
||||
if t.Status == "DONE" || t.Status == "CANCELLED" {
|
||||
fail(w, http.StatusBadRequest, "任务已结束,无法取消")
|
||||
return
|
||||
}
|
||||
operator := r.Header.Get("X-Username")
|
||||
// 已下发的先通知 RCS 取消
|
||||
if t.HikTaskCode != "" && (t.Status == "DISPATCHED" || t.Status == "DELIVERING") {
|
||||
if cerr := ctx.Agv.CancelTask(ctx0(), t.HikTaskCode, "CANCEL", req.Reason); cerr != nil {
|
||||
fail(w, http.StatusBadGateway, "RCS 取消失败: "+cerr.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := ctx.EntClient.AgvTask.UpdateOneID(t.ID).
|
||||
SetStatus("CANCELLED").SetRemark(req.Reason).Exec(ctx0()); err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
// 关联备料单行退回待发料
|
||||
mats := []agvSubmitRow{}
|
||||
_ = json.Unmarshal([]byte(t.MaterialsJSON), &mats)
|
||||
for _, row := range mats {
|
||||
_ = ctx.Mes.MarkStatus(ctx0(), row.RequestNo, "WAIT_SEND")
|
||||
}
|
||||
ctx.EventLog.Write(ctx0(), "agv.cancel", operator, "agv_task", t.TaskNo,
|
||||
"取消AGV搬运 "+t.SourceDock+"→"+t.TargetDock, map[string]any{"reason": req.Reason})
|
||||
ok(w, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// agvModeHandler 返回 AGV 对接模式(mock / 真实 RCS),供前端提示当前是否在模拟。
|
||||
func agvModeHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
mock := ctx.Agv.Disable()
|
||||
ok(w, map[string]any{
|
||||
"mock": mock,
|
||||
"tip": func() string {
|
||||
if mock {
|
||||
return "当前为模拟模式(未接真实海康 RCS):任务会立即标记为已到位。现场对接请在配置中关闭 EnableMock 并填写 RCS 地址/appKey/appSecret。"
|
||||
}
|
||||
return "已对接真实海康 RCS。"
|
||||
}(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func listDocksHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
|
||||
Reference in New Issue
Block a user