go 封装角色模块权限控制
目的
创建通用代码方法实现角色模块的权限控制
实现
-
表结构
-
保存
- JS
function saveData() { let powerPriArr= []; $(".role-menu").each(function (i, v) { let privilegeJson={} if ($("#Privilege-"+$(v).attr("data-modNo")).length>0){ //存在模块操作权限 $($("#Privilege-"+$(v).attr("data-modNo")).find('input[type=checkbox]')) .each(function (m,n) { privilegeJson[$(n).attr("data-name")]=$(n).is(":checked") }) } let powerPriJson = { "mod_no":$(v).attr("data-modNo"), //模块编号 "is_selected":$(v).is(":checked"), //是否选中 "power_privilege":JSON.stringify(privilegeJson), }; powerPriArr.push(powerPriJson) }); let data = { "SaveRole": { "RoleId": parseInt($("#page-data-id").val()), "Name": $("#inputName").val(), "Memo": $("#textMemo").val() }, //"SavePower": JSON.stringify(powerJson) "save_power_privilege":powerPriArr }; $.ajax({ type: 'POST', url: "/systemRole/save", data: JSON.stringify(data), dataType: 'json', contentType: "application/json", async: false, success: function (result) { if (result.success) { $("#page-data-id").val(result.id) swal("", result.message, "success"); setTimeout(function () { window.location.href = "/systemRole" }, 1000); } else { let errMsg = result.error ? result.message + "\n" + result.error : result.message swal("", errMsg, "error"); } } }); }
- service
type RoleSavePowerBasicReqParam struct {
ModNo string `json:"mod_no"` //模块编号
IsSelected bool `json:"is_selected"` //是否选中
//模块下的具体权限(如增删改查{"Add":true,"Delete":true,"Edit":true,"Import":true,"Query":true})
//当IsSelected==true时生效
PowerPrivilege string `json:"power_privilege"`
}
type RoleSaveParam struct {
SaveRole model.SysRole
//角色拥有的菜单模块权限
SavePowerPrivilege []RoleSavePowerBasicReqParam `json:"save_power_privilege"`
}
// RoleSaveService 保存
func RoleSaveService(c *gin.Context) {
var saveParam RoleSaveParam
var err error
var errMsg string
var gormDB *gorm.DB
// 判断记录是否重复
ifExistsModel := &model.SysRole{}
ifExistsModelArr := &[]model.SysRole{}
err = c.BindJSON(&saveParam)
// 检查参数是否有效
if err != nil {
goto ERR
}
// 检查参数必填项目
if common.IsEmpty(saveParam.SaveRole.Name) {
errMsg = fmt.Sprintf("%s", "角色名称不能为空!")
err = errors.New(errMsg)
goto ERR
}
gormDB = dao.QueryArrays(ifExistsModel.TableName(), ifExistsModelArr, []string{},
"RoleId!=? and Name=?",
&[]interface{}{saveParam.SaveRole.RoleId,
saveParam.SaveRole.Name},
[]string{})
if gormDB.Error == nil && len(*ifExistsModelArr) > 0 {
// exist record
errMsg = fmt.Sprintf("%s", "角色名称")
err = errors.New(errMsg)
goto ERR
}
// 保存记录
if saveParam.SaveRole.RoleId == 0 {
// 新增
gormDB = dao.Insert(&saveParam.SaveRole)
} else {
// 更新
updateVal := map[string]interface{}{
"Name": saveParam.SaveRole.Name, //varchar(200) not null,
"Memo": saveParam.SaveRole.Memo, //varchar(200),
"Privilege": saveParam.SaveRole.Privilege,
}
gormDB = dao.UpdateById(saveParam.SaveRole, "RoleId", saveParam.SaveRole.RoleId,
updateVal)
}
if gormDB.Error != nil {
err = gormDB.Error
errMsg = "数据保存失败"
goto ERR
}
//add Power
if len(saveParam.SavePowerPrivilege) > 0 {
for _, power := range saveParam.SavePowerPrivilege {
powerModel := model.SysRolePrivilege{
RoleId: saveParam.SaveRole.RoleId,
MeuNo: power.ModNo,
PrivilegeDetail: power.PowerPrivilege,
PrivilegeFlag: 1, // 1:有权限;9:无权限
}
//当前模块未选中,执行删除
if !power.IsSelected {
errByDelPower := dao.DeleteByQuery(powerModel, "1=? And RoleId=? And MeuNo=?",
&[]interface{}{1, powerModel.RoleId,
powerModel.MeuNo})
if errByDelPower.Error != nil {
logs.Error("RoleSaveService,删除用户(%v)菜单(%v)权限失败,error:%v",
powerModel.RoleId, power.ModNo, errByDelPower.Error.Error())
}
//跳出当前循环
continue
}
//当前模块选中,执行保存更新
//添加 save
errBySavePower := dao.MySQLConn.Save(&powerModel)
if errBySavePower.Error != nil {
logs.Error("RoleSaveService,保存用户(%v)菜单(%v)权限失败,error:%v",
powerModel.RoleId, power.ModNo, errBySavePower.Error.Error())
}
}
}
ERR:
if err != nil {
logs.Error("RoleSaveService,保存失败,%s,error:%v", errMsg, err.Error())
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "失败",
"error": errMsg,
})
return
}
// success
c.JSON(http.StatusOK, gin.H{
"id": saveParam.SaveRole.RoleId,
"success": true,
"message": "成功!",
})
return
}
-
数据回显
- service
type RoleMenuPowerPrivilegeBasicParam struct { NameZhCN string `json:"Name_zhCN"` //具体操作的中文名称,如查询 NameTwCN string `json:"Name_zhTW"` //具体操作的繁体名称,如查询 NameEnUS string `json:"Name_enUS"` //具体操作的英文名称,如Query IsSelected bool `json:"is_selected"` //是否选中 } type RoleMenuRespParam struct { model.SysMenu ModNo string `json:"mod_no"` //模块编号 IsSelected bool `json:"is_selected"` //是否选中 PowerPrivilege []RoleMenuPowerPrivilegeBasicParam `json:"power_privilege"` ChildNum int `json:"child_num"` Children []RoleMenuRespParam `json:"children"` //子节点模块 } // RoleEditService 编辑 func RoleEditService(c *gin.Context) { var err error var errMsg string var gormDB *gorm.DB usrPowerMenuModel := model.SysRolePrivilege{} var userMenusArr []model.SysRolePrivilege modelRtn := model.SysRole{} var menus *[]base.BpmMenuArr userMenusMap := make(map[string]interface{}) id := c.Param("id") // 查询系统菜单列表 roleMenuPower, _ := TPFunGetRoleMenuService(id) if common.IsEmpty(id) { errMsg = fmt.Sprintf("%s", "角色不存在") err = errors.New(errMsg) goto ERR } // 如果记录不存在则返回到列表页 gormDB = dao.QueryById(&modelRtn, "RoleId", id) if gormDB.Error != nil || gormDB.RowsAffected != 1 { c.Redirect(http.StatusPermanentRedirect, "/systemRole") return } //查询菜单 //userMenus := service.GetSysUserMenu(userId) menus = base.GetSysUserMenu("") gormDB = dao.QueryArrays(usrPowerMenuModel.TableName(), &userMenusArr, []string{"MeuNo"}, "1=? And RoleId=?", &[]interface{}{1, id}, nil) if gormDB.Error != nil { logs.Error("RoleEditService,查询用户菜单失败,error:%v", gormDB.Error.Error()) } for _, p := range userMenusArr { userMenusMap[p.MeuNo] = true } ERR: if err != nil { c.HTML(http.StatusOK, "role_edit.html", base.GinHData(c, "Account", gin.H{ "success": false, "message": "失败", "error": err, "id": id, "roleMenus": menus, "userMenusMap": userMenusMap, "model": modelRtn, "roleMenuPower": roleMenuPower, })) return } c.HTML(http.StatusOK, "role_edit.html", base.GinHData(c, "Account", gin.H{ "success": true, "message": "success", "id": id, "roleMenus": menus, "userMenusMap": userMenusMap, "model": modelRtn, "roleMenuPower": roleMenuPower, })) return } //封装角色权限数据 func TPFunGetRoleMenuService(usrId string) ([]RoleMenuRespParam, error) { var err error var gormDB *gorm.DB privilegeModel := model.SysRolePrivilege{} var privilegeList = make([]model.SysRolePrivilege, 0) var privilegeMap = make(map[string]map[string]bool) //查询用户拥有的权限 gormDB = dao.QueryArrays(privilegeModel.TableName(), &privilegeList, []string{"MeuNo"}, "1=? And RoleId=?", &[]interface{}{1, usrId}, nil) if gormDB.Error != nil { logs.Error("RoleEditService,查询用户菜单失败,error:%v", gormDB.Error.Error()) } for _, p := range privilegeList { var privilegeDetailMap = make(map[string]bool) _ = json.Unmarshal([]byte(p.PrivilegeDetail), &privilegeDetailMap) privilegeMap[p.MeuNo] = privilegeDetailMap } //menuArrRtn := &[]base.BpmMenuArr{} respData := &[]RoleMenuRespParam{} // 查询数据库 menuBasicModel := &model.SysMenu{} var menuBasicList = make([]model.SysMenu, 0) var queryStr = "1=?" queryErrDb := dao.QueryArrays(menuBasicModel.TableName(), &menuBasicList, []string{"SortString asc"}, queryStr, &[]interface{}{1}, nil) if queryErrDb.Error != nil { logs.Error("查询系统菜单失败:", queryErrDb.Error) } for _, v := range menuBasicList { // 权限,如果该用户所属角色没有该菜单权限,则不添加到返回数组 var power = make([]base.MenuPowerDefine, 0) if !common.IsEmpty(v.Privilege) { powerMarshalErr := json.Unmarshal([]byte(v.Privilege), &power) if powerMarshalErr != nil { logs.Error("Invalid Menu Power,", v.MeuNo, v.NameEn, v.Privilege) } } TPFunAddMenuToRespArr(respData, &v, privilegeMap) } return *respData, err } func TPFunAddMenuToRespArr(respData *[]RoleMenuRespParam, menuModel *model.SysMenu, privilegeMap map[string]map[string]bool) { if len(*respData) == 0 || menuModel.LevNo == 1 { var powerPrivilegeList = make([]RoleMenuPowerPrivilegeBasicParam, 0) var power = make([]base.MenuPowerDefine, 0) _ = json.Unmarshal([]byte(menuModel.Privilege), &power) for _, p := range power { var powerPrivilege = RoleMenuPowerPrivilegeBasicParam{ NameZhCN: p.NameZhCN,//具体操作的中文名称,如查询 NameTwCN: p.NameTwCN, //具体操作的繁体名称,如查询 NameEnUS: p.NameEnUS,//具体操作的英文名称,如Query IsSelected: privilegeMap[menuModel.MeuNo][p.NameEnUS], //是否选中 } powerPrivilegeList = append(powerPrivilegeList, powerPrivilege) } isSelected := false if _, ok := privilegeMap[menuModel.MeuNo]; ok { isSelected = true } *respData = append(*respData, RoleMenuRespParam{ SysMenu: *menuModel, ModNo: menuModel.MeuNo, PowerPrivilege: powerPrivilegeList, IsSelected: isSelected, Children: []RoleMenuRespParam{}, }) } else { var lastMenuArr = respData Search: for { for i, m := range *lastMenuArr { if strings.Index(menuModel.SortString, m.SortString) == 0 { var levNoDiff = len(menuModel.SortString) - len(m.SortString) switch { case levNoDiff == 2: var powerPrivilegeList = make([]RoleMenuPowerPrivilegeBasicParam, 0) var power = make([]base.MenuPowerDefine, 0) _ = json.Unmarshal([]byte(menuModel.Privilege), &power) for _, p := range power { var powerPrivilege = RoleMenuPowerPrivilegeBasicParam{ NameZhCN: p.NameZhCN, //具体操作的中文名称,如查询 NameTwCN: p.NameTwCN,//具体操作的繁体名称,如查询 NameEnUS: p.NameEnUS, //具体操作的英文名称,如Query //是否选中 IsSelected: privilegeMap[menuModel.MeuNo][p.NameEnUS], } powerPrivilegeList = append(powerPrivilegeList, powerPrivilege) } isSelected := false if _, ok := privilegeMap[menuModel.MeuNo]; ok { isSelected = true } m.Children = append(m.Children, RoleMenuRespParam{ SysMenu: *menuModel, ModNo: menuModel.MeuNo, PowerPrivilege: powerPrivilegeList, IsSelected: isSelected, Children: []RoleMenuRespParam{}, }) m.ChildNum = len(m.Children) // 放到父节点 (*lastMenuArr)[i] = m break Search case levNoDiff > 2: // 同层级下钻 lastMenuArr = &m.Children continue Search } } } break Search } } }
- html
内部代码:
<div class="form-group"> <label class="col-sm-2 control-label form-label" style="font-weight:normal;text-align: right;">权限</label> <div class="col-sm-10"> <p class=""> </p> {{range $i,$v:=$.roleMenuPower}} {{/*一级菜单 MAIN/SYSTEM */}} <div class="checkbox checkbox-success" style="display: none;"> <input type="checkbox" id="{{$v.MeuNo}}" class="role-menu" data-modNo="{{$v.MeuNo}}" value="option1" checked="checked"> <label for="{{$v.MeuNo}}"> {{$v.NameZh}} </label> </div> <div></div> {{if gt $v.ChildNum 0}} {{/*遍历二级菜单*/}} {{range $a,$b:=$v.Children}} <div> <div class="col-sm-12 margin-b-10 checkbox checkbox-success margin-l-10"> <input type="checkbox" id="{{$b.MeuNo}}" class="role-menu" data-modNo="{{$b.MeuNo}}" value="option1" {{if eq $v.IsSelected true}}checked{{end}}> <label for="{{$b.MeuNo}}"> {{$b.NameZh}}</label> </div> {{if gt $b.ChildNum 0}} <div class="col-sm-12 panel-default margin-l-10"> {{/* 遍历三级菜单 panel panel-default*/}} {{range $c,$d:=$b.Children}} <div> <div class="checkbox checkbox-inline mod-checkbox-input margin-b-5"> <input type="checkbox" id="{{$d.MeuNo}}" data-modNo="{{$d.MeuNo}}" class="{{$d.ParentModNo}} role-menu" {{if eq $d.IsSelected true}}checked{{end}}> <label for="{{$d.MeuNo}}"> {{$d.NameZh}} </label> </div> {{if gt $d.ChildNum 0}} {{range $e,$f:=$d.Children}} <div class="checkbox checkbox-inline "> <input type="checkbox" id="{{$f.MeuNo}}" class="{{$f.ParentModNo}} role-menu" data-modNo="{{$f.MeuNo}}" value="option1" {{if eq $f.IsSelected true}}checked{{end}}> <label for="{{$f.MeuNo}}"> {{$f.NameZh}} </label> </div> {{end}} {{else}} {{if gt (len $d.PowerPrivilege) 0}} <div class="panel panel-default"> {{/*当前模块无子模块,展示模块权限*/}} {{/*新添加*/}} <div id="Privilege-{{$d.MeuNo}}"> {{range $m,$n:=$d.PowerPrivilege}} <div class="checkbox checkbox-inline "> <input id="{{$d.MeuNo}}-PriInput-{{$n.NameEnUS}}" class="role-menu-pri {{$d.MeuNo}}PriInput" data-name="{{$n.NameEnUS}}" {{if eq $n.IsSelected true}}checked{{end}} type="checkbox"> <label for="{{$d.MeuNo}}-PriInput-{{$n.NameEnUS}}"> {{$n.NameZhCN}}</label> </div> {{end}} </div> </div> {{end}} {{end}} </div> {{end}} </div> {{else}} {{if gt (len $b.PowerPrivilege) 0}} <div class="col-sm-12 panel panel-default padding-10 margin-b-5 margin-l-25"> {{/*当前模块无子模块,展示模块权限*/}} {{/*新添加*/}} <div id="Privilege-{{$b.MeuNo}}"> {{range $m,$n:=$b.PowerPrivilege}} <div class="checkbox checkbox-inline "> <input id="{{$b.MeuNo}}-PriInput-{{$n.NameEnUS}}" class="role-menu-pri {{$b.MeuNo}}PriInput" data-name="{{$n.NameEnUS}}" {{if eq $n.IsSelected true}}checked{{end}} type="checkbox"> <label for="{{$b.MeuNo}}-PriInput-{{$n.NameEnUS}}"> {{$n.NameZhCN}}</label> </div> {{end}} </div> </div> {{end}} {{end}} </div> {{end}} {{end}} {{end}} </div> </div>
- js
$(function () { //控制模块的点击 $(".role-menu").on('change', function (e) { //获取当前状态 let isChecked = $(this).attr("checked"); if (isNotNull(isChecked)) { //选中变不选中(包括子节点) $($(this).parent().parent().find('input[type=checkbox]')).each(function (i, v) { $(v).removeAttr("checked"); $(v).next().removeClass("menu-child-checkbox") }) } else { $($(this).parent().parent().find('input[type=checkbox]')).each(function (i, v) { //不选中变选中(不包括子节点) $(v).attr("checked", "checked"); //选中 $(v).next().addClass("menu-child-checkbox") }) } }) //控制模块权限的点击 $(".role-menu-pri").on('change', function (e) { //获取当前状态 let isChecked = $(this).attr("checked"); if (isNotNull(isChecked)) { //选中变不选中(包括子节点) $(this).removeAttr("checked"); $(this).next().removeClass("menu-child-checkbox") } else { //不选中变选中(不包括子节点) $(this).attr("checked", "checked"); //选中 $(this).next().addClass("menu-child-checkbox") } }) });
网友评论