refactor: 重构工艺工序相关命名与数据模型
1. 全局替换"工序"为"工艺"统一术语,包括页面文案、枚举、注释
2. 重构工单与工件工艺数据模型:
- 新增工艺组合表flow_material作为备料/齐套唯一源头
- 新增工位状态表station_state支持自主停单/恢复接单
- 移除station_process派工表,改用工单工艺组合作为路线唯一源头
- 替换processCode为flowId作为工艺关联标识
- 重构工件当前进度字段为currentStationNo
3. 删除冗余的静态备份资源文件
4. 调整物料选择组件默认启用仅显示激活物料
5. 优化工单创建/编辑逻辑,新增工艺组合校验与保存
This commit is contained in:
@@ -21,8 +21,8 @@ import (
|
||||
"bj_power_mes/ent/workorder"
|
||||
"bj_power_mes/ent/workpieceprocess"
|
||||
"bj_power_mes/internal/logic"
|
||||
"bj_power_mes/internal/wmsclient"
|
||||
"bj_power_mes/internal/svc"
|
||||
"bj_power_mes/internal/wmsclient"
|
||||
)
|
||||
|
||||
// ModelProcessCardHandler GET /api/v1/process-card/model?productTypeId=&productCode=[&format=json]
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
// 该型号的完整制造定义,用于工艺交底/审核/客户查阅:
|
||||
//
|
||||
// 产品型号 → 工位组合 → 每工位工艺流程与步骤(含采集方式/检测点/拧紧/考核标准/工艺图纸)
|
||||
// → 物料清单(按 BOM 分组,含装配工位/单台用量/损耗/需求总量)
|
||||
// → 物料清单(按 BOM 分组,含工艺清单/单台用量/损耗/需求总量)
|
||||
// → 检验卡项(所有"检测确认"步骤汇总为检验项清单)
|
||||
// → 各环节时间(工单计划时间 + 该型号历史实绩的首末作业时间)
|
||||
//
|
||||
@@ -116,7 +116,7 @@ type modelBomItem struct {
|
||||
Spec string
|
||||
Unit string
|
||||
ManageMode string
|
||||
StationNo string
|
||||
FlowNames string // 使用该物料的工艺清单(经 flow_material 映射)
|
||||
UnitQty string
|
||||
LossRate string
|
||||
RequiredQty string
|
||||
@@ -158,37 +158,40 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
return nil, fmt.Errorf("产品型号不存在")
|
||||
}
|
||||
|
||||
// 2) 产品最近工单(仅取工单号/计划时间用于卡头展示;路线不再存工单)
|
||||
// 2) 产品最近工单(卡头展示 + 工艺组合路线唯一来源)
|
||||
var refWO *ent.WorkOrder
|
||||
if productCode != "" {
|
||||
if wo, err := client.WorkOrder.Query().
|
||||
refWO, _ = client.WorkOrder.Query().
|
||||
Where(workorder.ProductCode(productCode)).
|
||||
Order(ent.Desc(workorder.FieldID)).First(ctx); err == nil && wo != nil {
|
||||
card.OrderNo = wo.WorkOrderNo
|
||||
if wo.PlanStart != nil {
|
||||
card.PlanStart = wo.PlanStart.Format("2006-01-02 15:04")
|
||||
}
|
||||
if wo.PlanEnd != nil {
|
||||
card.PlanEnd = wo.PlanEnd.Format("2006-01-02 15:04")
|
||||
}
|
||||
Order(ent.Desc(workorder.FieldID)).First(ctx)
|
||||
}
|
||||
if refWO != nil {
|
||||
card.OrderNo = refWO.WorkOrderNo
|
||||
if refWO.PlanStart != nil {
|
||||
card.PlanStart = refWO.PlanStart.Format("2006-01-02 15:04")
|
||||
}
|
||||
if refWO.PlanEnd != nil {
|
||||
card.PlanEnd = refWO.PlanEnd.Format("2006-01-02 15:04")
|
||||
}
|
||||
}
|
||||
|
||||
// 3) 工位组合:由「今日工位派工(station_process)」派生;未派工则展示全产线已配置工艺流的工位
|
||||
seq, _ := logic.RouteStations(ctx, client, logic.TodayStr(), "")
|
||||
if len(seq) == 0 {
|
||||
// 3) 工位组合:唯一路线源头 = 最近工单的工艺组合;未配置则展示全产线已配置工艺的工位
|
||||
var seq []int
|
||||
if items, _ := logic.RouteStationsFromWO(ctx, client, refWO); len(items) > 0 {
|
||||
seq = logic.RouteStationsOfWO(items)
|
||||
card.SeqSource = "取自最近工单的工艺组合(工单 " + refWO.WorkOrderNo + ")"
|
||||
} else {
|
||||
sts, _ := client.Station.Query().Where(station.FlowIdGT(0)).Order(ent.Asc(station.FieldStationNo)).All(ctx)
|
||||
for _, st := range sts {
|
||||
seq = append(seq, st.StationNo)
|
||||
}
|
||||
card.SeqSource = "今日未派工,按全产线已配置工位顺序展示"
|
||||
} else {
|
||||
card.SeqSource = "取自今日工位派工路线"
|
||||
card.SeqSource = "未配置工艺组合,按全产线已配置工位顺序展示"
|
||||
}
|
||||
sort.Ints(seq)
|
||||
card.ProcessSeq = joinInts(seq)
|
||||
card.StationCount = len(seq)
|
||||
|
||||
// 3) 工位 + 工艺流程 + 步骤 + 考核标准
|
||||
// 4) 工位 + 工艺流程 + 步骤 + 考核标准
|
||||
sts, _ := client.Station.Query().Where(station.StationNoIn(seq...)).All(ctx)
|
||||
stationByName := map[int]*ent.Station{}
|
||||
flowIds := []int{}
|
||||
@@ -227,8 +230,9 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
|
||||
for _, no := range seq {
|
||||
st := stationByName[no]
|
||||
ms := modelStation{StationNo: no, StationName: fmt.Sprintf("工位%d", no), RefTime: refTimes[no]}
|
||||
ms := modelStation{StationNo: no, StationName: fmt.Sprintf("工位%d", no)}
|
||||
if st != nil {
|
||||
ms.RefTime = refTimes[st.FlowId]
|
||||
if st.Name != "" {
|
||||
ms.StationName = st.Name
|
||||
}
|
||||
@@ -263,8 +267,22 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
card.Stations = append(card.Stations, ms)
|
||||
}
|
||||
|
||||
// 4) 物料清单(按 BOM 名称分组)
|
||||
// 5) 物料清单(按 BOM 名称分组;工艺清单经 flow_material + process_flow 映射)
|
||||
if productCode != "" {
|
||||
// 物料编码 → 使用该物料的工艺名列表(工艺物料清单是装配绑定的唯一依据)
|
||||
flowNames := map[string][]string{}
|
||||
if fms, e := client.FlowMaterial.Query().All(ctx); e == nil {
|
||||
flowAll, _ := client.ProcessFlow.Query().All(ctx)
|
||||
nameById := map[int]string{}
|
||||
for _, f := range flowAll {
|
||||
nameById[f.ID] = f.Name
|
||||
}
|
||||
for _, fm := range fms {
|
||||
if n := nameById[fm.FlowId]; n != "" {
|
||||
flowNames[fm.MaterialCode] = append(flowNames[fm.MaterialCode], n)
|
||||
}
|
||||
}
|
||||
}
|
||||
items, _ := client.BomItem.Query().
|
||||
Where(bomitem.ProductCode(productCode)).
|
||||
Order(ent.Asc(bomitem.FieldBomName), ent.Asc(bomitem.FieldMaterialCode)).All(ctx)
|
||||
@@ -280,9 +298,9 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
gi = len(card.BomGroups) - 1
|
||||
groupIdx[name] = gi
|
||||
}
|
||||
stationNo := "-"
|
||||
if it.ProcessCode > 0 {
|
||||
stationNo = fmt.Sprintf("工位%d", it.ProcessCode)
|
||||
fnames := "-"
|
||||
if ns := flowNames[it.MaterialCode]; len(ns) > 0 {
|
||||
fnames = strings.Join(ns, "、")
|
||||
}
|
||||
card.BomGroups[gi].Items = append(card.BomGroups[gi].Items, modelBomItem{
|
||||
MaterialCode: it.MaterialCode,
|
||||
@@ -290,7 +308,7 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
Spec: it.Spec,
|
||||
Unit: it.Unit,
|
||||
ManageMode: manageModeCN(it.ManageMode),
|
||||
StationNo: stationNo,
|
||||
FlowNames: fnames,
|
||||
UnitQty: f2s(it.UnitQty),
|
||||
LossRate: f2s(it.LossRate),
|
||||
RequiredQty: f2s(it.RequiredQty),
|
||||
@@ -303,7 +321,7 @@ func buildModelCard(ctx context.Context, svcCtx *svc.ServiceContext, productType
|
||||
return card, nil
|
||||
}
|
||||
|
||||
// stationRefTimes 该产品型号历史实绩按工位聚合的首末作业时间(无实绩则返回空 map)
|
||||
// stationRefTimes 该产品型号历史实绩按工艺聚合的首末作业时间(无实绩则返回空 map,键=工艺ID)
|
||||
func stationRefTimes(ctx context.Context, client *ent.Client, productCode string) map[int]string {
|
||||
out := map[int]string{}
|
||||
if productCode == "" {
|
||||
@@ -326,10 +344,10 @@ func stationRefTimes(ctx context.Context, client *ent.Client, productCode string
|
||||
}
|
||||
m := map[int]*span{}
|
||||
for _, p := range procs {
|
||||
s := m[p.ProcessCode]
|
||||
s := m[p.FlowId]
|
||||
if s == nil {
|
||||
s = &span{}
|
||||
m[p.ProcessCode] = s
|
||||
m[p.FlowId] = s
|
||||
}
|
||||
if p.StartedAt != nil {
|
||||
t := p.StartedAt.Unix()
|
||||
@@ -346,15 +364,15 @@ func stationRefTimes(ctx context.Context, client *ent.Client, productCode string
|
||||
s.seen = true
|
||||
}
|
||||
}
|
||||
for code, s := range m {
|
||||
for flowId, s := range m {
|
||||
if !s.seen {
|
||||
continue
|
||||
}
|
||||
if s.last == 0 {
|
||||
out[code] = tsText(s.first) + " 起(未完成)"
|
||||
out[flowId] = tsText(s.first) + " 起(未完成)"
|
||||
continue
|
||||
}
|
||||
out[code] = tsText(s.first) + " → " + tsText(s.last)
|
||||
out[flowId] = tsText(s.first) + " → " + tsText(s.last)
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -511,7 +529,7 @@ func renderModelCard(c *modelCard) (string, error) {
|
||||
{{if .Steps}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th colspan="6" class="st-name">工位{{.StationNo}} {{.StationName}} · {{if .FlowName}}{{.FlowName}}{{else}}未绑定流程{{end}}</th></tr>
|
||||
<tr><th colspan="6" class="st-name">工位{{.StationNo}} {{.StationName}} · {{if .FlowName}}{{.FlowName}}{{else}}未绑定工艺{{end}}</th></tr>
|
||||
<tr><th style="width:64px;">步骤号</th><th style="width:26%;">步骤名称</th><th>采集方式</th><th>检测确认</th><th>拧紧采集</th><th>考核标准</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -534,13 +552,13 @@ func renderModelCard(c *modelCard) (string, error) {
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th colspan="9" class="st-name">BOM:{{.BomName}}</th></tr>
|
||||
<tr><th>图号</th><th>物料名称</th><th>规格</th><th>单位</th><th>管理方式</th><th>装配工位</th><th>单台用量</th><th>损耗率(%)</th><th>需求总量</th></tr>
|
||||
<tr><th>图号</th><th>物料名称</th><th>规格</th><th>单位</th><th>管理方式</th><th>工艺清单</th><th>单台用量</th><th>损耗率(%)</th><th>需求总量</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Items}}
|
||||
<tr>
|
||||
<td>{{.MaterialCode}}</td><td class="left">{{.MaterialName}}</td><td class="left">{{.Spec}}</td>
|
||||
<td>{{.Unit}}</td><td>{{.ManageMode}}</td><td>{{.StationNo}}</td>
|
||||
<td>{{.Unit}}</td><td>{{.ManageMode}}</td><td>{{.FlowNames}}</td>
|
||||
<td>{{.UnitQty}}</td><td>{{.LossRate}}</td><td>{{.RequiredQty}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user