user.go 17 KB

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