user.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. package entity
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "sync"
  8. "time"
  9. "github.com/zeromicro/go-zero/core/logx"
  10. MC "app.yhyue.com/moapp/jybase/common"
  11. "app.yhyue.com/moapp/jybase/redis"
  12. )
  13. const (
  14. RedisCode = "newother"
  15. RedisMenuKey = "jy_workdesktopmenu_%s_%s_%s_%s"
  16. UserPowerRedisKey = "jy_userpowerredis_%s_%d_%s"
  17. UserRegisterTime = "jy_userregistertime_%s"
  18. )
  19. type UserInfo struct {
  20. Capitals map[string]int
  21. Permissions map[string]int
  22. Lock *sync.Mutex
  23. }
  24. var (
  25. CapitalRetention = "capital_retention"
  26. OverallLock = &sync.Mutex{}
  27. UserInfoMap = map[int64]*UserInfo{}
  28. UserRolePowers = map[string][]string{}
  29. )
  30. /*
  31. *待调整 调整为存redis
  32. *测试用例放的地方不对 待调整
  33. */
  34. // AutoUserPowerInfo 用户权限 初始化
  35. func (m *WorkDesktopMenu) AutoUserPowerInfo() map[string]int {
  36. /*
  37. * 商机管理--》新版商机管理vs老版商机管理
  38. * 大会员--》bigmember_service
  39. * 超级订阅--》新版超级订阅vs老版超级订阅
  40. * 免费用户--》新免费用户
  41. */
  42. /*
  43. * P278 用户身份切换
  44. * 用户权益 通过 权益中台rpc获取
  45. * 用户资源 通过 资源中台rpc获取
  46. */
  47. var UserPowerMap = map[string]int{}
  48. //redis newother 查询是否存在用户功能信息
  49. userPowerRedisKey := fmt.Sprintf(UserPowerRedisKey, m.AppId, time.Now().Day(), m.UserId)
  50. bytes, err := redis.GetBytes(RedisCode, userPowerRedisKey)
  51. if err == nil && len(*bytes) > 0 {
  52. if err = json.Unmarshal(*bytes, &UserPowerMap); err == nil {
  53. return UserPowerMap
  54. }
  55. }
  56. //数据库查询 、资源中台获取、权益中台获取 查询用户信息
  57. var (
  58. registerTime int64
  59. )
  60. //以上获取不到的信息 再自主查库
  61. userInfoRpc := UserInfoRpc{
  62. AppId: m.AppId,
  63. UserId: m.UserId,
  64. BaseUserId: m.NewUserId,
  65. EntId: m.EntId,
  66. EntUserId: m.EntUserId,
  67. AccountId: m.AccountId,
  68. EntAccountId: m.EntAccountId,
  69. PositionType: m.PositionType,
  70. PositionId: m.PositionId,
  71. MgoUserId: m.MgoUserId,
  72. }
  73. logx.Info(m.MgoUserId, m.PositionId, "------------------userInfoRpc-------------------------:", userInfoRpc)
  74. //权益中台获取权益
  75. userPowers := userInfoRpc.GetUserPowers()
  76. if userPowers != nil {
  77. logx.Info(userInfoRpc.MgoUserId, "------------userPowers:", userPowers)
  78. //注册时间
  79. registerTime = userPowers.Free.Registedate
  80. //大会员
  81. member := userPowers.Member
  82. //超级订阅
  83. vip := userPowers.Vip
  84. //企业信息
  85. entInfo := userPowers.Ent
  86. //商机管理
  87. entNiche := userPowers.Entniche
  88. //免费用户
  89. free := userPowers.Free
  90. if member.Status > 0 || ConfigJson.BigMemberOff {
  91. if member.Status > 0 {
  92. UserPowerMap["0"] = int(member.Status)
  93. UserPowerMap[strconv.Itoa(50+int(member.Status))] = 1
  94. }
  95. //大会员用户购买的服务 也有可能是非大会员用户 购买这些服务
  96. if member.MemberPowerList != nil && len(member.MemberPowerList) > 0 {
  97. for _, mp := range member.MemberPowerList {
  98. UserPowerMap[strconv.FormatInt(mp, 10)] = MC.If(member.Status > 0, int(member.Status), 1).(int)
  99. }
  100. }
  101. }
  102. if vip.Status > 0 {
  103. if registerTime < vip.EndTime {
  104. registerTime = vip.EndTime
  105. }
  106. UserPowerMap["200"] = int(vip.Status)
  107. UserPowerMap["201"] = int(vip.Upgrade)
  108. //
  109. if vip.Upgrade > 0 && member.Status < 1 {
  110. UserPowerMap["202"] = int(vip.Status)
  111. }
  112. if entInfo.EntRoleId == 1 {
  113. UserPowerMap["203"] = 1 //企业管理员
  114. } else if entInfo.EntRoleId == 2 {
  115. UserPowerMap["204"] = 1 //部门管理员
  116. }
  117. }
  118. //企业信息
  119. if m.EntId > 0 {
  120. UserPowerMap["702"] = 1
  121. //机构中心 由企业 且 是企业版
  122. if m.PositionType > 0 {
  123. UserPowerMap["901"] = 1
  124. }
  125. switch entInfo.EntRoleId {
  126. case 1: //企业管理员
  127. UserPowerMap["902"] = 1
  128. case 2: //部门管理员
  129. UserPowerMap["903"] = 1
  130. }
  131. }
  132. if entNiche.Status > 0 && entNiche.IsEntPower > 0 {
  133. //entInfo.EntRoleId 1:企业管理员 2:部门管理员
  134. //管理员 entInfo.EntRoleId>0 并不一定 entNiche.IsEntPower==1,entNiche.IsEntPower==0 也有权限(已废除)
  135. //管理员he员工被分配后 entNiche.IsEntPower==1否则没有权限
  136. //if entNiche.IsEntPower > 0 || entInfo.EntRoleId > 0{//(已废除)
  137. //商机管理服务 P259需求
  138. //有商机管理服务 不会再有商机管理订阅菜单
  139. //商机管理服务,上次陈老师说叫“企业管理服务”,不然和商机管理产品容易混淆-- 杨蘭 2022/12/14
  140. switch entNiche.PowerSource {
  141. case 0:
  142. switch entNiche.IsNew {
  143. case 1: //新版商机管理
  144. UserPowerMap["110"] = 1
  145. switch entInfo.EntRoleId {
  146. case 2: //部门管理员
  147. UserPowerMap["111"] = 1
  148. case 1: //企业管理员
  149. UserPowerMap["112"] = 1
  150. }
  151. case 0: //老版商机管理
  152. UserPowerMap["100"] = 1
  153. switch entInfo.EntRoleId {
  154. case 2: //部门管理员
  155. UserPowerMap["101"] = 1
  156. case 1: //企业管理员
  157. UserPowerMap["102"] = 1
  158. }
  159. //老版商机管理: model:1-统一订阅,2-个人订阅
  160. if entNiche.Model == 1 {
  161. UserPowerMap["103"] = 1
  162. } else if entNiche.Model == 2 {
  163. UserPowerMap["104"] = 1
  164. }
  165. }
  166. case 1:
  167. //客户管理服务(商机管理服务) [前提:大会员、超级订阅、医械通用户]---免费用户也可以用 (需求调整来自刘苗:产品已确认)
  168. UserPowerMap["600"] = 1
  169. switch entInfo.EntRoleId {
  170. case 2: //部门管理员
  171. UserPowerMap["602"] = 1
  172. case 1: //企业管理员
  173. UserPowerMap["601"] = 1
  174. }
  175. //}
  176. }
  177. }
  178. if free.IsFree {
  179. UserPowerMap["300"] = 1
  180. if free.IsUpgrade {
  181. //新免费用户
  182. UserPowerMap["301"] = MC.If(free.IsUpgrade, 1, 0).(int)
  183. }
  184. switch entInfo.EntRoleId {
  185. case 1: //企业管理员
  186. UserPowerMap["302"] = 1
  187. case 2: //部门管理员
  188. UserPowerMap["303"] = 1
  189. }
  190. }
  191. //----------其他-----------
  192. //广东移动DICT
  193. if entInfo.PrivateGD {
  194. UserPowerMap["400"] = 1
  195. }
  196. //人员行为统计菜单-1、购买大会员且创建了企业的管理员;2、新版商机管理管理员;3、商机管理服务管理员
  197. if member.Status > 0 {
  198. UserPowerMap["50"] = 1 //
  199. if entInfo.EntRoleId == 1 {
  200. UserPowerMap["58"] = 1 //企业管理员
  201. } else if entInfo.EntRoleId == 2 {
  202. UserPowerMap["59"] = 1 // 部门管理员
  203. }
  204. }
  205. //必须是企业管理员-&-购买了企业级应用服务
  206. //企业级服务 权限管理(只有企业管理员有权限)
  207. entService := entInfo.BuyMember > 0 || entInfo.BuyVip > 0
  208. if entService {
  209. if entInfo.EntRoleId == 1 {
  210. UserPowerMap["700"] = 1
  211. } else if entInfo.EntRoleId == 2 {
  212. //企业级服务 部门管理员
  213. UserPowerMap["703"] = 1
  214. }
  215. }
  216. //企业级服务 企业订阅--
  217. //1、存在未到期的购买主体为“企业”切购买产品为大会员或者超级订阅的部门管理员或企业管理员;c > 0
  218. //2、存在未到期的老版或者新版商机管理的企业管理员或部门管理员(非商机管理服务)。entnicheIsNew > -1 && powerSource == 0
  219. if entInfo.EntSubscribe > 0 {
  220. UserPowerMap["701"] = 1
  221. }
  222. //领域化产品权限
  223. //第一版:必须是大会员或者超级订阅用户 且留资 留资表:capital_retention;source = 'medical_domain',未留资提示留资信息
  224. //第二版:调资源中台rpc获取用户是否有使用领域化产品的权限 无权限则去购买
  225. //需求调整:
  226. //1:是否是大会员或者超级订阅用户 否:提示购买到超级订阅购买页; 是>-2
  227. //2:判断用户是否留资 否:提示用去留资;是:>-3
  228. //3:资源中台获取用户权限码判断是否有权限 否:提示用户去联系客服
  229. if member.Status > 0 || vip.Status > 0 {
  230. userRegisterTimeKey := fmt.Sprintf(UserRegisterTime, m.UserId)
  231. redis.Put(RedisCode, userRegisterTimeKey, strconv.Itoa(int(registerTime)), int(registerTime))
  232. UserPowerMap["500"] = 1
  233. }
  234. }
  235. //资源中台获取权限
  236. powerList := userInfoRpc.GetUserResources()
  237. if len(powerList) > 0 {
  238. for _, plv := range powerList {
  239. UserPowerMap[plv] = 1
  240. }
  241. }
  242. //其他权益数据库查询
  243. func(mgoUserId string) {
  244. //伙伴计划是否加入(移动端我的伙伴计划菜单)
  245. if count := Mysql.CountBySql(`select count(*) from dis_partner where uid=? and type=2`, mgoUserId); count > 0 {
  246. UserPowerMap["801"] = 1
  247. } else {
  248. UserPowerMap["800"] = 1
  249. }
  250. }(m.MgoUserId)
  251. //缓存
  252. if UserPowerMap != nil {
  253. bytes, err := json.Marshal(UserPowerMap)
  254. if err == nil && len(bytes) > 0 {
  255. redis.PutBytes(RedisCode, userPowerRedisKey, &bytes, ConfigJson.InternalTime)
  256. }
  257. }
  258. return UserPowerMap
  259. }
  260. // ClearUserPowerFunc clear One userId>positionId 职位id
  261. func ClearUserPowerFunc(positionId, appId string) bool {
  262. if positionId == "" {
  263. return false
  264. }
  265. for _, v := range []string{"PC", "APP", "WX"} {
  266. redis.Del(RedisCode, fmt.Sprintf(RedisMenuKey, appId, v, ConfigJson.MenuCacheKey, positionId))
  267. }
  268. //用户权限缓存
  269. redis.Del(RedisCode, fmt.Sprintf(UserPowerRedisKey, appId, time.Now().Day(), positionId))
  270. //用户菜单缓存
  271. return true
  272. }
  273. // UserRolePowerInit 用户角色权限初始化
  274. func UserRolePowerInit(strs []string) {
  275. if len(strs) > 0 {
  276. jyUserRoleData := BaseMysql.SelectBySql(`SELECT id,name FROM jyfunction WHERE status = 1`)
  277. if jyUserRoleData != nil && len(*jyUserRoleData) > 0 {
  278. for _, jv := range *jyUserRoleData {
  279. for _, v := range strs {
  280. if strings.Contains(MC.ObjToString(jv["name"]), v) {
  281. UserRolePowers[v] = append(UserRolePowers[v], strconv.Itoa(MC.IntAll(jv["id"])))
  282. }
  283. }
  284. }
  285. }
  286. }
  287. }
  288. /*
  289. 1、不符合可以留资申请开通权限的用户
  290. 1、免费用户
  291. 2、超级订阅用户、大会员用户到期时间是否超过3个月
  292. (1、2:弹窗-医械通上线啦)
  293. 2、符合可以留资申请开通的用户
  294. 1、未留资
  295. (1:弹窗-完善基本信息)
  296. 2、已留资未开通
  297. 3、已留资且开通
  298. (2、3:弹窗-恭喜留资成功)
  299. */
  300. /*
  301. 1、判断是否满足超级订阅用户或大会员用户 且到期时间超过90天(配置);
  302. 1.1、否:权限=0;提示上线啦
  303. 1.2、是:是否留资
  304. 1.2.1、否:权限=0;提示留资
  305. 1.2.2、是:是否开通权限
  306. 1.2.2.1、否:权限=0;提示恭喜留资成功,客服联系
  307. 1.2.2.2、是:权限=1
  308. */
  309. /*存在超级订阅 或 大会员到期 而医械通未到期的情况*/
  310. // CheckCapitalResources 是否需要留资 且权限验证--弹窗处理
  311. // b 一级权限(超级订阅、大会员等)
  312. // p 二级权限(请求资源中台:医械通等)
  313. func CheckCapitalResources(menu *JYMenu, wd *WorkDesktopMenu, b, p bool) (title, content, confirmUrl, confirmText, appType, openType string, isShowCancel, usable bool) {
  314. OverallLock.Lock()
  315. userInfo := UserInfoMap[wd.NewUserId]
  316. if userInfo == nil {
  317. userInfo = &UserInfo{}
  318. userInfo.Lock = &sync.Mutex{}
  319. userInfo.Capitals = map[string]int{}
  320. userInfo.Permissions = map[string]int{}
  321. UserInfoMap[wd.NewUserId] = userInfo
  322. }
  323. OverallLock.Unlock()
  324. userInfo.Lock.Lock()
  325. defer userInfo.Lock.Unlock()
  326. var (
  327. capitalBool = true //是否留资
  328. permissionBool = true //是否有功能权限
  329. //customPopup = true //自定义弹窗
  330. defaultPopup = false //默认弹窗
  331. )
  332. //大会员超级订阅用户 才有权限去验证是否有医疗权限
  333. //用户是否需要留资
  334. if menu.CapitalCode != "" {
  335. capitalBool = false
  336. for _, cv := range strings.Split(menu.CapitalCode, ",") {
  337. if userInfo.Capitals[cv] == 0 {
  338. if c := BaseMysql.CountBySql(`SELECT COUNT(id) FROM `+CapitalRetention+` WHERE source = ? AND position_id = ? AND appid = ?`, cv, wd.PositionId, wd.AppId); c > 0 {
  339. userInfo.Capitals[cv] = 1
  340. } else {
  341. userInfo.Capitals[cv] = -1
  342. }
  343. }
  344. if userInfo.Capitals[cv] < 0 {
  345. //customPopup = false
  346. //留资弹窗信息
  347. title = menu.CapitalInfo.Title
  348. content = menu.CapitalInfo.Content
  349. confirmUrl = menu.CapitalInfo.ConfirmUrl
  350. confirmText = menu.CapitalInfo.ConfirmText
  351. isShowCancel = menu.CapitalInfo.IsShowCancel
  352. appType = menu.CapitalInfo.AppType
  353. openType = menu.CapitalInfo.OpenType
  354. } else {
  355. capitalBool = true
  356. //无权限(有权限未留资|留资了未开通权限) --》 没有配置弹窗信息 --》自定义弹窗
  357. title = menu.AdditionalInfo[wd.Platform].Title
  358. content = menu.AdditionalInfo[wd.Platform].Content
  359. confirmUrl = menu.AdditionalInfo[wd.Platform].ConfirmUrl
  360. confirmText = menu.AdditionalInfo[wd.Platform].ConfirmText
  361. isShowCancel = menu.AdditionalInfo[wd.Platform].IsShowCancel
  362. appType = menu.AdditionalInfo[wd.Platform].AppType
  363. openType = menu.AdditionalInfo[wd.Platform].OpenType
  364. break
  365. }
  366. }
  367. }
  368. //无权限(医械通-:1:免费用户;2:超级订阅、大会员到期时间不在规定范围内)
  369. if b {
  370. //资源中台--- 无权限弹窗信息为默认信息(先留资)
  371. if menu.PermissionCode != "" {
  372. permissionBool = false
  373. if (menu.CapitalCode != "" && capitalBool) || menu.CapitalCode == "" {
  374. if p {
  375. title = ""
  376. permissionBool = true
  377. //customPopup = false
  378. }
  379. }
  380. }
  381. //有剑鱼用户权限 查看资源中台功能权限
  382. //医械通---用户没有资源中台功能权限 也没有留资 查看
  383. if !permissionBool {
  384. switch menu.PowerIds {
  385. case "500":
  386. userRegisterTime, _ := strconv.ParseInt(redis.GetStr(RedisCode, fmt.Sprintf(UserRegisterTime, wd.UserId)), 10, 64)
  387. //超级订阅 大会员到期时间 是否 大于 90天
  388. if userRegisterTime-time.Now().Unix() < ConfigJson.MedicalFieldTimespan {
  389. //即使是超级订阅或大会员 也没有权限
  390. defaultPopup = true
  391. }
  392. }
  393. }
  394. }
  395. //
  396. usable = func() bool {
  397. switch menu.Authority {
  398. case 0:
  399. return b && permissionBool && capitalBool
  400. case 1:
  401. return b || permissionBool || capitalBool
  402. case 2:
  403. return b || permissionBool && capitalBool
  404. case 3:
  405. return b && permissionBool || capitalBool
  406. case 4:
  407. return b && capitalBool || permissionBool
  408. default:
  409. return false
  410. }
  411. }()
  412. //无权限--免费用户||不符合条件的付费用户
  413. if !b || defaultPopup {
  414. //配置弹窗信息
  415. if ConfigJson.DefaultPopup[menu.PowerIds].Title != "" {
  416. //customPopup = false
  417. title = ConfigJson.DefaultPopup[menu.PowerIds].Title
  418. content = ConfigJson.DefaultPopup[menu.PowerIds].Content
  419. confirmUrlArr := strings.Split(ConfigJson.DefaultPopup[menu.PowerIds].ConfirmUrl, "__")
  420. confirmUrl = MC.InterfaceToStr(MC.If(wd.Platform == "PC", confirmUrlArr[1], confirmUrlArr[0]))
  421. confirmText = ConfigJson.DefaultPopup[menu.PowerIds].ConfirmText
  422. isShowCancel = ConfigJson.DefaultPopup[menu.PowerIds].IsShowCancel
  423. appType = ConfigJson.DefaultPopup[menu.PowerIds].AppType
  424. openType = ConfigJson.DefaultPopup[menu.PowerIds].OpenType
  425. }
  426. }
  427. return
  428. }