fix: rebuild MES as compilable go-zero+ent backend (renamed bj_power_mes), restore 3 workstation projects from pristine original, align naming; all Go projects go build clean

This commit is contained in:
SunYF
2026-08-27 10:56:41 +08:00
parent 380715f8a9
commit 371b494c54
523 changed files with 67923 additions and 24758 deletions
@@ -0,0 +1,139 @@
package job
import (
"context"
"fmt"
"bj_power_mes/common/errorx"
"bj_power_mes/ent"
entjob "bj_power_mes/ent/job"
"bj_power_mes/ent/recipestep"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetJobLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetJobLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetJobLogic {
return &GetJobLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetJobLogic) GetJob(req *types.PathId) (*types.JobDetailReply, error) {
j, err := l.svcCtx.EntClient.Job.Query().
Where(entjob.ID(req.Id)).
WithWorkOrder().
WithProductType().
WithRecipe(func(q *ent.RecipeQuery) {
q.WithSteps(func(sq *ent.RecipeStepQuery) {
sq.Order(ent.Asc(recipestep.FieldStepIndex))
})
}).
WithStepInstances().
Only(l.ctx)
if ent.IsNotFound(err) {
return nil, errorx.New(errorx.WorkpieceNotFound)
} else if err != nil {
return nil, err
}
reply := &types.JobDetailReply{
JobReply: types.JobReply{
Id: j.ID,
WorkOrderId: j.WorkOrderId,
WorkpieceNo: j.WorkpieceNo,
ProductTypeId: j.ProductTypeId,
RecipeId: j.RecipeId,
CurrentStepId: j.CurrentStepId,
CurrentStepName: stepName(j),
Status: string(j.Status),
PositionType: string(j.PositionType),
PositionRefId: j.PositionRefId,
Priority: j.Priority,
SuspendedReason: j.SuspendedReason,
Version: j.Version,
},
}
if !j.CreatedAt.IsZero() {
reply.CreatedAt = j.CreatedAt.Format("2006-01-02 15:04:05")
}
if j.UpdatedAt != nil && !j.UpdatedAt.IsZero() {
reply.UpdatedAt = j.UpdatedAt.Format("2006-01-02 15:04:05")
}
if !j.CompletedAt.IsZero() {
reply.CompletedTime = j.CompletedAt.Format("2006-01-02 15:04:05")
}
if !j.CncStartedAt.IsZero() {
reply.CncStartedAt = j.CncStartedAt.Format("2006-01-02 15:04:05")
}
if !j.CncCompletedAt.IsZero() {
reply.CncCompletedAt = j.CncCompletedAt.Format("2006-01-02 15:04:05")
}
if j.Context != nil {
reply.Context = j.Context
}
if wo, err := j.Edges.WorkOrderOrErr(); err == nil {
reply.WorkOrderNo = fmt.Sprintf("WO-%d", wo.ID)
}
if pt, err := j.Edges.ProductTypeOrErr(); err == nil {
reply.ProductTypeName = string(pt.Category)
}
if r, err := j.Edges.RecipeOrErr(); err == nil {
reply.RecipeName = r.Name
if r.Edges.Steps != nil {
reply.RecipeSteps = make([]types.RecipeStepBrief, 0, len(r.Edges.Steps))
for _, s := range r.Edges.Steps {
reply.RecipeSteps = append(reply.RecipeSteps, types.RecipeStepBrief{
StepId: s.StepId,
StepName: s.StepName,
})
}
}
}
if j.DockNo != nil {
reply.DockNo = *j.DockNo
}
if j.DockSlotNo != nil {
reply.DockSlotNo = *j.DockSlotNo
}
if j.TempSlotNo != nil {
reply.TempSlotNo = *j.TempSlotNo
}
stepInstances, err := j.Edges.StepInstancesOrErr()
if err == nil {
reply.StepInstances = make([]types.JobStepInstanceReply, 0, len(stepInstances))
for _, si := range stepInstances {
item := types.JobStepInstanceReply{
Id: si.ID,
StepId: si.StepId,
AttemptNo: si.AttemptNo,
Status: string(si.Status),
}
if si.EquipmentId != nil {
item.EquipmentId = *si.EquipmentId
}
if si.StartTime != nil {
item.StartTime = si.StartTime.Format("2006-01-02 15:04:05")
}
if si.EndTime != nil && !si.EndTime.IsZero() {
item.EndTime = si.EndTime.Format("2006-01-02 15:04:05")
}
reply.StepInstances = append(reply.StepInstances, item)
}
}
return reply, nil
}
@@ -0,0 +1,164 @@
package job
import (
"context"
"bj_power_mes/constants"
"bj_power_mes/ent"
entjob "bj_power_mes/ent/job"
"bj_power_mes/ent/predicate"
entrecipestep "bj_power_mes/ent/recipestep"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryJobsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryJobsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryJobsLogic {
return &QueryJobsLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
}
func (l *QueryJobsLogic) QueryJobs(req *types.QueryJobsReq) (resp *types.QueryJobsReply, err error) {
var conditions []predicate.Job
if req.Keyword != "" {
conditions = append(conditions, entjob.WorkpieceNoContains(req.Keyword))
}
if req.WorkOrderId > 0 {
conditions = append(conditions, entjob.WorkOrderId(req.WorkOrderId))
}
if req.ProductTypeId > 0 {
conditions = append(conditions, entjob.ProductTypeId(req.ProductTypeId))
}
if len(req.Statuses) > 0 {
statuses := make([]constants.JobStatus, 0, len(req.Statuses))
for _, s := range req.Statuses {
statuses = append(statuses, constants.JobStatus(s))
}
conditions = append(conditions, entjob.StatusIn(statuses...))
}
if req.PositionType != "" {
conditions = append(conditions, entjob.PositionTypeEQ(constants.PositionType(req.PositionType)))
}
q := l.svcCtx.EntClient.Job.Query().Where(conditions...).
WithRecipe(func(rq *ent.RecipeQuery) {
rq.WithSteps(func(sq *ent.RecipeStepQuery) {
sq.Order(ent.Asc(entrecipestep.FieldStepIndex))
})
})
total, err := q.Count(l.ctx)
if err != nil {
return nil, err
}
orderFn := ent.Desc(entjob.FieldID)
if req.Sort != "" {
switch req.Sort {
case "workpieceNo":
if req.Order == "ascend" {
orderFn = ent.Asc(entjob.FieldWorkpieceNo)
} else {
orderFn = ent.Desc(entjob.FieldWorkpieceNo)
}
case "workOrderId":
if req.Order == "ascend" {
orderFn = ent.Asc(entjob.FieldWorkOrderId)
} else {
orderFn = ent.Desc(entjob.FieldWorkOrderId)
}
case "status":
if req.Order == "ascend" {
orderFn = ent.Asc(entjob.FieldStatus)
} else {
orderFn = ent.Desc(entjob.FieldStatus)
}
default:
if req.Order == "ascend" {
orderFn = ent.Asc(entjob.FieldID)
} else {
orderFn = ent.Desc(entjob.FieldID)
}
}
}
offset := (req.Page - 1) * req.Limit
jobs, err := q.
Order(orderFn).
Offset(offset).
Limit(req.Limit).
All(l.ctx)
if err != nil {
return nil, err
}
data := make([]types.JobReply, 0, len(jobs))
for _, j := range jobs {
item := types.JobReply{
Id: j.ID,
WorkOrderId: j.WorkOrderId,
WorkpieceNo: j.WorkpieceNo,
ProductTypeId: j.ProductTypeId,
RecipeId: j.RecipeId,
CurrentStepId: j.CurrentStepId,
CurrentStepName: stepName(j),
Status: string(j.Status),
PositionType: string(j.PositionType),
PositionRefId: j.PositionRefId,
Priority: j.Priority,
SuspendedReason: j.SuspendedReason,
Version: j.Version,
}
if !j.CreatedAt.IsZero() {
item.CreatedAt = j.CreatedAt.Format("2006-01-02 15:04:05")
}
if j.UpdatedAt != nil && !j.UpdatedAt.IsZero() {
item.UpdatedAt = j.UpdatedAt.Format("2006-01-02 15:04:05")
}
if !j.CncStartedAt.IsZero() {
item.CncStartedAt = j.CncStartedAt.Format("2006-01-02 15:04:05")
}
if !j.CncCompletedAt.IsZero() {
item.CncCompletedAt = j.CncCompletedAt.Format("2006-01-02 15:04:05")
}
if j.Context != nil {
item.Context = j.Context
}
if !j.CompletedAt.IsZero() {
item.CompletedAt = j.CompletedAt.Format("2006-01-02 15:04:05")
}
data = append(data, item)
}
return &types.QueryJobsReply{
PageReply: types.PageReply{Page: req.Page, Limit: req.Limit, Total: total},
Data: data,
}, nil
}
func stepName(j *ent.Job) string {
if j.CurrentStepId == "" {
return ""
}
r, err := j.Edges.RecipeOrErr()
if err != nil || r == nil {
return j.CurrentStepId
}
steps, err := r.Edges.StepsOrErr()
if err != nil {
return j.CurrentStepId
}
for _, s := range steps {
if s.StepId == j.CurrentStepId {
return s.StepName
}
}
return j.CurrentStepId
}
@@ -0,0 +1,105 @@
package job
import (
"context"
"bj_power_mes/constants"
"bj_power_mes/ent"
entjob "bj_power_mes/ent/job"
"bj_power_mes/ent/predicate"
entrecipestep "bj_power_mes/ent/recipestep"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryJobsOfWorkOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryJobsOfWorkOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryJobsOfWorkOrderLogic {
return &QueryJobsOfWorkOrderLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
}
func (l *QueryJobsOfWorkOrderLogic) QueryJobsOfWorkOrder(req *types.QueryJobsOfWorkOrderReq) (resp *types.QueryJobsReply, err error) {
var conditions []predicate.Job
// req.Id is the work order ID from the path
conditions = append(conditions, entjob.WorkOrderId(req.Id))
if len(req.Statuses) > 0 {
statuses := make([]constants.JobStatus, 0, len(req.Statuses))
for _, s := range req.Statuses {
statuses = append(statuses, constants.JobStatus(s))
}
conditions = append(conditions, entjob.StatusIn(statuses...))
}
q := l.svcCtx.EntClient.Job.Query().Where(conditions...).
WithRecipe(func(rq *ent.RecipeQuery) {
rq.WithSteps(func(sq *ent.RecipeStepQuery) {
sq.Order(ent.Asc(entrecipestep.FieldStepIndex))
})
})
total, err := q.Count(l.ctx)
if err != nil {
return nil, err
}
offset := (req.Page - 1) * req.Limit
jobs, err := q.
Order(ent.Desc(entjob.FieldID)).
Offset(offset).
Limit(req.Limit).
All(l.ctx)
if err != nil {
return nil, err
}
data := make([]types.JobReply, 0, len(jobs))
for _, j := range jobs {
item := types.JobReply{
Id: j.ID,
WorkOrderId: j.WorkOrderId,
WorkpieceNo: j.WorkpieceNo,
ProductTypeId: j.ProductTypeId,
RecipeId: j.RecipeId,
CurrentStepId: j.CurrentStepId,
CurrentStepName: stepName(j),
Status: string(j.Status),
PositionType: string(j.PositionType),
PositionRefId: j.PositionRefId,
Priority: j.Priority,
SuspendedReason: j.SuspendedReason,
Version: j.Version,
}
if !j.CreatedAt.IsZero() {
item.CreatedAt = j.CreatedAt.Format("2006-01-02 15:04:05")
}
if j.UpdatedAt != nil && !j.UpdatedAt.IsZero() {
item.UpdatedAt = j.UpdatedAt.Format("2006-01-02 15:04:05")
}
if !j.CncStartedAt.IsZero() {
item.CncStartedAt = j.CncStartedAt.Format("2006-01-02 15:04:05")
}
if !j.CncCompletedAt.IsZero() {
item.CncCompletedAt = j.CncCompletedAt.Format("2006-01-02 15:04:05")
}
if j.Context != nil {
item.Context = j.Context
}
if !j.CompletedAt.IsZero() {
item.CompletedAt = j.CompletedAt.Format("2006-01-02 15:04:05")
}
data = append(data, item)
}
return &types.QueryJobsReply{
PageReply: types.PageReply{Page: req.Page, Limit: req.Limit, Total: total},
Data: data,
}, nil
}
@@ -0,0 +1,60 @@
package job
import (
"context"
"fmt"
"time"
"bj_power_mes/common/errorx"
"bj_power_mes/internal/processor/eventloop"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ResumeJobLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewResumeJobLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ResumeJobLogic {
return &ResumeJobLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ResumeJobLogic) ResumeJob(req *types.ResumeJobReq) error {
// 查询工件关联的工单状态
j, err := l.svcCtx.EntClient.Job.Get(l.ctx, req.Id)
if err != nil {
return fmt.Errorf("查询工件失败: %w", err)
}
wo, err := l.svcCtx.EntClient.WorkOrder.Get(l.ctx, j.WorkOrderId)
if err != nil {
return fmt.Errorf("查询工单失败: %w", err)
}
if wo.Status == "PAUSED" {
return errorx.NewDirectError(fmt.Sprintf("工单 #%d 处于暂停状态,请先恢复工单", wo.ID))
}
if wo.Status != "IN_PROGRESS" {
return fmt.Errorf("工单 #%d 状态为 %s,无法恢复工件", wo.ID, wo.Status)
}
result, err := l.svcCtx.EventLoop.SendSync(eventloop.EventLoopMessage{
Type: eventloop.CmdResumeJob,
Payload: map[string]any{
"jobId": req.Id,
},
}, 5*time.Second)
if err != nil {
return err
}
if !result.Success {
return errorx.NewDirectError(fmt.Sprintf("resume job %d failed: %s", req.Id, result.Error))
}
return nil
}
@@ -0,0 +1,41 @@
package job
import (
"context"
"fmt"
"time"
"bj_power_mes/internal/processor/eventloop"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ReworkJobLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewReworkJobLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ReworkJobLogic {
return &ReworkJobLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
}
func (l *ReworkJobLogic) ReworkJob(req *types.ReworkJobReq) error {
result, err := l.svcCtx.EventLoop.SendSync(eventloop.EventLoopMessage{
Type: eventloop.CmdReworkJob,
Payload: map[string]any{
"jobId": req.Id,
"targetStepId": req.TargetStepId,
"reason": req.Reason,
},
}, 5*time.Second)
if err != nil {
return err
}
if !result.Success {
return fmt.Errorf("rework job %d failed: %s", req.Id, result.Error)
}
return nil
}
@@ -0,0 +1,48 @@
package job
import (
"context"
"fmt"
"time"
"bj_power_mes/internal/processor/eventloop"
"bj_power_mes/internal/svc"
"bj_power_mes/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SuspendJobLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSuspendJobLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SuspendJobLogic {
return &SuspendJobLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SuspendJobLogic) SuspendJob(req *types.SuspendJobReq) error {
reason := req.Reason
if reason == "" {
reason = "manual"
}
result, err := l.svcCtx.EventLoop.SendSync(eventloop.EventLoopMessage{
Type: eventloop.CmdSuspendJob,
Payload: map[string]any{
"jobId": req.Id,
"reason": reason,
},
}, 5*time.Second)
if err != nil {
return err
}
if !result.Success {
return fmt.Errorf("suspend job %d failed: %s", req.Id, result.Error)
}
return nil
}