Cube/NewLife.CubeNC/Areas/Admin/Index/IndexController.cs

295 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using NewLife.Common;
using NewLife.Cube.Extensions;
using NewLife.Cube.ViewModels;
using NewLife.Log;
using NewLife.Reflection;
using XCode.Membership;
namespace NewLife.Cube.Areas.Admin.Controllers;
/// <summary>首页</summary>
[DisplayName("首页")]
[AdminArea]
[Menu(0, false, Icon = "fa-home")]
public class IndexController : ControllerBaseX
{
private readonly IManageProvider _provider;
private readonly IHostApplicationLifetime _applicationLifetime;
static IndexController() => MachineInfo.RegisterAsync();
private IndexController() => PageSetting.EnableNavbar = false;
/// <summary>实例化</summary>
/// <param name="manageProvider"></param>
/// <param name="appLifetime"></param>
public IndexController(IManageProvider manageProvider, IHostApplicationLifetime appLifetime) : this()
{
_provider = manageProvider;
_applicationLifetime = appLifetime;
}
/// <summary>首页</summary>
/// <returns></returns>
[AllowAnonymous]
public ActionResult Index()
{
var user = _provider.TryLogin(HttpContext);
if (user == null) return RedirectToAction("Login", "User", new { r = Request.GetEncodedPathAndQuery() });
ViewBag.User = _provider.Current;
ViewBag.Config = SysConfig.Current;
//!!! 租户切换
var set = CubeSetting.Current;
var tenantId = Request.Query["TenantId"].ToInt(-1);
if (tenantId >= 0 && set.EnableTenant)
{
// 判断租户关系
var list = TenantUser.FindAllByUserId(user.ID);
if (list.Any(e => e.TenantId == tenantId) || tenantId == 0)
{
var tenant = Tenant.FindById(tenantId);
XTrace.WriteLine("用户[{0}]切换到租户[{1}/{2}]", user, tenant?.Name ?? "系统管理员", tenant?.Code ?? "0");
// 切换租户保存到Cookie
HttpContext.SaveTenant(tenantId);
return Redirect("/Admin");
}
}
// 工作台页面
var startPage = Request.GetRequestValue("page");
if (startPage.IsNullOrEmpty()) startPage = CubeSetting.Current.StartPage;
ViewBag.Main = startPage;
var module = Request.GetRequestValue("module");
//var modules = (user as User)?.GetModules();
ViewBag.Menus = GetMenu(module);
var uAgent = Request.Headers["User-Agent"] + "";
var isMobile = uAgent.Contains("Android") || uAgent.Contains("iPhone") || uAgent.Contains("iPad");
return isMobile ? View("MCubeIndex") : View("CubeIndex");
}
/// <summary>服务器信息</summary>
/// <param name="id"></param>
/// <returns></returns>
[DisplayName("服务器信息")]
[EntityAuthorize(PermissionFlags.Detail)]
[Menu(10, true, Icon = "fa-home")]
public ActionResult Main(String id)
{
ViewBag.Act = id;
ViewBag.Config = SysConfig.Current;
ViewBag.MyAsms = GetMyAssemblies().OrderBy(e => e.Name).OrderByDescending(e => e.Compile).ToArray();
var Asms = AssemblyX.GetAssemblies(null).ToArray();
Asms = Asms.OrderBy(e => e.Name).OrderByDescending(e => e.Compile).ToArray();
ViewBag.Asms = Asms;
return ((id + "").ToLower()) switch
{
"processmodules" => View("ProcessModules"),
"assembly" => View("Assembly"),
"session" => View("Session"),
"cache" => View("Cache"),
"servervar" => View("ServerVar"),
_ => View(),
};
}
/// <summary>获取当前应用程序的所有程序集,不包括系统程序集,仅限本目录</summary>
/// <returns></returns>
public static List<AssemblyX> GetMyAssemblies()
{
var list = new List<AssemblyX>();
var hs = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
var cur = AppDomain.CurrentDomain.BaseDirectory.CombinePath("../").GetFullPath();
foreach (var asmx in AssemblyX.GetAssemblies())
{
// 加载程序集列表很容易抛出异常,全部屏蔽
try
{
if (asmx.FileVersion.IsNullOrEmpty()) continue;
var file = asmx.Asm.Location;
if (file.IsNullOrEmpty()) continue;
if (file.StartsWith("file:///"))
{
file = file.TrimStart("file:///");
if (Path.DirectorySeparatorChar == '\\')
file = file.Replace('/', '\\');
else
file = file.Replace('\\', '/').EnsureStart("/");
}
if (!file.StartsWithIgnoreCase(cur)) continue;
if (!hs.Contains(file))
{
hs.Add(file);
list.Add(asmx);
}
}
catch { }
}
return list;
}
/// <summary>重启</summary>
/// <returns></returns>
[DisplayName("重启")]
[EntityAuthorize((PermissionFlags)16)]
public ActionResult Restart()
{
//var manager = ApplicationManager.Load();
try
{
var p = Process.GetCurrentProcess();
var fileName = p.MainModule.FileName;
var args = Environment.CommandLine.TrimStart(Path.ChangeExtension(fileName, ".dll")).Trim();
args += " -delay";
WriteLog("Restart", true, $"fileName={fileName} args={args}");
Process.Start(fileName, args);
ThreadPool.QueueUserWorkItem(s =>
{
Thread.Sleep(100);
// 本进程退出
//manager.Stop();
Thread.Sleep(200);
//p.Kill();
Environment.Exit(0);
});
}
catch (Exception ex)
{
XTrace.WriteException(ex);
//manager.Restart();
}
return JsonRefresh("重启成功", 2);
}
/// <summary>
/// 释放内存参考之前的Runtime方法
/// </summary>
/// <returns></returns>
[DisplayName("释放内存")]
[EntityAuthorize((PermissionFlags)32)]
public ActionResult MemoryFree()
{
try
{
GC.Collect();
// 释放当前进程所占用的内存
var p = Process.GetCurrentProcess();
SetProcessWorkingSetSize(p.Handle, -1, -1);
}
catch (Exception ex)
{
XTrace.WriteException(ex);
}
return RedirectToAction(nameof(Main));
}
[DllImport("kernel32.dll")]
private static extern Boolean SetProcessWorkingSetSize(IntPtr proc, Int32 min, Int32 max);
/// <summary>
/// 获取菜单树
/// </summary>
/// <returns></returns>
[EntityAuthorize]
public ActionResult GetMenuTree(String module) => Ok(data: GetMenu(module));
private IList<MenuTree> GetMenu(String module)
{
var user = _provider.Current as IUser;
var fact = ManageProvider.Menu;
var menus = fact.Root.Childs;
if (user?.Role != null)
{
menus = fact.GetMySubMenus(fact.Root.ID, user, true);
}
// 根据模块过滤菜单
if (module.EqualIgnoreCase("base"))
{
// 直接取base下级以及所有仅有二级的菜单
var ms = menus.FirstOrDefault(e => e.Name.EqualIgnoreCase("base"))?.Childs ?? [];
foreach (var item in menus)
{
if (!item.Name.EqualIgnoreCase("base") && item.Childs.All(e => e.Childs.Count == 0))
{
ms.Add(item);
}
}
menus = ms;
}
else if (!module.IsNullOrEmpty())
{
menus = menus.FirstOrDefault(e => e.Name.EqualIgnoreCase(module))?.Childs ?? [];
}
else
{
// 去掉三级菜单,仅显示二级菜单。如果没有可用菜单,则取第一个有可访问子菜单的模块来显示
var ms = menus.Where(e => e.Childs.All(x => x.Childs.Count == 0)).ToList() as IList<IMenu>;
if (ms.Count == 0)
{
foreach (var item in menus)
{
ms = fact.GetMySubMenus(item.ID, user, true);
if (ms.Count > 0) break;
}
}
menus = ms;
}
// 如果顶级只有一层,并且至少有三级目录,则提升一级
if (menus.Count == 1 && menus[0].Childs.All(m => m.Childs.Count > 0)) { menus = menus[0].Childs; }
var menuTree = MenuTree.GetMenuTree(m => fact.GetMySubMenus(m.ID, user, true), list =>
{
var menuList = (from menu in list
// where m.Visible
select new MenuTree
{
ID = menu.ID,
Name = menu.Name,
DisplayName = menu.DisplayName ?? menu.Name,
FullName = menu.FullName,
Url = menu.Url,
Icon = menu.Icon,
Visible = menu.Visible,
NewWindow = menu.NewWindow,
ParentID = menu.ParentID,
Permissions = menu.Permissions
}).ToList();
return menuList.Count > 0 ? menuList : null;
}, menus);
return menuTree;
}
}