package entity import ( MC "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/encrypt" "bp.jydev.jianyu360.cn/BaseService/userCenter/rpc/pb" "database/sql" "encoding/json" "errors" "fmt" "github.com/zeromicro/go-zero/core/logx" "sort" "strconv" "strings" ) // WorkDesktopMenu 工作桌面菜单信息 type WorkDesktopMenu struct { MenuTree []*JYMenu //菜单 UserId string //用户id NewUserId int64 //base_userid EntId int64 //企业id EntUserId int64 //企业用户id AppId string //appid 剑鱼:10000 IntranetBool bool //是否开启内网访问模式 Platform string //平台来源 WorkStatus int64 //菜单分组 AccountId int64 //账户id EntAccountId int64 //企业账户id PositionType int64 //职位类型 0:个人 1:企业 PositionId int64 //职位id MgoUserId string //原mongo userId -- p278 } // JYMenu 工作桌面菜单内容 type JYMenu struct { Id int Name string //菜单名称 Match string //滤镜过滤正则 OrderId int //菜单排序id ParentId int //父级id PowerIds string //权限id CheckCode int //是否必须验证权限才显示菜单 Url string //菜单跳转链接 Icon string //菜单图标 AdditionalInfo map[string]Additional //附加弹窗信息 AppType string //菜单模式 OpenType string //打开方式 Status int //是否是可用服务 PermissionCode string //功能代码 CapitalCode string //留资代码 CapitalInfo Additional //留资弹窗 Children []*JYMenu //菜单s Authority int //权限逻辑备注 默认0:功能权限、资源权限、留资权限必须全部满足;1:功能权限或资源权限或留资权限满足其一就行; Level int //1:一级菜单;2:二级菜单;3:三级菜单;4:四级菜单 } type Additional struct { Title string `json:"title"` //弹窗标题 Content string `json:"content"` //弹窗提示信息 ConfirmUrl string `json:"confirmUrl,optional"` //确认按钮跳转地址 ConfirmText string `json:"confirmText,optional"` //确认按钮 IsShowCancel bool `json:"isShowCancel,optional"` //是否显示取消按钮 AppType string `json:"appType,optional,omitempty"` //跳转方式 OpenType string `json:"openType,optional,omitempty"` } // GetMenuTreeData 获取有效菜单数据 func (m *WorkDesktopMenu) GetMenuTreeData() error { //P278 身份切换 positionType := `` switch m.PositionType { //职位类型 0:个人 1:企业 case 0: positionType = `AND available <= 2` case 1: positionType = `AND available >= 2` } //tidb数据 query := fmt.Sprintf(`SELECT * FROM `+ConfigJson.WorkTableOut+` WHERE appid=? AND status=%d %s ORDER BY id ASC`, m.WorkStatus, positionType) //是否开启内网访问数据权限---对应 api 配置文件 if m.IntranetBool { query = fmt.Sprintf(`SELECT * FROM `+ConfigJson.WorkTableInside+` WHERE appid=? AND status>=0 %s ORDER BY id ASC`, positionType) } logx.Info("query:", query) menuData := BaseMysql.SelectBySql(query, m.AppId) if menuData == nil || len(*menuData) == 0 { return errors.New("查询数据异常") } for _, v := range *menuData { menu := &JYMenu{ Id: MC.IntAll(v["id"]), Name: MC.ObjToString(v["name"]), Match: MC.ObjToString(v["match"]), OrderId: MC.IntAll(v["orderid"]), ParentId: MC.IntAll(v["parentid"]), PowerIds: MC.ObjToString(v["powerids"]), CheckCode: MC.IntAll(v["checkcode"]), Icon: MC.ObjToString(v["icon"]), AppType: MC.ObjToString(v["apptype"]), OpenType: MC.ObjToString(v["opentype"]), Status: MC.IntAll(v["status"]), PermissionCode: MC.ObjToString(v["permissioncode"]), CapitalCode: MC.ObjToString(v["capitalcode"]), Authority: MC.IntAll(v["authority"]), } var OpenType = map[string]string{} if err := json.Unmarshal([]byte(MC.ObjToString(v["opentype"])), &OpenType); err == nil { menu.OpenType = OpenType[m.Platform] } switch m.Platform { case "WX": menu.Url = MC.ObjToString(v["wxurl"]) menu.PowerIds = MC.ObjToString(v["wxpids"]) case "APP": menu.Url = MC.ObjToString(v["appurl"]) menu.PowerIds = MC.ObjToString(v["apppids"]) default: menu.Url = MC.ObjToString(v["pcurl"]) } //菜单(移动端)是否需要显示:PC端菜单不需要在移动端显示;或移动端菜单不需要在PC端显示。 if menu.Url == "-1" { continue } if additionalInfo := MC.ObjToString(v["additionalinfo"]); additionalInfo != "" { additional := map[string]Additional{} if json.Unmarshal([]byte(additionalInfo), &additional) == nil { menu.AdditionalInfo = map[string]Additional{ m.Platform: additional[m.Platform], } } } if capitalInfo := MC.ObjToString(v["capitalinfo"]); capitalInfo != "" { additional := Additional{} if json.Unmarshal([]byte(capitalInfo), &additional) == nil { menu.CapitalInfo = additional } } if menu.Id > 0 { m.MenuTree = append(m.MenuTree, menu) } } return nil } // WorkMenuTree 菜单-格式化-tree func (m *WorkDesktopMenu) WorkMenuTree(parentId int) (jyMenu []*JYMenu) { jyMenu = make([]*JYMenu, 0) for _, mv := range m.MenuTree { if mv.ParentId == parentId { mv.Children = m.WorkMenuTree(mv.Id) sort.SliceStable(mv.Children, func(i, j int) bool { return mv.Children[i].OrderId < mv.Children[j].OrderId }) jyMenu = append(jyMenu, mv) } } sort.SliceStable(jyMenu, func(i, j int) bool { return jyMenu[i].OrderId < jyMenu[j].OrderId }) return } // WorkMenuFormat 菜单 格式化 func (m *WorkDesktopMenu) WorkMenuFormat() ([]*pb.MenuList, error) { //logx.Info("树的长度:", len(m.MenuTree)) menuList := make([]*pb.MenuList, 0) for _, mv := range m.MenuTree { //if mv.Id < 466 { // continue //} //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示) usable := m.VerifyPermissions(mv.PowerIds) //checkCode==1 验证权限结果 无权限不显示 if !usable && mv.CheckCode == 1 { continue } //GetResources(m.AppId, m.NewUserId, m.EntId, m.EntUserId) oneLevel := &pb.MenuList{ Name: mv.Name, Icon: mv.Icon, Url: mv.Url, Id: encrypt.SE.EncodeString(strconv.Itoa(mv.Id)), //功能id加密 Usable: usable, //MC.If(mv.PowerIds != "", usable && mv.CheckCode == 1, true).(bool), AppType: mv.AppType, OpenType: mv.OpenType, Child: []*pb.SecondLevelMenu{}, TipInfo: &pb.TipInfo{ Title: mv.AdditionalInfo[m.Platform].Title, Content: mv.AdditionalInfo[m.Platform].Content, ConfirmUrl: mv.AdditionalInfo[m.Platform].ConfirmUrl, ConfirmText: mv.AdditionalInfo[m.Platform].ConfirmText, IsShowCancel: mv.AdditionalInfo[m.Platform].IsShowCancel, AppType: mv.AdditionalInfo[m.Platform].AppType, OpenType: mv.AdditionalInfo[m.Platform].OpenType, }, Match: MC.If(mv.Match != "", strings.Split(mv.Match, ","), []string{}).([]string), } if len(mv.Children) > 0 { for _, sv := range mv.Children { //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示) usable := m.VerifyPermissions(sv.PowerIds) //checkCode==1 验证权限结果 无权限不显示 if !usable && sv.CheckCode == 1 { continue } secondLevel := &pb.SecondLevelMenu{ Name: sv.Name, Icon: sv.Icon, Url: sv.Url, Id: encrypt.SE.EncodeString(strconv.Itoa(sv.Id)), //功能id加密 Usable: usable, //MC.If(sv.PowerIds != "", usable && sv.CheckCode == 1, true).(bool), Child: []*pb.ThreeLevelMenu{}, AppType: sv.AppType, OpenType: sv.OpenType, TipInfo: &pb.TipInfo{ Title: sv.AdditionalInfo[m.Platform].Title, Content: sv.AdditionalInfo[m.Platform].Content, ConfirmUrl: sv.AdditionalInfo[m.Platform].ConfirmUrl, ConfirmText: sv.AdditionalInfo[m.Platform].ConfirmText, IsShowCancel: sv.AdditionalInfo[m.Platform].IsShowCancel, AppType: sv.AdditionalInfo[m.Platform].AppType, OpenType: sv.AdditionalInfo[m.Platform].OpenType, }, Match: MC.If(sv.Match != "", strings.Split(sv.Match, ","), []string{}).([]string), } if len(sv.Children) > 0 { for _, tv := range sv.Children { //附件下载包、采购单位画像记录、企业画像记录 如果是大会员 排除此三项菜单 //灵活性降低 if (strings.Contains(tv.Name, "附件下载包") && m.VerifyPermissions("3")) || (tv.Name == "采购单位画像记录" && m.VerifyPermissions("5")) || (tv.Name == "企业画像记录" && m.VerifyPermissions("4,12,13,19,20,21,23")) { continue } //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示) usable := m.VerifyPermissions(tv.PowerIds) //checkCode==1 验证权限结果 无权限不显示 if !usable && tv.CheckCode == 1 { continue } var ( //数据库默认提示弹窗信息 title, content, confirmUrl, confirmText, isShowCancel, appType, openType, feasibility = tv.AdditionalInfo[m.Platform].Title, tv.AdditionalInfo[m.Platform].Content, tv.AdditionalInfo[m.Platform].ConfirmUrl, tv.AdditionalInfo[m.Platform].ConfirmText, tv.AdditionalInfo[m.Platform].IsShowCancel, tv.AdditionalInfo[m.Platform].AppType, tv.AdditionalInfo[m.Platform].OpenType, usable ) //三级菜单------ if len(tv.Children) == 0 && (tv.CapitalCode != "" || tv.PermissionCode != "") { //用户是否需要留资 //资源中台获取用户权限--没有权限:title等置空 //ResourceLib.PowerHandle() title, content, confirmUrl, confirmText, appType, openType, isShowCancel, feasibility = CheckCapitalResources(tv, m, usable, m.VerifyPermissions(tv.PermissionCode)) } //弹框地址处理 threeLevel := &pb.ThreeLevelMenu{ Name: tv.Name, Icon: tv.Icon, Url: tv.Url, Id: encrypt.SE.EncodeString(strconv.Itoa(tv.Id)), //功能id加密 Usable: feasibility, //MC.If(tv.PowerIds != "", usable && tv.CheckCode == 1, true).(bool), AppType: tv.AppType, OpenType: tv.OpenType, TipInfo: &pb.TipInfo{ Title: title, Content: content, ConfirmUrl: confirmUrl, ConfirmText: confirmText, IsShowCancel: isShowCancel, AppType: appType, OpenType: openType, }, Match: MC.If(tv.Match != "", strings.Split(tv.Match, ","), []string{}).([]string), } if len(tv.Children) > 0 { L: for _, fv := range tv.Children { if fv.Name == "" { continue } if fv.CapitalCode != "" || fv.PermissionCode != "" { //用户是否需要留资 //资源中台获取用户权限--没有权限:title等置空 //ResourceLib.PowerHandle() //判断资源中台权限 title, content, confirmUrl, confirmText, appType, openType, isShowCancel, feasibility = CheckCapitalResources(fv, m, usable, m.VerifyPermissions(fv.PermissionCode)) } threeLevel.Url = MC.If(fv.Url != "", fv.Url, tv.Url).(string) threeLevel.Icon = MC.If(fv.Icon != "", fv.Icon, tv.Icon).(string) threeLevel.AppType = fv.AppType threeLevel.OpenType = fv.OpenType threeLevel.Usable = feasibility if title != "" { threeLevel.TipInfo = &pb.TipInfo{ Title: title, Content: content, ConfirmUrl: confirmUrl, ConfirmText: confirmText, IsShowCancel: isShowCancel, AppType: appType, OpenType: openType, } } threeLevel.Match = MC.If(fv.Match != "", strings.Split(fv.Match, ","), []string{}).([]string) //四级菜单必须有顺序性,大会员》商机管理》超级订阅》免费用户 name := MC.If(strings.Contains(fv.Name, "-"), strings.Split(fv.Name, "-")[0], "免费").(string) if len(UserRolePowers[name]) > 0 && m.VerifyPermissions(strings.Join(UserRolePowers[name], ",")) && m.VerifyPermissions(fv.PowerIds) { break L } } } //无资源中台权限 菜单不显示 if !feasibility && tv.CheckCode == 1 { continue } if threeLevel != nil { secondLevel.Child = append(secondLevel.Child, threeLevel) } } } //二级菜单 有三级子菜单;才会显示 if len(secondLevel.Child) == 0 && sv.CheckCode == 1 { continue } oneLevel.Child = append(oneLevel.Child, secondLevel) } } //一级菜单 有二级子菜单;才会显示 if len(oneLevel.Child) == 0 && mv.CheckCode == 1 { continue } menuList = append(menuList, oneLevel) } //清用户内存信息 func(baseUserid int64, appId, userId string) { OverallLock.Lock() defer OverallLock.Unlock() userInfo := UserInfoMap[baseUserid] if userInfo != nil { userInfo.Lock.Lock() defer userInfo.Lock.Unlock() userInfo.Permissions = map[string]int{} userInfo.Capitals = map[string]int{} } }(m.NewUserId, m.AppId, m.UserId) //bytes, _ := json.MarshalIndent(menuList, "", " ") //fmt.Printf("%s\n", bytes) return menuList, nil } // VerifyPermissions 是否有权限可用此服务 func (m *WorkDesktopMenu) VerifyPermissions(powerIds string) (b bool) { if powerIds == "" { return true } if len(strings.Split(powerIds, ",")) > 0 { userPower := m.AutoUserPowerInfo() //m.TimeOut, m.BigMemberOff, func(powerIds string) { for _, pv := range strings.Split(powerIds, ",") { if userPower[pv] > 0 { b = true break } } }(powerIds) } return } // WorkCommonly 常用功能 var ( WorkCommonly = "work_commonly" //WorkMenu = "work_menu" ) // CommonlyUpdate 更新常用功能 func CommonlyUpdate(in *pb.WorkDesktopComprehensiveReq) (B bool, M string) { //事务 1:查; 2: 存;3: 删; var ( ids []string mk int ) for _, mid := range strings.Split(in.MenuIds, ",") { if mid == "" { continue } mk++ //常用功能数量限制 if ConfigJson.CommonlySize > 0 && mk >= int(ConfigJson.CommonlySize) { break } //id 解密 ids = append(ids, encrypt.SE.DecodeString(mid)) } //更新此用户设置的常用功能 if B = BaseMysql.ExecTx("常用功能批量更新", func(tx *sql.Tx) bool { //查询此用户常用功能是否已存在记录 var ( id = 0 existingData *[]map[string]interface{} ) //P278 身份切换 常用功能和职业id 绑定 existingData = BaseMysql.SelectBySqlByTx(tx, `SELECT id FROM `+WorkCommonly+` WHERE base_userid = ? AND appid = ? AND field = ? AND userid = ? ORDER BY id DESC `, in.NewUserId, in.AppId, in.ActionMode, in.UserId) if existingData != nil && len(*existingData) > 0 { id = MC.IntAll((*existingData)[0]["id"]) //} else { // //P278 之前版本查询逻辑 // existingData = BaseMysql.SelectBySqlByTx(tx, `SELECT id FROM `+WorkCommonly+` WHERE base_userid = ? AND appid = ? AND field = ? ORDER BY id DESC `, in.NewUserId, in.AppId, in.ActionMode) // if existingData != nil && len(*existingData) > 0 { // id = MC.IntAll((*existingData)[0]["id"]) // } } switch { case id > 0: //更新 if BaseMysql.UpdateOrDeleteBySqlByTx(tx, `UPDATE `+WorkCommonly+` SET value = ?,userid = ? WHERE id = ?`, strings.Join(ids, ","), in.UserId, id) < 0 { logx.Info("常用功能-更新数据失败") return false } default: //插入 if BaseMysql.InsertBySqlByTx(tx, `INSERT INTO `+WorkCommonly+` (appid,base_userid,platform,field,value,userid) VALUES (?,?,?,?,?,?)`, in.AppId, in.NewUserId, in.Platform, in.ActionMode, strings.Join(ids, ","), in.UserId) < 0 { logx.Info("常用功能-插入数据失败") return false } } return true }); !B { M = "常用功能更新数据失败" } return } // CommonlyFormat 常用功能 格式化 func (m *WorkDesktopMenu) CommonlyFormat(childMenus map[int][]*JYMenu) ([]*pb.ThreeLevelMenu, []string, bool) { menuList := make([]*pb.ThreeLevelMenu, 0) subLevel := map[int]bool{} delBool := false //更新因超级订阅用户,又购买大会员得用户 导致附件下载包||采购单位画像记录||企业画像记录 不应该展示 var saveIds []string for _, mv := range m.MenuTree { //三级菜单已处理,子级四级菜单不再处理 //过滤子级 ++ if subLevel[mv.ParentId] { continue } //三级下架菜单:mv.Status == 1 if mv.Status == 1 { delBool = true continue } //附件下载包、采购单位画像记录、企业画像记录 如果是大会员 排除此三项菜单 //灵活性降低 if (mv.Name == "附件下载包" && m.VerifyPermissions("3")) || (mv.Name == "采购单位画像记录" && m.VerifyPermissions("5")) || (mv.Name == "企业画像记录" && m.VerifyPermissions("4,12,13,19,20,21,23")) { delBool = true continue } saveIds = append(saveIds, encrypt.SE.EncodeString(strconv.Itoa(mv.Id))) subLevel[mv.Id] = true //0:默认展示;1:需验证权限,有权限展示;2:需验证权限,无权限也可展示(可用服务无权限不展示) usable := m.VerifyPermissions(mv.PowerIds) feasibility := usable //三级菜单------ if len(childMenus[mv.Id]) == 0 && (mv.CapitalCode != "" || mv.PermissionCode != "") { _, _, _, _, _, _, _, feasibility = CheckCapitalResources(mv, m, usable, m.VerifyPermissions(mv.PermissionCode)) } oneLevel := &pb.ThreeLevelMenu{ Name: mv.Name, Icon: mv.Icon, Url: mv.Url, Id: encrypt.SE.EncodeString(strconv.Itoa(mv.Id)), //功能id加密 Usable: feasibility, //MC.If(mv.PowerIds != "", usable && mv.CheckCode == 1, true).(bool), AppType: mv.AppType, OpenType: mv.OpenType, TipInfo: &pb.TipInfo{ Title: mv.AdditionalInfo[m.Platform].Title, Content: mv.AdditionalInfo[m.Platform].Content, ConfirmUrl: mv.AdditionalInfo[m.Platform].ConfirmUrl, ConfirmText: mv.AdditionalInfo[m.Platform].ConfirmText, IsShowCancel: mv.AdditionalInfo[m.Platform].IsShowCancel, AppType: mv.AppType, OpenType: mv.OpenType, }, Match: MC.If(mv.Match != "", strings.Split(mv.Match, ","), []string{}).([]string), } //处理子级 if childMenus[mv.Id] != nil && len(childMenus[mv.Id]) > 0 { childMenu := childMenus[mv.Id] sort.Slice(childMenu, func(i, j int) bool { return childMenu[i].OrderId < childMenu[j].OrderId }) L: for _, cv := range childMenu { //cv.Status < 0 四级菜单 生效不再处理;因为常用功能设置保存的都是三级菜单id,如果三级菜单功能下架,只处理三级菜单。 if cv.Name == "" || cv.ParentId != mv.Id || cv.Status < 0 { continue } if cv.CapitalCode != "" || cv.PermissionCode != "" { _, _, _, _, _, _, _, feasibility = CheckCapitalResources(cv, m, usable, m.VerifyPermissions(cv.PermissionCode)) } oneLevel.Url = MC.If(cv.Url != "", cv.Url, mv.Url).(string) oneLevel.Icon = MC.If(cv.Icon != "", cv.Icon, mv.Icon).(string) oneLevel.AppType = cv.AppType oneLevel.OpenType = cv.OpenType oneLevel.Usable = feasibility if cv.AdditionalInfo[m.Platform].Title != "" { oneLevel.TipInfo = &pb.TipInfo{ Title: cv.AdditionalInfo[m.Platform].Title, Content: cv.AdditionalInfo[m.Platform].Content, ConfirmUrl: cv.AdditionalInfo[m.Platform].ConfirmUrl, ConfirmText: cv.AdditionalInfo[m.Platform].ConfirmText, IsShowCancel: cv.AdditionalInfo[m.Platform].IsShowCancel, AppType: cv.AppType, OpenType: cv.OpenType, } } oneLevel.Match = MC.If(cv.Match != "", strings.Split(cv.Match, ","), []string{}).([]string) name := MC.If(strings.Contains(cv.Name, "-"), strings.Split(cv.Name, "-")[0], "免费").(string) if len(UserRolePowers[name]) > 0 && m.VerifyPermissions(strings.Join(UserRolePowers[name], ",")) { break L } } } //跨平台,非本平台功能,给用户提示信息 if oneLevel.Url == "-1" { oneLevel.TipInfo = &pb.TipInfo{ Title: ConfigJson.DefaultPopup[m.Platform].Title, Content: ConfigJson.DefaultPopup[m.Platform].Content, ConfirmUrl: ConfigJson.DefaultPopup[m.Platform].ConfirmUrl, ConfirmText: ConfigJson.DefaultPopup[m.Platform].ConfirmText, IsShowCancel: ConfigJson.DefaultPopup[m.Platform].IsShowCancel, } if oneLevel.TipInfo.ConfirmUrl == "" { oneLevel.TipInfo.AppType = "" oneLevel.TipInfo.OpenType = "" } oneLevel.Url = "" oneLevel.Usable = false } //1、当前平台有权限,清空提示信息 //2、提示信息内容为空,清空提示信息 if oneLevel.Usable || oneLevel.TipInfo.Content == "" { oneLevel.TipInfo = &pb.TipInfo{} } menuList = append(menuList, oneLevel) } return menuList, saveIds, delBool }