serv_menu.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. package service
  2. import (
  3. dto2 "Medical_OAuth/common/dto"
  4. "Medical_OAuth/common/global"
  5. cModel "Medical_OAuth/common/model"
  6. "encoding/json"
  7. "fmt"
  8. "gogs.baozhida.cn/zoie/OAuth-core/service"
  9. "strings"
  10. "github.com/pkg/errors"
  11. "gorm.io/gorm"
  12. "Medical_OAuth/app/admin/model"
  13. "Medical_OAuth/app/admin/service/dto"
  14. "gogs.baozhida.cn/zoie/OAuth-core/pkg"
  15. )
  16. type ServMenu struct {
  17. service.Service
  18. }
  19. // GetPage 获取ServMenu列表
  20. func (e *ServMenu) GetPage(c *dto.ServMenuGetPageReq, menus *[]model.ServMenu) *ServMenu {
  21. var menu = make([]model.ServMenu, 0)
  22. err := e.getPage(c, &menu).Error
  23. if err != nil {
  24. _ = e.AddError(global.GetFailedErr)
  25. return e
  26. }
  27. for i := 0; i < len(menu); i++ {
  28. if menu[i].ParentId != 0 {
  29. continue
  30. }
  31. menusInfo := servMenuCall(&menu, menu[i])
  32. *menus = append(*menus, menusInfo)
  33. }
  34. if len(*menus) == 0 {
  35. parentMap, flag := getServMenuParent(&menu)
  36. if flag {
  37. for i := 0; i < len(menu); i++ {
  38. if parentMap[menu[i].ParentId] {
  39. continue
  40. }
  41. menusInfo := servMenuCall(&menu, menu[i])
  42. *menus = append(*menus, menusInfo)
  43. }
  44. } else {
  45. for i := 0; i < len(menu); i++ {
  46. menusInfo := servMenuCall(&menu, menu[i])
  47. *menus = append(*menus, menusInfo)
  48. }
  49. }
  50. }
  51. return e
  52. }
  53. // 获取搜索出来的菜单的父菜单
  54. func getServMenuParent(menuList *[]model.ServMenu) (map[int]bool, bool) {
  55. list := *menuList
  56. var flag = false
  57. var parentMap = map[int]bool{}
  58. for j := 0; j < len(list); j++ {
  59. parentMap[list[j].ParentId] = false
  60. }
  61. for j := 0; j < len(list); j++ {
  62. if _, ok := parentMap[list[j].Id]; !ok {
  63. continue
  64. }
  65. parentMap[list[j].Id] = true
  66. flag = true
  67. }
  68. return parentMap, flag
  69. }
  70. // getPage 菜单分页列表
  71. func (e *ServMenu) getPage(c *dto.ServMenuGetPageReq, list *[]model.ServMenu) *ServMenu {
  72. var err error
  73. var data model.ServMenu
  74. var tempList []model.ServMenu
  75. err = e.Orm.Model(&data).
  76. Scopes(dto2.MakeCondition(c.GetNeedSearch())).
  77. Find(&tempList).Error
  78. if err != nil {
  79. e.Log.Errorf("getServMenuPage error: %s", err)
  80. _ = e.AddError(err)
  81. return e
  82. }
  83. // 获取菜单及其子菜单下ID
  84. for _, menu := range tempList {
  85. var menuList = make([]model.ServMenu, 0)
  86. err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Order(fmt.Sprintf("sort %s", c.SortOrder)).Find(&menuList).Error
  87. *list = append(*list, menuList...)
  88. }
  89. *list = DeduplicateServMenu(*list)
  90. return e
  91. }
  92. // Get 获取ServMenu对象
  93. func (e *ServMenu) Get(d *dto.ServMenuGetReq, menuModel *model.ServMenu) *ServMenu {
  94. err := e.Orm.First(menuModel, d.GetId()).Error
  95. if err != nil {
  96. e.Log.Errorf("db error: %s", err)
  97. if errors.Is(err, gorm.ErrRecordNotFound) {
  98. err = global.GetNotFoundOrNoPermissionErr
  99. } else {
  100. err = global.GetFailedErr
  101. }
  102. _ = e.AddError(err)
  103. return e
  104. }
  105. return e
  106. }
  107. // Insert 创建ServMenu对象
  108. func (e *ServMenu) Insert(c *dto.ServMenuInsertReq) *ServMenu {
  109. var err error
  110. var data model.ServMenu
  111. tx := e.Orm.Begin()
  112. defer func() {
  113. if err != nil {
  114. tx.Rollback()
  115. } else {
  116. tx.Commit()
  117. }
  118. }()
  119. c.Generate(&data)
  120. err = tx.Create(&data).Error
  121. if err != nil {
  122. e.Log.Errorf("db error: %s", err)
  123. _ = e.AddError(global.CreateFailedErr)
  124. return e
  125. }
  126. c.Id = data.Id
  127. menuPath, err := e.initPaths(&data)
  128. if err != nil {
  129. e.Log.Errorf("db error: %s", err)
  130. _ = e.AddError(err)
  131. return e
  132. }
  133. err = tx.Model(&data).Where("id = ?", data.Id).Update("menu_path", menuPath).Error
  134. if err != nil {
  135. e.Log.Errorf("db error: %s", err)
  136. _ = e.AddError(global.CreateFailedErr)
  137. return e
  138. }
  139. return e
  140. }
  141. func (e *ServMenu) initPaths(menu *model.ServMenu) (menuPath string, err error) {
  142. var data model.ServMenu
  143. parentMenu := new(model.ServMenu)
  144. if menu.ParentId != 0 {
  145. e.Orm.Model(&data).Where("service_id = ?", menu.ServiceId).First(parentMenu, menu.ParentId)
  146. if parentMenu.MenuPath == "" {
  147. err = errors.New("父级menu_path异常,请尝试对当前节点父级菜单进行更新操作!")
  148. return menuPath, err
  149. }
  150. menuPath = parentMenu.MenuPath + "/" + pkg.IntToString(menu.Id)
  151. } else {
  152. menuPath = "/0/" + pkg.IntToString(menu.Id)
  153. }
  154. return menuPath, nil
  155. }
  156. // Update 修改ServMenu对象
  157. func (e *ServMenu) Update(c *dto.ServMenuUpdateReq) *ServMenu {
  158. var err error
  159. tx := e.Orm.Debug().Begin()
  160. defer func() {
  161. if err != nil {
  162. tx.Rollback()
  163. } else {
  164. tx.Commit()
  165. }
  166. }()
  167. var menuModel = model.ServMenu{}
  168. err = tx.First(&menuModel, c.GetId()).Error
  169. if err != nil {
  170. e.Log.Errorf("db error: %s", err)
  171. if errors.Is(err, gorm.ErrRecordNotFound) {
  172. err = global.UpdateNotFoundOrNoPermissionErr
  173. } else {
  174. err = global.UpdateFailedErr
  175. }
  176. _ = e.AddError(err)
  177. return e
  178. }
  179. oldPath := menuModel.MenuPath
  180. oldParentId := menuModel.ParentId
  181. c.Generate(&menuModel)
  182. // 替换旧的path
  183. if c.ParentId != oldParentId {
  184. menuPath, err := e.initPaths(&menuModel)
  185. if err != nil {
  186. e.Log.Errorf("db error: %s", err)
  187. _ = e.AddError(err)
  188. return e
  189. }
  190. menuModel.MenuPath = menuPath
  191. }
  192. // 更新菜单信息
  193. err = tx.Model(&menuModel).Save(&menuModel).Error
  194. if err != nil {
  195. e.Log.Errorf("db error: %s", err)
  196. _ = e.AddError(global.UpdateFailedErr)
  197. return e
  198. }
  199. // 替换旧的path
  200. if oldPath != menuModel.MenuPath {
  201. var menuList []model.ServMenu
  202. tx.Where("menu_path like ?", oldPath+"%").Find(&menuList)
  203. for _, v := range menuList {
  204. v.MenuPath = strings.Replace(v.MenuPath, oldPath, menuModel.MenuPath, 1)
  205. err := tx.Model(&v).Update("menu_path", v.MenuPath).Error
  206. if err != nil {
  207. e.Log.Errorf("db error: %s", err)
  208. _ = e.AddError(global.CreateFailedErr)
  209. return e
  210. }
  211. }
  212. }
  213. // 修改服务菜单后删除角色菜单缓存,防止系统菜单与服务菜单不同步
  214. err = model.DeleteAllRoleMenuCache()
  215. if err != nil {
  216. _ = e.AddError(err)
  217. return e
  218. }
  219. return e
  220. }
  221. // Remove 删除ServMenu
  222. func (e *ServMenu) Remove(d *dto.ServMenuDeleteReq) *ServMenu {
  223. var err error
  224. tx := e.Orm.Begin()
  225. defer func() {
  226. if err != nil {
  227. tx.Rollback()
  228. } else {
  229. tx.Commit()
  230. }
  231. }()
  232. var menuList = make([]model.ServMenu, 0)
  233. tx.Where("id in (?)", d.GetId(), d.GetId()).Find(&menuList)
  234. if len(menuList) == 0 {
  235. return e
  236. }
  237. for _, menu := range menuList {
  238. err = e.Orm.Where("menu_path like ?", menu.MenuPath+"%").Delete(&model.ServMenu{}).Error
  239. if err != nil {
  240. e.Log.Errorf("Delete error: %s", err)
  241. _ = e.AddError(global.DeleteFailedErr)
  242. return e
  243. }
  244. }
  245. // 删除服务菜单后删除角色菜单缓存,防止系统菜单与服务菜单不同步
  246. err = model.DeleteAllRoleMenuCache()
  247. if err != nil {
  248. e.Log.Errorf("删除角色菜单缓存失败 %s", err)
  249. _ = e.AddError(err)
  250. return e
  251. }
  252. return e
  253. }
  254. // GetList 获取菜单数据
  255. func (e *ServMenu) GetList(c *dto.ServMenuGetPageReq, list *[]model.ServMenu) error {
  256. var err error
  257. var data model.ServMenu
  258. err = e.Orm.Model(&data).
  259. Scopes(
  260. dto2.MakeCondition(c.GetNeedSearch()),
  261. ).
  262. Find(list).Error
  263. if err != nil {
  264. e.Log.Errorf("db error: %s", err)
  265. return global.GetFailedErr
  266. }
  267. return nil
  268. }
  269. // servMenuCall 构建菜单树
  270. func servMenuCall(menuList *[]model.ServMenu, menu model.ServMenu) model.ServMenu {
  271. list := *menuList
  272. min := make([]model.ServMenu, 0)
  273. for j := 0; j < len(list); j++ {
  274. if menu.Id != list[j].ParentId {
  275. continue
  276. }
  277. mi := model.ServMenu{}
  278. mi.Id = list[j].Id
  279. mi.Name = list[j].Name
  280. mi.Icon = list[j].Icon
  281. mi.Path = list[j].Path
  282. mi.MenuType = list[j].MenuType
  283. mi.Permission = list[j].Permission
  284. mi.ParentId = list[j].ParentId
  285. mi.Component = list[j].Component
  286. mi.Sort = list[j].Sort
  287. mi.Visible = list[j].Visible
  288. mi.CreatedAt = list[j].CreatedAt
  289. mi.Children = []model.ServMenu{}
  290. if mi.MenuType != cModel.Button {
  291. ms := servMenuCall(menuList, mi)
  292. min = append(min, ms)
  293. } else {
  294. min = append(min, mi)
  295. }
  296. }
  297. menu.Children = min
  298. return menu
  299. }
  300. // DeduplicateServMenu 菜单列表去重
  301. func DeduplicateServMenu(list []model.ServMenu) []model.ServMenu {
  302. seen := make(map[string]bool)
  303. deduplicated := []model.ServMenu{}
  304. for _, v := range list {
  305. // 将结构体编码为 JSON 字符串
  306. key, err := json.Marshal(v)
  307. if err != nil {
  308. // 处理错误
  309. continue
  310. }
  311. // 将 JSON 字符串作为键插入到 map 中
  312. if _, ok := seen[string(key)]; !ok {
  313. seen[string(key)] = true
  314. deduplicated = append(deduplicated, v)
  315. }
  316. }
  317. return deduplicated
  318. }