2026-08-28 15:06:01 +08:00
|
|
|
|
package handler
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-09-17 12:49:07 +08:00
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"io"
|
2026-08-28 15:06:01 +08:00
|
|
|
|
"net/http"
|
|
|
|
|
|
"strconv"
|
2026-09-17 12:49:07 +08:00
|
|
|
|
"strings"
|
2026-08-28 15:06:01 +08:00
|
|
|
|
|
2026-09-17 12:49:07 +08:00
|
|
|
|
"bj_power_workstation/internal/store"
|
2026-08-28 15:06:01 +08:00
|
|
|
|
"bj_power_workstation/internal/svc"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// tighteningListHandler GET /api/tightening/list?sn=&only_pending=true&limit=100
|
|
|
|
|
|
// 查询本地 torque_results(最新优先)。
|
|
|
|
|
|
func tighteningListHandler(ctx *svc.ServiceContext) http.HandlerFunc {
|
|
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
q := r.URL.Query()
|
|
|
|
|
|
sn := q.Get("sn")
|
|
|
|
|
|
|
|
|
|
|
|
onlyPending := false
|
|
|
|
|
|
if v, err := strconv.ParseBool(q.Get("only_pending")); err == nil {
|
|
|
|
|
|
onlyPending = v
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
limit := atoi(q.Get("limit"), 100)
|
|
|
|
|
|
if limit <= 0 || limit > 500 {
|
|
|
|
|
|
limit = 500
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
list, err := ctx.Store.ListTorqueResults(sn, onlyPending, limit)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
fail(w, http.StatusInternalServerError, "查询拧紧结果失败:"+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
ok(w, map[string]any{
|
|
|
|
|
|
"total": len(list),
|
|
|
|
|
|
"list": list,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-09-17 12:49:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// tighteningRecordHandler POST /api/tightening/record —— 录入一条拧紧数据。
|
|
|
|
|
|
// 真实场景:工件走到「需要拧紧枪」的工艺步骤时界面聚焦拧紧输入框,人工操作拧紧枪把采集到的
|
|
|
|
|
|
// 扭矩值打入输入框回车 → 本接口按当前工件 SN + 工艺步骤落本地库,再由后台同步器上报 MES。
|
|
|
|
|
|
// 入参 {sn, workOrderNo, stepId, stepName, screwNo, torque, angle, result, operator};
|
|
|
|
|
|
// result 由前端按该步骤考核标准(扭矩 RANGE)判定后传入,非 NG 一律记 OK。
|
|
|
|
|
|
func tighteningRecordHandler(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 struct {
|
|
|
|
|
|
Sn string `json:"sn"`
|
|
|
|
|
|
WorkOrderNo string `json:"workOrderNo"`
|
|
|
|
|
|
StepId string `json:"stepId"`
|
|
|
|
|
|
StepName string `json:"stepName"`
|
|
|
|
|
|
ScrewNo string `json:"screwNo"`
|
|
|
|
|
|
Torque float64 `json:"torque"`
|
|
|
|
|
|
Angle float64 `json:"angle"`
|
|
|
|
|
|
Result string `json:"result"`
|
|
|
|
|
|
Operator string `json:"operator"`
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := json.Unmarshal(payload, &req); err != nil {
|
|
|
|
|
|
fail(w, http.StatusBadRequest, "请求体解析失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if strings.TrimSpace(req.Sn) == "" {
|
|
|
|
|
|
fail(w, http.StatusBadRequest, "缺少工件 SN,请先上料")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if strings.TrimSpace(req.StepId) == "" {
|
|
|
|
|
|
fail(w, http.StatusBadRequest, "缺少拧紧工艺步骤")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.Result != "NG" {
|
|
|
|
|
|
req.Result = "OK"
|
|
|
|
|
|
}
|
|
|
|
|
|
dockCode := fmt.Sprintf("DOCK%02d", ctx.Config.Station.StationNo)
|
|
|
|
|
|
id, err := ctx.Store.InsertTorqueResult(store.TorqueResult{
|
|
|
|
|
|
WorkOrderNo: req.WorkOrderNo,
|
|
|
|
|
|
Sn: req.Sn,
|
|
|
|
|
|
DockCode: dockCode,
|
|
|
|
|
|
ScrewNo: req.ScrewNo,
|
|
|
|
|
|
StepId: req.StepId,
|
|
|
|
|
|
StepName: req.StepName,
|
|
|
|
|
|
Torque: req.Torque,
|
|
|
|
|
|
Angle: req.Angle,
|
|
|
|
|
|
Result: req.Result,
|
|
|
|
|
|
Operator: req.Operator,
|
|
|
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
fail(w, http.StatusInternalServerError, "拧紧数据入库失败:"+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
ctx.Store.AddEventLog(req.WorkOrderNo, req.Operator, "torque_record",
|
|
|
|
|
|
fmt.Sprintf("拧紧录入 sn=%s 步骤=%s 扭矩=%.1f 结果=%s", req.Sn, req.StepName, req.Torque, req.Result))
|
|
|
|
|
|
ok(w, map[string]any{"id": id, "result": req.Result})
|
|
|
|
|
|
}
|
2026-08-28 15:06:01 +08:00
|
|
|
|
}
|