workDesktop.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. package entity
  2. import (
  3. MC "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/encrypt"
  5. "bp.jydev.jianyu360.cn/BaseService/userCenter/rpc/pb"
  6. "database/sql"
  7. "github.com/zeromicro/go-zero/core/logx"
  8. "sort"
  9. "strconv"
  10. "strings"
  11. )
  12. // WorkDesktopMenu 工作桌面菜单信息
  13. type WorkDesktopMenu struct {
  14. MenuTree []*JYMenu
  15. UserId string
  16. NewUserId string
  17. EntId int64
  18. EntUserId int64
  19. AppId string
  20. }
  21. // JYMenu 工作桌面菜单内容
  22. type JYMenu struct {
  23. Id int
  24. Name string //菜单名称
  25. Match string //滤镜过滤正则
  26. OrderId int //菜单排序id
  27. ParentId int //父级id
  28. PowerIds string //权限id
  29. CheckCode int //是否必须验证权限才显示菜单
  30. Url string //菜单跳转链接
  31. Icon string //菜单图标
  32. AdditionalInfo Additional //附加弹窗信息
  33. AppType string //菜单模式
  34. OpenType string //打开方式
  35. Status int //是否是可用服务
  36. PermissionCode string //功能代码
  37. CapitalCode string //留资代码
  38. CapitalInfo Additional //留资弹窗
  39. Children []*JYMenu
  40. }
  41. type Additional struct {
  42. Title string `json:"title"` //弹窗标题
  43. Content string `json:"content"` //弹窗提示信息
  44. ConfirmUrl string `json:"confirmUrl"` //确认按钮跳转地址
  45. ConfirmText string `json:"confirmText"` //确认按钮
  46. IsShowCancel bool `json:"isShowCancel,optional"` //是否显示取消按钮
  47. AppType string `json:"appType,optional,omitempty"` //跳转方式
  48. OpenType string `json:"openType,optional,omitempty"`
  49. }
  50. // WorkMenuTree 菜单-格式化-tree
  51. func (m *WorkDesktopMenu) WorkMenuTree(parentId int) (jyMenu []*JYMenu) {
  52. jyMenu = make([]*JYMenu, 0)
  53. for _, mv := range m.MenuTree {
  54. if mv.ParentId == parentId {
  55. mv.Children = m.WorkMenuTree(mv.Id)
  56. sort.SliceStable(mv.Children, func(i, j int) bool {
  57. return mv.Children[i].OrderId < mv.Children[j].OrderId
  58. })
  59. jyMenu = append(jyMenu, mv)
  60. }
  61. }
  62. sort.SliceStable(jyMenu, func(i, j int) bool {
  63. return jyMenu[i].OrderId < jyMenu[j].OrderId
  64. })
  65. return
  66. }
  67. // WorkMenuFormat 菜单 格式化
  68. func (m *WorkDesktopMenu) WorkMenuFormat() ([]*pb.MenuList, error) {
  69. //logx.Info("树的长度:", len(m.MenuTree))
  70. menuList := make([]*pb.MenuList, 0)
  71. for _, mv := range m.MenuTree {
  72. //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示)
  73. usable := m.VerifyPermissions(mv.PowerIds)
  74. //checkCode==1 验证权限结果 无权限不显示
  75. if !usable && mv.CheckCode == 1 {
  76. continue
  77. }
  78. //GetResources(m.AppId, m.NewUserId, m.EntId, m.EntUserId)
  79. oneLevel := &pb.MenuList{
  80. Name: mv.Name,
  81. Icon: mv.Icon,
  82. Url: mv.Url,
  83. Id: encrypt.SE.EncodeString(strconv.Itoa(mv.Id)), //功能id加密
  84. Usable: usable, //MC.If(mv.PowerIds != "", usable && mv.CheckCode == 1, true).(bool),
  85. AppType: mv.AppType,
  86. OpenType: mv.OpenType,
  87. Child: []*pb.SecondLevelMenu{},
  88. TipInfo: &pb.TipInfo{
  89. Title: mv.AdditionalInfo.Title,
  90. Content: mv.AdditionalInfo.Content,
  91. ConfirmUrl: mv.AdditionalInfo.ConfirmUrl,
  92. ConfirmText: mv.AdditionalInfo.ConfirmText,
  93. IsShowCancel: mv.AdditionalInfo.IsShowCancel,
  94. AppType: mv.AdditionalInfo.AppType,
  95. OpenType: mv.AdditionalInfo.OpenType,
  96. },
  97. Match: MC.If(mv.Match != "", strings.Split(mv.Match, ","), []string{}).([]string),
  98. }
  99. if len(mv.Children) > 0 {
  100. for _, sv := range mv.Children {
  101. //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示)
  102. usable := m.VerifyPermissions(sv.PowerIds)
  103. //checkCode==1 验证权限结果 无权限不显示
  104. if !usable && sv.CheckCode == 1 {
  105. continue
  106. }
  107. secondLevel := &pb.SecondLevelMenu{
  108. Name: sv.Name,
  109. Icon: sv.Icon,
  110. Url: sv.Url,
  111. Id: encrypt.SE.EncodeString(strconv.Itoa(sv.Id)), //功能id加密
  112. Usable: usable, //MC.If(sv.PowerIds != "", usable && sv.CheckCode == 1, true).(bool),
  113. Child: []*pb.ThreeLevelMenu{},
  114. AppType: sv.AppType,
  115. OpenType: sv.OpenType,
  116. TipInfo: &pb.TipInfo{
  117. Title: sv.AdditionalInfo.Title,
  118. Content: sv.AdditionalInfo.Content,
  119. ConfirmUrl: sv.AdditionalInfo.ConfirmUrl,
  120. ConfirmText: sv.AdditionalInfo.ConfirmText,
  121. IsShowCancel: sv.AdditionalInfo.IsShowCancel,
  122. AppType: sv.AdditionalInfo.AppType,
  123. OpenType: sv.AdditionalInfo.OpenType,
  124. },
  125. Match: MC.If(sv.Match != "", strings.Split(sv.Match, ","), []string{}).([]string),
  126. }
  127. if len(sv.Children) > 0 {
  128. for _, tv := range sv.Children {
  129. //附件下载包、采购单位画像记录、企业画像记录 如果是大会员+超级订阅 排除此三项菜单
  130. //灵活性降低,不应该这么搞
  131. if (tv.Name == "附件下载包" && m.VerifyPermissions("3")) || (tv.Name == "采购单位画像记录" && m.VerifyPermissions("5")) || (tv.Name == "企业画像记录" && m.VerifyPermissions("4,12,13,19,20,21,23")) {
  132. continue
  133. }
  134. //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示)
  135. usable := m.VerifyPermissions(tv.PowerIds)
  136. //checkCode==1 验证权限结果 无权限不显示
  137. if !usable && tv.CheckCode == 1 {
  138. continue
  139. }
  140. var (
  141. title, content, confirmUrl, confirmText, isShowCancel, appType, openType, feasibility = tv.AdditionalInfo.Title, tv.AdditionalInfo.Content, tv.AdditionalInfo.ConfirmUrl, tv.AdditionalInfo.ConfirmText, tv.AdditionalInfo.IsShowCancel, tv.AdditionalInfo.AppType, tv.AdditionalInfo.OpenType, usable
  142. )
  143. //三级菜单------
  144. if len(tv.Children) == 0 && (tv.CapitalCode != "" || tv.PermissionCode != "") {
  145. //用户是否需要留资
  146. //资源中台获取用户权限--没有权限:title等置空
  147. //ResourceLib.PowerHandle()
  148. title, content, confirmUrl, confirmText, appType, openType, isShowCancel, feasibility = CheckCapitalResources(tv, m.NewUserId, m.AppId, m.EntId, m.EntUserId, usable)
  149. }
  150. threeLevel := &pb.ThreeLevelMenu{
  151. Name: tv.Name,
  152. Icon: tv.Icon,
  153. Url: tv.Url,
  154. Id: encrypt.SE.EncodeString(strconv.Itoa(tv.Id)), //功能id加密
  155. Usable: feasibility, //MC.If(tv.PowerIds != "", usable && tv.CheckCode == 1, true).(bool),
  156. AppType: tv.AppType,
  157. OpenType: tv.OpenType,
  158. TipInfo: &pb.TipInfo{
  159. Title: title,
  160. Content: content,
  161. ConfirmUrl: confirmUrl,
  162. ConfirmText: confirmText,
  163. IsShowCancel: isShowCancel,
  164. AppType: appType,
  165. OpenType: openType,
  166. },
  167. Match: MC.If(tv.Match != "", strings.Split(tv.Match, ","), []string{}).([]string),
  168. }
  169. if len(tv.Children) > 0 {
  170. L:
  171. for _, fv := range tv.Children {
  172. if fv.Name == "" {
  173. continue
  174. }
  175. if fv.CapitalCode != "" || fv.PermissionCode != "" {
  176. //用户是否需要留资
  177. //资源中台获取用户权限--没有权限:title等置空
  178. //ResourceLib.PowerHandle()
  179. title, content, confirmUrl, confirmText, appType, openType, isShowCancel, feasibility = CheckCapitalResources(fv, m.NewUserId, m.AppId, m.EntId, m.EntUserId, usable)
  180. }
  181. threeLevel.Url = MC.If(fv.Url != "", fv.Url, tv.Url).(string)
  182. threeLevel.Icon = MC.If(fv.Icon != "", fv.Icon, tv.Icon).(string)
  183. threeLevel.AppType = fv.AppType
  184. threeLevel.OpenType = fv.OpenType
  185. threeLevel.Usable = feasibility
  186. if fv.AdditionalInfo.Title != "" {
  187. threeLevel.TipInfo = &pb.TipInfo{
  188. Title: title,
  189. Content: content,
  190. ConfirmUrl: confirmUrl,
  191. ConfirmText: confirmText,
  192. IsShowCancel: isShowCancel,
  193. AppType: appType,
  194. OpenType: openType,
  195. }
  196. }
  197. threeLevel.Match = MC.If(fv.Match != "", strings.Split(fv.Match, ","), []string{}).([]string)
  198. //四级菜单必须有顺序性,大会员》商机管理》超级订阅》免费用户
  199. name := MC.If(strings.Contains(fv.Name, "-"), strings.Split(fv.Name, "-")[0], "免费").(string)
  200. if len(UserRolePowers[name]) > 0 && m.VerifyPermissions(strings.Join(UserRolePowers[name], ",")) {
  201. break L
  202. }
  203. }
  204. }
  205. //无资源中台权限 菜单不显示
  206. if !feasibility && tv.CheckCode == 1 {
  207. continue
  208. }
  209. if threeLevel != nil {
  210. secondLevel.Child = append(secondLevel.Child, threeLevel)
  211. }
  212. }
  213. }
  214. //二级菜单 有三级子菜单;才会显示
  215. if len(secondLevel.Child) == 0 && sv.CheckCode == 1 {
  216. continue
  217. }
  218. oneLevel.Child = append(oneLevel.Child, secondLevel)
  219. }
  220. }
  221. //一级菜单 有二级子菜单;才会显示
  222. if len(oneLevel.Child) == 0 && mv.CheckCode == 1 {
  223. continue
  224. }
  225. menuList = append(menuList, oneLevel)
  226. }
  227. //清用户内存信息
  228. func(baseUserid string) {
  229. OverallLock.Lock()
  230. defer OverallLock.Unlock()
  231. userInfo := UserInfoMap[baseUserid]
  232. if userInfo != nil {
  233. userInfo.Lock.Lock()
  234. defer userInfo.Lock.Unlock()
  235. userInfo.Permissions = map[string]int{}
  236. userInfo.Capitals = map[string]int{}
  237. }
  238. }(m.NewUserId)
  239. //bytes, _ := json.MarshalIndent(menuList, "", " ")
  240. //fmt.Printf("%s\n", bytes)
  241. return menuList, nil
  242. }
  243. // VerifyPermissions 是否有权限可用此服务
  244. func (m *WorkDesktopMenu) VerifyPermissions(powerIds string) (b bool) {
  245. if powerIds == "" {
  246. return true
  247. }
  248. if len(strings.Split(powerIds, ",")) > 0 {
  249. userPower := AutoUserPowerInfo(m.UserId, m.AppId, m.EntId) //m.TimeOut, m.BigMemberOff,
  250. func(powerIds string) {
  251. for _, pv := range strings.Split(powerIds, ",") {
  252. if userPower[pv] > 0 {
  253. b = true
  254. break
  255. }
  256. }
  257. }(powerIds)
  258. }
  259. return
  260. }
  261. //常用功能
  262. const (
  263. WorkCommonly = "work_commonly"
  264. WorkMenu = "work_menu"
  265. )
  266. // CommonlyUpdate 更新常用功能
  267. func CommonlyUpdate(in *pb.WorkDesktopComprehensiveReq) (B bool, M string) {
  268. //事务 1:查; 2: 存;3: 删;
  269. var (
  270. ids []string
  271. mk int
  272. )
  273. for _, mid := range strings.Split(in.MenuIds, ",") {
  274. if mid == "" {
  275. continue
  276. }
  277. mk++
  278. //常用功能数量限制
  279. if ConfigJson.CommonlySize > 0 && mk >= int(ConfigJson.CommonlySize) {
  280. break
  281. }
  282. //id 解密
  283. ids = append(ids, encrypt.SE.DecodeString(mid))
  284. }
  285. //更新此用户设置的常用功能
  286. if B = BaseMysql.ExecTx("常用功能批量更新", func(tx *sql.Tx) bool {
  287. //查询此用户常用功能是否已存在记录
  288. var id = 0
  289. existingData := BaseMysql.SelectBySqlByTx(tx, `SELECT id FROM `+WorkCommonly+` WHERE base_userid = ? AND appid = ? AND field = ? AND platform = ? ORDER BY id DESC `, in.NewUserId, in.AppId, in.ActionMode, in.Platform)
  290. if existingData != nil && len(*existingData) > 0 {
  291. id = MC.IntAll((*existingData)[0]["id"])
  292. }
  293. switch {
  294. case id > 0: //更新
  295. if BaseMysql.UpdateOrDeleteBySqlByTx(tx, `UPDATE `+WorkCommonly+` SET value = ? WHERE id = ?`, strings.Join(ids, ","), id) < 0 {
  296. logx.Info("常用功能-更新数据失败")
  297. return false
  298. }
  299. default: //插入
  300. if BaseMysql.InsertBySqlByTx(tx, `INSERT INTO `+WorkCommonly+` (appid,base_userid,platform,field,value) VALUES (?,?,?,?,?)`, in.AppId, in.NewUserId, in.Platform, in.ActionMode, strings.Join(ids, ",")) < 0 {
  301. logx.Info("常用功能-插入数据失败")
  302. return false
  303. }
  304. }
  305. return true
  306. }); !B {
  307. M = "常用功能更新数据失败"
  308. }
  309. return
  310. }
  311. // CommonlyFormat 常用功能 格式化
  312. func (m *WorkDesktopMenu) CommonlyFormat(childMenus map[int][]*JYMenu) ([]*pb.ThreeLevelMenu, []string, bool) {
  313. menuList := make([]*pb.ThreeLevelMenu, 0)
  314. subLevel := map[int]bool{}
  315. delBool := false //更新因超级订阅用户,又购买大会员得用户 导致附件下载包||采购单位画像记录||企业画像记录 不应该展示
  316. var saveIds []string
  317. for _, mv := range m.MenuTree {
  318. //过滤子级 ++ 三级下架菜单:mv.Status == 1
  319. if subLevel[mv.ParentId] || mv.Status == 1 {
  320. continue
  321. }
  322. //附件下载包、采购单位画像记录、企业画像记录 如果是大会员+超级订阅 排除此三项菜单
  323. //灵活性降低,不应该这么搞
  324. if (mv.Name == "附件下载包" && m.VerifyPermissions("3")) || (mv.Name == "采购单位画像记录" && m.VerifyPermissions("5")) || (mv.Name == "企业画像记录" && m.VerifyPermissions("4,12,13,19,20,21,23")) {
  325. delBool = true
  326. continue
  327. }
  328. saveIds = append(saveIds, encrypt.SE.EncodeString(strconv.Itoa(mv.Id)))
  329. subLevel[mv.Id] = true
  330. //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示)
  331. usable := m.VerifyPermissions(mv.PowerIds)
  332. oneLevel := &pb.ThreeLevelMenu{
  333. Name: mv.Name,
  334. Icon: mv.Icon,
  335. Url: mv.Url,
  336. Id: encrypt.SE.EncodeString(strconv.Itoa(mv.Id)), //功能id加密
  337. Usable: usable, //MC.If(mv.PowerIds != "", usable && mv.CheckCode == 1, true).(bool),
  338. AppType: mv.AppType,
  339. OpenType: mv.OpenType,
  340. TipInfo: &pb.TipInfo{
  341. Title: mv.AdditionalInfo.Title,
  342. Content: mv.AdditionalInfo.Content,
  343. ConfirmUrl: mv.AdditionalInfo.ConfirmUrl,
  344. ConfirmText: mv.AdditionalInfo.ConfirmText,
  345. IsShowCancel: mv.AdditionalInfo.IsShowCancel,
  346. AppType: mv.AppType,
  347. OpenType: mv.OpenType,
  348. },
  349. Match: MC.If(mv.Match != "", strings.Split(mv.Match, ","), []string{}).([]string),
  350. }
  351. //处理子级
  352. if childMenus[mv.Id] != nil && len(childMenus[mv.Id]) > 0 {
  353. childMenu := childMenus[mv.Id]
  354. sort.Slice(childMenu, func(i, j int) bool {
  355. return childMenu[i].OrderId > childMenu[j].OrderId
  356. })
  357. L:
  358. for _, cv := range childMenu {
  359. if cv.Name == "" || cv.ParentId != mv.Id {
  360. continue
  361. }
  362. oneLevel.Url = MC.If(cv.Url != "", cv.Url, mv.Url).(string)
  363. oneLevel.Icon = MC.If(cv.Icon != "", cv.Icon, mv.Icon).(string)
  364. oneLevel.AppType = cv.AppType
  365. oneLevel.OpenType = cv.OpenType
  366. if cv.AdditionalInfo.Title != "" {
  367. oneLevel.TipInfo = &pb.TipInfo{
  368. Title: cv.AdditionalInfo.Title,
  369. Content: cv.AdditionalInfo.Content,
  370. ConfirmUrl: cv.AdditionalInfo.ConfirmUrl,
  371. ConfirmText: cv.AdditionalInfo.ConfirmText,
  372. IsShowCancel: cv.AdditionalInfo.IsShowCancel,
  373. AppType: cv.AppType,
  374. OpenType: cv.OpenType,
  375. }
  376. }
  377. oneLevel.Match = MC.If(cv.Match != "", strings.Split(cv.Match, ","), []string{}).([]string)
  378. name := MC.If(strings.Contains(cv.Name, "-"), strings.Split(cv.Name, "-")[0], "免费").(string)
  379. if len(UserRolePowers[name]) > 0 && m.VerifyPermissions(strings.Join(UserRolePowers[name], ",")) {
  380. break L
  381. }
  382. }
  383. }
  384. menuList = append(menuList, oneLevel)
  385. }
  386. return menuList, saveIds, delBool
  387. }