package entity import ( "encoding/json" "fmt" "strconv" "strings" "sync" "time" "github.com/zeromicro/go-zero/core/logx" MC "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/redis" ) const ( RedisCode = "newother" RedisMenuKey = "jy_workdesktopmenu_%s_%s_%s" UserPowerRedisKey = "jy_userpowerredis_%s_%d_%s" UserRegisterTime = "jy_userregistertime_%s" UserPowerEndTime = "jy_user_power_end_time_%s" ) type UserInfo struct { Capitals map[string]int Permissions map[string]int Lock *sync.Mutex } var ( CapitalRetention = "capital_retention" OverallLock = &sync.Mutex{} UserInfoMap = map[int64]*UserInfo{} UserRolePowers = map[string][]string{} ) /* *待调整 调整为存redis *测试用例放的地方不对 待调整 */ // AutoUserPowerInfo 用户权限 初始化 func (m *WorkDesktopMenu) AutoUserPowerInfo() map[string]int { /* * 商机管理--》新版商机管理vs老版商机管理 * 大会员--》bigmember_service * 超级订阅--》新版超级订阅vs老版超级订阅 * 免费用户--》新免费用户 */ /* * P278 用户身份切换 * 用户权益 通过 权益中台rpc获取 * 用户资源 通过 资源中台rpc获取 */ var UserPowerMap = map[string]int{} //redis newother 查询是否存在用户功能信息 userPowerRedisKey := fmt.Sprintf(UserPowerRedisKey, m.AppId, time.Now().Day(), m.UserId) bytes, err := redis.GetBytes(RedisCode, userPowerRedisKey) if err == nil && len(*bytes) > 0 { if err = json.Unmarshal(*bytes, &UserPowerMap); err == nil { return UserPowerMap } } //数据库查询 、资源中台获取、权益中台获取 查询用户信息 var ( registerTime int64 powerEndTime int64 ) //以上获取不到的信息 再自主查库 userInfoRpc := UserInfoRpc{ AppId: m.AppId, UserId: m.UserId, BaseUserId: m.NewUserId, EntId: m.EntId, EntUserId: m.EntUserId, AccountId: m.AccountId, EntAccountId: m.EntAccountId, PositionType: m.PositionType, PositionId: m.PositionId, MgoUserId: m.MgoUserId, } logx.Info(m.MgoUserId, m.PositionId, "------------------userInfoRpc-------------------------:", userInfoRpc) //权益中台获取权益 userPowers := userInfoRpc.GetUserPowers() if userPowers != nil { logx.Info(userInfoRpc.MgoUserId, "------------userPowers:", userPowers) //注册时间 registerTime = userPowers.Free.Registedate //大会员 member := userPowers.Member //超级订阅 vip := userPowers.Vip //企业信息 entInfo := userPowers.Ent //商机管理 entNiche := userPowers.Entniche //免费用户 free := userPowers.Free if member.Status > 0 || ConfigJson.BigMemberOff { if member.Status > 0 { UserPowerMap["0"] = int(member.Status) UserPowerMap[strconv.Itoa(50+int(member.Status))] = 1 //此处 如果 member.Status >7,和 下面58 会有冲突 //人员行为统计菜单-1、购买大会员且创建了企业的管理员;2、新版商机管理管理员;3、商机管理服务管理员 UserPowerMap["50"] = 1 // if entInfo.EntRoleId == 1 { UserPowerMap["58"] = 1 //企业管理员 } else if entInfo.EntRoleId == 2 { UserPowerMap["59"] = 1 // 部门管理员 } powerEndTime = member.EndTime } //大会员用户购买的服务 也有可能是非大会员用户 购买这些服务 if member.MemberPowerList != nil && len(member.MemberPowerList) > 0 { for _, mp := range member.MemberPowerList { UserPowerMap[strconv.FormatInt(mp, 10)] = MC.If(member.Status > 0, int(member.Status), 1).(int) } } } if vip.Status > 0 { // if powerEndTime < vip.EndTime { powerEndTime = vip.EndTime } UserPowerMap["200"] = int(vip.Status) UserPowerMap["201"] = int(vip.Upgrade) // if vip.Upgrade > 0 && member.Status < 1 { UserPowerMap["202"] = int(vip.Status) } if entInfo.EntRoleId == 1 { UserPowerMap["203"] = 1 //企业管理员 } else if entInfo.EntRoleId == 2 { UserPowerMap["204"] = 1 //部门管理员 } } //企业信息 if m.EntId > 0 { UserPowerMap["702"] = 1 //机构中心 由企业 且 是企业版 //m.PositionType 肯定大于 0; 702 和 901 是同样的权限。 if m.PositionType > 0 { UserPowerMap["901"] = 1 } //P386 switch entInfo.EntRoleId { case 1: //企业管理员 UserPowerMap["902"] = 1 case 2: //部门管理员 UserPowerMap["903"] = 1 } } if entNiche.Status > 0 && entNiche.IsEntPower > 0 { //entInfo.EntRoleId 1:企业管理员 2:部门管理员 //管理员 entInfo.EntRoleId>0 并不一定 entNiche.IsEntPower==1,entNiche.IsEntPower==0 也有权限(已废除) //管理员he员工被分配后 entNiche.IsEntPower==1否则没有权限 //if entNiche.IsEntPower > 0 || entInfo.EntRoleId > 0{//(已废除) //商机管理服务 P259需求 //有商机管理服务 不会再有商机管理订阅菜单 //商机管理服务,上次陈老师说叫“企业管理服务”,不然和商机管理产品容易混淆-- 杨蘭 2022/12/14 switch entNiche.PowerSource { case 0: switch entNiche.IsNew { case 1: //新版商机管理 UserPowerMap["110"] = 1 switch entInfo.EntRoleId { case 2: //部门管理员 UserPowerMap["111"] = 1 case 1: //企业管理员 UserPowerMap["112"] = 1 } case 0: //老版商机管理 UserPowerMap["100"] = 1 switch entInfo.EntRoleId { case 2: //部门管理员 UserPowerMap["101"] = 1 case 1: //企业管理员 UserPowerMap["102"] = 1 } //老版商机管理: model:1-统一订阅,2-个人订阅 if entNiche.Model == 1 { UserPowerMap["103"] = 1 } else if entNiche.Model == 2 { UserPowerMap["104"] = 1 } } case 1: //客户管理服务(商机管理服务) [前提:大会员、超级订阅、医械通用户]---免费用户也可以用 (需求调整来自刘苗:产品已确认) UserPowerMap["600"] = 1 switch entInfo.EntRoleId { case 2: //部门管理员 UserPowerMap["602"] = 1 case 1: //企业管理员 UserPowerMap["601"] = 1 } //} } } if free.IsFree { UserPowerMap["300"] = 1 if free.IsUpgrade { //新免费用户 UserPowerMap["301"] = MC.If(free.IsUpgrade, 1, 0).(int) } //P386 switch entInfo.EntRoleId { case 1: //企业管理员 UserPowerMap["302"] = 1 case 2: //部门管理员 UserPowerMap["303"] = 1 } } //----------其他----------- //广东移动DICT if entInfo.PrivateGD { UserPowerMap["400"] = 1 } //人员行为统计菜单-1、购买大会员且创建了企业的管理员;2、新版商机管理管理员;3、商机管理服务管理员 //必须是企业管理员-&-购买了企业级应用服务 //企业级服务 权限管理(只有企业管理员有权限) entService := entInfo.BuyMember > 0 || entInfo.BuyVip > 0 || entInfo.Services //P386: 只要购买了企业级产品 且是企业管理员 就有>> 权限管理 if entService { if entInfo.EntRoleId == 1 { UserPowerMap["700"] = 1 } else if entInfo.EntRoleId == 2 { //企业级服务 部门管理员 UserPowerMap["703"] = 1 } } //企业级服务 企业订阅-- //1、存在未到期的购买主体为“企业”切购买产品为大会员或者超级订阅的部门管理员或企业管理员;c > 0 //2、存在未到期的老版或者新版商机管理的企业管理员或部门管理员(非商机管理服务)。entnicheIsNew > -1 && powerSource == 0 if entInfo.EntSubscribe > 0 { UserPowerMap["701"] = 1 } //领域化产品权限 //第一版:必须是大会员或者超级订阅用户 且留资 留资表:capital_retention;source = 'medical_domain',未留资提示留资信息 //第二版:调资源中台rpc获取用户是否有使用领域化产品的权限 无权限则去购买 //需求调整: //1:是否是大会员或者超级订阅用户 否:提示购买到超级订阅购买页; 是>-2 //2:判断用户是否留资 否:提示用去留资;是:>-3 //3:资源中台获取用户权限码判断是否有权限 否:提示用户去联系客服 userRegisterTimeKey := fmt.Sprintf(UserRegisterTime, m.UserId) redis.Put(RedisCode, userRegisterTimeKey, strconv.Itoa(int(registerTime)), int(registerTime)) if member.Status > 0 || vip.Status > 0 { userPowerEndTimeKey := fmt.Sprintf(UserPowerEndTime, m.UserId) redis.Put(RedisCode, userPowerEndTimeKey, strconv.Itoa(int(powerEndTime)), int(powerEndTime)) UserPowerMap["500"] = 1 } } //资源中台获取权限 powerList := userInfoRpc.GetUserResources() if len(powerList) > 0 { for _, plv := range powerList { UserPowerMap[plv] = 1 } } //其他权益数据库查询 func(mgoUserId string) { //伙伴计划是否加入(移动端我的伙伴计划菜单) if count := Mysql.CountBySql(`select count(*) from dis_partner where uid=? and type=2`, mgoUserId); count > 0 { UserPowerMap["801"] = 1 } else { UserPowerMap["800"] = 1 } }(m.MgoUserId) //缓存 if UserPowerMap != nil { bytes, err := json.Marshal(UserPowerMap) if err == nil && len(bytes) > 0 { redis.PutBytes(RedisCode, userPowerRedisKey, &bytes, ConfigJson.InternalTime) } } return UserPowerMap } // ClearUserPowerFunc clear One userId>positionId 职位id func ClearUserPowerFunc(positionId, appId string) bool { if positionId == "" { return false } for _, v := range strings.Split(positionId, ",") { for _, vv := range []string{"PC", "APP", "WX"} { //用户菜单缓存 redis.Del(RedisCode, fmt.Sprintf(RedisMenuKey, appId, vv, v)) } //用户权限缓存 redis.Del(RedisCode, fmt.Sprintf(UserPowerRedisKey, appId, time.Now().Day(), v)) } return true } // UserRolePowerInit 用户角色权限初始化 func UserRolePowerInit(strs []string) { if len(strs) > 0 { jyUserRoleData := BaseMysql.SelectBySql(`SELECT id,name FROM jyfunction WHERE status = 1`) if jyUserRoleData != nil && len(*jyUserRoleData) > 0 { for _, jv := range *jyUserRoleData { for _, v := range strs { if strings.Contains(MC.ObjToString(jv["name"]), v) { UserRolePowers[v] = append(UserRolePowers[v], strconv.Itoa(MC.IntAll(jv["id"]))) } } } } } } /* 菜单弹窗逻辑 如果需要留资 默认: 1、先判断是否已留资 2、再判断是否有权限 医械通: 1、不符合可以留资申请开通权限的用户 1、免费用户 2、超级订阅用户、大会员用户到期时间是否超过3个月 (1、2:弹窗-医械通上线啦) 2、符合可以留资申请开通的用户 1、未留资 (1:弹窗-完善基本信息) 2、已留资未开通 3、已留资且开通 (2、3:弹窗-恭喜留资成功) */ /* 1、判断是否满足超级订阅用户或大会员用户 且到期时间超过90天(配置); 1.1、否:权限=0;提示上线啦 1.2、是:是否留资 1.2.1、否:权限=0;提示留资 1.2.2、是:是否开通权限 1.2.2.1、否:权限=0;提示恭喜留资成功,客服联系 1.2.2.2、是:权限=1 */ /*存在超级订阅 或 大会员到期 而医械通未到期的情况*/ // CheckCapitalResources 是否需要留资 且权限验证--弹窗处理 // b 一级权限(超级订阅、大会员等) // p 二级权限(请求资源中台:医械通等) func CheckCapitalResources(menu *JYMenu, wd *WorkDesktopMenu, b, p bool, pUrl string) (title, content, confirmUrl, confirmText, appType, openType string, isShowCancel, usable bool) { var defaultPopupFunc = func() { title = ConfigJson.DefaultPopup[wd.Platform].Title content = ConfigJson.DefaultPopup[wd.Platform].Content confirmUrlArr := strings.Split(ConfigJson.DefaultPopup[wd.Platform].ConfirmUrl, "__") if len(confirmUrlArr) > 1 { confirmUrl = MC.InterfaceToStr(MC.If(wd.Platform == "PC", confirmUrlArr[1], confirmUrlArr[0])) } confirmText = ConfigJson.DefaultPopup[wd.Platform].ConfirmText isShowCancel = ConfigJson.DefaultPopup[wd.Platform].IsShowCancel appType = ConfigJson.DefaultPopup[wd.Platform].AppType openType = ConfigJson.DefaultPopup[wd.Platform].OpenType } OverallLock.Lock() userInfo := UserInfoMap[wd.NewUserId] if userInfo == nil { userInfo = &UserInfo{} userInfo.Lock = &sync.Mutex{} userInfo.Capitals = map[string]int{} userInfo.Permissions = map[string]int{} UserInfoMap[wd.NewUserId] = userInfo } OverallLock.Unlock() userInfo.Lock.Lock() defer userInfo.Lock.Unlock() var ( defaultPopup = false //默认弹窗 capitalBool = func() bool { //用户是否需要留资 if menu.CapitalCode != "" { capitalBool := false for _, cv := range strings.Split(menu.CapitalCode, ",") { if userInfo.Capitals[cv] <= 0 { if c := BaseMysql.CountBySql(`SELECT COUNT(id) FROM `+CapitalRetention+` WHERE source = ? AND position_id = ? AND appid = ?`, cv, wd.PositionId, wd.AppId); c > 0 { userInfo.Capitals[cv] = 1 } else { userInfo.Capitals[cv] = -1 } } if userInfo.Capitals[cv] > 0 { capitalBool = true break } } return capitalBool } return true }() ) // usable = func() bool { switch menu.Authority { case 0: return b && p && capitalBool case 1: return b || p || capitalBool case 2: return b || p && capitalBool case 3: return b && p || capitalBool case 4: return b && capitalBool || p default: return false } }() //P630人脉管理 //用户 有权限 不再判断 弹窗提示信息 if usable { //菜单在当前平台没有权限 if menu.Url == "" && pUrl == "" { usable = false defaultPopupFunc() } return } // 需要特殊处理的菜单 弹窗提示信息 /* 菜单弹窗逻辑 如果需要留资 默认: 1、先判断是否已留资 2、再判断是否有权限 医械通: 1、不符合可以留资申请开通权限的用户 1、免费用户 2、超级订阅用户、大会员用户到期时间是否超过3个月 (1、2:弹窗-医械通上线啦) 2、符合可以留资申请开通的用户 1、未留资 (1:弹窗-完善基本信息) 2、已留资未开通 3、已留资且开通 (2、3:弹窗-恭喜留资成功) */ if PopupIdMap[menu.Id] || PopupIdMap[menu.ParentId] { // 超级订阅 or 大会员 if b { userPowerEndTimeKey := fmt.Sprintf(UserPowerEndTime, wd.UserId) powerEndTime, _ := strconv.ParseInt(redis.GetStr(RedisCode, userPowerEndTimeKey), 10, 64) //超级订阅 大会员到期时间 是否 大于 90天 if powerEndTime == 0 || powerEndTime-time.Now().Unix() < ConfigJson.MedicalFieldTimespan { //即使是超级订阅或大会员 也没有权限 defaultPopup = true } } // 免费用户 或者 不满足条件的超级订阅or大会员用户 if (!b || defaultPopup) && ConfigJson.DefaultPopup[menu.PowerIds].Title != "" { defaultPopupFunc() } else if capitalBool { //已留资的用户 //留资弹窗信息 title = menu.CapitalInfo.Title content = menu.CapitalInfo.Content confirmUrl = menu.CapitalInfo.ConfirmUrl confirmText = menu.CapitalInfo.ConfirmText isShowCancel = menu.CapitalInfo.IsShowCancel appType = menu.CapitalInfo.AppType openType = menu.CapitalInfo.OpenType } else { title = menu.AdditionalInfo[wd.Platform].Title content = menu.AdditionalInfo[wd.Platform].Content confirmUrl = menu.AdditionalInfo[wd.Platform].ConfirmUrl confirmText = menu.AdditionalInfo[wd.Platform].ConfirmText isShowCancel = menu.AdditionalInfo[wd.Platform].IsShowCancel appType = menu.AdditionalInfo[wd.Platform].AppType openType = menu.AdditionalInfo[wd.Platform].OpenType } } else { //默认 // 留资 if !capitalBool { //留资弹窗信息 title = menu.CapitalInfo.Title content = menu.CapitalInfo.Content confirmUrl = menu.CapitalInfo.ConfirmUrl confirmText = menu.CapitalInfo.ConfirmText isShowCancel = menu.CapitalInfo.IsShowCancel appType = menu.CapitalInfo.AppType openType = menu.CapitalInfo.OpenType } else { title = menu.AdditionalInfo[wd.Platform].Title content = menu.AdditionalInfo[wd.Platform].Content confirmUrl = menu.AdditionalInfo[wd.Platform].ConfirmUrl confirmText = menu.AdditionalInfo[wd.Platform].ConfirmText isShowCancel = menu.AdditionalInfo[wd.Platform].IsShowCancel appType = menu.AdditionalInfo[wd.Platform].AppType openType = menu.AdditionalInfo[wd.Platform].OpenType } } return }