Files
bj_power/bj_power_mes/internal/logic/dashboard.go
T
SunYF ae4c292487 feat: 完成产线MES系统全流程功能迭代与优化
本提交完成了多个核心模块的功能完善与业务对齐:
1. 工位终端:固定工位配置、移除自选工位逻辑、适配配置化工位号
2. MES核心:重构工位组合逻辑、新增工单/流程状态管理、补全报工/追溯逻辑
3. WMS客户端:新增修改密码功能、优化帮助弹窗逻辑
4. 文档与权限:补充完整操作手册、统一菜单名称与权限描述
5. 修复多业务校验:排产数量校验、工单状态校验、工位绑定规则
2026-08-31 12:58:28 +08:00

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": "存在待完成工位组合", "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
}