146 lines
5.2 KiB
Go
146 lines
5.2 KiB
Go
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
|
||
|
|
}
|