refactor: 重构产线工位与备料流程,移除冗余字段

1. 移除工单、工件、日排产中的冗余工位组合/接驳台字段
2. 新增工位接驳台编码字段与唯一约束,关联WMS接驳台主数据
3. 重构日排产为工位产量分配模式,替代原接驳台列表
4. 新增备料单工位级字段与分批出库支持
5. 移除定时同步可生产数量,改为WMS实时拉取接口
6. 过滤操作日志,排除登录/退出相关日志
7. 调整仪表盘工序展示逻辑为今日派工路线
8. 新增接驳台维护菜单与基础数据
This commit is contained in:
SunYF
2026-09-19 07:50:21 +08:00
parent 543655d441
commit 37f10d3a13
156 changed files with 4489 additions and 1285 deletions
@@ -223,7 +223,7 @@ func ListMaterialRequestsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
q := r.URL.Query()
data, err := logic.New(svcCtx).ListMaterialRequestsFiltered(r.Context(),
q.Get("orderNo"), q.Get("planDate"), q.Get("status"),
q.Get("materialCode"), q.Get("materialName"), q.Get("targetDock"))
q.Get("materialCode"), q.Get("materialName"), q.Get("targetDock"), q.Get("stationNo"))
if err != nil {
httpx.Fail(w, 3104, err.Error())
return
@@ -237,7 +237,7 @@ func ListMaterialRequestsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
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"))
data, err := logic.New(svcCtx).ListMaterialRequests(r.Context(), q.Get("orderNo"), q.Get("planDate"), q.Get("status"), q.Get("stationNo"))
if err != nil {
httpx.Fail(w, 3105, err.Error())
return
@@ -268,4 +268,59 @@ func MarkMaterialRequestStatusInternalHandler(svcCtx *svc.ServiceContext) http.H
}
httpx.Ok(w, nil)
}
}
// ---------- 接驳台 / 接料确认 ----------
// ListDocksHandler GET /docks 拉取 WMS 接驳台主数据(dock 真源在 WMS)。
// WMS 不可达降级为错误,前端仍可用写死兜底下拉。
func ListDocksHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
list, err := svcCtx.Wms.ListDocks(r.Context())
if err != nil {
httpx.Fail(w, 3113, "拉取接驳台失败:"+err.Error())
return
}
httpx.Ok(w, list)
}
}
// ReceiveMaterialRequestHandler POST /material-requests/receive 接料确认(MES 备料页人工点「已接料」)。
// qty 可空(≤0 表示确认本批全部剩余);累加 sentQty 封顶 reqQty,达量自动 DONE。
func ReceiveMaterialRequestHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
RequestNo string `json:"requestNo"`
Qty int `json:"qty"`
}
if err := httpx.ParseJSON(r, &req); err != nil || req.RequestNo == "" {
httpx.BadRequest(w, "缺少备料单号")
return
}
if err := logic.New(svcCtx).ReceiveMaterialRequest(r.Context(), req.RequestNo, req.Qty, operator(r, "")); err != nil {
httpx.Fail(w, 3114, err.Error())
return
}
httpx.OkMessage(w, "已接料", nil)
}
}
// StationReceiveMaterialInternalHandler POST /api/internal/station/receive-material 接料确认内部接口。
// 供工位终端代理调用(工人扫码接料主入口),X-API-TOKEN 保护。逻辑同 ReceiveMaterialRequestHandler。
func StationReceiveMaterialInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
RequestNo string `json:"requestNo"`
Qty int `json:"qty"`
}
if err := httpx.ParseJSON(r, &req); err != nil || req.RequestNo == "" {
httpx.BadRequest(w, "缺少备料单号")
return
}
if err := logic.New(svcCtx).ReceiveMaterialRequest(r.Context(), req.RequestNo, req.Qty, operator(r, "")); err != nil {
httpx.Fail(w, 3114, err.Error())
return
}
httpx.Ok(w, nil)
}
}
@@ -0,0 +1,22 @@
package production
import (
"net/http"
"bj_power_mes/common/httpx"
"bj_power_mes/internal/logic"
"bj_power_mes/internal/svc"
)
// ProducibleInternalHandler 内部接口:WMS 打开「可生产数量」时实时拉取。
// 不做定时/批量同步——WMS 需要时来拉一次,MES 现算现返(BOM 单台用量在 MES、可用量在 WMS)。
func ProducibleInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
res, err := logic.New(svcCtx).ComputeProducible(r.Context())
if err != nil {
httpx.Fail(w, 3401, err.Error())
return
}
httpx.Ok(w, res)
}
}
@@ -0,0 +1,69 @@
package production
import (
"net/http"
"bj_power_mes/common/httpx"
"bj_power_mes/internal/logic"
"bj_power_mes/internal/svc"
)
// ---------- 工位派工(工位↔工序,替代原工序组合串) ----------
// ListStationProcessHandler GET /station-process 查询某日班次全部工位派工(按工位号升序)
func ListStationProcessHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
data, err := logic.New(svcCtx).ListStationProcess(r.Context(), q.Get("effectDate"), q.Get("shift"))
if err != nil {
httpx.Fail(w, 3301, err.Error())
return
}
httpx.Ok(w, data)
}
}
// SaveStationProcessHandler POST /station-process/save 保存单条工位派工
// 校验:同工位同天同班次唯一;已派工工位沿工位号必须单调不降、不可穿插。processCode=0 表示解除派工。
func SaveStationProcessHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req logic.StationProcessReq
if err := httpx.ParseJSON(r, &req); err != nil {
httpx.BadRequest(w, "请求体解析失败")
return
}
if req.Operator == "" {
req.Operator = operator(r, "")
}
if err := logic.New(svcCtx).UpsertStationProcess(r.Context(), req); err != nil {
httpx.Fail(w, 3302, err.Error())
return
}
httpx.OkMessage(w, "保存成功", nil)
}
}
// RouteStationProcessHandler GET /station-process/route 派生路线(工位号列表/工序映射/串)
// 供流程卡、PLC 下发、备料单等依赖"今日路线"的模块读取,不再手填组合串。
func RouteStationProcessHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
ctx := r.Context()
stations, err := logic.RouteStations(ctx, svcCtx.EntClient, q.Get("effectDate"), q.Get("shift"))
if err != nil {
httpx.Fail(w, 3303, err.Error())
return
}
procMap, err := logic.RouteStationProcessCodeMap(ctx, svcCtx.EntClient, q.Get("effectDate"), q.Get("shift"))
if err != nil {
httpx.Fail(w, 3303, err.Error())
return
}
str, _ := logic.RouteStationsStr(ctx, svcCtx.EntClient, q.Get("effectDate"), q.Get("shift"))
httpx.Ok(w, map[string]any{
"stations": stations,
"processByStation": procMap,
"routeStr": str,
})
}
}