package service import ( "errors" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/util" "xorm.io/xorm" "go.uber.org/zap" "strings" "time" ) type SystemMenu struct { User entity.SystemUserInfo } func (s *SystemMenu) AddSystemMenu(input request.SystemMenuReq) (interface{}, error) { db, err := client.GetDbClient() if err != nil { return nil, resp.DbConnectError.ErrorDetail(err) } var sameLevelMenu, parentMenu entity.SystemMenu if input.PMenuId != "" { has, err := db.Table("system_menu").Where("p_menu_id = ? and is_deleted = 0", input.PMenuId).Limit(1, 0).OrderBy("sort desc").Get(&sameLevelMenu) if err != nil { conf.Logger.Error("获取同级菜单信息失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if !has { _, err := db.Table("system_menu").Where("menu_id = ? and is_deleted = 0", input.PMenuId).Limit(1, 0).OrderBy("sort desc").Get(&parentMenu) if err != nil { conf.Logger.Error("获取父级菜单信息失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } input.Level = parentMenu.Level + 1 input.Sort = 1 } else { input.Level = sameLevelMenu.Level input.Sort = sameLevelMenu.Sort + 1 } } else { //查询根目录同级别sort _, err := db.Table("system_menu").Where("is_deleted = 0 and level = 1").Limit(1, 0).OrderBy("sort desc").Get(&sameLevelMenu) if err != nil { conf.Logger.Error("获取同级菜单信息失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } input.Sort = sameLevelMenu.Sort + 1 input.Level = 1 } if input.PMenuId != "" { switch input.MenuType { case 0: //目录,不允许在level为2下的目录下新建目录 var pMenu entity.SystemMenu _, err := db.Table("system_menu").Where("menu_id = ? and menu_type = 0", input.PMenuId).Get(&pMenu) if err != nil { conf.Logger.Error("获取上级目录失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if pMenu.Level >= 3 { conf.Logger.Error("创建失败,目录最多可创建两级!", zap.Error(errors.New("创建失败,目录最多可创建两级!"))) return nil, resp.DbSelectError.ErrorDetail(errors.New("创建失败,目录最多可创建三级!")) } case 1: //菜单,只允许最多能查询到一个上级菜单,如果存在两个菜单,返回异常 var pMenu, ppMenu entity.SystemMenu _, err := db.Table("system_menu").Where("menu_id = ? and menu_type = 1", input.PMenuId).Get(&pMenu) if err != nil { conf.Logger.Error("获取上级菜单失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if pMenu.PMenuId != "" { _, err = db.Table("system_menu").Where("menu_id = ? and menu_type = 1", pMenu.PMenuId).Get(&ppMenu) if err != nil { conf.Logger.Error("获取上上级菜单失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if ppMenu.MenuId != "" { conf.Logger.Error("创建失败,菜单最多可创建两级!", zap.Error(errors.New("创建失败,菜单最多可创建两级!"))) return nil, resp.DbSelectError.ErrorDetail(errors.New("创建失败,菜单最多可创建两级!")) } } case 2: //子页面,只允许最多能查询到两个上级菜单,如果存在两个菜单,返回异常 var pMenu, ppMenu, pppMenu entity.SystemMenu _, err := db.Table("system_menu").Where("menu_id = ? and menu_type = 2", input.PMenuId).Get(&pMenu) if err != nil { conf.Logger.Error("获取上级子页面失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if pMenu.PMenuId != "" { _, err = db.Table("system_menu").Where("menu_id = ? and menu_type = 2", pMenu.PMenuId).Get(&ppMenu) if err != nil { conf.Logger.Error("获取上上级子页面失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if ppMenu.MenuId != "" { _, err = db.Table("system_menu").Where("menu_id = ? and menu_type = 2", ppMenu.PMenuId).Get(&pppMenu) if err != nil { conf.Logger.Error("获取上上上级子页面失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } if pppMenu.MenuId != "" { conf.Logger.Error("创建失败,子页面最多可创建三级!", zap.Error(errors.New("创建失败,子页面最多可创建三级!"))) return nil, resp.DbSelectError.ErrorDetail(errors.New("创建失败,子页面最多可创建三级!")) } } } } } ins := s.GetInputToEntityMenu(input) _, err = db.Table("system_menu").Insert(&ins) if err != nil { conf.Logger.Error("Insert AddSystemMenu", zap.String("error", err.Error())) return nil, resp.DbInsertError.ErrorDetail(err) } return ins.MenuId, nil } func (s *SystemMenu) DeleteMenu(id int64) error { db, err := client.GetDbClient() if err != nil { return resp.DbConnectError.ErrorDetail(err) } _, err = db.Transaction(func(session *xorm.Session) (interface{}, error) { var menu entity.SystemMenu basehas, err := session.Table("system_menu").ID(id).Where("is_deleted = 0").Get(&menu) if err != nil { conf.Logger.Error("查询基础组织信息失败", zap.Error(err)) return nil, resp.DbDeleteError.ErrorDetail(err) } //目录 目录没有下级可删除 if menu.MenuType == 0 { if !basehas { return nil, resp.DbDeleteError.ErrorDetail(errors.New("该目录不存在")) } //验证目录是否有下级 has, err := session.Table("system_menu").Where("is_deleted = 0 and p_menu_id = ?", menu.MenuId).Exist(&entity.SystemMenu{}) if err != nil { conf.Logger.Error("验证目录是否有下级查询基础菜单信息失败", zap.Error(err)) return nil, resp.DbDeleteError.ErrorDetail(err) } if has { return nil, resp.DbDeleteError.ErrorDetail(errors.New("该目录下有数据,不可删除!")) } } //删除 _, err = session.Table("system_menu").Cols("is_deleted, updated_time, updated_by").ID(id).Update(&entity.SystemMenu{IsDeleted: 1, UpdatedBy: s.User.Id}) return nil, err }) return err } // 菜单排序 func (s *SystemMenu) SortMenu(input []request.MenuSortInput) error { db, err := client.GetDbClient() if err != nil { return resp.DbConnectError.ErrorDetail(err) } _, err = db.Transaction(func(x *xorm.Session) (interface{}, error) { for _, v := range input { _, err := x.Table("system_menu").Cols("sort, updated_time, updated_by").Where("id = ? and is_deleted = 0", v.Id).Update( &entity.SystemMenu{ Sort: v.Sort, UpdatedBy: s.User.Id, }) if err != nil { conf.Logger.Error("排序失败", zap.Error(err)) return nil, resp.DbUpdateError.ErrorDetail(err) } } return nil, nil }) return err } // 更新菜单 func (s *SystemMenu) UpdateMenu(id int64, input request.SystemMenuReq) error { db, err := client.GetDbClient() if err != nil { return resp.DbConnectError.ErrorDetail(err) } var menu entity.SystemMenu has, err := db.Table("system_menu").ID(id).Where("is_deleted = 0").Get(&menu) if err != nil { conf.Logger.Error("获取菜单信息失败", zap.Error(err)) return resp.DbSelectError.ErrorDetail(err) } if input.PMenuId != "" { switch input.MenuType { case 0: //目录,不允许在level为2下的目录下新建目录 var pMenu entity.SystemMenu _, err := db.Table("system_menu").Where("menu_id = ? and menu_type = 0", input.PMenuId).Get(&pMenu) if err != nil { conf.Logger.Error("获取上级目录失败", zap.Error(err)) return resp.DbSelectError.ErrorDetail(err) } if pMenu.Level >= 3 { conf.Logger.Error("创建失败,目录最多可创建两级!", zap.Error(errors.New("创建失败,目录最多可创建两级!"))) return resp.DbSelectError.ErrorDetail(errors.New("创建失败,目录最多可创建两级!")) } case 1: //菜单,只允许最多能查询到一个上级菜单,如果存在两个菜单,返回异常 var pMenu, ppMenu entity.SystemMenu _, err := db.Table("system_menu").Where("menu_id = ? and menu_type = 1", input.PMenuId).Get(&pMenu) if err != nil { conf.Logger.Error("获取上级菜单失败", zap.Error(err)) return resp.DbSelectError.ErrorDetail(err) } if pMenu.PMenuId != "" { _, err = db.Table("system_menu").Where("menu_id = ? and menu_type = 1", pMenu.PMenuId).Get(&ppMenu) if err != nil { conf.Logger.Error("获取上上级菜单失败", zap.Error(err)) return resp.DbSelectError.ErrorDetail(err) } if ppMenu.MenuId != "" { conf.Logger.Error("创建失败,菜单最多可创建两级!", zap.Error(errors.New("创建失败,菜单最多可创建两级!"))) return resp.DbSelectError.ErrorDetail(errors.New("创建失败,菜单最多可创建两级!")) } } } } if !has { return resp.DbSelectError.ErrorDetail(errors.New("该菜单不存在")) } if _, err := db.Table("system_menu").Cols("menu_name, dict_group_id, state, menu_url, menu_logo, updated_by, updated_time", "source", "new_window", "remark", "system_type"). Where("id = ?", id).Update(&entity.SystemMenu{ MenuName: input.MenuName, DictGroupId: input.DictGroupId, State: input.State, MenuUrl: input.MenuUrl, MenuLogo: input.MenuLogo, UpdatedBy: s.User.Id, UpdatedTime: time.Now(), Source: input.Source, NewWindow: input.NewWindow, Remark: input.Remark, SystemType: input.SystemType, }); err != nil { conf.Logger.Error("更新菜单失败", zap.Error(err)) return resp.DbUpdateError.ErrorDetail(err) } return nil } // 查询菜单树 func (s *SystemMenu) GetMenuTree() (interface{}, error) { db, err := client.GetDbClient() if err != nil { return nil, resp.DbConnectError.ErrorDetail(err) } var menus []response.SystemMenuTree if err := db.Table("system_menu").Where("is_deleted = 0").OrderBy("level").OrderBy("sort").Find(&menus); err != nil { conf.Logger.Error("查询菜单树失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } var result []response.SystemMenuTree // 组装树形 for i, v := range menus { if v.Level == 1 { changeMenuTree(&menus[i], menus) result = append(result, menus[i]) } } return result, nil } // 获取字典菜单分组 func (s *SystemMenu) GetGroupDict() (interface{}, error) { db, err := client.GetDbClient() if err != nil { return nil, resp.DbConnectError.ErrorDetail(err) } dict := make([]entity.DictBase, 0) err = db.Table("dict").Where("is_delete = 0 and status = 1").And("class = 4").Find(&dict) if err != nil { conf.Logger.Error("查询字典失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } return dict, nil } // 查询系统用户菜单树 func (s *SystemMenu) GetSystemTree(search string) (interface{}, error) { db, err := client.GetDbClient() if err != nil { return nil, resp.DbConnectError.ErrorDetail(err) } var menus []response.SystemMenuTreePer if err := db.Table("system_user_role").Alias("sur"). Join("INNER", []string{"system_role_menu", "srm"}, "sur.role_id = srm.role_id"). Join("INNER", []string{"system_menu", "sm"}, "sm.menu_id = srm.menu_id"). Join("INNER", []string{"system_role", "sr"}, "sur.role_id = sr.role_id"). Select("max(sur.system_id::varchar) as system_id,sm.*"). Where("sm.is_deleted = 0 and sm.state = 1 and sur.role_id = ?", s.User.Id). And("sr.state = 1 and sr.is_deleted = 0"). GroupBy("sm.id"). OrderBy("sm.level").OrderBy("sm.sort").Find(&menus); err != nil { conf.Logger.Error("查询菜单树失败", zap.Error(err)) return nil, resp.DbSelectError.ErrorDetail(err) } var result []response.SystemMenuTreePer // 组装树形 for i, v := range menus { if v.Level == 1 { if !strings.Contains(v.MenuName, search) { continue } changeMenuTreePer(&menus[i], menus, search) result = append(result, menus[i]) } } return result, nil } func (s *SystemMenu) GetInputToEntityMenu(input request.SystemMenuReq) (res entity.SystemMenu) { //重置二级以下的菜单以及子页面 if input.Level > 2 && input.MenuType != 0 { input.DictGroupId = "" } res = entity.SystemMenu{ Level: input.Level, Sort: input.Sort, MenuName: input.MenuName, MenuType: input.MenuType, DictGroupId: input.DictGroupId, State: input.State, MenuUrl: input.MenuUrl, MenuLogo: input.MenuLogo, CreatedBy: s.User.Id, CreatedTime: time.Now(), IsDeleted: 0, MenuId: util.GetUUID(), PMenuId: input.PMenuId, Source: input.Source, NewWindow: input.NewWindow, Remark: input.Remark, SystemType: input.SystemType, } return res } func changeMenuTree(parent *response.SystemMenuTree, all []response.SystemMenuTree) { for i, v := range all { if v.PMenuId == parent.MenuId { //二级以下分组继承 if v.Level > 2 { all[i].DictGroupId = parent.DictGroupId } changeMenuTree(&all[i], all) parent.Child = append(parent.Child, all[i]) } } } func changeMenuTreePer(parent *response.SystemMenuTreePer, all []response.SystemMenuTreePer, search string) { for i, v := range all { if v.PMenuId == parent.MenuId { //二级以下分组继承 if v.Level > 2 { all[i].DictGroupId = parent.DictGroupId } all[i].ParentPath = parent.Path changeMenuTreePer(&all[i], all, search) parent.Children = append(parent.Children, all[i]) } } }