feat: 完成产线MES系统全流程功能迭代与优化

本提交完成了多个核心模块的功能完善与业务对齐:
1. 工位终端:固定工位配置、移除自选工位逻辑、适配配置化工位号
2. MES核心:重构工位组合逻辑、新增工单/流程状态管理、补全报工/追溯逻辑
3. WMS客户端:新增修改密码功能、优化帮助弹窗逻辑
4. 文档与权限:补充完整操作手册、统一菜单名称与权限描述
5. 修复多业务校验:排产数量校验、工单状态校验、工位绑定规则
This commit is contained in:
SunYF
2026-08-31 12:58:28 +08:00
parent a3145a8bd6
commit ae4c292487
53 changed files with 1475 additions and 912 deletions
+2
View File
@@ -16,12 +16,14 @@ var pathPermMap = map[string]string{
"DELETE:/api/v1/product-types/*": "produce.product:delete",
"POST:/api/v1/work-orders": "produce.workorder:add",
"PUT:/api/v1/work-orders": "produce.workorder:edit",
"POST:/api/v1/work-orders/status": "produce.workorder:edit",
"DELETE:/api/v1/work-orders/*": "produce.workorder:delete",
"POST:/api/v1/daily-plans": "produce.workorder:dailyplan",
"PUT:/api/v1/bom": "produce.bom:edit",
"POST:/api/v1/material-requests/generate": "produce.material:generate",
"POST:/api/v1/plc/send-process": "produce.plc:send",
"POST:/api/v1/process-flows": "produce.processflow:add",
"POST:/api/v1/process-flows/status": "produce.processflow:edit",
"DELETE:/api/v1/process-flows/*": "produce.processflow:delete",
"POST:/api/v1/process-flows/upload": "produce.processflow:upload",
"POST:/api/v1/process-steps": "produce.processflow:edit",
+23 -4
View File
@@ -8,11 +8,11 @@ import (
"bj_power_mes/internal/svc"
)
// ListProcessFlowsHandler GET /process-flows?processCode=
// ListProcessFlowsHandler GET /process-flows?stationNo=
func ListProcessFlowsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
code := atoiDefault(r.URL.Query().Get("processCode"), 0)
data, err := logic.New(svcCtx).ListFlows(r.Context(), code)
stationNo := atoiDefault(r.URL.Query().Get("stationNo"), 0)
data, err := logic.New(svcCtx).ListFlows(r.Context(), stationNo)
if err != nil {
httpx.Fail(w, 2201, err.Error())
return
@@ -21,7 +21,7 @@ func ListProcessFlowsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
}
}
// SaveProcessFlowHandler POST /process-flows(新建或更新工艺流程,含步骤模板
// SaveProcessFlowHandler POST /process-flows(新建或更新工艺流程,含工序步骤)
func SaveProcessFlowHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req logic.FlowReq
@@ -98,3 +98,22 @@ func SaveStationHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
httpx.OkMessage(w, "工位绑定已保存", nil)
}
}
// SetFlowStatusHandler POST /process-flows/status(工艺流程启用/停用)
func SetFlowStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
Id int `json:"id"`
Status string `json:"status"`
}
if err := httpx.ParseJSON(r, &req); err != nil {
httpx.BadRequest(w, "请求体解析失败")
return
}
if err := logic.New(svcCtx).SetFlowStatus(r.Context(), req.Id, req.Status, operator(r, "")); err != nil {
httpx.Fail(w, 2207, err.Error())
return
}
httpx.OkMessage(w, "操作成功", nil)
}
}
@@ -104,20 +104,16 @@ func ScanRecordsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
}
}
// ProcessStepsHandler 查询工位工序步骤模板(参数采集模板),供手动报工页动态渲染
// ProcessStepsHandler 查询工位工序步骤(参数采集模板),供手动报工页动态渲染
// 按 stationNo 加载该工位启用工艺流程的工序步骤。
func ProcessStepsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
code := atoiDefault(r.URL.Query().Get("processCode"), 0)
if code <= 0 {
data, err := logic.New(svcCtx).AllProcessSteps(r.Context(), 0)
if err != nil {
httpx.Fail(w, 3207, err.Error())
return
}
httpx.Ok(w, data)
stationNo := atoiDefault(r.URL.Query().Get("stationNo"), 0)
if stationNo <= 0 {
httpx.Fail(w, 3207, "缺少 stationNo 参数")
return
}
data, err := logic.New(svcCtx).ListProcessSteps(r.Context(), code)
data, err := logic.New(svcCtx).ListStationSteps(r.Context(), stationNo)
if err != nil {
httpx.Fail(w, 3207, err.Error())
return
@@ -125,19 +121,3 @@ func ProcessStepsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
httpx.Ok(w, data)
}
}
// SaveProcessStepsHandler 覆盖式保存某工序的步骤模板及考核标准
func SaveProcessStepsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req []logic.StepItemReq
if err := httpx.ParseJSON(r, &req); err != nil {
httpx.BadRequest(w, "请求体解析失败")
return
}
if err := logic.New(svcCtx).SaveProcessSteps(r.Context(), req, operator(r, "")); err != nil {
httpx.Fail(w, 3208, err.Error())
return
}
httpx.OkMessage(w, "工艺参数已保存", nil)
}
}
@@ -94,7 +94,7 @@ func WorkpieceTraceInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc
func OrderQueryInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
orderNo := r.URL.Query().Get("orderNo")
list, err := logic.New(svcCtx).ListWorkOrders(r.Context(), orderNo, "")
list, err := logic.New(svcCtx).ListWorkOrders(r.Context(), orderNo, "", "", "")
if err != nil {
httpx.Fail(w, 2004, err.Error())
return
@@ -75,9 +75,9 @@ func DeleteProductTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func ListWorkOrdersHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
orderNo := r.URL.Query().Get("orderNo")
status := r.URL.Query().Get("status")
data, err := logic.New(svcCtx).ListWorkOrders(r.Context(), orderNo, status)
q := r.URL.Query()
data, err := logic.New(svcCtx).ListWorkOrders(r.Context(),
q.Get("orderNo"), q.Get("status"), q.Get("productCode"), q.Get("productName"))
if err != nil {
httpx.Fail(w, 3004, err.Error())
return
@@ -127,6 +127,36 @@ func GetWorkOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
}
}
// SetWorkOrderStatusHandler POST /work-orders/status(工单状态流转)
func SetWorkOrderStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
Id int `json:"id"`
Status string `json:"status"`
}
if err := httpx.ParseJSON(r, &req); err != nil {
httpx.BadRequest(w, "请求体解析失败")
return
}
if err := logic.New(svcCtx).SetWorkOrderStatus(r.Context(), req.Id, req.Status, operator(r, "")); err != nil {
httpx.Fail(w, 3008, err.Error())
return
}
httpx.OkMessage(w, "状态已更新", nil)
}
}
// DeleteWorkOrderHandler DELETE /work-orders/:id(满足安全条件时删除)
func DeleteWorkOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := logic.New(svcCtx).DeleteWorkOrder(r.Context(), pathID(r), operator(r, "")); err != nil {
httpx.Fail(w, 3009, err.Error())
return
}
httpx.OkMessage(w, "工单已删除", nil)
}
}
// ---------- 日排产 ----------
func SaveDailyPlanHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
@@ -82,7 +82,9 @@ func RegisterProductionRoutes(server *rest.Server, serverCtx *svc.ServiceContext
{Method: http.MethodGet, Path: "/work-orders", Handler: production.ListWorkOrdersHandler(serverCtx)},
{Method: http.MethodPost, Path: "/work-orders", Handler: production.CreateWorkOrderHandler(serverCtx)},
{Method: http.MethodPut, Path: "/work-orders", Handler: production.UpdateWorkOrderHandler(serverCtx)},
{Method: http.MethodPost, Path: "/work-orders/status", Handler: production.SetWorkOrderStatusHandler(serverCtx)},
{Method: http.MethodGet, Path: "/work-orders/:id", Handler: production.GetWorkOrderHandler(serverCtx)},
{Method: http.MethodDelete, Path: "/work-orders/:id", Handler: production.DeleteWorkOrderHandler(serverCtx)},
{Method: http.MethodPost, Path: "/daily-plans", Handler: production.SaveDailyPlanHandler(serverCtx)},
{Method: http.MethodPut, Path: "/daily-plans", Handler: production.SaveDailyPlanHandler(serverCtx)},
{Method: http.MethodGet, Path: "/daily-plans", Handler: production.ListDailyPlansHandler(serverCtx)},
@@ -103,7 +105,6 @@ func RegisterProductionRoutes(server *rest.Server, serverCtx *svc.ServiceContext
{Method: http.MethodPost, Path: "/scan/report", Handler: production.ScanReportHandler(serverCtx)},
{Method: http.MethodGet, Path: "/scan/records", Handler: production.ScanRecordsHandler(serverCtx)},
{Method: http.MethodGet, Path: "/process-steps", Handler: production.ProcessStepsHandler(serverCtx)},
{Method: http.MethodPost, Path: "/process-steps", Handler: production.SaveProcessStepsHandler(serverCtx)},
{Method: http.MethodPost, Path: "/workpiece/online", Handler: production.OnlineWorkpieceHandler(serverCtx)},
{Method: http.MethodPost, Path: "/workpiece/process/report", Handler: production.ReportWorkpieceProcessHandler(serverCtx)},
@@ -119,6 +120,7 @@ func RegisterProductionRoutes(server *rest.Server, serverCtx *svc.ServiceContext
// ---------- 工艺流程/工位(块3 ----------
{Method: http.MethodGet, Path: "/process-flows", Handler: ListProcessFlowsHandler(serverCtx)},
{Method: http.MethodPost, Path: "/process-flows", Handler: SaveProcessFlowHandler(serverCtx)},
{Method: http.MethodPost, Path: "/process-flows/status", Handler: SetFlowStatusHandler(serverCtx)},
{Method: http.MethodDelete, Path: "/process-flows/:id", Handler: DeleteProcessFlowHandler(serverCtx)},
{Method: http.MethodPost, Path: "/process-flows/upload", Handler: UploadPdfHandler(serverCtx)},
{Method: http.MethodGet, Path: "/stations", Handler: ListStationsHandler(serverCtx)},
+2 -1
View File
@@ -106,10 +106,11 @@ func StationReportInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
}
// WorkloadInternalHandler 工作量/绩效报表(工位终端"我的工作量" + MES 绩效报表共用)
// operator=操作人、stationNo=工位号(空=全部工位)、from/to=日期范围
func WorkloadInternalHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
data, err := logic.New(svcCtx).Workload(r.Context(), q.Get("operator"), q.Get("from"), q.Get("to"))
data, err := logic.New(svcCtx).Workload(r.Context(), q.Get("operator"), q.Get("stationNo"), q.Get("from"), q.Get("to"))
if err != nil {
httpx.Fail(w, 2105, err.Error())
return