feat&refactor: 完成多模块功能迭代与配置优化
本次提交覆盖多个业务模块的功能完善与体验优化:
1. **鉴权与配置调整**:
- 统一JWT滑动续签逻辑,简化Token存储,移除RefreshToken相关冗余代码
- 调整多项目配置文件中JWT过期时间为3600秒,统一会话闲置窗口
- 工位配置放开1~12限制,改为仅校验大于0
2. **术语统一替换**:全链路将"精密件"替换为"电气件",修正物料管理描述
3. **功能新增**:
- 新增工位类型、工艺路线与产线点位台账模块
- 添加工艺PDF预览面板、工位终端代理转发接口
- 新增操作日志按操作人列表筛选、工位登出日志记录
- 新增PLC移料指令与产线点位状态管理
4. **业务流程优化**:
- 调整BOM物料删除校验逻辑,优化工单备料计算
- 补充物料图号、检测单号等追溯字段
- 完善工艺流程图与工位绑定关系说明
- 优化前端页面文案与交互细节
5. **代码规范与维护**:
- 新增通用工具函数与前端静态资源
- 整理路由权限与中间件逻辑
- 修复部分接口与配置的不兼容问题
This commit is contained in:
@@ -18,25 +18,22 @@ import (
|
||||
|
||||
// ---------- 工艺流程(块3) ----------
|
||||
|
||||
// FlowReq 工艺流程保存请求
|
||||
// StationNo:主工序编号 1..12(流程承载的工序号,沿用既有语义);
|
||||
// Stations:绑定工位列表(可多选,一个流程可绑多个工位;不传时默认只绑 StationNo)。
|
||||
// FlowReq 工艺流程保存请求(流程=菜谱,只描述"怎么干")
|
||||
// Stations:绑定工位列表(可多选,一个流程可绑多个工位)。
|
||||
type FlowReq struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StationNo int `json:"stationNo"`
|
||||
Stations []int `json:"stations"`
|
||||
PdfFile string `json:"pdfFile"`
|
||||
Status string `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
Steps []StepItemReq `json:"steps"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Stations []int `json:"stations"`
|
||||
PdfFile string `json:"pdfFile"`
|
||||
Status string `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
Steps []StepItemReq `json:"steps"`
|
||||
}
|
||||
|
||||
// FlowVO 工艺流程视图(含工序步骤 + 绑定该流程的工位号)
|
||||
type FlowVO struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
StationNo int `json:"stationNo"`
|
||||
PdfFile string `json:"pdfFile"`
|
||||
Status string `json:"status"`
|
||||
Remark string `json:"remark"`
|
||||
@@ -45,11 +42,11 @@ type FlowVO struct {
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
// ListFlows 查询工艺流程(可按工位号过滤:命中绑定该工位或主工序号的流程)
|
||||
// ListFlows 查询工艺流程(可按工位号过滤:只认「关联工位」页的绑定关系 station.flow_id)
|
||||
// page>0 时真分页返回 map{total,list,page,pageSize}(管理页用);page=0 全量数组(工位终端兼容)
|
||||
func (s *Service) ListFlows(ctx context.Context, stationNo, page, pageSize int) (any, error) {
|
||||
q := s.ctx.EntClient.ProcessFlow.Query().
|
||||
Order(ent.Asc(processflow.FieldProcessCode), ent.Asc(processflow.FieldID))
|
||||
Order(ent.Asc(processflow.FieldID))
|
||||
flows, err := q.All(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -63,7 +60,7 @@ func (s *Service) ListFlows(ctx context.Context, stationNo, page, pageSize int)
|
||||
}
|
||||
out := make([]*FlowVO, 0, len(flows))
|
||||
for _, f := range flows {
|
||||
// 过滤:指定工位号时,只返回"绑定列表或主工序号"命中该工位的流程
|
||||
// 过滤:指定工位号时,只返回绑定了该工位的流程
|
||||
if stationNo > 0 {
|
||||
hit := false
|
||||
for _, st := range flowToStations[f.ID] {
|
||||
@@ -72,14 +69,14 @@ func (s *Service) ListFlows(ctx context.Context, stationNo, page, pageSize int)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hit && f.ProcessCode != stationNo {
|
||||
if !hit {
|
||||
continue
|
||||
}
|
||||
}
|
||||
vo := &FlowVO{
|
||||
Id: f.ID, Name: f.Name, StationNo: f.ProcessCode,
|
||||
Id: f.ID, Name: f.Name,
|
||||
PdfFile: f.PdfFile, Status: f.Status, Remark: f.Remark,
|
||||
Stations: []int{}, Steps: s.flowSteps(ctx, f.ID, f.ProcessCode), CreatedAt: f.CreatedAt,
|
||||
Stations: []int{}, Steps: s.flowSteps(ctx, f.ID), CreatedAt: f.CreatedAt,
|
||||
}
|
||||
if list, ok := flowToStations[f.ID]; ok {
|
||||
vo.Stations = list
|
||||
@@ -102,34 +99,23 @@ func (s *Service) ListFlows(ctx context.Context, stationNo, page, pageSize int)
|
||||
}
|
||||
|
||||
// SaveFlow 保存工艺流程(可一次绑定多个工位)。
|
||||
// 约束:① 工位号/绑定工位 1..12;② 一个工位同时只能绑定一个"启用"流程(保存时校验冲突);
|
||||
// 约束:① 绑定工位必须已存在(工位主数据由数据库维护,本接口不自动创建);
|
||||
// ② 一个工位同时只能绑定一个流程(保存时直接覆盖旧绑定);
|
||||
// ③ 停用流程不再自动解绑工位(绑定关系由本保存接口显式维护,启停只切流程状态)。
|
||||
func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) error {
|
||||
if req.Name == "" {
|
||||
return errors.New("流程名称必填")
|
||||
}
|
||||
// 工序编号与物理工位解耦:工序是流程步骤编号(1~999,流程内唯一即可),
|
||||
// 工位对应关系由「关联工位」页维护(2026-09-08)
|
||||
if req.StationNo < 1 || req.StationNo > 999 {
|
||||
return errors.New("主工序编号应为 1~999 的整数")
|
||||
}
|
||||
// 解析绑定工位列表:显式 stations 优先,否则回退到 StationNo(兼容旧调用)
|
||||
bindStations := req.Stations
|
||||
if len(bindStations) == 0 {
|
||||
bindStations = []int{req.StationNo}
|
||||
}
|
||||
// 解析绑定工位列表
|
||||
seen := map[int]bool{}
|
||||
stations := []int{}
|
||||
for _, no := range bindStations {
|
||||
if no < 1 || no > 12 || seen[no] {
|
||||
for _, no := range req.Stations {
|
||||
if no < 1 || seen[no] {
|
||||
continue
|
||||
}
|
||||
seen[no] = true
|
||||
stations = append(stations, no)
|
||||
}
|
||||
if len(stations) == 0 {
|
||||
return errors.New("请至少选择一个绑定工位")
|
||||
}
|
||||
status := req.Status
|
||||
if status == "" {
|
||||
status = "ACTIVE"
|
||||
@@ -142,7 +128,7 @@ func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) er
|
||||
var flowID int
|
||||
if req.Id > 0 {
|
||||
upd := s.ctx.EntClient.ProcessFlow.UpdateOneID(req.Id).
|
||||
SetName(req.Name).SetProcessCode(req.StationNo).SetStatus(status).SetRemark(req.Remark)
|
||||
SetName(req.Name).SetStatus(status).SetRemark(req.Remark)
|
||||
if req.PdfFile != "" {
|
||||
upd.SetPdfFile(req.PdfFile)
|
||||
}
|
||||
@@ -152,7 +138,7 @@ func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) er
|
||||
flowID = req.Id
|
||||
} else {
|
||||
f, err := s.ctx.EntClient.ProcessFlow.Create().
|
||||
SetName(req.Name).SetProcessCode(req.StationNo).SetPdfFile(req.PdfFile).
|
||||
SetName(req.Name).SetPdfFile(req.PdfFile).
|
||||
SetStatus(status).SetRemark(req.Remark).Save(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -167,7 +153,9 @@ func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) er
|
||||
}
|
||||
}
|
||||
for _, no := range stations {
|
||||
s.syncStationFlow(ctx, no, flowID)
|
||||
if err := s.syncStationFlow(ctx, no, flowID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// 覆盖式重建该流程的工序步骤及考核标准
|
||||
_, _ = s.ctx.EntClient.ProcessStep.Delete().Where(processstep.FlowId(flowID)).Exec(ctx)
|
||||
@@ -176,8 +164,8 @@ func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) er
|
||||
continue
|
||||
}
|
||||
rec, err := s.ctx.EntClient.ProcessStep.Create().
|
||||
SetFlowId(flowID).SetProcessCode(req.StationNo).SetSeq(st.Seq).SetName(st.Name).
|
||||
SetCollectType(st.CollectType).SetIsTorque(st.IsTorque).SetRemark(st.Remark).Save(ctx)
|
||||
SetFlowId(flowID).SetSeq(st.Seq).SetName(st.Name).
|
||||
SetCollectType(st.CollectType).SetIsTorque(st.IsTorque).SetNeedCheck(st.NeedCheck).SetRemark(st.Remark).Save(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -200,20 +188,18 @@ func (s *Service) SaveFlow(ctx context.Context, req FlowReq, operator string) er
|
||||
}
|
||||
}
|
||||
s.ctx.EventLog.Write(ctx, "process.flow.save", "", operator, "process_flow", "", "维护工艺流程",
|
||||
map[string]any{"flowId": flowID, "processCode": req.StationNo, "stations": stations, "steps": len(req.Steps)})
|
||||
map[string]any{"flowId": flowID, "stations": stations, "steps": len(req.Steps)})
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncStationFlow 同步工位绑定:工位 stationNo 绑定到 flowID(无工位记录时自动创建)
|
||||
func (s *Service) syncStationFlow(ctx context.Context, stationNo, flowID int) {
|
||||
// syncStationFlow 同步工位绑定:工位 stationNo 绑定到 flowID(工位不存在时报错,不自动创建)
|
||||
func (s *Service) syncStationFlow(ctx context.Context, stationNo, flowID int) error {
|
||||
st, err := s.ctx.EntClient.Station.Query().Where(station.StationNo(stationNo)).First(ctx)
|
||||
if err != nil {
|
||||
_, _ = s.ctx.EntClient.Station.Create().
|
||||
SetStationNo(stationNo).SetName(fmt.Sprintf("工位%d", stationNo)).
|
||||
SetFlowId(flowID).Save(ctx)
|
||||
return
|
||||
return fmt.Errorf("工位 %d 不存在,请先在工位主数据中维护", stationNo)
|
||||
}
|
||||
_, _ = s.ctx.EntClient.Station.UpdateOneID(st.ID).SetFlowId(flowID).Save(ctx)
|
||||
_, err = s.ctx.EntClient.Station.UpdateOneID(st.ID).SetFlowId(flowID).Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) DeleteFlow(ctx context.Context, id int, operator string) error {
|
||||
@@ -227,14 +213,14 @@ func (s *Service) DeleteFlow(ctx context.Context, id int, operator string) error
|
||||
}
|
||||
|
||||
// flowSteps 查询某流程的工序步骤(含考核标准)
|
||||
func (s *Service) flowSteps(ctx context.Context, flowId, processCode int) []*ProcessStepTemplate {
|
||||
func (s *Service) flowSteps(ctx context.Context, flowId int) []*ProcessStepTemplate {
|
||||
steps, _ := s.ctx.EntClient.ProcessStep.Query().
|
||||
Where(processstep.FlowId(flowId)).Order(ent.Asc(processstep.FieldSeq)).All(ctx)
|
||||
out := make([]*ProcessStepTemplate, 0, len(steps))
|
||||
for _, st := range steps {
|
||||
t := &ProcessStepTemplate{
|
||||
ID: st.ID, ProcessCode: st.ProcessCode, Seq: st.Seq,
|
||||
Name: st.Name, CollectType: st.CollectType, IsTorque: st.IsTorque,
|
||||
ID: st.ID, Seq: st.Seq,
|
||||
Name: st.Name, CollectType: st.CollectType, IsTorque: st.IsTorque, NeedCheck: st.NeedCheck,
|
||||
Remark: st.Remark, Criteria: []CriterionVO{},
|
||||
}
|
||||
crits, _ := s.ctx.EntClient.StepCriterion.Query().
|
||||
@@ -253,10 +239,11 @@ func (s *Service) flowSteps(ctx context.Context, flowId, processCode int) []*Pro
|
||||
// ---------- 工位主数据(块3) ----------
|
||||
|
||||
type StationReq struct {
|
||||
Id int `json:"id"`
|
||||
StationNo int `json:"stationNo"`
|
||||
Name string `json:"name"`
|
||||
FlowId int `json:"flowId"`
|
||||
Id int `json:"id"`
|
||||
StationNo int `json:"stationNo"`
|
||||
Name string `json:"name"`
|
||||
StationType *string `json:"stationType"`
|
||||
FlowId *int `json:"flowId"`
|
||||
}
|
||||
|
||||
type StationVO struct {
|
||||
@@ -265,7 +252,7 @@ type StationVO struct {
|
||||
Name string `json:"name"`
|
||||
FlowId int `json:"flowId"`
|
||||
FlowName string `json:"flowName"`
|
||||
ProcessCode int `json:"processCode"`
|
||||
StationType string `json:"stationType"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
@@ -281,43 +268,51 @@ func (s *Service) ListStations(ctx context.Context) ([]*StationVO, error) {
|
||||
}
|
||||
out := make([]*StationVO, 0, len(stas))
|
||||
for _, st := range stas {
|
||||
vo := &StationVO{Id: st.ID, StationNo: st.StationNo, Name: st.Name, FlowId: st.FlowId, Status: st.Status}
|
||||
vo := &StationVO{Id: st.ID, StationNo: st.StationNo, Name: st.Name, FlowId: st.FlowId, StationType: st.StationType, Status: st.Status}
|
||||
if f, ok := flowMap[st.FlowId]; ok {
|
||||
vo.FlowName = f.Name
|
||||
vo.ProcessCode = f.ProcessCode
|
||||
}
|
||||
out = append(out, vo)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SaveStation 维护工位:只改名称/绑定流程。工位主数据由数据库维护,本接口不新增工位。
|
||||
func (s *Service) SaveStation(ctx context.Context, req StationReq, operator string) error {
|
||||
if req.StationNo <= 0 || req.StationNo > 12 {
|
||||
return errors.New("工位号必须在 1~12")
|
||||
if req.StationNo <= 0 {
|
||||
return errors.New("工位号非法")
|
||||
}
|
||||
st, err := s.ctx.EntClient.Station.Query().Where(station.StationNo(req.StationNo)).First(ctx)
|
||||
if err != nil {
|
||||
if _, err := s.ctx.EntClient.Station.Create().
|
||||
SetStationNo(req.StationNo).SetName(req.Name).Save(ctx); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("工位 %d 不存在,请先在工位主数据中维护", req.StationNo)
|
||||
}
|
||||
// 仅改名称:flowId 不传(nil)保留原绑定;0=解绑;>0=绑定指定启用流程
|
||||
upd := s.ctx.EntClient.Station.UpdateOneID(st.ID).SetName(req.Name)
|
||||
if req.StationType != nil {
|
||||
t := *req.StationType
|
||||
if t != "LINE" && t != "OFFLINE" {
|
||||
return errors.New("工位类型仅支持 LINE/OFFLINE")
|
||||
}
|
||||
} else {
|
||||
// 仅改名称:flowId 不传时保留原绑定
|
||||
upd := s.ctx.EntClient.Station.UpdateOneID(st.ID).SetName(req.Name)
|
||||
if req.FlowId > 0 {
|
||||
flow, fErr := s.ctx.EntClient.ProcessFlow.Get(ctx, req.FlowId)
|
||||
upd.SetStationType(t)
|
||||
}
|
||||
if req.FlowId != nil {
|
||||
fid := *req.FlowId
|
||||
if fid > 0 {
|
||||
flow, fErr := s.ctx.EntClient.ProcessFlow.Get(ctx, fid)
|
||||
if fErr != nil {
|
||||
return errors.New("所选工艺流程不存在")
|
||||
}
|
||||
if flow.Status != "ACTIVE" {
|
||||
return errors.New("该工艺流程已停用,请先启用后再绑定工位")
|
||||
}
|
||||
upd.SetFlowId(req.FlowId)
|
||||
}
|
||||
if _, err := upd.Save(ctx); err != nil {
|
||||
return err
|
||||
upd.SetFlowId(fid)
|
||||
} else {
|
||||
upd.SetFlowId(0)
|
||||
}
|
||||
}
|
||||
if _, err := upd.Save(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
s.ctx.EventLog.Write(ctx, "station.save", "", operator, "station", "", "维护工位",
|
||||
map[string]any{"stationNo": req.StationNo})
|
||||
return nil
|
||||
@@ -348,7 +343,7 @@ func (s *Service) SetFlowStatus(ctx context.Context, id int, status, operator st
|
||||
if status == "ACTIVE" {
|
||||
action = "启用工艺流程"
|
||||
}
|
||||
s.ctx.EventLog.Write(ctx, "process.flow.status", "", operator, "process_flow", "", action, map[string]any{"flowId": id, "status": status, "name": flow.Name, "processCode": flow.ProcessCode})
|
||||
s.ctx.EventLog.Write(ctx, "process.flow.status", "", operator, "process_flow", "", action, map[string]any{"flowId": id, "status": status, "name": flow.Name})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -359,14 +354,6 @@ func (s *Service) StationTask(ctx context.Context, stationNo int) (map[string]an
|
||||
if err != nil {
|
||||
return nil, errors.New("工位不存在或未配置")
|
||||
}
|
||||
var flow *ent.ProcessFlow
|
||||
if st.FlowId > 0 {
|
||||
flow, _ = s.ctx.EntClient.ProcessFlow.Get(ctx, st.FlowId)
|
||||
}
|
||||
steps := []*ProcessStepTemplate{}
|
||||
if flow != nil && flow.Status == "ACTIVE" {
|
||||
steps = s.flowSteps(ctx, flow.ID, flow.ProcessCode)
|
||||
}
|
||||
orderNos := []string{}
|
||||
wos, _ := s.ctx.EntClient.WorkOrder.Query().
|
||||
Where(workorder.StatusIn("CREATED", "RELEASED", "IN_PROGRESS")).
|
||||
@@ -374,27 +361,107 @@ func (s *Service) StationTask(ctx context.Context, stationNo int) (map[string]an
|
||||
for _, w := range wos {
|
||||
orderNos = append(orderNos, w.WorkOrderNo)
|
||||
}
|
||||
// M4:工位终端按"工艺路线段"驱动(段=并行工位组,谁空停谁)。
|
||||
// 解析活跃工单的 routeSnapshot,找出本工位所属的路线段,供终端按段执行流程。
|
||||
routeSegments := []map[string]any{}
|
||||
for _, w := range wos {
|
||||
if len(w.RouteSnapshot) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, seg := range w.RouteSnapshot {
|
||||
stations, _ := seg["stations"].([]any)
|
||||
inSeg := false
|
||||
for _, sv := range stations {
|
||||
switch n := sv.(type) {
|
||||
case float64:
|
||||
if int(n) == stationNo {
|
||||
inSeg = true
|
||||
}
|
||||
case int:
|
||||
if n == stationNo {
|
||||
inSeg = true
|
||||
}
|
||||
}
|
||||
if inSeg {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inSeg {
|
||||
continue
|
||||
}
|
||||
flowId := 0
|
||||
if fv, ok := seg["flowId"].(float64); ok {
|
||||
flowId = int(fv)
|
||||
} else if fv, ok := seg["flowId"].(int); ok {
|
||||
flowId = fv
|
||||
}
|
||||
routeSegments = append(routeSegments, map[string]any{
|
||||
"orderNo": w.WorkOrderNo,
|
||||
"seq": seg["seq"],
|
||||
"segmentType": seg["segmentType"],
|
||||
"flowId": flowId,
|
||||
"stations": stations,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 按段驱动:本工位实际执行的工艺流程取自「本工位所属路线段」的 flowId;
|
||||
// 工单未配置路线段(旧数据/未排路线)时回退到工位绑定的 flow_id。
|
||||
activeFlowId := 0
|
||||
currentSegment := map[string]any{}
|
||||
minSeq := -1
|
||||
for _, sg := range routeSegments {
|
||||
seq, _ := sg["seq"].(float64)
|
||||
seqInt := int(seq)
|
||||
if sgv, ok := sg["seq"].(int); ok {
|
||||
seqInt = sgv
|
||||
}
|
||||
if minSeq < 0 || seqInt < minSeq {
|
||||
minSeq, currentSegment = seqInt, sg
|
||||
}
|
||||
}
|
||||
if len(currentSegment) > 0 {
|
||||
switch v := currentSegment["flowId"].(type) {
|
||||
case int:
|
||||
activeFlowId = v
|
||||
case float64:
|
||||
activeFlowId = int(v)
|
||||
}
|
||||
}
|
||||
if activeFlowId == 0 {
|
||||
activeFlowId = st.FlowId
|
||||
}
|
||||
var flow *ent.ProcessFlow
|
||||
if activeFlowId > 0 {
|
||||
flow, _ = s.ctx.EntClient.ProcessFlow.Get(ctx, activeFlowId)
|
||||
}
|
||||
steps := []*ProcessStepTemplate{}
|
||||
if flow != nil && flow.Status == "ACTIVE" {
|
||||
steps = s.flowSteps(ctx, flow.ID)
|
||||
}
|
||||
return map[string]any{
|
||||
"stationNo": st.StationNo,
|
||||
"stationName": st.Name,
|
||||
"flow": flow,
|
||||
"flowActive": flow != nil && flow.Status == "ACTIVE",
|
||||
"steps": steps,
|
||||
"orderNos": orderNos,
|
||||
"stationNo": st.StationNo,
|
||||
"stationName": st.Name,
|
||||
"flowId": activeFlowId,
|
||||
"segment": currentSegment,
|
||||
"flow": flow,
|
||||
"flowActive": flow != nil && flow.Status == "ACTIVE",
|
||||
"steps": steps,
|
||||
"orderNos": orderNos,
|
||||
"routeSegments": routeSegments,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ---------- 工作量/绩效报表(块6) ----------
|
||||
|
||||
// WorkloadRow 绩效/工作量聚合行(按人/按工位/明细三视图共用)
|
||||
type WorkloadRow struct {
|
||||
Operator string `json:"operator"`
|
||||
StationNo string `json:"stationNo"`
|
||||
Date string `json:"date"`
|
||||
ProcessCode int `json:"processCode"`
|
||||
ProcessName string `json:"processName"`
|
||||
DoneCount int `json:"doneCount"`
|
||||
OkCount int `json:"okCount"`
|
||||
NgCount int `json:"ngCount"`
|
||||
Operator string
|
||||
StationNo string
|
||||
Date string
|
||||
ProcessCode int
|
||||
ProcessName string
|
||||
DoneCount int
|
||||
OkCount int
|
||||
NgCount int
|
||||
}
|
||||
|
||||
func (s *Service) Workload(ctx context.Context, operator, stationNo, from, to string,
|
||||
@@ -420,7 +487,10 @@ func (s *Service) Workload(ctx context.Context, operator, stationNo, from, to st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type key struct{ op, station, date string; code int }
|
||||
type key struct {
|
||||
op, station, date string
|
||||
code int
|
||||
}
|
||||
agg := map[key]*WorkloadRow{}
|
||||
for _, r := range rows {
|
||||
k := key{r.Operator, r.StationNo, r.CreatedAt.Format("2006-01-02"), r.ProcessCode}
|
||||
@@ -459,13 +529,17 @@ func (s *Service) Workload(ctx context.Context, operator, stationNo, from, to st
|
||||
for _, v := range list {
|
||||
opKey := v.Operator
|
||||
if o, ok := byOpAgg[opKey]; ok {
|
||||
o.DoneCount += v.DoneCount; o.OkCount += v.OkCount; o.NgCount += v.NgCount
|
||||
o.DoneCount += v.DoneCount
|
||||
o.OkCount += v.OkCount
|
||||
o.NgCount += v.NgCount
|
||||
} else {
|
||||
byOpAgg[opKey] = &WorkloadRow{Operator: v.Operator, DoneCount: v.DoneCount, OkCount: v.OkCount, NgCount: v.NgCount}
|
||||
}
|
||||
stKey := v.StationNo
|
||||
if o, ok := byStAgg[stKey]; ok {
|
||||
o.DoneCount += v.DoneCount; o.OkCount += v.OkCount; o.NgCount += v.NgCount
|
||||
o.DoneCount += v.DoneCount
|
||||
o.OkCount += v.OkCount
|
||||
o.NgCount += v.NgCount
|
||||
} else {
|
||||
byStAgg[stKey] = &WorkloadRow{StationNo: v.StationNo, DoneCount: v.DoneCount, OkCount: v.OkCount, NgCount: v.NgCount}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user