vboot框架 后台动态获取权限
前言:
以前用的框架总感觉有不舒服的地方,然后就一直在寻找一个理想的框架,研究了几十个框架,vboot框架让我眼前一亮,
上手后发现服务端权限角色功能没有实现,一度想抛弃,后来下决心费点功夫补充一下,没办法实在太喜欢这个框架了,
还有很多需要完善的地方,目前只实现了:用户的角色权限(菜单权限、按钮权限),其他的(部门权限、岗位权限、群组权限)没有实现
基本能满足一般项目的要求
感谢框架的作者,也感谢我的好友“风清扬”给与的大力帮助,水平有限仅供参考,欢迎提出宝贵意见
相关文档:https://vvbin.cn/doc-next/guide/auth.html#%E5%90%8E%E5%8F%B0%E5%8A%A8%E6%80%81%E8%8E%B7%E5%8F%96
一、vboot-net后台需要修改的几个地方:
1、SysOrgUser.cs增加一个字段
[SugarColumn(ColumnDescription = "系统管理员", DefaultValue="0", IsNullable = true)]
public int AdminType { get; set; }
2、AdminType.cs 修改:普通账号 NOne=0
public enum AdminType
{
///
/// 超级管理员
///
[Description("超级管理员")]
SuperAdmin = 1,
///
/// 管理员
///
[Description("管理员")]
Admin = 2,
///
/// 普通账号
///
[Description("普通账号")]
None = 0
}
3、PubAuthInitService.cs
所有的comp = "/sys/org/dept/index.vue"去掉【.vue】,前端会自动补上.vue,
否则找不到页面,如果数据库已生成可直接改数据库表的数据
二、vboot-net后台
1、PubAuthApi.cs增加已下接口
[HttpGet("/getMenuList")] 2、LoginService.cs增加以下代码 using System.Collections.Generic; LoginService.cs 三、前端vboot-vben 1、projectSetting.ts 权限模式改为 // Permission mode 2、BACK模式下默认访问views路径不是pages路径,所以要把pages下相应的目录及文件要拷贝到views下,如下图所示: 3、前端按钮权限的实现 v-auth="'权限标识'" 到此,用户的菜单权限、按钮权限基本就完成了,亲测可用
[AllowAnonymous]
public async Task<dynamic> getMenuList()
{
//生成树形菜单
List
return treelist;
}
[HttpGet("/getPermCode")]
[AllowAnonymous]
public async Taskstring>> getPermCode()
{
//按钮权限标识
List<string> permlist = await _loginService.GetPermCode(_userManager.UserId, _userManager.User.AdminType);
return permlist;
}
using System.Linq;
using System.Threading.Tasks;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using SqlSugar;
using Vboot.Core.Common;
using Vboot.Core.Module.Pub.Auth;
using Vboot.Core.Module.Sys;
namespace Vboot.Core.Module.Pub
{
public class LoginService : ITransient
{
private readonly ISqlSugarRepository
public LoginService(ISqlSugarRepository
{
_repo = repo;
}
public async Task
{
const string sql = "select id,name,pacod,retag from sys_org_user where usnam=@username and avtag=1";
var dbUser = await _repo.Ado.SqlQuerySingleAsync
// if (dbUser == null)
// {
// throw new Exception("账号不存在或密码错误");
// }
if (dbUser == null)
{
throw Oops.Oh(ErrorCode.D1000);
}
return dbUser;
}
///
/// 根据当前登录用户生成菜单树
///
///
///
///
public async Task> GetMenuList(string userid, int admintype)
{
List
List
List
return treelist;
}
///
/// 获取当前登录用户的PermCode
///
///
///
///
public async Taskstring>> GetPermCode(string userid, int admintype)
{
List<string> perm = new List<string>();
string sql;
if (admintype == (int)AdminType.SuperAdmin)
{
sql = $@"SELECT perm
FROM sys_auth_menu
WHERE `type`='B'";
}
else
{
sql = $@"SELECT perm
FROM sys_auth_menu
WHERE `type`='B' AND shtag=1 AND avtag=1 AND id IN
(
SELECT `mid`
FROM sys_auth_role_menu a
LEFT JOIN sys_auth_role_org b ON b.rid=a.rid
WHERE b.oid='{userid}'
)";
}
List
for (int i = 0; i
{
perm.Add(menulist[i].perm);
}
return perm;
}
///
/// 从数据库获取菜单列表转换成前端需要的格式
///
///
///
///
private async Task> GetRouteList(string userid, int admintype)
{
string sql;
if (admintype == (int)AdminType.SuperAdmin)
{
sql = $@"SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
where `type`!='B'
ORDER BY ornum";
}
else
{
sql = $@"SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
WHERE `type`!='B' AND shtag=1 AND avtag=1 and id IN
(
SELECT a.mid
FROM sys_auth_role_menu a
LEFT JOIN sys_auth_role b ON b.id=a.rid
LEFT JOIN sys_auth_role_org c ON c.rid=b.id
WHERE c.oid='{userid}'
)
ORDER BY ornum";
}
List
return routelist;
}
///
/// 取当前登录用户权限的根菜单列表
///
///
///
///
private async Task> GetRootList(string userid, int admintype)
{
string sql;
if (admintype == (int)AdminType.SuperAdmin)
{
sql = $@"SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
WHERE isnull(pid)=true and `type`!='B'
ORDER BY ornum";
}
else
{
sql = $@"SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
WHERE id IN
(
SELECT pid
FROM
(
SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
WHERE `type`!='B' AND shtag=1 AND avtag=1 and id IN
(
SELECT a.mid
FROM sys_auth_role_menu a
LEFT JOIN sys_auth_role b ON b.id=a.rid
LEFT JOIN sys_auth_role_org c ON c.rid=b.id
WHERE c.oid='{userid}'
)
) a
)
AND id NOT IN
(
SELECT id
FROM
(
SELECT id,pid,ornum,`name`,icon,path,comp,`code`,redirect
FROM sys_auth_menu
WHERE `type`!='B' AND shtag=1 AND avtag=1 and id IN
(
SELECT a.mid
FROM sys_auth_role_menu a
LEFT JOIN sys_auth_role b ON b.id=a.rid
LEFT JOIN sys_auth_role_org c ON c.rid=b.id
WHERE c.oid='{userid}'
)
) b
)
ORDER BY ornum";
}
List
return rootlist;
}
///
/// 取菜单列表转web端格式列表
///
///
///
private async Task> ToWebmenuList(string sql)
{
List
var menulist = await _repo.Context
.SqlQueryable
.ToListAsync();
for (int i = 0; i
{
RouteMeta meta = new RouteMeta();
meta.orderNo = menulist[i].ornum;
meta.icon = menulist[i].icon;
meta.title = menulist[i].name;
RouteItem item = new RouteItem();
item.id = menulist[i].id;
item.pid = menulist[i].pid;
item.path = menulist[i].path;
item.component = menulist[i].comp;
//item.compOnent= "/sys/auth/role/index";
item.name = menulist[i].code;
item.redirect = menulist[i].redirect;
item.meta = meta;
item.children = new List
list.Add(item);
}
return list;
}
///
/// 生成树形菜单
///
///
///
///
private List
{
if (menulist == null)
{
menulist = new List
}
List
treelist.AddRange(rootlist);
GetChildrenList(menulist, rootlist);
return treelist;
}
///
/// 取子菜单
///
///
///
private void GetChildrenList(List
{
foreach (RouteItem item in plist)
{
List
item.children.AddRange(childrenlist);
GetChildrenList(menulist, childrenlist);
}
}
}
public class RouteMeta
{
public int? orderNo { get; set; }
// title
public string title { get; set; }
//// dynamic router level.
//public int? dynamicLevel{get;set;}
//// dynamic router real route path (For performance).
//public string realPath{get;set;}
//// Whether to ignore permissions
//public bool? ignoreAuth{get;set;}
//// role info RoleEnum[]
//public object roles { get; set; }
//// Whether not to cache
//ignoreKeepAlive?: boolean;
//// Is it fixed on tab
//affix?: boolean;
//icon on tab
public string icon { get; set; }
//frameSrc?: string;
//// current page transition
//transitionName?: string;
//// Whether the route has been dynamically added
//hideBreadcrumb?: boolean;
//// Hide submenu
//hideChildrenInMenu?: boolean;
//// Carrying parameters
//carryParam?: boolean;
//// Used internally to mark single-level menus
//single?: boolean;
//// Currently active menu
//currentActiveMenu?: string;
//// Never show in tab
//hideTab?: boolean;
//// Never show in menu
//hideMenu?: boolean;
//isLink?: boolean;
//// only build for Menu
//ignoreRoute?: boolean;
//// Hide path for children
//hidePathForChildren?: boolean;
}
public class RouteItem
{
public string id { get; set; }
public string pid { get; set; }
public string path { get; set; }
// component: any;
public object component { get; set; }
public RouteMeta meta { get; set; }
public string name { get; set; }
//alias?: string | string[];
public string redirect { get; set; }
//public bool? caseSensitive{get;set;}
public List
}
}BACK
模式
//permissionMode: PermissionModeEnum.ROUTE_MAPPING,
permissionMode: PermissionModeEnum.BACK,