diff --git a/api/version1/entry.go b/api/version1/entry.go index c8ebd07..a0a3b95 100644 --- a/api/version1/entry.go +++ b/api/version1/entry.go @@ -1,9 +1,13 @@ package version1 -import "appPlatform/api/version1/user" +import ( + "appPlatform/api/version1/menus" + "appPlatform/api/version1/user" +) type ApiEntry struct { - UserApi user.ApiMethod //人员信息 + UserApi user.ApiMethod //人员信息 + MenusApi menus.ApiMethod //菜单路由 } var AppApiEntry = new(ApiEntry) diff --git a/api/version1/menus/menus.go b/api/version1/menus/menus.go new file mode 100644 index 0000000..adb0b6d --- /dev/null +++ b/api/version1/menus/menus.go @@ -0,0 +1,99 @@ +package menus + +import ( + "appPlatform/models/modelAppPlatform" + "appPlatform/overall" + "appPlatform/overall/publicmethod" + + "github.com/gin-gonic/gin" +) + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 13:26:16 +@ 功能: 获取路由树 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (a *ApiMethod) GetMenusThree(c *gin.Context) { + var menusList []modelAppPlatform.Menus + err := overall.CONSTANT_DB_AppPlatform.Where("visible IN ?", []int{1, 2}).Find(&menusList).Error + if err != nil && len(menusList) < 1 { + publicmethod.Result(1, err, c, "没有路由!") + return + } + routerThree := publicmethod.GetMenuRouterThree(0, menusList) + publicmethod.Result(0, routerThree, c) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 15:36:33 +@ 功能: 获取菜单列表树 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (a *ApiMethod) GetMenusListTree(c *gin.Context) { + var requestData ShearMenu + c.ShouldBindJSON(&requestData) + var menusList []modelAppPlatform.Menus + gormDb := overall.CONSTANT_DB_AppPlatform.Where("visible IN ?", []int{1, 2}) + if requestData.Title != "" { + gormDb = gormDb.Where("`name` LIKE ?", "%"+requestData.Title+"%") + } + err := gormDb.Find(&menusList).Error + if err != nil && len(menusList) < 1 { + publicmethod.Result(1, err, c, "没有路由!") + return + } + routerThree := publicmethod.GetAppMenuThree(0, menusList) + publicmethod.Result(0, routerThree, c) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 16:21:11 +@ 功能: 菜单下拉列表 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (a *ApiMethod) MenuOptions(c *gin.Context) { + var menusList []modelAppPlatform.Menus + err := overall.CONSTANT_DB_AppPlatform.Model(&modelAppPlatform.Menus{}).Select("`id`,`name`,`parentId`").Where("visible IN ?", []int{1, 2}).Find(&menusList).Error + if err != nil && len(menusList) < 1 { + publicmethod.Result(1, err, c, "没有路由!") + return + } + routerThree := publicmethod.GetMenuOptionsThree(0, menusList) + publicmethod.Result(0, routerThree, c) +} diff --git a/api/version1/menus/type.go b/api/version1/menus/type.go new file mode 100644 index 0000000..dbfb0d4 --- /dev/null +++ b/api/version1/menus/type.go @@ -0,0 +1,41 @@ +package menus + +import ( + "appPlatform/overall/publicmethod" + "sync" + + "github.com/gin-gonic/gin" +) + +type ApiMethod struct{} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 13:17:38 +@ 功能: 菜单路由入口 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (a *ApiMethod) Index(c *gin.Context) { + outputCont := publicmethod.MapOut[string]() + outputCont["index"] = "菜单路由入口" + publicmethod.Result(0, outputCont, c) +} + +// 协程设置 +var syncSeting = sync.WaitGroup{} + +// 菜单搜索关键字 +type ShearMenu struct { + Title string `json:"title"` +} diff --git a/api/version1/user/type.go b/api/version1/user/type.go index 6379675..6265c5c 100644 --- a/api/version1/user/type.go +++ b/api/version1/user/type.go @@ -18,3 +18,20 @@ func (a *ApiMethod) Index(c *gin.Context) { // 协程设置 var syncSeting = sync.WaitGroup{} + +// 输出当前登录用户信息 +type SendUserCont struct { + UserId string `json:"userId"` //用户识别符 + Number string `json:"number"` //用户工号 + NickName string `json:"nickname"` //用户名称 + Company string `json:"company"` //公司 + CompanyName string `json:"companyname"` //公司名称 + Department string `json:"department"` //主部门 + DepartmentName string `json:"departmentname"` //主部门名称 + Organization string `json:"organization"` //行政组织 + OrganizationName string `json:"organizationgname"` //行政组织名称 + Avatar string `json:"avatar"` + Roles []string `json:"roles"` + Perms []string `json:"perms"` + Managementcope []string `json:"managementcope"` //可操作得行政组织 +} diff --git a/api/version1/user/userCont.go b/api/version1/user/userCont.go new file mode 100644 index 0000000..21b2e9a --- /dev/null +++ b/api/version1/user/userCont.go @@ -0,0 +1,131 @@ +package user + +import ( + "appPlatform/models/modelshr" + "appPlatform/models/modelssystempermission" + "appPlatform/overall" + "appPlatform/overall/publicmethod" + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/gin-gonic/gin" +) + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 10:54:15 +@ 功能: 获取当前登录用户信息 +@ 参数 + + # + +@ 返回值 + + # + +@ 方法原型 + + # +*/ +func (a *ApiMethod) GetUserCont(c *gin.Context) { + context, _ := c.Get(overall.MyContJwt) + var myContInfo modelshr.ManCont + jsonCont, _ := json.Marshal(context) + jsonUnErr := json.Unmarshal(jsonCont, &myContInfo) + outMap := publicmethod.MapOut[string]() + outMap["context"] = context + outMap["exi"] = jsonUnErr + outMap["myContInfo"] = myContInfo + var sendData SendUserCont + sendData.UserId = strconv.FormatInt(myContInfo.Key, 10) + sendData.Number = myContInfo.Number + sendData.NickName = myContInfo.Name + sendData.Company = strconv.FormatInt(myContInfo.Company, 10) //公司 + var companyCont modelshr.AdministrativeOrganization + companyCont.GetCont(map[string]interface{}{"`id`": myContInfo.Company}, "`name`") + sendData.CompanyName = companyCont.Name //公司名称 + sendData.Department = strconv.FormatInt(myContInfo.MainDeparment, 10) //主部门 + var departCont modelshr.AdministrativeOrganization + departCont.GetCont(map[string]interface{}{"`id`": myContInfo.MainDeparment}, "`name`") + sendData.DepartmentName = departCont.Name //主部门名称 + sendData.Organization = strconv.FormatInt(myContInfo.AdminOrg, 10) //行政组织 + var orgCont modelshr.AdministrativeOrganization + orgCont.GetCont(map[string]interface{}{"`id`": myContInfo.MainDeparment}, "`name`") + sendData.OrganizationName = orgCont.Name //行政组织名称 + sendData.Avatar = myContInfo.Icon + roleList := strings.Split(myContInfo.Role, ",") + roleList = append(roleList, "ROOT") + sendData.Roles = roleList + //获取权限 + menuPoint, opeart, orgList := GetUserPower("app", myContInfo.Position, roleList) + fmt.Printf("menuPoint======>%v\nopeart======>%v\norgList======>%v\n", menuPoint, opeart, orgList) + sendData.Perms = menuPoint + publicmethod.Result(0, sendData, c) +} + +/* +* +@ 作者: 秦东 +@ 时间: 2023-05-22 11:30:44 +@ 功能: 获取用户权限 +@ 参数 + + #appType 系统标识 + #postId 职务 + #roleList 角色列表 + +@ 返回值 + + #menuPoint 菜单操作列表 + #opeart 点位 + #orgList 行政组织 + +@ 方法原型 + + #func GetUserPower(appType string, postId int64, roleList []string) (menuPoint []string, opeart []string, orgList []string) +*/ +func GetUserPower(appType string, postId int64, roleList []string) (menuPoint, opeart, orgList []string) { + //获取职务权限 + var emPower modelssystempermission.Empower + err := emPower.GetCont(map[string]interface{}{"`post_id`": postId, "`system`": appType}) + if err == nil { + if emPower.PointId != "" { + pointIdList := strings.Split(emPower.PointId, ",") + menuPoint = publicmethod.MergeStruct[string](pointIdList, menuPoint) + } + if emPower.Operation != "" { + operationIdList := strings.Split(emPower.Operation, ",") + opeart = publicmethod.MergeStruct[string](operationIdList, opeart) + } + if emPower.Organization != "" { + orgIdList := strings.Split(emPower.Organization, ",") + orgList = publicmethod.MergeStruct[string](orgIdList, orgList) + } + } + //获取角色权限 + if len(roleList) > 0 { + for _, v := range roleList { + var roleEmpower modelssystempermission.RoleEmpower + err = roleEmpower.GetCont(map[string]interface{}{"`role_id`": v, "`system`": appType}) + if err == nil { + if roleEmpower.PointId != "" { + pointIdList := strings.Split(roleEmpower.PointId, ",") + menuPoint = publicmethod.MergeStruct[string](pointIdList, menuPoint) + } + if roleEmpower.Operation != "" { + operationIdList := strings.Split(roleEmpower.Operation, ",") + opeart = publicmethod.MergeStruct[string](operationIdList, opeart) + } + if roleEmpower.Organization != "" { + orgIdList := strings.Split(roleEmpower.Organization, ",") + orgList = publicmethod.MergeStruct[string](orgIdList, orgList) + } + } + } + } + + return +} diff --git a/apirouter/entry.go b/apirouter/entry.go index d01f9ec..9015392 100644 --- a/apirouter/entry.go +++ b/apirouter/entry.go @@ -2,13 +2,15 @@ package apirouter import ( "appPlatform/apirouter/apishiyan" + menusrouters "appPlatform/apirouter/v1/menusRouters" userrouters "appPlatform/apirouter/v1/userRouters" ) // 路由结构 type RouterGroup struct { - ShiyanApi apishiyan.ApiRouter - UserRouter userrouters.ApiRouter + ShiyanApi apishiyan.ApiRouter + UserRouter userrouters.ApiRouter + MenusRouter menusrouters.ApiRouter } var RouterGroupEntry = new(RouterGroup) diff --git a/apirouter/v1/menusRouters/pc.go b/apirouter/v1/menusRouters/pc.go new file mode 100644 index 0000000..199501f --- /dev/null +++ b/apirouter/v1/menusRouters/pc.go @@ -0,0 +1,21 @@ +package menusrouters + +import ( + "appPlatform/api/version1" + + "github.com/gin-gonic/gin" +) + +// 权限管理PC端 +func (a *ApiRouter) RouterGroupPc(router *gin.RouterGroup) { + apiRouter := router.Group("menus") + + var methodBinding = version1.AppApiEntry.MenusApi + { + apiRouter.GET("", methodBinding.Index) //入口 + apiRouter.POST("", methodBinding.Index) //入口 + apiRouter.GET("get_routers_three", methodBinding.GetMenusThree) //获取路由树 + apiRouter.GET("get_menus_three", methodBinding.GetMenusListTree) //获取菜单树 + apiRouter.GET("menu_options", methodBinding.MenuOptions) //菜单下拉列表 + } +} diff --git a/apirouter/v1/menusRouters/type.go b/apirouter/v1/menusRouters/type.go new file mode 100644 index 0000000..91f7c53 --- /dev/null +++ b/apirouter/v1/menusRouters/type.go @@ -0,0 +1,4 @@ +package menusrouters + +//菜单路由 +type ApiRouter struct{} diff --git a/apirouter/v1/userRouters/pc.go b/apirouter/v1/userRouters/pc.go index 2259f09..c31c7a2 100644 --- a/apirouter/v1/userRouters/pc.go +++ b/apirouter/v1/userRouters/pc.go @@ -12,8 +12,8 @@ func (a *ApiRouter) RouterGroupPc(router *gin.RouterGroup) { var methodBinding = version1.AppApiEntry.UserApi { - apiRouter.GET("", methodBinding.Index) //入口 - apiRouter.POST("", methodBinding.Index) //入口 - + apiRouter.GET("", methodBinding.Index) //入口 + apiRouter.POST("", methodBinding.Index) //入口 + apiRouter.GET("get_user_cont", methodBinding.GetUserCont) //获取登陆人信息 } } diff --git a/initialization/route/initRoute.go b/initialization/route/initRoute.go index 80d1d1d..3fff3a5 100644 --- a/initialization/route/initRoute.go +++ b/initialization/route/initRoute.go @@ -41,6 +41,9 @@ func InitialRouter() *gin.Engine { //主体内容 version1HonorsApi := apirouter.RouterGroupEntry.UserRouter version1HonorsApi.RouterGroupPc(VerifyIdentity) + //菜单路由 + menuRouterApi := apirouter.RouterGroupEntry.MenusRouter + menuRouterApi.RouterGroupPc(VerifyIdentity) } //验证身份接口 无需鉴权Url(主要web端使用) diff --git a/models/modelAppPlatform/menus.go b/models/modelAppPlatform/menus.go new file mode 100644 index 0000000..5b7c26d --- /dev/null +++ b/models/modelAppPlatform/menus.go @@ -0,0 +1,67 @@ +package modelAppPlatform + +import ( + "appPlatform/overall" + "strings" +) + +// 行政组织类型 +type Menus struct { + Id int `json:"id" gorm:"primaryKey;column:id;type:int(5) unsigned;not null;comment:Id;index"` + Name string `json:"name" gorm:"column:name;type:varchar(255) unsigned;default:'';not null;comment:菜单名称"` + Types int `json:"type" gorm:"column:type;type:int(1) unsigned;default:1;not null;comment:菜单类型(1-菜单;2-目录;3-外链;4-按钮权限"` + Path string `json:"path" gorm:"column:path;type:varchar(255) ;default:'';comment:路由路径"` + Component string `json:"component" gorm:"column:component;type:varchar(255) ;default:'';comment:组件路径(vue页面完整路径,省略.vue后缀)"` + Perm int64 `json:"perm" gorm:"column:perm;type:bigint(20) unsigned;default:0;not null;comment:权限标识"` + Visible int `json:"visible" gorm:"column:visible;type:int(1) unsigned;default:1;not null;comment:显示状态(1:显示;2:隐藏,3:删除)"` + Sort int `json:"sort" gorm:"column:sort;type:int(1) unsigned;default:50;not null;comment:排序(数字越小排名越靠前))"` + Icon string `json:"icon" gorm:"column:icon;type:varchar(255) ;default:'';comment:菜单图标"` + Redirect string `json:"redirect" gorm:"column:redirect;type:varchar(255) ;default:'';comment:跳转路径"` + ParentId int `json:"parentId" gorm:"column:parentId;type:int(5) unsigned;default:0;not null;comment:父菜单ID"` + Time int `json:"time" gorm:"column:time;type:bigint(20) unsigned;default:0;not null;comment:创建时间"` +} + +func (menus *Menus) TableName() string { + return "menus" +} + +// 编辑内容 +func (cont *Menus) EiteCont(whereMap interface{}, saveData interface{}) (err error) { + err = overall.CONSTANT_DB_AppPlatform.Model(&cont).Where(whereMap).Updates(saveData).Error + return +} + +// 获取内容 +func (cont *Menus) GetCont(whereMap interface{}, field ...string) (err error) { + gormDb := overall.CONSTANT_DB_AppPlatform.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + gormDb = gormDb.Where(whereMap) + err = gormDb.First(&cont).Error + return +} + +// 根据条件获取总数 +func (cont *Menus) CountCont(whereMap interface{}) (countId int64) { + overall.CONSTANT_DB_AppPlatform.Model(&cont).Where(whereMap).Count(&countId) + return +} + +// 读取全部信息 +func (cont *Menus) ContMap(whereMap interface{}, field ...string) (countAry []Menus, err error) { + gormDb := overall.CONSTANT_DB_AppPlatform.Model(&cont) + if len(field) > 0 { + fieldStr := strings.Join(field, ",") + gormDb = gormDb.Select(fieldStr) + } + err = gormDb.Where(whereMap).Find(&countAry).Error + return +} + +// 删除内容 +func (cont *Menus) DelCont(whereMap interface{}) (err error) { + err = overall.CONSTANT_DB_AppPlatform.Where(whereMap).Delete(&cont).Error + return +} diff --git a/overall/publicmethod/technique.go b/overall/publicmethod/technique.go index 46977f4..e705404 100644 --- a/overall/publicmethod/technique.go +++ b/overall/publicmethod/technique.go @@ -3,6 +3,7 @@ package publicmethod import ( "appPlatform/middleware/grocerystore" "appPlatform/middleware/snowflake" + "appPlatform/models/modelAppPlatform" "appPlatform/models/modelshr" "appPlatform/models/modelsschool" "appPlatform/models/modelsstorage" @@ -2133,3 +2134,97 @@ func StrNumberToInt64(val string, cheng float64) (valInt int64) { valInt, _ = strconv.ParseInt(valStr, 10, 64) return } + +/* +递归无限极菜单树 +*/ +func GetMenuRouterThree(parentId int, threeData []modelAppPlatform.Menus) []MenusRouterThree { + treeList := []MenusRouterThree{} + for _, v := range threeData { + if v.ParentId == parentId { + child := GetMenuRouterThree(v.Id, threeData) + var node MenusRouterThree + node.Path = v.Path //路由路径 + node.Component = v.Component //组件路径 + node.Redirect = v.Redirect //跳转链接 + node.Name = v.Name //路由名称 + var metaCont MenusRouterThreeMet + metaCont.Title = v.Name //路由title + metaCont.Icon = v.Icon //ICON + if v.Visible == 1 { + metaCont.Hidden = false //否隐藏 + } else { + metaCont.Hidden = true //否隐藏 + } + metaCont.Roles = []string{} //拥有路由权限的角色编码 + metaCont.KeepAlive = true //是否开启缓存 + node.Meta = metaCont //路由属性类型 + node.Children = child //子路由列表 + // // fmt.Printf("GetMenuThree-22222--%v--->%v\n", v.Id, node) + treeList = append(treeList, node) + } + } + return treeList +} + +/* +递归无限极菜单树 +*/ +func GetAppMenuThree(parentId int, threeData []modelAppPlatform.Menus) []AppMenusThree { + treeList := []AppMenusThree{} + for _, v := range threeData { + if v.ParentId == parentId { + child := GetAppMenuThree(v.Id, threeData) + var node AppMenusThree + node.Id = v.Id // + node.Name = v.Name //菜单名称"` + node.Types = v.Types //菜单类型(1-菜单;2-目录;3-外链;4-按钮权限"` + node.Path = v.Path //路由路径"` + node.Component = v.Component //组件路径(vue页面完整路径,省略.vue后缀)"` + node.Perm = v.Perm // 权限标识"` + node.Visible = v.Visible //显示状态(1:显示;2:隐藏,3:删除)"` + node.Sort = v.Sort //排序(数字越小排名越靠前))"` + node.Icon = v.Icon //菜单图标"` + node.Redirect = v.Redirect //跳转路径"` + node.ParentId = v.ParentId //父菜单ID"` + node.Time = v.Time //创建时间"` + node.Class = menuType(v.Types) + node.Children = child //子路由列表 + // // fmt.Printf("GetMenuThree-22222--%v--->%v\n", v.Id, node) + treeList = append(treeList, node) + } + } + return treeList +} +func GetMenuOptionsThree(parentId int, threeData []modelAppPlatform.Menus) []AppMenusOptionsThree { + treeList := []AppMenusOptionsThree{} + for _, v := range threeData { + if v.ParentId == parentId { + child := GetMenuOptionsThree(v.Id, threeData) + var node AppMenusOptionsThree + node.Label = v.Name //路由名称 + node.Value = v.Id //路由ID + node.Children = child //子路由列表 + // // fmt.Printf("GetMenuThree-22222--%v--->%v\n", v.Id, node) + treeList = append(treeList, node) + } + } + return treeList +} + +// 菜单类型对照 +func menuType(class int) string { + switch class { + case 1: + return "MENU" + case 2: + return "CATALOG" + case 3: + return "EXTLINK" + case 4: + return "BUTTON" + default: + return "CATALOG" + } + return "CATALOG" +} diff --git a/overall/publicmethod/type.go b/overall/publicmethod/type.go index cd61f85..22be385 100644 --- a/overall/publicmethod/type.go +++ b/overall/publicmethod/type.go @@ -1,6 +1,7 @@ package publicmethod import ( + "appPlatform/models/modelAppPlatform" "appPlatform/models/modelshr" "appPlatform/models/modelssystempermission" ) @@ -291,3 +292,33 @@ type WechatCallBack struct { MsgId string `json:"msgid"` //消息id,用于撤回应用消息 ResponseCode string `json:"response_code"` //仅消息类型为“按钮交互型”,“投票选择型”和“多项选择型”的模板卡片消息返回,应用可使用response_code调用更新模版卡片消息接口,72小时内有效,且只能使用一次 } + +// 菜单路由树 +type MenusRouterThree struct { + Path string `json:"path"` //路由路径 + Component string `json:"component"` //组件路径 + Redirect string `json:"redirect"` //跳转链接 + Name string `json:"name"` //路由名称 + Meta MenusRouterThreeMet `json:"meta"` //路由属性类型 + Children []MenusRouterThree `json:"children"` //子路由列表 +} + +// 路由属性类型 +type MenusRouterThreeMet struct { + Title string `json:"title"` //路由title + Icon string `json:"icon"` //ICON + Hidden bool `json:"hidden"` //否隐藏 + Roles []string `json:"roles"` //拥有路由权限的角色编码 + KeepAlive bool `json:"keepAlive"` //是否开启缓存 +} + +type AppMenusThree struct { + modelAppPlatform.Menus + Class string `json:"class"` //类型对照 + Children []AppMenusThree `json:"children"` //子路由列表 +} +type AppMenusOptionsThree struct { + Label string `json:"label"` // + Value int `json:"value"` //类型对照 + Children []AppMenusOptionsThree `json:"children"` //子路由列表 +}