sys_menu.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. package service
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "github.com/go-admin-team/go-admin-core/sdk/pkg"
  7. "github.com/pkg/errors"
  8. "gorm.io/gorm"
  9. "go-admin/app/admin/models"
  10. "go-admin/app/admin/service/dto"
  11. cDto "go-admin/common/dto"
  12. cModels "go-admin/common/models"
  13. "github.com/go-admin-team/go-admin-core/sdk/service"
  14. )
  15. type SysMenu struct {
  16. service.Service
  17. }
  18. // GetPage 获取SysMenu列表
  19. func (e *SysMenu) GetPage(c *dto.SysMenuGetPageReq, menus *[]models.SysMenu) *SysMenu {
  20. var menu = make([]models.SysMenu, 0)
  21. err := e.getPage(c, &menu).Error
  22. if err != nil {
  23. _ = e.AddError(err)
  24. return e
  25. }
  26. for i := 0; i < len(menu); i++ {
  27. if menu[i].ParentId != 0 {
  28. continue
  29. }
  30. menusInfo := menuCall(&menu, menu[i])
  31. *menus = append(*menus, menusInfo)
  32. }
  33. return e
  34. }
  35. // getPage 菜单分页列表
  36. func (e *SysMenu) getPage(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) *SysMenu {
  37. var err error
  38. var data models.SysMenu
  39. err = e.Orm.Model(&data).
  40. Scopes(
  41. cDto.OrderDest("sort", false),
  42. cDto.MakeCondition(c.GetNeedSearch()),
  43. ).Preload("SysApi").
  44. Find(list).Error
  45. if err != nil {
  46. e.Log.Errorf("getSysMenuPage error:%s", err)
  47. _ = e.AddError(err)
  48. return e
  49. }
  50. return e
  51. }
  52. // Get 获取SysMenu对象
  53. func (e *SysMenu) Get(d *dto.SysMenuGetReq, model *models.SysMenu) *SysMenu {
  54. var err error
  55. var data models.SysMenu
  56. db := e.Orm.Model(&data).Preload("SysApi").
  57. First(model, d.GetId())
  58. err = db.Error
  59. if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
  60. err = errors.New("查看对象不存在或无权查看")
  61. e.Log.Errorf("GetSysMenu error:%s", err)
  62. _ = e.AddError(err)
  63. return e
  64. }
  65. if err != nil {
  66. e.Log.Errorf("db error:%s", err)
  67. _ = e.AddError(err)
  68. return e
  69. }
  70. apis := make([]int, 0)
  71. for _, v := range model.SysApi {
  72. apis = append(apis, v.Id)
  73. }
  74. model.Apis = apis
  75. return e
  76. }
  77. // Insert 创建SysMenu对象
  78. func (e *SysMenu) Insert(c *dto.SysMenuInsertReq) *SysMenu {
  79. var err error
  80. var data models.SysMenu
  81. c.Generate(&data)
  82. tx := e.Orm.Debug().Begin()
  83. defer func() {
  84. if err != nil {
  85. tx.Rollback()
  86. } else {
  87. tx.Commit()
  88. }
  89. }()
  90. err = tx.Where("id in ?", c.Apis).Find(&data.SysApi).Error
  91. if err != nil {
  92. tx.Rollback()
  93. e.Log.Errorf("db error:%s", err)
  94. _ = e.AddError(err)
  95. }
  96. err = tx.Create(&data).Error
  97. if err != nil {
  98. tx.Rollback()
  99. e.Log.Errorf("db error:%s", err)
  100. _ = e.AddError(err)
  101. }
  102. c.MenuId = data.MenuId
  103. err = e.initPaths(tx, &data)
  104. if err != nil {
  105. tx.Rollback()
  106. e.Log.Errorf("db error:%s", err)
  107. _ = e.AddError(err)
  108. }
  109. tx.Commit()
  110. return e
  111. }
  112. func (e *SysMenu) initPaths(tx *gorm.DB, menu *models.SysMenu) error {
  113. var err error
  114. var data models.SysMenu
  115. parentMenu := new(models.SysMenu)
  116. if menu.ParentId != 0 {
  117. err = tx.Model(&data).First(parentMenu, menu.ParentId).Error
  118. if err != nil {
  119. return err
  120. }
  121. if parentMenu.Paths == "" {
  122. err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!")
  123. return err
  124. }
  125. menu.Paths = parentMenu.Paths + "/" + pkg.IntToString(menu.MenuId)
  126. } else {
  127. menu.Paths = "/0/" + pkg.IntToString(menu.MenuId)
  128. }
  129. err = tx.Model(&data).Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths).Error
  130. return err
  131. }
  132. // Update 修改SysMenu对象
  133. func (e *SysMenu) Update(c *dto.SysMenuUpdateReq) *SysMenu {
  134. var err error
  135. tx := e.Orm.Debug().Begin()
  136. defer func() {
  137. if err != nil {
  138. tx.Rollback()
  139. } else {
  140. tx.Commit()
  141. }
  142. }()
  143. var alist = make([]models.SysApi, 0)
  144. var model = models.SysMenu{}
  145. tx.Preload("SysApi").First(&model, c.GetId())
  146. oldPath := model.Paths
  147. tx.Where("id in ?", c.Apis).Find(&alist)
  148. err = tx.Model(&model).Association("SysApi").Delete(model.SysApi)
  149. if err != nil {
  150. e.Log.Errorf("delete policy error:%s", err)
  151. _ = e.AddError(err)
  152. return e
  153. }
  154. c.Generate(&model)
  155. model.SysApi = alist
  156. db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
  157. if err = db.Error; err != nil {
  158. e.Log.Errorf("db error:%s", err)
  159. _ = e.AddError(err)
  160. return e
  161. }
  162. if db.RowsAffected == 0 {
  163. _ = e.AddError(errors.New("无权更新该数据"))
  164. return e
  165. }
  166. var menuList []models.SysMenu
  167. tx.Where("paths like ?", oldPath+"%").Find(&menuList)
  168. for _, v := range menuList {
  169. v.Paths = strings.Replace(v.Paths, oldPath, model.Paths, 1)
  170. tx.Model(&v).Update("paths", v.Paths)
  171. }
  172. return e
  173. }
  174. // Remove 删除SysMenu
  175. func (e *SysMenu) Remove(d *dto.SysMenuDeleteReq) *SysMenu {
  176. var err error
  177. var data models.SysMenu
  178. db := e.Orm.Model(&data).Delete(&data, d.Ids)
  179. if err = db.Error; err != nil {
  180. err = db.Error
  181. e.Log.Errorf("Delete error: %s", err)
  182. _ = e.AddError(err)
  183. }
  184. if db.RowsAffected == 0 {
  185. err = errors.New("无权删除该数据")
  186. _ = e.AddError(err)
  187. }
  188. return e
  189. }
  190. // GetList 获取菜单数据
  191. func (e *SysMenu) GetList(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) error {
  192. var err error
  193. var data models.SysMenu
  194. err = e.Orm.Model(&data).
  195. Scopes(
  196. cDto.MakeCondition(c.GetNeedSearch()),
  197. ).
  198. Find(list).Error
  199. if err != nil {
  200. e.Log.Errorf("db error:%s", err)
  201. return err
  202. }
  203. return nil
  204. }
  205. // SetLabel 修改角色中 设置菜单基础数据
  206. func (e *SysMenu) SetLabel() (m []dto.MenuLabel, err error) {
  207. var list []models.SysMenu
  208. err = e.GetList(&dto.SysMenuGetPageReq{}, &list)
  209. m = make([]dto.MenuLabel, 0)
  210. for i := 0; i < len(list); i++ {
  211. if list[i].ParentId != 0 {
  212. continue
  213. }
  214. e := dto.MenuLabel{}
  215. e.Id = list[i].MenuId
  216. e.Label = list[i].Title
  217. deptsInfo := menuLabelCall(&list, e)
  218. m = append(m, deptsInfo)
  219. }
  220. return
  221. }
  222. // GetSysMenuByRoleName 左侧菜单
  223. func (e *SysMenu) GetSysMenuByRoleName(roleName ...string) ([]models.SysMenu, error) {
  224. var MenuList []models.SysMenu
  225. var role models.SysRole
  226. var err error
  227. admin := false
  228. for _, s := range roleName {
  229. if s == "admin" {
  230. admin = true
  231. }
  232. }
  233. if len(roleName) > 0 && admin {
  234. var data []models.SysMenu
  235. err = e.Orm.Where(" menu_type in ('M','C')").
  236. Order("sort").
  237. Find(&data).
  238. Error
  239. MenuList = data
  240. } else {
  241. err = e.Orm.Model(&role).Preload("SysMenu", func(db *gorm.DB) *gorm.DB {
  242. return db.Where(" menu_type in ('M','C')").Order("sort")
  243. }).Where("role_name in ?", roleName).Find(&role).
  244. Error
  245. MenuList = *role.SysMenu
  246. }
  247. if err != nil {
  248. e.Log.Errorf("db error:%s", err)
  249. }
  250. return MenuList, err
  251. }
  252. // menuLabelCall 递归构造组织数据
  253. func menuLabelCall(eList *[]models.SysMenu, dept dto.MenuLabel) dto.MenuLabel {
  254. list := *eList
  255. min := make([]dto.MenuLabel, 0)
  256. for j := 0; j < len(list); j++ {
  257. if dept.Id != list[j].ParentId {
  258. continue
  259. }
  260. mi := dto.MenuLabel{}
  261. mi.Id = list[j].MenuId
  262. mi.Label = list[j].Title
  263. mi.Children = []dto.MenuLabel{}
  264. if list[j].MenuType != "F" {
  265. ms := menuLabelCall(eList, mi)
  266. min = append(min, ms)
  267. } else {
  268. min = append(min, mi)
  269. }
  270. }
  271. if len(min) > 0 {
  272. dept.Children = min
  273. } else {
  274. dept.Children = nil
  275. }
  276. return dept
  277. }
  278. // menuCall 构建菜单树
  279. func menuCall(menuList *[]models.SysMenu, menu models.SysMenu) models.SysMenu {
  280. list := *menuList
  281. min := make([]models.SysMenu, 0)
  282. for j := 0; j < len(list); j++ {
  283. if menu.MenuId != list[j].ParentId {
  284. continue
  285. }
  286. mi := models.SysMenu{}
  287. mi.MenuId = list[j].MenuId
  288. mi.MenuName = list[j].MenuName
  289. mi.Title = list[j].Title
  290. mi.Icon = list[j].Icon
  291. mi.Path = list[j].Path
  292. mi.MenuType = list[j].MenuType
  293. mi.Action = list[j].Action
  294. mi.Permission = list[j].Permission
  295. mi.ParentId = list[j].ParentId
  296. mi.NoCache = list[j].NoCache
  297. mi.Breadcrumb = list[j].Breadcrumb
  298. mi.Component = list[j].Component
  299. mi.Sort = list[j].Sort
  300. mi.Visible = list[j].Visible
  301. mi.CreatedAt = list[j].CreatedAt
  302. mi.SysApi = list[j].SysApi
  303. mi.Children = []models.SysMenu{}
  304. if mi.MenuType != cModels.Button {
  305. ms := menuCall(menuList, mi)
  306. min = append(min, ms)
  307. } else {
  308. min = append(min, mi)
  309. }
  310. }
  311. menu.Children = min
  312. return menu
  313. }
  314. func menuDistinct(menuList []models.SysMenu) (result []models.SysMenu) {
  315. distinctMap := make(map[int]struct{}, len(menuList))
  316. for _, menu := range menuList {
  317. if _, ok := distinctMap[menu.MenuId]; !ok {
  318. distinctMap[menu.MenuId] = struct{}{}
  319. result = append(result, menu)
  320. }
  321. }
  322. return result
  323. }
  324. func recursiveSetMenu(orm *gorm.DB, mIds []int, menus *[]models.SysMenu) error {
  325. if len(mIds) == 0 || menus == nil {
  326. return nil
  327. }
  328. var subMenus []models.SysMenu
  329. err := orm.Where(fmt.Sprintf(" menu_type in ('%s', '%s', '%s') and menu_id in ?",
  330. cModels.Directory, cModels.Menu, cModels.Button), mIds).Order("sort").Find(&subMenus).Error
  331. if err != nil {
  332. return err
  333. }
  334. subIds := make([]int, 0)
  335. for _, menu := range subMenus {
  336. if menu.ParentId != 0 {
  337. subIds = append(subIds, menu.ParentId)
  338. }
  339. if menu.MenuType != cModels.Button {
  340. *menus = append(*menus, menu)
  341. }
  342. }
  343. return recursiveSetMenu(orm, subIds, menus)
  344. }
  345. // SetMenuRole 获取左侧菜单树使用
  346. func (e *SysMenu) SetMenuRole(roleName string) (m []models.SysMenu, err error) {
  347. menus, err := e.getByRoleName(roleName)
  348. m = make([]models.SysMenu, 0)
  349. for i := 0; i < len(menus); i++ {
  350. if menus[i].ParentId != 0 {
  351. continue
  352. }
  353. menusInfo := menuCall(&menus, menus[i])
  354. m = append(m, menusInfo)
  355. }
  356. return
  357. }
  358. func (e *SysMenu) getByRoleName(roleName string) ([]models.SysMenu, error) {
  359. var role models.SysRole
  360. var err error
  361. data := make([]models.SysMenu, 0)
  362. if roleName == "admin" {
  363. err = e.Orm.Where(" menu_type in ('M','C') and deleted_at is null").
  364. Order("sort").
  365. Find(&data).
  366. Error
  367. err = errors.WithStack(err)
  368. } else {
  369. role.RoleKey = roleName
  370. err = e.Orm.Model(&role).Where("role_key = ? ", roleName).Preload("SysMenu").First(&role).Error
  371. if role.SysMenu != nil {
  372. mIds := make([]int, 0)
  373. for _, menu := range *role.SysMenu {
  374. mIds = append(mIds, menu.MenuId)
  375. }
  376. if err := recursiveSetMenu(e.Orm, mIds, &data); err != nil {
  377. return nil, err
  378. }
  379. data = menuDistinct(data)
  380. }
  381. }
  382. sort.Sort(models.SysMenuSlice(data))
  383. return data, err
  384. }