sys_menu.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. package service
  2. import (
  3. "IotAdmin/common/global"
  4. "IotAdmin/core/sdk/config"
  5. "IotAdmin/core/tools/utils"
  6. "fmt"
  7. "sort"
  8. "strings"
  9. "IotAdmin/core/sdk/pkg"
  10. "github.com/pkg/errors"
  11. "gorm.io/gorm"
  12. "IotAdmin/app/system/models"
  13. "IotAdmin/app/system/service/dto"
  14. cDto "IotAdmin/common/dto"
  15. "IotAdmin/core/sdk/service"
  16. )
  17. type SysMenuService struct {
  18. service.Service
  19. }
  20. // GetPage 获取SysMenu列表
  21. func (e *SysMenuService) GetPage(c *dto.SysMenuGetPageReq, menus *[]models.SysMenu) *SysMenuService {
  22. var menu = make([]models.SysMenu, 0)
  23. err := e.getPage(c, &menu).Error
  24. if err != nil {
  25. _ = e.AddError(err)
  26. return e
  27. }
  28. for i := 0; i < len(menu); i++ {
  29. if menu[i].ParentId != 0 {
  30. continue
  31. }
  32. menusInfo := menuCall(&menu, menu[i])
  33. *menus = append(*menus, menusInfo)
  34. }
  35. return e
  36. }
  37. // getPage 菜单分页列表
  38. func (e *SysMenuService) getPage(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) *SysMenuService {
  39. var err error
  40. var data models.SysMenu
  41. err = e.Orm.Model(&data).
  42. Scopes(
  43. cDto.OrderDest("sort", false),
  44. cDto.MakeCondition(c.GetNeedSearch()),
  45. ).Preload("SysApi").
  46. Find(list).Error
  47. if err != nil {
  48. e.Log.Errorf("getSysMenuPage error:%s", err)
  49. _ = e.AddError(err)
  50. return e
  51. }
  52. return e
  53. }
  54. // Get 获取SysMenu对象
  55. func (e *SysMenuService) Get(d *dto.SysMenuGetReq, model *models.SysMenu) *SysMenuService {
  56. var err error
  57. var data models.SysMenu
  58. db := e.Orm.Model(&data).Preload("SysApi").
  59. First(model, d.GetId())
  60. err = db.Error
  61. if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
  62. err = errors.New("查看对象不存在或无权查看")
  63. e.Log.Errorf("GetSysMenu error:%s", err)
  64. _ = e.AddError(err)
  65. return e
  66. }
  67. if err != nil {
  68. e.Log.Errorf("db error:%s", err)
  69. _ = e.AddError(err)
  70. return e
  71. }
  72. apis := make([]int, 0)
  73. for _, v := range model.SysApi {
  74. apis = append(apis, v.Id)
  75. }
  76. model.Apis = apis
  77. return e
  78. }
  79. // Insert 创建SysMenu对象
  80. func (e *SysMenuService) Insert(c *dto.SysMenuInsertReq) *SysMenuService {
  81. var err error
  82. var data models.SysMenu
  83. c.Generate(&data)
  84. tx := e.Orm.Debug().Begin()
  85. defer func() {
  86. if err != nil {
  87. tx.Rollback()
  88. } else {
  89. tx.Commit()
  90. }
  91. }()
  92. err = tx.Where("id in ?", c.Apis).Find(&data.SysApi).Error
  93. if err != nil {
  94. tx.Rollback()
  95. e.Log.Errorf("db error:%s", err)
  96. _ = e.AddError(err)
  97. }
  98. err = tx.Create(&data).Error
  99. if err != nil {
  100. tx.Rollback()
  101. e.Log.Errorf("db error:%s", err)
  102. _ = e.AddError(err)
  103. }
  104. c.MenuId = data.MenuId
  105. err = e.InIitPaths(tx, &data)
  106. if err != nil {
  107. tx.Rollback()
  108. e.Log.Errorf("db error:%s", err)
  109. _ = e.AddError(err)
  110. }
  111. tx.Commit()
  112. return e
  113. }
  114. func (e *SysMenuService) InIitPaths(tx *gorm.DB, menu *models.SysMenu) error {
  115. var err error
  116. var data models.SysMenu
  117. parentMenu := new(models.SysMenu)
  118. if menu.ParentId != 0 {
  119. err = tx.Model(&data).First(parentMenu, menu.ParentId).Error
  120. if err != nil {
  121. return err
  122. }
  123. if parentMenu.Paths == "" {
  124. err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!")
  125. return err
  126. }
  127. menu.Paths = parentMenu.Paths + "/" + pkg.IntToString(menu.MenuId)
  128. } else {
  129. menu.Paths = "/0/" + pkg.IntToString(menu.MenuId)
  130. }
  131. err = tx.Model(&data).Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths).Error
  132. return err
  133. }
  134. // Update 修改SysMenu对象
  135. func (e *SysMenuService) Update(c *dto.SysMenuUpdateReq) *SysMenuService {
  136. var err error
  137. tx := e.Orm.Debug().Begin()
  138. defer func() {
  139. if err != nil {
  140. tx.Rollback()
  141. } else {
  142. tx.Commit()
  143. }
  144. }()
  145. var aList = make([]models.SysApi, 0)
  146. var model = models.SysMenu{}
  147. tx.Preload("SysApi").First(&model, c.GetId())
  148. oldPath := model.Paths
  149. tx.Where("id in ?", c.Apis).Find(&aList)
  150. err = tx.Model(&model).Association("SysApi").Delete(model.SysApi)
  151. if err != nil {
  152. e.Log.Errorf("delete policy error:%s", err)
  153. _ = e.AddError(err)
  154. return e
  155. }
  156. c.Generate(&model)
  157. model.SysApi = aList
  158. db := tx.Model(&model).Session(&gorm.Session{FullSaveAssociations: true}).Debug().Save(&model)
  159. if err = db.Error; err != nil {
  160. e.Log.Errorf("db error:%s", err)
  161. _ = e.AddError(err)
  162. return e
  163. }
  164. if db.RowsAffected == 0 {
  165. _ = e.AddError(errors.New("无权更新该数据"))
  166. return e
  167. }
  168. var menuList []models.SysMenu
  169. tx.Where("paths like ?", oldPath+"%").Find(&menuList)
  170. for _, v := range menuList {
  171. v.Paths = strings.Replace(v.Paths, oldPath, model.Paths, 1)
  172. tx.Model(&v).Update("paths", v.Paths)
  173. }
  174. return e
  175. }
  176. // Remove 删除SysMenu
  177. func (e *SysMenuService) Remove(d *dto.SysMenuDeleteReq) *SysMenuService {
  178. var err error
  179. var data models.SysMenu
  180. db := e.Orm.Model(&data).Delete(&data, d.Ids)
  181. if err = db.Error; err != nil {
  182. err = db.Error
  183. e.Log.Errorf("Delete error: %s", err)
  184. _ = e.AddError(err)
  185. }
  186. if db.RowsAffected == 0 {
  187. err = errors.New("无权删除该数据")
  188. _ = e.AddError(err)
  189. }
  190. return e
  191. }
  192. // GetList 获取菜单数据
  193. func (e *SysMenuService) GetList(c *dto.SysMenuGetPageReq, list *[]models.SysMenu) error {
  194. var err error
  195. var data models.SysMenu
  196. err = e.Orm.Model(&data).
  197. Scopes(
  198. cDto.MakeCondition(c.GetNeedSearch()),
  199. ).
  200. Find(list).Error
  201. if err != nil {
  202. e.Log.Errorf("db error:%s", err)
  203. return err
  204. }
  205. return nil
  206. }
  207. // SetLabel 修改角色中 设置菜单基础数据
  208. func (e *SysMenuService) SetLabel() (m []dto.MenuLabel, err error) {
  209. var list []models.SysMenu
  210. err = e.GetList(&dto.SysMenuGetPageReq{}, &list)
  211. m = make([]dto.MenuLabel, 0)
  212. for i := 0; i < len(list); i++ {
  213. if list[i].ParentId != 0 {
  214. continue
  215. }
  216. e := dto.MenuLabel{}
  217. e.Id = list[i].MenuId
  218. e.Label = list[i].MenuName
  219. orgsInfo := menuLabelCall(&list, e)
  220. m = append(m, orgsInfo)
  221. }
  222. return
  223. }
  224. // GetSysMenuByRoleName 左侧菜单
  225. func (e *SysMenuService) GetSysMenuByRoleName(roleName ...string) ([]models.SysMenu, error) {
  226. var MenuList []models.SysMenu
  227. var role models.SysRole
  228. var err error
  229. admin := false
  230. for _, s := range roleName {
  231. if s == "admin" {
  232. admin = true
  233. }
  234. }
  235. if len(roleName) > 0 && admin {
  236. var data []models.SysMenu
  237. err = e.Orm.Where(" menu_type in ('M','C')").
  238. Order("sort").
  239. Find(&data).
  240. Error
  241. MenuList = data
  242. } else {
  243. err = e.Orm.Model(&role).Preload("Menus", func(db *gorm.DB) *gorm.DB {
  244. return db.Where(" menu_type in ('M','C')").Order("sort")
  245. }).Where("role_name in ?", roleName).Find(&role).
  246. Error
  247. MenuList = *role.Menus
  248. }
  249. if err != nil {
  250. e.Log.Errorf("db error:%s", err)
  251. }
  252. return MenuList, err
  253. }
  254. // GetBtnChildrenByPerm 根据权限获取按钮菜单
  255. func (e *SysMenuService) GetBtnChildrenByPerm(permission string) ([]models.SysMenu, error) {
  256. var (
  257. //menu models.Menus
  258. menuList []models.SysMenu
  259. )
  260. err := e.Orm.Model(&menuList).Where("parent_id = (?) AND is_hide = 0 AND menu_type = ?", e.Orm.Table("sys_menu").Select("menu_id").Where("permission = ?", permission), global.Button).Find(&menuList).Error
  261. if err != nil {
  262. e.Log.Errorf("db error:%s", err)
  263. return nil, err
  264. }
  265. return menuList, err
  266. }
  267. // menuLabelCall 递归构造组织数据
  268. func menuLabelCall(eList *[]models.SysMenu, org dto.MenuLabel) dto.MenuLabel {
  269. list := *eList
  270. menuLabels := make([]dto.MenuLabel, 0)
  271. for j := 0; j < len(list); j++ {
  272. if org.Id != list[j].ParentId {
  273. continue
  274. }
  275. mi := dto.MenuLabel{}
  276. mi.Id = list[j].MenuId
  277. mi.Label = list[j].MenuName
  278. mi.Children = []dto.MenuLabel{}
  279. if list[j].MenuType != "F" {
  280. ms := menuLabelCall(eList, mi)
  281. menuLabels = append(menuLabels, ms)
  282. } else {
  283. menuLabels = append(menuLabels, mi)
  284. }
  285. }
  286. if len(menuLabels) > 0 {
  287. org.Children = menuLabels
  288. } else {
  289. org.Children = nil
  290. }
  291. return org
  292. }
  293. // menuCall 构建菜单树
  294. func menuCall(menuList *[]models.SysMenu, menu models.SysMenu) models.SysMenu {
  295. list := *menuList
  296. menus := make([]models.SysMenu, 0)
  297. for j := 0; j < len(list); j++ {
  298. if menu.MenuId != list[j].ParentId || list[j].IsHide {
  299. continue
  300. }
  301. mi := models.SysMenu{}
  302. mi.MenuId = list[j].MenuId
  303. mi.Path = list[j].Path
  304. mi.MenuName = list[j].MenuName
  305. mi.Icon = list[j].Icon
  306. //mi.Path = list[j].Path
  307. mi.MenuType = list[j].MenuType
  308. mi.Action = list[j].Action
  309. mi.Permission = list[j].Permission
  310. mi.ParentId = list[j].ParentId
  311. mi.NoCache = list[j].NoCache
  312. //mi.Breadcrumb = list[j].Breadcrumb
  313. mi.Component = list[j].Component
  314. mi.BtnClass = list[j].BtnClass
  315. mi.BtnScript = list[j].BtnScript
  316. mi.Sort = list[j].Sort
  317. mi.IsHide = list[j].IsHide
  318. mi.IsFrame = list[j].IsFrame
  319. mi.CreatedAt = list[j].CreatedAt
  320. mi.SysApi = list[j].SysApi
  321. mi.Children = []models.SysMenu{}
  322. if mi.MenuType != global.Button {
  323. ms := menuCall(menuList, mi)
  324. menus = append(menus, ms)
  325. } else {
  326. menus = append(menus, mi)
  327. }
  328. }
  329. menu.Children = menus
  330. return menu
  331. }
  332. func menuDistinct(menuList []models.SysMenu) (result []models.SysMenu) {
  333. distinctMap := make(map[int]struct{}, len(menuList))
  334. for _, menu := range menuList {
  335. if _, ok := distinctMap[menu.MenuId]; !ok {
  336. distinctMap[menu.MenuId] = struct{}{}
  337. result = append(result, menu)
  338. }
  339. }
  340. return result
  341. }
  342. func recursiveSetMenu(orm *gorm.DB, mIds []int, menus *[]models.SysMenu) error {
  343. if len(mIds) == 0 || menus == nil {
  344. return nil
  345. }
  346. var subMenus []models.SysMenu
  347. err := orm.Where(fmt.Sprintf(" menu_type in ('%s', '%s', '%s') and menu_id in ?",
  348. global.Directory, global.Menu, global.Button), mIds).Order("menu_type").Order("sort").Find(&subMenus).Error
  349. if err != nil {
  350. return err
  351. }
  352. subIds := make([]int, 0)
  353. for _, menu := range subMenus {
  354. if menu.ParentId != 0 {
  355. subIds = append(subIds, menu.ParentId)
  356. }
  357. if menu.MenuType != global.Button {
  358. *menus = append(*menus, menu)
  359. }
  360. }
  361. return recursiveSetMenu(orm, subIds, menus)
  362. }
  363. // GetMenuRouter 获取左侧菜单路由
  364. func (e *SysMenuService) GetMenuRouter(roleName string) (result []dto.SysRouterVo, err error) {
  365. menus, err := e.getByRoleName(roleName)
  366. if err != nil {
  367. return
  368. }
  369. menus = buildMenuTree(menus)
  370. result = buildRouters(menus)
  371. return
  372. }
  373. func buildMenuTree(menus []models.SysMenu) (m []models.SysMenu) {
  374. m = make([]models.SysMenu, 0)
  375. for i := 0; i < len(menus); i++ {
  376. menu := menus[i]
  377. if menu.ParentId != 0 {
  378. continue
  379. }
  380. menusInfo := menuCall(&menus, menus[i])
  381. m = append(m, menusInfo)
  382. }
  383. return
  384. }
  385. func buildRouters(menus []models.SysMenu) []dto.SysRouterVo {
  386. voList := make([]dto.SysRouterVo, 0)
  387. for i := 0; i < len(menus); i++ {
  388. menu := menus[i]
  389. if config.ApplicationConfig.Mode != "dev" && menu.Path == "dev-tools" {
  390. continue
  391. }
  392. if menu.MenuType == global.Button {
  393. continue
  394. }
  395. routerVo := &dto.SysRouterVo{}
  396. routerVo.Generate(&menu)
  397. routerVo.Component = getComponent(menu)
  398. routerVo.Path = getRouterPath(menu)
  399. if len(menu.Children) > 0 && menu.MenuType == global.Directory {
  400. routerVo.AlwaysShow = true
  401. routerVo.Redirect = "noRedirect"
  402. routerVo.Children = buildRouters(menu.Children)
  403. } else if isMenuFrame(menu) {
  404. routerVo.Meta = dto.SysRouterMetaVo{}
  405. child := &dto.SysRouterVo{}
  406. child.Generate(&menu)
  407. child.Hidden = false
  408. routerVo.Children = append(routerVo.Children, *child)
  409. } else if menu.ParentId == 0 && isInnerLink(menu) {
  410. routerVo.Path = "/"
  411. child := &dto.SysRouterVo{}
  412. child.Generate(&menu)
  413. child.Hidden = false
  414. child.Component = ""
  415. routerVo.Children = append(routerVo.Children, *child)
  416. }
  417. voList = append(voList, *routerVo)
  418. }
  419. return voList
  420. }
  421. func getRouterPath(menu models.SysMenu) string {
  422. routerPath := menu.Path
  423. // 内链打开外网方式
  424. if menu.ParentId != 0 && isInnerLink(menu) {
  425. routerPath = strings.Replace(routerPath, "http://", "", 1)
  426. routerPath = strings.Replace(routerPath, "https://", "", 1)
  427. routerPath = strings.Replace(routerPath, "www", "", 1)
  428. routerPath = strings.Replace(routerPath, ".", "/", 1)
  429. }
  430. // 非外链并且是一级目录(类型为目录)
  431. if menu.ParentId == 0 && menu.MenuType == global.Directory && !menu.IsFrame {
  432. routerPath = "/" + menu.Path
  433. } else if isMenuFrame(menu) {
  434. // 非外链并且是一级目录(类型为菜单)
  435. routerPath = "/"
  436. }
  437. return routerPath
  438. }
  439. func getComponent(menu models.SysMenu) string {
  440. component := dto.LAYOUT
  441. if menu.Component != "" && !isMenuFrame(menu) {
  442. component = menu.Component
  443. } else if menu.Component == "" && menu.ParentId != 0 && isInnerLink(menu) {
  444. component = dto.INNER_LINK
  445. } else if menu.Component == "" && isParentView(menu) {
  446. component = dto.PARENT_VIEW
  447. }
  448. return component
  449. }
  450. func isInnerLink(menu models.SysMenu) bool {
  451. return !menu.IsFrame && utils.HasPrefix(&menu.Path, "http")
  452. }
  453. func isParentView(menu models.SysMenu) bool {
  454. return menu.ParentId == 0 && menu.MenuType == global.Directory
  455. }
  456. func isMenuFrame(menu models.SysMenu) bool {
  457. return menu.ParentId == 0 && menu.MenuType == global.Menu && menu.IsFrame
  458. }
  459. func (e *SysMenuService) getByRoleName(roleName string) ([]models.SysMenu, error) {
  460. var role models.SysRole
  461. var err error
  462. data := make([]models.SysMenu, 0)
  463. if roleName == "admin" {
  464. err = e.Orm.Where(" menu_type in ('M','C') and deleted_at is null").
  465. Order("sort").
  466. Find(&data).
  467. Error
  468. err = errors.WithStack(err)
  469. } else {
  470. role.RoleKey = roleName
  471. err = e.Orm.Model(&role).Where("role_key = ? ", roleName).Preload("Menus").First(&role).Error
  472. if role.Menus != nil {
  473. mIds := make([]int, 0)
  474. for _, menu := range *role.Menus {
  475. mIds = append(mIds, menu.MenuId)
  476. }
  477. if err := recursiveSetMenu(e.Orm, mIds, &data); err != nil {
  478. return nil, err
  479. }
  480. data = menuDistinct(data)
  481. }
  482. }
  483. sort.Sort(models.SysMenuSlice(data))
  484. return data, err
  485. }