新增多租户开关,同时根据租户模式和管理模式,控制不同的菜单显示
This commit is contained in:
parent
73404fa854
commit
bbac7f9d33
|
@ -865,6 +865,7 @@ public static class ViewHelper
|
|||
ID = menu.ID,
|
||||
Name = menu.Name,
|
||||
DisplayName = menu.DisplayName ?? menu.Name,
|
||||
FullName = menu.FullName,
|
||||
Url = menu.Url,
|
||||
Icon = menu.Icon,
|
||||
Visible = menu.Visible,
|
||||
|
|
|
@ -82,16 +82,6 @@ public class CubeSetting : Config<CubeSetting>
|
|||
[Description("机器人错误码。设置后拦截各种爬虫并返回相应错误,如404/500,默认0不拦截")]
|
||||
[Category("通用")]
|
||||
public Int32 RobotError { get; set; }
|
||||
|
||||
/// <summary>用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2</summary>
|
||||
[Description("用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2")]
|
||||
[Category("通用")]
|
||||
public Int32 EnableUserOnline { get; set; } = 2;
|
||||
|
||||
/// <summary>用户统计。是否统计用户访问,默认true</summary>
|
||||
[Description("用户统计。是否统计用户访问,默认true")]
|
||||
[Category("通用")]
|
||||
public Boolean EnableUserStat { get; set; } = true;
|
||||
#endregion
|
||||
|
||||
#region 用户登录
|
||||
|
@ -278,6 +268,23 @@ public class CubeSetting : Config<CubeSetting>
|
|||
public String StarWeb { get; set; }
|
||||
#endregion
|
||||
|
||||
#region 系统功能
|
||||
/// <summary>多租户。是否支持多租户,租户模式禁止访问系统管理,平台管理模式禁止访问租户页面</summary>
|
||||
[Description("多租户。是否支持多租户,租户模式禁止访问系统管理,平台管理模式禁止访问租户页面")]
|
||||
[Category("系统功能")]
|
||||
public Boolean EnableTenant { get; set; }
|
||||
|
||||
/// <summary>用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2</summary>
|
||||
[Description("用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2")]
|
||||
[Category("系统功能")]
|
||||
public Int32 EnableUserOnline { get; set; } = 2;
|
||||
|
||||
/// <summary>用户统计。是否统计用户访问,默认true</summary>
|
||||
[Description("用户统计。是否统计用户访问,默认true")]
|
||||
[Category("系统功能")]
|
||||
public Boolean EnableUserStat { get; set; } = true;
|
||||
#endregion
|
||||
|
||||
#region 方法
|
||||
/// <summary>实例化</summary>
|
||||
public CubeSetting() { }
|
||||
|
|
|
@ -242,6 +242,7 @@ public class IndexController : ControllerBaseX
|
|||
ID = menu.ID,
|
||||
Name = menu.Name,
|
||||
DisplayName = menu.DisplayName ?? menu.Name,
|
||||
FullName = menu.FullName,
|
||||
Url = menu.Url,
|
||||
Icon = menu.Icon,
|
||||
Visible = menu.Visible,
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using XCode.Membership;
|
||||
|
||||
namespace NewLife.Cube;
|
||||
|
||||
/// <summary>租户控制器</summary>
|
||||
public interface ITenantController
|
||||
{
|
||||
///// <summary>是否租户实体类</summary>
|
||||
//Boolean IsTenantSource { get; }
|
||||
}
|
|
@ -263,7 +263,7 @@ public class ReadOnlyEntityController<TEntity> : ControllerBaseX where TEntity :
|
|||
}
|
||||
|
||||
/// <summary>是否租户实体类</summary>
|
||||
protected Boolean IsTenantSource => typeof(TEntity).GetInterfaces().Any(e => e == typeof(ITenantSource));
|
||||
public Boolean IsTenantSource => typeof(TEntity).GetInterfaces().Any(e => e == typeof(ITenantSource));
|
||||
|
||||
/// <summary>获取选中键</summary>
|
||||
/// <returns></returns>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NewLife.Cube.ViewModels;
|
||||
using NewLife.Log;
|
||||
using NewLife.Reflection;
|
||||
using XCode;
|
||||
|
@ -261,4 +262,30 @@ public static class MenuHelper
|
|||
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>根据租户隔离菜单</summary>
|
||||
/// <param name="menus"></param>
|
||||
/// <param name="isTenant"></param>
|
||||
/// <returns></returns>
|
||||
public static IList<MenuTree> FilterByTenant(IList<MenuTree> menus, Boolean isTenant)
|
||||
{
|
||||
var list = new List<MenuTree>();
|
||||
|
||||
foreach (var item in menus)
|
||||
{
|
||||
var flag = false;
|
||||
if (!item.FullName.IsNullOrEmpty())
|
||||
{
|
||||
var type = Type.GetType(item.FullName);
|
||||
if (type != null && type.As<ITenantController>())
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTenant && flag || !isTenant && !flag) list.Add(item);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -79,16 +79,6 @@ public class CubeSetting : Config<CubeSetting>
|
|||
[Description("机器人错误码。设置后拦截各种爬虫并返回相应错误,如404/500,默认0不拦截")]
|
||||
[Category("通用")]
|
||||
public Int32 RobotError { get; set; }
|
||||
|
||||
/// <summary>用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2</summary>
|
||||
[Description("用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2")]
|
||||
[Category("通用")]
|
||||
public Int32 EnableUserOnline { get; set; } = 2;
|
||||
|
||||
/// <summary>用户统计。是否统计用户访问,默认true</summary>
|
||||
[Description("用户统计。是否统计用户访问,默认true")]
|
||||
[Category("通用")]
|
||||
public Boolean EnableUserStat { get; set; } = true;
|
||||
#endregion
|
||||
|
||||
#region 用户登录
|
||||
|
@ -275,6 +265,23 @@ public class CubeSetting : Config<CubeSetting>
|
|||
public String StarWeb { get; set; }
|
||||
#endregion
|
||||
|
||||
#region 系统功能
|
||||
/// <summary>多租户。是否支持多租户,租户模式禁止访问系统管理,平台管理模式禁止访问租户页面</summary>
|
||||
[Description("多租户。是否支持多租户,租户模式禁止访问系统管理,平台管理模式禁止访问租户页面")]
|
||||
[Category("系统功能")]
|
||||
public Boolean EnableTenant { get; set; }
|
||||
|
||||
/// <summary>用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2</summary>
|
||||
[Description("用户在线。是否记录用户在线信息,0表示不记录,1表示仅记录已登录用户,2表示记录所有访客。默认2")]
|
||||
[Category("系统功能")]
|
||||
public Int32 EnableUserOnline { get; set; } = 2;
|
||||
|
||||
/// <summary>用户统计。是否统计用户访问,默认true</summary>
|
||||
[Description("用户统计。是否统计用户访问,默认true")]
|
||||
[Category("系统功能")]
|
||||
public Boolean EnableUserStat { get; set; } = true;
|
||||
#endregion
|
||||
|
||||
#region 方法
|
||||
/// <summary>实例化</summary>
|
||||
public CubeSetting() { }
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace NewLife.Cube.ViewModels
|
|||
/// 显示名
|
||||
/// </summary>
|
||||
public String DisplayName { get; set; }
|
||||
/// <summary>全名</summary>
|
||||
public String FullName { get; set; }
|
||||
/// <summary>
|
||||
/// 父级id
|
||||
/// </summary>
|
||||
|
|
|
@ -117,53 +117,53 @@
|
|||
<script src="@res/artDialog/dist/dialog.new.life.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var $frmContent = $('#main');
|
||||
function fixFrmContentSize() {
|
||||
var offset = $frmContent.offset();
|
||||
var top = offset.top;
|
||||
var height = document.documentElement.clientHeight;
|
||||
$frmContent.height(height - top);
|
||||
$(function () {
|
||||
var $frmContent = $('#main');
|
||||
function fixFrmContentSize() {
|
||||
var offset = $frmContent.offset();
|
||||
var top = offset.top;
|
||||
var height = document.documentElement.clientHeight;
|
||||
$frmContent.height(height - top);
|
||||
}
|
||||
fixFrmContentSize();
|
||||
$(window).resize(fixFrmContentSize);
|
||||
|
||||
//增加iframe被嵌套的检测2015-6-4 景裔增加
|
||||
if (window != top) {
|
||||
top.location.href = location.href;
|
||||
}
|
||||
|
||||
//菜单active样式
|
||||
$(".nav-list").children("li").click(function () {
|
||||
var $this = $(this);
|
||||
$this.siblings("li").each(function () {
|
||||
var $item = $(this);
|
||||
if ($item.attr("class") == "open") {
|
||||
$item.removeClass("open");
|
||||
$item.children(".submenu").hide();
|
||||
}
|
||||
fixFrmContentSize();
|
||||
$(window).resize(fixFrmContentSize);
|
||||
|
||||
//增加iframe被嵌套的检测2015-6-4 景裔增加
|
||||
if (window != top) {
|
||||
top.location.href = location.href;
|
||||
}
|
||||
|
||||
//菜单active样式
|
||||
$(".nav-list").children("li").click(function () {
|
||||
var $this = $(this);
|
||||
$this.siblings("li").each(function () {
|
||||
var $item = $(this);
|
||||
if ($item.attr("class") == "open") {
|
||||
$item.removeClass("open");
|
||||
$item.children(".submenu").hide();
|
||||
}
|
||||
});
|
||||
$this.addClass('open');
|
||||
});
|
||||
|
||||
$(".submenu li").click(function () {
|
||||
var $this = $(this);
|
||||
//兄弟节点去焦
|
||||
$this.siblings("li").removeClass("active");
|
||||
$this.addClass('active');
|
||||
//父节点获取焦点
|
||||
var $parent = $this.parent().parent();
|
||||
$parent.addClass("active");
|
||||
$parent.siblings("li").each(function () {
|
||||
var $item = $(this);
|
||||
$item.removeClass("open").removeClass("active");
|
||||
$item.children(".submenu").hide();
|
||||
if ($item.children(".submenu").length != 0) {
|
||||
$item.children(".submenu").children("li").removeClass("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
$this.addClass('open');
|
||||
});
|
||||
|
||||
$(".submenu li").click(function () {
|
||||
var $this = $(this);
|
||||
//兄弟节点去焦
|
||||
$this.siblings("li").removeClass("active");
|
||||
$this.addClass('active');
|
||||
//父节点获取焦点
|
||||
var $parent = $this.parent().parent();
|
||||
$parent.addClass("active");
|
||||
$parent.siblings("li").each(function () {
|
||||
var $item = $(this);
|
||||
$item.removeClass("open").removeClass("active");
|
||||
$item.children(".submenu").hide();
|
||||
if ($item.children(".submenu").length != 0) {
|
||||
$item.children(".submenu").children("li").removeClass("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
@using NewLife.Model;
|
||||
@using NewLife.Cube.Membership;
|
||||
@using NewLife.Model;
|
||||
@using NewLife.Cube.ViewModels;
|
||||
@{
|
||||
String[] icos = new String[] { "fa-tachometer", "fa-desktop", "fa-list", "fa-pencil-square-o", "fa-list-alt", "fa-calendar", "fa-picture-o", "fa-tag", "fa-file-o" };
|
||||
Int32 _idx = 0;
|
||||
var menus = ViewBag.Menus as IList<MenuTree> ?? new List<MenuTree>();
|
||||
|
||||
// 根据租户模式过滤菜单
|
||||
var ctx = TenantContext.Current;
|
||||
var set = CubeSetting.Current;
|
||||
if (set.EnableTenant) menus = MenuHelper.FilterByTenant(menus, ctx != null && ctx.TenantId > 0);
|
||||
}
|
||||
<ul class="nav nav-list">
|
||||
@foreach (var menu in menus.Where(w=>w.Visible))
|
||||
@foreach (var menu in menus.Where(w => w.Visible))
|
||||
{
|
||||
var childs = menu.Children ?? new List<MenuTree>();
|
||||
if (_idx >= icos.Length) { _idx = 0; }
|
||||
|
@ -23,18 +29,11 @@
|
|||
<b class="arrow"></b>
|
||||
|
||||
<ul @Html.Raw(menu == menus[0] ? "class=\"submenu nav-show\" style=\"display:block;\"" : "class=\"submenu nav-hide\" style=\"display:none;\"")>
|
||||
@foreach (var menu2 in childs.Where(w=>w.Visible))
|
||||
@foreach (var menu2 in childs.Where(w => w.Visible))
|
||||
{
|
||||
@await Html.PartialAsync("_Left_Item", menu2);
|
||||
@await Html.PartialAsync("_Left_Item", menu2)
|
||||
}
|
||||
</ul>
|
||||
|
||||
@*<ul class="submenu">
|
||||
@foreach (IMenu menu2 in childs)
|
||||
{
|
||||
@await Html.PartialAsync("_Left_Item", menu2);
|
||||
}
|
||||
</ul>*@
|
||||
}
|
||||
</li>
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@using NewLife.Model;
|
||||
@using NewLife.Cube.Membership;
|
||||
@using NewLife.Model;
|
||||
@using XCode.Membership;
|
||||
@using NewLife.Cube.ViewModels;
|
||||
@{
|
||||
|
@ -6,6 +7,11 @@
|
|||
var childs = item.Children ?? new List<MenuTree>();
|
||||
var url = item.Url.IsNullOrEmpty() ? "" : Url.Content(item.Url);
|
||||
var ico = !item.Icon.IsNullOrEmpty() ? item.Icon : "fa-caret-right";
|
||||
|
||||
// 根据租户模式过滤菜单
|
||||
var ctx = TenantContext.Current;
|
||||
var set = CubeSetting.Current;
|
||||
if (set.EnableTenant) childs = MenuHelper.FilterByTenant(childs, ctx != null && ctx.TenantId > 0);
|
||||
}
|
||||
<li>
|
||||
@if (childs.Any())
|
||||
|
|
|
@ -12,14 +12,7 @@
|
|||
var cfg = ViewBag.Config as SysConfig;
|
||||
var name = cfg == null ? "" : cfg.DisplayName;
|
||||
|
||||
var tList = TenantUser.FindAllByUserId(user.ID);
|
||||
if (roleNames.Contains("管理员")) tList.Add(new TenantUser() { TenantId = 0 });
|
||||
|
||||
var tenant = XCode.Membership.Tenant.FindById(TenantContext.Current?.TenantId ?? 0);
|
||||
var lastTenant = tList.LastOrDefault();
|
||||
|
||||
var tenantName = tenant != null ? tList.Select(e => e.TenantId).Contains(tenant.Id) ? tenant.Name : lastTenant?.TenantName : lastTenant?.TenantName;
|
||||
var flag = false;
|
||||
var set = CubeSetting.Current;
|
||||
}
|
||||
<!-- #section:basics/navbar.layout -->
|
||||
<div id="navbar" class="navbar navbar-default">
|
||||
|
@ -67,7 +60,7 @@
|
|||
<li>
|
||||
<a href="~/" target="_blank">
|
||||
<i class="ace-icon fa fa-cog"></i>
|
||||
网站首页
|
||||
系统首页
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
|
@ -91,35 +84,42 @@
|
|||
</div>
|
||||
|
||||
<!--tenant-->
|
||||
@if (tList.Count > 0)
|
||||
@if (set.EnableTenant && user != null)
|
||||
{
|
||||
var tList = TenantUser.FindAllByUserId(user.ID);
|
||||
|
||||
var tenant = XCode.Membership.Tenant.FindById(TenantContext.Current?.TenantId ?? 0);
|
||||
var tenantName = tenant?.Name;
|
||||
|
||||
<div class="navbar-buttons navbar-header pull-right" role="navigation">
|
||||
<ul class="nav ace-nav">
|
||||
<li class="light-blue">
|
||||
<a data-toggle="dropdown" href="#" class="dropdown-toggle" target="main">
|
||||
<span class="hidden-xs" title="@tenantName" style="line-height:45px;top:0px;">
|
||||
@(tenantName ?? "管理员")
|
||||
<span class="hidden-xs" title="租户模式禁止访问系统管理,平台管理模式禁止访问租户页面" style="line-height:45px;top:0px;">
|
||||
@(tenantName ?? "系统后台")
|
||||
</span>
|
||||
<i class="ace-icon fa fa-caret-down"></i>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu-right dropdown-menu dropdown-caret">
|
||||
@if (user.Roles.Any(e => e.IsSystem))
|
||||
{
|
||||
<li>
|
||||
<a href="~/Admin/Index?tenantid=0">
|
||||
<span class="hidden-xs" title="系统管理后台,用于管理租户,但不能访问租户页面" style="line-height:45px;top:0px;">
|
||||
系统管理后台
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
}
|
||||
|
||||
@foreach (var item in tList)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
<li class="divider"></li>
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
|
||||
<li>
|
||||
<a href="~/Admin/Index?tenantid=@item.TenantId" target="_blank">
|
||||
<a href="~/Admin/Index?tenantid=@item.TenantId">
|
||||
<i class="ace-icon fa fa-cog"></i>
|
||||
@(item.TenantName ?? "管理员")
|
||||
@item.TenantName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
@using NewLife.Model;
|
||||
@using NewLife.Cube.Membership;
|
||||
@using NewLife.Model;
|
||||
@using NewLife.Cube.ViewModels;
|
||||
@{
|
||||
var menus = ViewBag.Menus as IList<MenuTree> ?? new List<MenuTree>();
|
||||
var flag = true;
|
||||
|
||||
// 根据租户模式过滤菜单
|
||||
var ctx = TenantContext.Current;
|
||||
var set = CubeSetting.Current;
|
||||
if (set.EnableTenant) menus = MenuHelper.FilterByTenant(menus, ctx != null && ctx.TenantId > 0);
|
||||
}
|
||||
|
||||
<div class="layui-side layui-bg-black">
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
@using NewLife.Model;
|
||||
@using NewLife.Cube.Membership;
|
||||
@using NewLife.Model;
|
||||
@using XCode.Membership;
|
||||
@using NewLife.Cube.ViewModels;
|
||||
@{
|
||||
var item = Model as MenuTree;
|
||||
var childs = item.Children ?? new List<MenuTree>();
|
||||
var url = item.Url.IsNullOrEmpty() ? "" : Url.Content(item.Url);
|
||||
|
||||
// 根据租户模式过滤菜单
|
||||
var ctx = TenantContext.Current;
|
||||
var set = CubeSetting.Current;
|
||||
if (set.EnableTenant) childs = MenuHelper.FilterByTenant(childs, ctx != null && ctx.TenantId > 0);
|
||||
}
|
||||
|
||||
@if (item.Visible)
|
||||
|
|
|
@ -12,14 +12,7 @@
|
|||
var cfg = ViewBag.Config as SysConfig;
|
||||
var name = cfg == null ? "" : cfg.DisplayName;
|
||||
|
||||
var tList = TenantUser.FindAllByUserId(user.ID);
|
||||
if (roleNames.Contains("管理员")) tList.Add(new TenantUser() { TenantId = 0 });
|
||||
|
||||
var tenant = XCode.Membership.Tenant.FindById(TenantContext.Current?.TenantId ?? 0);
|
||||
var lastTenant = tList.LastOrDefault();
|
||||
|
||||
var tenantName = tenant != null ? tList.Select(e => e.TenantId).Contains(tenant.Id) ? tenant.Name : lastTenant?.TenantName : lastTenant?.TenantName;
|
||||
var flag = false;
|
||||
var set = CubeSetting.Current;
|
||||
}
|
||||
|
||||
<div class="layui-header">
|
||||
|
@ -50,26 +43,34 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
@if (tList.Count > 0)
|
||||
@if (set.EnableTenant && user != null)
|
||||
{
|
||||
var tList = TenantUser.FindAllByUserId(user.ID);
|
||||
|
||||
var tenant = XCode.Membership.Tenant.FindById(TenantContext.Current?.TenantId ?? 0);
|
||||
var tenantName = tenant?.Name;
|
||||
|
||||
<ul class="layui-nav layui-layout-right" style="right:140px;">
|
||||
<li class="layui-nav-item layui-show-md-inline-block">
|
||||
<a href="javascript:;">
|
||||
@(tenantName ?? "管理员")
|
||||
@(tenantName ?? "系统后台")
|
||||
</a>
|
||||
<dl class="layui-nav-child">
|
||||
@if (user.Roles.Any(e => e.IsSystem))
|
||||
{
|
||||
<dd>
|
||||
<a href="~/Admin/Index?tenantid=0">
|
||||
<span class="hidden-xs" title="系统管理后台,用于管理租户,但不能访问租户页面" style="line-height:45px;top:0px;">
|
||||
系统管理后台
|
||||
</span>
|
||||
</a>
|
||||
</dd>
|
||||
<dd class="divider"></dd>
|
||||
}
|
||||
|
||||
@foreach (var item in tList)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
<hr>
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
|
||||
<dd><a href="~/Admin/Index?tenantid=@item.TenantId" lay-header-event="menuSetting" data-title="@(item.TenantName??"管理员")">@(item.TenantName ?? "管理员")</a></dd>
|
||||
<dd><a href="~/Admin/Index?tenantid=@item.TenantId" lay-header-event="menuSetting">@item.TenantName</a></dd>
|
||||
}
|
||||
</dl>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue