Files
bj_power/bj_power_mes/internal/logic/inspection.go
T

145 lines
4.4 KiB
Go
Raw Normal View History

package logic
import (
"context"
"encoding/json"
"errors"
"strings"
"time"
"bj_power_mes/ent"
"bj_power_mes/ent/inspectionrecord"
)
// FlexStr 兼容客户端把数字字段传成 number 或 string(前端 stationNo 用数字,
// 标准 JSON 反序列化进 string 会报错 → 400 请求体解析失败)
type FlexStr string
func (f *FlexStr) UnmarshalJSON(b []byte) error {
s := strings.TrimSpace(string(b))
s = strings.Trim(s, `"`)
if s == "null" {
s = ""
}
*f = FlexStr(s)
return nil
}
// InspectionReq 巡检记录请求(PAD 巡检终端,块8)
type InspectionReq struct {
Category string `json:"category"` // CHECKIN/POINT/PROCESS/DONE/ALARM
StationNo FlexStr `json:"stationNo"`
Shift string `json:"shift"` // 早/中/晚
OrderNo string `json:"orderNo"` // 工单号
Sn string `json:"sn"` // 工件SN
Result string `json:"result"` // OK/NG
Items []string `json:"items"` // 点检项/异常类型
Photo string `json:"photo"` // 拍照文件名
Remark string `json:"remark"` // 文字描述/签字
Operator string `json:"operator"` // 操作人
}
// CreateInspection 提交巡检记录;ALARM 类型同时触发看板报警(SSE + 清缓存)
func (s *Service) CreateInspection(ctx context.Context, req InspectionReq, operator string) error {
if req.Category == "" {
return errors.New("记录类型必填")
}
category := req.Category
if !oneOf(category, "CHECKIN", "POINT", "PROCESS", "DONE", "ALARM") {
return errors.New("记录类型不合法")
}
result := req.Result
if result == "" {
result = "OK"
}
if req.Operator == "" {
req.Operator = operator
}
_, err := s.ctx.EntClient.InspectionRecord.Create().
SetCategory(category).
SetStationNo(string(req.StationNo)).
SetShift(req.Shift).
SetOrderNo(req.OrderNo).
SetSn(req.Sn).
SetResult(result).
SetItems(req.Items).
SetPhoto(req.Photo).
SetRemark(req.Remark).
SetOperator(req.Operator).
Save(ctx)
if err != nil {
return err
}
s.ctx.EventLog.Write(ctx, "inspection."+category, req.OrderNo, req.Operator, "inspection_record",
req.Sn, "巡检终端提交", map[string]any{"category": category, "stationNo": string(req.StationNo), "result": result})
if category == "ALARM" {
// 触发看板报警:SSE 推送 + 使 Redis 看板报警缓存失效
alarmJSON, _ := json.Marshal(map[string]any{
"level": "CRITICAL",
"type": "inspection_alarm",
"message": "巡检异常上报:" + req.Remark,
"station": string(req.StationNo),
"time": time.Now().Format("2006-01-02 15:04:05"),
})
if s.ctx.SSE != nil {
s.ctx.SSE.Publish("dashboard.alarm", string(alarmJSON))
}
if s.ctx.RedisClient != nil {
_, _ = s.ctx.RedisClient.Del("dashboard:alarms")
}
}
s.notifyDashboard()
return nil
}
// ListInspections 查询巡检记录(不分页,供内部/导出用,封顶 1000)
func (s *Service) ListInspections(ctx context.Context, category, operator, from, to string) ([]*ent.InspectionRecord, error) {
rows, _, err := s.ListInspectionsPaged(ctx, category, operator, from, to, "", "", 1, 1000)
return rows, err
}
// ListInspectionsPaged 分页查询巡检记录,返回 {rows, total};排序 id desc 最新置顶
// orderNo/stationNo2026-09-08 补充筛选(大小写不敏感)
func (s *Service) ListInspectionsPaged(ctx context.Context, category, operator, from, to, orderNo, stationNo string, page, pageSize int) ([]*ent.InspectionRecord, int, error) {
q := s.ctx.EntClient.InspectionRecord.Query()
if category != "" {
q = q.Where(inspectionrecord.Category(category))
}
if orderNo != "" {
q = q.Where(inspectionrecord.OrderNoEqualFold(orderNo))
}
if stationNo != "" {
q = q.Where(inspectionrecord.StationNoEqualFold(stationNo))
}
if operator != "" {
q = q.Where(inspectionrecord.Operator(operator))
}
if from != "" {
if f, err := time.Parse("2006-01-02", from); err == nil {
q = q.Where(inspectionrecord.CreatedAtGTE(f))
}
}
if to != "" {
if t, err := time.Parse("2006-01-02", to); err == nil {
q = q.Where(inspectionrecord.CreatedAtLT(t.Add(24 * time.Hour)))
}
}
total, err := q.Count(ctx)
if err != nil {
return nil, 0, err
}
rows, err := q.Order(ent.Desc(inspectionrecord.FieldID)).
Offset((page - 1) * pageSize).Limit(pageSize).All(ctx)
return rows, total, err
}
func oneOf(v string, items ...string) bool {
for _, it := range items {
if v == it {
return true
}
}
return false
}