Files
bj_power/bj_power_workstation/internal/handler/station_ops.go
T
SunYF 4a5e2d7bac feat: 完成多模块迭代更新
- 新增过程巡检按步骤上报、数量不符上报、工位退料功能
- 增加工单工程编号三级归属字段
- 新增物料安全库存与缺货预警
- 新增附件管理、退库单管理模块
- 优化生产看板展示逻辑与前端页面文案
- 清理冗余的工艺路线相关代码与备份文件
2026-09-15 16:37:39 +08:00

137 lines
4.8 KiB
Go

package handler
import (
"encoding/json"
"io"
"net/http"
"bj_power_workstation/internal/svc"
)
// ============ 工位终端 → MES 内部 API 代理(巡检/应急/数量不符/退料) ============
// MES 侧对应接口以 X-API-TOKEN 保护(/api/internal/station/*),本服务用配置 token 转发。
// 统一:读请求体 → 注入 operator(当前登录人) → POST MES → 原样透传响应体。
// inspectionSubmitHandler POST /api/inspection/submit(签到/点检/过程巡检/完工确认/异常)
// 请求体:{category, stationNo, orderNo, sn, shift, result, items, photo, remark, processCode, stepId, stepName, measuredValue}
func inspectionSubmitHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
fail(w, http.StatusBadRequest, "请求体读取失败")
return
}
var req map[string]any
if err := json.Unmarshal(payload, &req); err != nil {
fail(w, http.StatusBadRequest, "请求体解析失败")
return
}
if req["category"] == nil || req["category"] == "" {
fail(w, http.StatusBadRequest, "记录类型 category 必填")
return
}
injectOperator(req, r)
body, _ := json.Marshal(req)
resp, _, perr := ctx.Mes.Post("/api/internal/station/inspection", json.RawMessage(body))
mesJSON(w, resp, perr)
}
}
// emergencyCallHandler POST /api/emergency/call(应急呼叫:落 MES 预警中心)
// 请求体:{stationNo, orderNo, remark}
func emergencyCallHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
fail(w, http.StatusBadRequest, "请求体读取失败")
return
}
var req map[string]any
if err := json.Unmarshal(payload, &req); err != nil {
fail(w, http.StatusBadRequest, "请求体解析失败")
return
}
injectOperator(req, r)
body, _ := json.Marshal(req)
resp, _, perr := ctx.Mes.Post("/api/internal/station/emergency", json.RawMessage(body))
mesJSON(w, resp, perr)
}
}
// qtyReportHandler POST /api/qty-report(工位数量不符上报:应发/实收/差异+原因)
// 请求体:{stationNo, orderNo, sn, materialCode, materialName, planQty, actualQty, cause}
func qtyReportHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
fail(w, http.StatusBadRequest, "请求体读取失败")
return
}
var req map[string]any
if err := json.Unmarshal(payload, &req); err != nil {
fail(w, http.StatusBadRequest, "请求体解析失败")
return
}
if req["materialCode"] == nil || req["materialCode"] == "" {
fail(w, http.StatusBadRequest, "物料编码必填")
return
}
injectOperator(req, r)
body, _ := json.Marshal(req)
resp, _, perr := ctx.Mes.Post("/api/internal/station/qty-report", json.RawMessage(body))
mesJSON(w, resp, perr)
}
}
// returnMaterialHandler POST /api/return-material(工位退料回库房 → WMS 预建待确认退库单)
// 请求体:{orderNo, stationNo, sn, materialCode, materialName, spec, qty, unit, reason}
func returnMaterialHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
fail(w, http.StatusBadRequest, "请求体读取失败")
return
}
var req map[string]any
if err := json.Unmarshal(payload, &req); err != nil {
fail(w, http.StatusBadRequest, "请求体解析失败")
return
}
if req["materialCode"] == nil || req["materialCode"] == "" {
fail(w, http.StatusBadRequest, "物料编码必填")
return
}
if q, ok := req["qty"].(float64); !ok || int(q) <= 0 {
fail(w, http.StatusBadRequest, "退库数量必须大于 0")
return
}
injectOperator(req, r)
body, _ := json.Marshal(req)
resp, _, perr := ctx.Mes.Post("/api/internal/station/return-material", json.RawMessage(body))
mesJSON(w, resp, perr)
}
}
// inspectionUploadHandler POST /api/inspection/upload(巡检拍照 base64 上传,代理 MES 内部接口)
// 请求体:{filename, data(base64)}
func inspectionUploadHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
fail(w, http.StatusBadRequest, "请求体读取失败")
return
}
resp, _, perr := ctx.Mes.Post("/api/internal/station/inspection-upload", json.RawMessage(payload))
mesJSON(w, resp, perr)
}
}
// injectOperator 若请求体未带 operator,则补当前登录人(工位终端 JWT 解析)
func injectOperator(req map[string]any, r *http.Request) {
if req["operator"] == nil || req["operator"] == "" {
if u := currentUsername(r); u != "" {
req["operator"] = u
}
}
}