package logic import ( "context" "time" "bj_power_mes/ent/plcsendlog" "bj_power_mes/ent/scanrecord" "bj_power_mes/ent/torquerecord" "bj_power_mes/ent/workorder" "bj_power_mes/ent/workpiece" "bj_power_mes/ent/workpieceprocess" "github.com/zeromicro/go-zero/core/logx" ) const dashboardTTL = 60 // 秒,看板缓存 // DashboardOverview 生产总览 func (s *Service) DashboardOverview(ctx context.Context) (any, error) { return s.cached(ctx, "dashboard:overview", dashboardTTL, func() (any, error) { woCount, _ := s.ctx.EntClient.WorkOrder.Query().Count(ctx) woInProgress, _ := s.ctx.EntClient.WorkOrder.Query(). Where(workorder.StatusIn("CREATED", "RELEASED", "IN_PROGRESS")).Count(ctx) totalQty := s.sumInt(ctx, "SELECT COALESCE(SUM(quantity),0) FROM work_order") doneQuantity := s.sumInt(ctx, "SELECT COALESCE(SUM(finished_num),0) FROM work_order") workpieceInLine, _ := s.ctx.EntClient.Workpiece.Query(). Where(workpiece.DoneAtIsNil()).Count(ctx) ngCount, _ := s.ctx.EntClient.TorqueRecord.Query(). Where(torquerecord.Result("NG")).Count(ctx) torqueTotal, _ := s.ctx.EntClient.TorqueRecord.Query().Count(ctx) okRate := 100.0 if torqueTotal > 0 { okRate = float64(torqueTotal-ngCount) / float64(torqueTotal) * 100 } recentScan, _ := s.ctx.EntClient.ScanRecord.Query(). Order(scanrecord.ByID()).Limit(10).Count(ctx) return map[string]any{ "workOrderCount": woCount, "workOrderActive": woInProgress, "totalQuantity": totalQty, "doneQuantity": doneQuantity, "workpieceInLine": workpieceInLine, "okRate": okRate, "ngCount": ngCount, "torqueTotal": torqueTotal, "recentScans": recentScan, "updatedAt": time.Now(), }, nil }) } // DashboardEquipment 工位状态:按工件工序实绩聚合 12 工位 func (s *Service) DashboardEquipment(ctx context.Context) (any, error) { return s.cached(ctx, "dashboard:equipment", dashboardTTL, func() (any, error) { stations := make([]map[string]any, 0, 12) for i := 1; i <= 12; i++ { done, _ := s.ctx.EntClient.WorkpieceProcess.Query(). Where(workpieceprocess.ProcessCode(i)).Count(ctx) ng, _ := s.ctx.EntClient.WorkpieceProcess.Query(). Where(workpieceprocess.ProcessCode(i), workpieceprocess.Result("NG")).Count(ctx) status := "FREE" if done > 0 { status = "RUNNING" } stations = append(stations, map[string]any{ "stationNo": i, "status": status, "doneCount": done, "ngCount": ng, }) } return map[string]any{"stations": stations, "updatedAt": time.Now()}, nil }) } // DashboardProgress 工单进度 func (s *Service) DashboardProgress(ctx context.Context) (any, error) { return s.cached(ctx, "dashboard:progress", dashboardTTL, func() (any, error) { wos, _ := s.ctx.EntClient.WorkOrder.Query().Order(workorder.ByID()).Limit(20).All(ctx) return map[string]any{"workOrders": wos, "updatedAt": time.Now()}, nil }) } // DashboardAlarms 异常报警:拧紧NG、PLC等待/超时、进线扫码 func (s *Service) DashboardAlarms(ctx context.Context) (any, error) { return s.cached(ctx, "dashboard:alarms", dashboardTTL, func() (any, error) { ngTorque, _ := s.ctx.EntClient.TorqueRecord.Query(). Where(torquerecord.Result("NG")).Order(torquerecord.ByID()).Limit(20).Count(ctx) plcTimeout, _ := s.ctx.EntClient.PlcSendLog.Query(). Where(plcsendlog.Status("TIMEOUT")).Count(ctx) openPlc, _ := s.ctx.EntClient.PlcSendLog.Query(). Where(plcsendlog.Status("SENT")).Count(ctx) alarms := []map[string]any{} if ngTorque > 0 { alarms = append(alarms, map[string]any{"level": "WARN", "type": "torque_ng", "message": "存在拧紧NG记录", "count": ngTorque}) } if openPlc > 0 { alarms = append(alarms, map[string]any{"level": "INFO", "type": "plc_pending", "message": "存在待完成PLC工序", "count": openPlc}) } if plcTimeout > 0 { alarms = append(alarms, map[string]any{"level": "CRITICAL", "type": "plc_timeout", "message": "存在PLC下发超时", "count": plcTimeout}) } return map[string]any{ "alarms": alarms, "ngTorqueCount": ngTorque, "updatedAt": time.Now(), }, nil }) } // DashboardTrends 近7日产量趋势 func (s *Service) DashboardTrends(ctx context.Context) (any, error) { return s.cached(ctx, "dashboard:trends", dashboardTTL, func() (any, error) { result := []map[string]any{} for i := 6; i >= 0; i-- { start := time.Now().AddDate(0, 0, -i) start = time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, time.Local) date := start.Format("2006-01-02") end := start.Add(24 * time.Hour) cnt, _ := s.ctx.EntClient.Workpiece.Query(). Where(workpiece.DoneAtGTE(start), workpiece.DoneAtLT(end)).Count(ctx) torque, _ := s.ctx.EntClient.TorqueRecord.Query(). Where(torquerecord.TimeGTE(start), torquerecord.TimeLT(end)).Count(ctx) result = append(result, map[string]any{"date": date, "done": cnt, "torque": torque}) } return map[string]any{"trends": result, "updatedAt": time.Now()}, nil }) } func (s *Service) sumInt(ctx context.Context, sql string) int { row, err := s.ctx.EntClient.QueryContext(ctx, sql) if err != nil { logx.Debugf("sumInt err: %v", err) return 0 } defer row.Close() var v int if row.Next() { _ = row.Scan(&v) } return v }