package logic import ( "context" "strconv" "bj_power_mes/ent" "bj_power_mes/ent/permission" "bj_power_mes/ent/processflow" "bj_power_mes/ent/processstep" "bj_power_mes/ent/role" "bj_power_mes/ent/station" "bj_power_mes/ent/user" "golang.org/x/crypto/bcrypt" ) // Seed 初始化:超级管理员、默认角色、默认菜单权限、12 道工序与工位派工 func (s *Service) Seed(ctx context.Context) error { // 1. 默认角色(已存在则合并权限码,保证新按钮权限能落到已有角色上) roles := []struct{ name, code string }{ {"超级管理员", "SUPER_ADMIN"}, {"生产操作员", "OPERATOR"}, {"质检员", "INSPECTOR"}, } for _, r := range roles { codes := []string{"*"} if r.code == "OPERATOR" { codes = []string{ "produce.workorder", "produce.dailyplan", "produce.bom", "produce.material", "produce.scan", "produce.trace", "produce.torque", "produce.plc", "produce.product", "produce.processflow", "produce.station", "produce.performance", // 按钮级权限(块2) "produce.workorder:add", "produce.workorder:edit", "produce.workorder:delete", "produce.workorder:dailyplan", "produce.bom:edit", "produce.material:generate", "produce.plc:send", "produce.product:add", "produce.product:edit", "produce.product:delete", "produce.processflow:add", "produce.processflow:edit", "produce.processflow:delete", "produce.processflow:upload", "produce.station:edit", } } else if r.code == "INSPECTOR" { codes = []string{"produce.trace", "produce.torque", "produce.performance", "sys.eventlog", "sys.inspect", "sys.inspect:checkin", "sys.inspect:point", "sys.inspect:process", "sys.inspect:done", "sys.inspect:alarm", "sys.inspect:view"} } exist, err := s.ctx.EntClient.Role.Query().Where(role.Code(r.code)).First(ctx) if err != nil { _ = s.ctx.EntClient.Role.Create().SetName(r.name).SetCode(r.code).SetPermissionCodes(codes).Exec(ctx) } else { _ = s.ctx.EntClient.Role.UpdateOneID(exist.ID).SetPermissionCodes(mergeCodes(exist.PermissionCodes, codes)).Exec(ctx) } } // 2. 超级管理员账号 admin / 123456(对已存在的旧行做对齐,避免残留禁用状态) hash, _ := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost) adminRole, _ := s.ctx.EntClient.Role.Query().Where(role.Code("SUPER_ADMIN")).First(ctx) roleId := 0 if adminRole != nil { roleId = adminRole.ID } if s.ctx.EntClient.User.Query().Where(user.Username("admin")).ExistX(ctx) { _ = s.ctx.EntClient.User.Update(). Where(user.Username("admin")). SetPassword(string(hash)).SetStatus("ENABLED").SetRoleId(roleId).Exec(ctx) } else { _ = s.ctx.EntClient.User.Create(). SetUsername("admin").SetPassword(string(hash)).SetName("系统管理员"). SetRoleId(roleId).SetStatus("ENABLED").Exec(ctx) } // 3. 默认菜单权限 menus := []struct{ code, name, typ, path string }{ {"produce.workorder", "工单管理", "MENU", "/work-order"}, {"produce.dailyplan", "日排产", "MENU", "/daily-plan"}, {"produce.bom", "物料清单", "MENU", "/bom"}, {"produce.material", "备料单", "MENU", "/material-request"}, {"produce.plc", "工位组合下发", "MENU", "/plc-send"}, {"produce.torque", "拧紧查询", "MENU", "/torque"}, {"produce.processflow", "工艺流程", "MENU", "/process-flow"}, {"produce.station", "关联工位", "MENU", "/station"}, {"produce.performance", "绩效报表", "MENU", "/performance"}, {"produce.scan", "手动报工", "MENU", "/scan"}, {"produce.trace", "工件追溯", "MENU", "/trace"}, {"produce.product", "产品类型", "MENU", "/product-type"}, {"sys.inspect", "巡检终端", "MENU", "/inspect"}, {"sys.eventlog", "操作日志", "MENU", "/event-log"}, {"sys.rbac", "角色权限管理", "MENU", "/rbac"}, } for _, m := range menus { if s.ctx.EntClient.Permission.Query().Where(permission.Code(m.code)).ExistX(ctx) { continue } _ = s.ctx.EntClient.Permission.Create(). SetCode(m.code).SetName(m.name).SetType(m.typ).SetPath(m.path).Exec(ctx) } // 3.1 按钮级权限(块2):前端按钮 + 后端接口 双重校验 buttons := []struct{ code, name, typ, path string }{ {"produce.workorder:add", "工单-新增", "BUTTON", ""}, {"produce.workorder:edit", "工单-编辑", "BUTTON", ""}, {"produce.workorder:delete", "工单-删除", "BUTTON", ""}, {"produce.workorder:dailyplan", "工单-日排产", "BUTTON", ""}, {"produce.bom:edit", "物料清单-维护", "BUTTON", ""}, {"produce.material:generate", "备料单-生成", "BUTTON", ""}, {"produce.plc:send", "工位组合-下发", "BUTTON", ""}, {"produce.product:add", "产品类型-新增", "BUTTON", ""}, {"produce.product:edit", "产品类型-编辑", "BUTTON", ""}, {"produce.product:delete", "产品类型-删除", "BUTTON", ""}, {"produce.processflow:add", "工艺流程-新增", "BUTTON", ""}, {"produce.processflow:edit", "工艺流程-编辑", "BUTTON", ""}, {"produce.processflow:delete", "工艺流程-删除", "BUTTON", ""}, {"produce.processflow:upload", "工艺流程-上传图纸", "BUTTON", ""}, {"produce.station:edit", "工位-绑定", "BUTTON", ""}, {"sys.rbac:user", "权限-用户", "BUTTON", ""}, {"sys.rbac:role", "权限-角色", "BUTTON", ""}, {"sys.rbac:perm", "权限-权限码", "BUTTON", ""}, {"sys.inspect:checkin", "巡检-开工签到", "BUTTON", ""}, {"sys.inspect:point", "巡检-工位点检", "BUTTON", ""}, {"sys.inspect:process", "巡检-过程巡检", "BUTTON", ""}, {"sys.inspect:done", "巡检-完工确认", "BUTTON", ""}, {"sys.inspect:alarm", "巡检-异常上报", "BUTTON", ""}, {"sys.inspect:view", "巡检-记录查看", "BUTTON", ""}, } for _, b := range buttons { if s.ctx.EntClient.Permission.Query().Where(permission.Code(b.code)).ExistX(ctx) { continue } _ = s.ctx.EntClient.Permission.Create(). SetCode(b.code).SetName(b.name).SetType(b.typ).SetPath(b.path).Exec(ctx) } // 4. 12 个工位默认工艺流程 + 工位绑定(流程挂 process_code,工位绑流程) seedFlowsAndStations(ctx, s) return nil } func seedFlowsAndStations(ctx context.Context, s *Service) { // 每个工位(1~12)若未配置工艺流程,则创建默认流程并绑定;已有流程则跳过 for i := 1; i <= 12; i++ { flow, err := s.ctx.EntClient.ProcessFlow.Query(). Where(processflow.ProcessCode(i)). Order(ent.Asc(processflow.FieldID)).First(ctx) if err != nil { flow, _ = s.ctx.EntClient.ProcessFlow.Create(). SetName("工位" + strconv.Itoa(i) + "_默认"). SetProcessCode(i).SetStatus("ACTIVE").SetRemark("默认工艺流程").Save(ctx) } if flow == nil { continue } cnt, _ := s.ctx.EntClient.ProcessStep.Query().Where(processstep.FlowId(flow.ID)).Count(ctx) if cnt == 0 { stepID := 0 if step, err := s.ctx.EntClient.ProcessStep.Create(). SetFlowId(flow.ID).SetProcessCode(i).SetSeq(1).SetName("装配完成"). SetCollectType("NONE").Save(ctx); err == nil { stepID = step.ID } if i == 3 && stepID > 0 { _, _ = s.ctx.EntClient.ProcessStep.Create(). SetFlowId(flow.ID).SetProcessCode(i).SetSeq(2).SetName("拧紧扭矩"). SetCollectType("AUTO").SetIsTorque(true).Save(ctx) } } // 工位 N 绑定工位 N 的默认流程 st, err := s.ctx.EntClient.Station.Query().Where(station.StationNo(i)).First(ctx) if err != nil { _, _ = s.ctx.EntClient.Station.Create(). SetStationNo(i).SetName("装配工位" + strconv.Itoa(i)). SetFlowId(flow.ID).SetStatus("ENABLED").Save(ctx) } else if st.FlowId == 0 { _, _ = s.ctx.EntClient.Station.UpdateOneID(st.ID).SetFlowId(flow.ID).Save(ctx) } } } // mergeCodes 合并两份权限码列表(去重、保序) func mergeCodes(a, b []string) []string { seen := map[string]bool{} out := make([]string, 0, len(a)+len(b)) for _, c := range append(append([]string{}, a...), b...) { if c == "" || seen[c] { continue } seen[c] = true out = append(out, c) } return out }