feat: 完成产线与仓储系统多模块迭代升级
本次迭代覆盖MES与WMS核心业务: 1. 新增接驳台托盘传感器读取与AGV对接能力 2. 完善工单排产、备料流程与权限体系拆分 3. 优化看板接口与前端路由、样式 4. 新增操作日志、库存盘点与角色保护逻辑 5. 修复代理地址、BOM保存等已知问题
This commit is contained in:
@@ -45,6 +45,7 @@ func ListBomHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
|
||||
// ---------- 备料单 ----------
|
||||
|
||||
// GenerateMaterialHandler 按日排产生成备料单(生成前校验 BOM 物料在 WMS 档案存在)
|
||||
func GenerateMaterialHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
@@ -54,12 +55,17 @@ func GenerateMaterialHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
n, err := logic.New(svcCtx).GenerateMaterialRequest(r.Context(), req.PlanDate, operator(r, ""))
|
||||
count, missing, err := logic.New(svcCtx).GenerateMaterialRequest(r.Context(), req.PlanDate, operator(r, ""))
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3103, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "生成完成", map[string]int{"count": n})
|
||||
if len(missing) > 0 {
|
||||
// 有物料在 WMS 档案不存在:不生成,把缺失列表返回给前端弹窗
|
||||
httpx.Ok(w, map[string]any{"count": 0, "missing": missing, "blocked": true})
|
||||
return
|
||||
}
|
||||
httpx.OkMessage(w, "生成完成", map[string]any{"count": count, "blocked": false})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,4 +79,42 @@ func ListMaterialRequestsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
// ListMaterialRequestsInternalHandler 内部接口:供 WMS 拉取备料单(含 target_dock),X-API-TOKEN 保护。
|
||||
// WMS AGV 配送页据此展示待发料行,仓管确认 target_dock 后调用 WMS AGV 下发。
|
||||
func ListMaterialRequestsInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
data, err := logic.New(svcCtx).ListMaterialRequests(r.Context(), q.Get("orderNo"), q.Get("planDate"), q.Get("status"))
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3105, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
// MarkMaterialRequestStatusInternalHandler 内部接口:WMS 下发 AGV 后回写备料单状态(DELIVERING/DONE)。
|
||||
// 供 WMS AGV 任务推进状态时联动 MES 备料单,保持一致。
|
||||
func MarkMaterialRequestStatusInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
RequestNo string `json:"requestNo"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil || req.RequestNo == "" {
|
||||
httpx.BadRequest(w, "请求体缺失")
|
||||
return
|
||||
}
|
||||
if req.Status != "DELIVERING" && req.Status != "DONE" {
|
||||
httpx.Fail(w, 3106, "非法状态")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).SetMaterialRequestStatus(r.Context(), req.RequestNo, req.Status); err != nil {
|
||||
httpx.Fail(w, 3106, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"bj_power_mes/common/httpx"
|
||||
"bj_power_mes/internal/svc"
|
||||
)
|
||||
|
||||
// DockPalletInternalHandler 内部接口:读某接驳台是否有托盘(PLC 托盘传感器)。
|
||||
// WMS AGV 到达目的地前调用,确认接驳台空闲。
|
||||
func DockPalletInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
dockCode := r.URL.Query().Get("dockCode")
|
||||
if dockCode == "" {
|
||||
httpx.BadRequest(w, "缺少 dockCode")
|
||||
return
|
||||
}
|
||||
has, err := svcCtx.PLC.Get().QueryDockPallet(r.Context(), dockCode)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3201, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, map[string]any{"dockCode": dockCode, "hasPallet": has})
|
||||
}
|
||||
}
|
||||
|
||||
// SetDockPalletInternalHandler 内部接口:mock 联调用,手动置位某接驳台是否有托盘。
|
||||
// 仅在 mock 模式下生效(真实 PLC 模式忽略,读的是真实传感器)。
|
||||
func SetDockPalletInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
DockCode string `json:"dockCode"`
|
||||
HasPallet bool `json:"hasPallet"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil || req.DockCode == "" {
|
||||
httpx.BadRequest(w, "请求体缺失")
|
||||
return
|
||||
}
|
||||
svcCtx.PLC.SetMockDockPallet(req.DockCode, req.HasPallet)
|
||||
if !svcCtx.PLC.IsMock() {
|
||||
httpx.OkMessage(w, "真实 PLC 模式忽略手动置位", nil)
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, nil)
|
||||
}
|
||||
}
|
||||
@@ -105,9 +105,12 @@ func OrderQueryInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
|
||||
// ---------- 看板内部接口 ----------
|
||||
|
||||
func DashboardOverviewInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
// DashboardSnapshotInternalHandler 看板全量快照。
|
||||
// 结构与本项目看板前端 src/types.ts 严格对齐(见 internal/logic/dashboard_front.go),
|
||||
// 由 DashboardSnapshotInternalHandler 一次性返回,前端不再分接口拼装。
|
||||
func DashboardSnapshotInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).DashboardOverview(r.Context())
|
||||
data, err := logic.New(svcCtx).DashboardFrontSnapshot(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 2005, err.Error())
|
||||
return
|
||||
@@ -115,47 +118,3 @@ func DashboardOverviewInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFu
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
func DashboardEquipmentInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).DashboardEquipment(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 2006, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
func DashboardProgressInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).DashboardProgress(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 2007, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
func DashboardAlarmsInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).DashboardAlarms(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 2008, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
func DashboardTrendsInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := logic.New(svcCtx).DashboardTrends(r.Context())
|
||||
if err != nil {
|
||||
httpx.Fail(w, 2009, err.Error())
|
||||
return
|
||||
}
|
||||
httpx.Ok(w, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,18 +127,19 @@ func GetWorkOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// SetWorkOrderStatusHandler POST /work-orders/status(工单状态流转)
|
||||
// SetWorkOrderStatusHandler POST /work-orders/status(工单状态流转,可选原因)
|
||||
func SetWorkOrderStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Id int `json:"id"`
|
||||
Status string `json:"status"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if err := httpx.ParseJSON(r, &req); err != nil {
|
||||
httpx.BadRequest(w, "请求体解析失败")
|
||||
return
|
||||
}
|
||||
if err := logic.New(svcCtx).SetWorkOrderStatus(r.Context(), req.Id, req.Status, operator(r, "")); err != nil {
|
||||
if err := logic.New(svcCtx).SetWorkOrderStatus(r.Context(), req.Id, req.Status, req.Reason, operator(r, "")); err != nil {
|
||||
httpx.Fail(w, 3008, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -201,3 +202,16 @@ func DeleteDailyPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
httpx.Ok(w, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// SuggestedDockCodesHandler 查某工单「上次使用的接驳台」,供排产默认推荐
|
||||
func SuggestedDockCodesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
orderNo := r.URL.Query().Get("orderNo")
|
||||
if orderNo == "" {
|
||||
httpx.BadRequest(w, "缺少工单号")
|
||||
return
|
||||
}
|
||||
docks := logic.New(svcCtx).SuggestedDockCodes(r.Context(), orderNo)
|
||||
httpx.Ok(w, map[string]any{"dockCodes": docks})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package production
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"bj_power_mes/common/httpx"
|
||||
"bj_power_mes/internal/logic"
|
||||
@@ -114,8 +115,10 @@ func ListEventLogsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
q := r.URL.Query()
|
||||
page := atoiDefault(q.Get("page"), 1)
|
||||
pageSize := atoiDefault(q.Get("pageSize"), 20)
|
||||
fromMs, _ := strconv.ParseInt(q.Get("from"), 10, 64)
|
||||
toMs, _ := strconv.ParseInt(q.Get("to"), 10, 64)
|
||||
list, total, err := logic.New(svcCtx).ListEventLogs(r.Context(),
|
||||
q.Get("orderNo"), q.Get("operator"), q.Get("eventType"), page, pageSize)
|
||||
q.Get("orderNo"), q.Get("operator"), q.Get("eventType"), fromMs, toMs, page, pageSize)
|
||||
if err != nil {
|
||||
httpx.Fail(w, 3308, err.Error())
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user