using JNPF.Apps.Entitys; using JNPF.Apps.Entitys.Dto; using JNPF.Common.Core.Manager; using JNPF.Common.Core.Manager.Files; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.DatabaseAccessor; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.Systems.Entitys.Dto.Module; using JNPF.Systems.Entitys.Permission; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using SqlSugar; namespace JNPF.Systems; /// /// 菜单管理 /// 版 本:V3.2 /// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com) /// 日 期:2021-06-01. /// [ApiDescriptionSettings(Tag = "System", Name = "Menu", Order = 212)] [Route("api/system/[controller]")] public class ModuleService : IModuleService, IDynamicApiController, ITransient { /// /// 系统功能表仓储. /// private readonly ISqlSugarRepository _repository; /// /// 功能按钮服务. /// private readonly IModuleButtonService _moduleButtonService; /// /// 功能列表服务. /// private readonly IModuleColumnService _moduleColumnService; /// /// 功能数据资源服务. /// private readonly IModuleDataAuthorizeSchemeService _moduleDataAuthorizeSchemeService; /// /// 功能数据方案服务. /// private readonly IModuleDataAuthorizeService _moduleDataAuthorizeSerive; /// /// 功能表单服务. /// private readonly IModuleFormService _moduleFormSerive; /// /// 文件服务. /// private readonly IFileManager _fileManager; /// /// 用户管理器. /// private readonly IUserManager _userManager; /// /// 初始化一个类型的新实例. /// public ModuleService( ISqlSugarRepository repository, IFileManager fileManager, ModuleButtonService moduleButtonService, IModuleColumnService moduleColumnService, IModuleFormService moduleFormSerive, IModuleDataAuthorizeService moduleDataAuthorizeSerive, IModuleDataAuthorizeSchemeService moduleDataAuthorizeSchemeService, IUserManager userManager) { _repository = repository; _fileManager = fileManager; _moduleButtonService = moduleButtonService; _moduleColumnService = moduleColumnService; _moduleFormSerive = moduleFormSerive; _moduleDataAuthorizeSchemeService = moduleDataAuthorizeSchemeService; _moduleDataAuthorizeSerive = moduleDataAuthorizeSerive; _userManager = userManager; } #region GET /// /// 获取菜单列表. /// /// 模块ID. /// 参数. /// [HttpGet("ModuleBySystem/{systemId}")] public async Task GetList(string systemId, [FromQuery] ModuleListQuery input) { var data = await GetList(systemId); if (!string.IsNullOrEmpty(input.category)) data = data.FindAll(x => x.Category == input.category); if (!string.IsNullOrEmpty(input.keyword)) data = data.TreeWhere(t => t.FullName.Contains(input.keyword) || t.EnCode.Contains(input.keyword) || (t.UrlAddress.IsNotEmptyOrNull() && t.UrlAddress.Contains(input.keyword)), t => t.Id, t => t.ParentId); var treeList = data.Adapt>(); return new { list = treeList.ToTree("-1") }; } /// /// 获取菜单下拉框. /// /// 主键值. /// 菜单分类(参数有Web,App),默认显示所有分类. /// [HttpGet("Selector/{id}")] public async Task GetSelector(string id, string category) { var data = await GetList(_userManager.User.SystemId); if (!string.IsNullOrEmpty(category)) data = data.FindAll(x => x.Category == category && (x.Type == 1 || x.Type == 0)); if (!id.Equals("0")) data.RemoveAll(x => x.Id == id); var treeList = data.Where(x => x.EnabledMark.Equals(1)).ToList().Adapt>(); return new { list = treeList.ToTree("-1") }; } /// /// 获取菜单下拉框. /// /// 主键值. /// 模块ID. /// 菜单分类(参数有Web,App),默认显示所有分类. /// [HttpGet("Selector/{id}/{systemId}")] public async Task GetSelector(string id, string systemId, string category) { var data = await GetList(systemId); if (!string.IsNullOrEmpty(category)) data = data.FindAll(x => x.Category == category && (x.Type == 1 || x.Type == 0)); if (!id.Equals("0")) data.RemoveAll(x => x.Id == id); var treeList = data.Where(x => x.EnabledMark.Equals(1)).ToList().Adapt>(); return new { list = treeList.ToTree("-1") }; } /// /// 获取菜单列表(下拉框). /// /// 菜单分类(参数有Web,App). /// [HttpGet("Selector/All")] public async Task GetSelectorAll(string category) { var data = await _repository.AsQueryable().Where(x => x.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync(); if (!string.IsNullOrEmpty(category)) data = data.FindAll(x => x.Category == category); var systemList = await _repository.AsSugarClient().Queryable().Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToListAsync(); var treeList = data.Adapt>(); foreach (var item in treeList) { if (item.parentId == "-1") { item.parentId = item.systemId; } } treeList = treeList.Union(systemList.Select(x => new ModuleSelectorAllOutput() { id = x.Id, parentId = "0", fullName = x.FullName, icon = x.Icon, type = "0" })).ToList(); return new { list = treeList.ToTree() }; } /// /// 获取菜单信息. /// /// 主键id. /// [HttpGet("{id}")] public async Task GetInfo_Api(string id) { var data = await GetInfo(id); return data.Adapt(); } /// /// 导出. /// /// /// [HttpGet("{id}/Action/Export")] public async Task ActionsExport(string id) { var data = (await GetInfo(id)).Adapt(); data.buttonEntityList = (await _moduleButtonService.GetList(id)).Adapt>(); data.columnEntityList = (await _moduleColumnService.GetList(id)).Adapt>(); data.authorizeEntityList = (await _moduleDataAuthorizeSerive.GetList(id)).Adapt>(); data.schemeEntityList = (await _moduleDataAuthorizeSchemeService.GetList(id)).Adapt>(); data.formEntityList = (await _moduleFormSerive.GetList(id)).Adapt>(); var jsonStr = data.ToJsonString(); return await _fileManager.Export(jsonStr, data.fullName, ExportFileType.bm); } #endregion #region Post /// /// 添加菜单. /// /// 请求参数. /// [HttpPost("")] [UnitOfWork] public async Task Creater([FromBody] ModuleCrInput input) { if (await _repository.IsAnyAsync(x => x.EnCode == input.enCode && x.DeleteMark == null && x.Category == input.category)) throw Oops.Oh(ErrorCode.COM1004); if (await _repository.IsAnyAsync(x => (x.FullName == input.fullName) && x.DeleteMark == null && x.Category == input.category && input.parentId == x.ParentId && x.SystemId == input.systemId)) throw Oops.Oh(ErrorCode.COM1004); var entity = input.Adapt(); // 添加字典菜单按钮 if (entity.Type == 4) { foreach (var item in await _moduleButtonService.GetList()) { if (item.ModuleId == "-1") { item.ModuleId = entity.Id; await _moduleButtonService.Create(item); } } } var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); if (isOk < 1) throw Oops.Oh(ErrorCode.COM1000); } /// /// 修改菜单. /// /// /// /// [HttpPut("{id}")] public async Task Update(string id, [FromBody] ModuleUpInput input) { var info = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); if (await _repository.IsAnyAsync(x => x.Id != id && x.EnCode == input.enCode && x.DeleteMark == null && x.Category == input.category)) throw Oops.Oh(ErrorCode.COM1004); if (await _repository.IsAnyAsync(x => x.Id != id && (x.FullName == input.fullName) && x.DeleteMark == null && x.Category == input.category && input.parentId == x.ParentId && x.SystemId == input.systemId)) throw Oops.Oh(ErrorCode.COM1004); if (await _repository.IsAnyAsync(x => x.ParentId == id && x.DeleteMark == null && x.SystemId == input.systemId) && info.Type != input.type) throw Oops.Oh(ErrorCode.D4008); var entity = input.Adapt(); if (entity.Category.Equals("App")) { var appData = entity.Adapt(); appData.isData = _repository.AsSugarClient().Queryable().Any(x => x.ObjectType == "2" && x.CreatorUserId == _userManager.UserId && x.ObjectId == appData.id && x.DeleteMark == null); var objData = appData.ToJsonString(); await _repository.AsSugarClient().Updateable().SetColumns(it => new AppDataEntity() { ObjectData = objData }).Where(it => it.ObjectId == id).ExecuteCommandAsync(); } var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1001); } /// /// 删除菜单. /// /// /// [HttpDelete("{id}")] [UnitOfWork] public async Task Delete(string id) { var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); if (entity == null || await _repository.IsAnyAsync(x => x.ParentId == id && x.DeleteMark == null)) throw Oops.Oh(ErrorCode.D1007); if (entity.Category.Equals("App")) { await _repository.AsSugarClient().Updateable().SetColumns(it => new AppDataEntity() { DeleteMark = 1, DeleteUserId = _userManager.UserId, DeleteTime = SqlFunc.GetDate() }).Where(it => it.ObjectId == id && it.CreatorUserId == _userManager.UserId).ExecuteCommandAsync(); } var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1002); } /// /// 更新菜单状态. /// /// 菜单id. /// [HttpPut("{id}/Actions/State")] public async Task ActionsState(string id) { var isOk = await _repository.AsUpdateable().SetColumns(it => new ModuleEntity() { EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1), LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == id).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1003); } /// /// 导入. /// /// /// [HttpPost("{systemId}/Action/Import")] [UnitOfWork] public async Task ActionsImport(string systemId, IFormFile file, string parentId, string category) { var fileType = Path.GetExtension(file.FileName).Replace(".", string.Empty); if (!fileType.ToLower().Equals(ExportFileType.bm.ToString())) throw Oops.Oh(ErrorCode.D3006); var josn = _fileManager.Import(file); var moduleModel = josn.ToObject(); moduleModel.moduleId = null; moduleModel.parentId = parentId; if (moduleModel == null) throw Oops.Oh(ErrorCode.D3006); var oldCode = moduleModel.enCode; moduleModel.enCode = string.Format("{0}_{1}", moduleModel.enCode, new Random().NextNumberString(6)); if (moduleModel.type == 3) { moduleModel.urlAddress = moduleModel.urlAddress.Replace(oldCode, moduleModel.enCode); } if (moduleModel.parentId != "-1" && !await _repository.IsAnyAsync(x => x.Id == moduleModel.parentId && x.DeleteMark == null && x.SystemId == systemId)) throw Oops.Oh(ErrorCode.D3007); if (category.Equals("Web") && !category.Equals(moduleModel.category)) throw Oops.Oh(ErrorCode.D4013); if (category.Equals("App") && !category.Equals(moduleModel.category)) throw Oops.Oh(ErrorCode.D4012); if (await _repository.IsAnyAsync(x => x.ParentId == moduleModel.parentId && x.FullName == moduleModel.fullName && x.DeleteMark == null && x.Category == moduleModel.category && x.SystemId == systemId)) throw Oops.Oh(ErrorCode.D4000); moduleModel.systemId = systemId; await ImportData(moduleModel); } #endregion #region PublicMethod /// /// 列表. /// /// [NonAction] public async Task> GetList(string systemId) { if (systemId.IsNullOrEmpty() || systemId.Equals("0")) { var systemList = await _repository.AsSugarClient().Queryable().Where(x => x.DeleteMark == null). Select(x => new ModuleEntity { Id = x.Id, ParentId = "-1", EnabledMark = x.EnabledMark, Type = 0, Category = "Web", FullName = x.FullName, Icon = x.Icon, EnCode = x.EnCode, SystemId = x.Id }).ToListAsync(); var moduleList = await _repository.AsQueryable().Where(x => x.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync(); moduleList.Where(x => x.ParentId.Equals("-1")).ToList().ForEach(it => it.ParentId = it.SystemId); moduleList.AddRange(systemList); var appSystemList = systemList.Copy(); appSystemList.ForEach(item => item.Category = "App"); moduleList.AddRange(appSystemList); return moduleList; } return await _repository.AsQueryable().Where(x => x.DeleteMark == null && x.SystemId == systemId).OrderBy(o => o.SortCode).ToListAsync(); } /// /// 信息. /// /// 主键值. /// [NonAction] public async Task GetInfo(string id) { return await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null); } /// /// 获取用户树形模块功能列表. /// /// 登录类型. [NonAction] public async Task> GetUserTreeModuleList(string type) { var output = new List(); var userSystemId = _userManager.User.SystemId; if (!_userManager.IsAdministrator) { var roles = _userManager.Roles; if (roles.Any()) { var items = await _repository.AsSugarClient().Queryable().In(a => a.ObjectId, roles).Where(a => a.ItemType == "module").Select(a => a.ItemId).ToListAsync(); if (_userManager.User.SystemId.IsNotEmptyOrNull()) { var menus = await _repository.AsQueryable().Where(a => a.SystemId.Equals(userSystemId) && items.Contains(a.Id)) .Where(a => a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null) .Select().OrderBy(q => q.ParentId).OrderBy(q => q.SortCode).ToListAsync(); output = menus.Adapt>(); } else { output = new List(); } } } else { if (_userManager.User.SystemId.IsNullOrEmpty()) { var systemId = (await _repository.AsSugarClient().Queryable().Where(x => x.EnCode.Equals("mainSystem")).FirstAsync()).Id; await _repository.AsSugarClient().Updateable().SetColumns(it => new UserEntity() { SystemId = systemId }).Where(it => it.Id == _userManager.User.Id).ExecuteCommandAsync(); } var menus = await _repository.AsQueryable().Where(a => a.SystemId.Equals(_userManager.User.SystemId) && a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null) .Select().OrderBy(q => q.ParentId).OrderBy(q => q.SortCode).ToListAsync(); output = menus.Adapt>(); } return output.ToTree("-1"); } /// /// 获取用户树形模块功能列表根据 SystemId. /// /// 登录类型. /// SystemId. [NonAction] public async Task> GetUserTreeModuleListBySystemId(string type, string systemId) { var output = new List(); if (!_userManager.IsAdministrator) { var roles = _userManager.Roles; if (roles.Any()) { var items = await _repository.AsSugarClient().Queryable().In(a => a.ObjectId, roles).Where(a => a.ItemType == "module").Select(a => a.ItemId).ToListAsync(); if (systemId.IsNotEmptyOrNull()) { var menus = await _repository.AsQueryable().Where(a => a.SystemId.Equals(systemId) && items.Contains(a.Id)) .Where(a => a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null).Select().OrderBy(q => q.ParentId).OrderBy(q => q.SortCode).ToListAsync(); output = menus.Adapt>(); } else { output = new List(); } } } else { var menus = await _repository.AsQueryable().Where(a => a.SystemId.Equals(systemId) && a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null) .Select().OrderBy(q => q.ParentId).OrderBy(q => q.SortCode).ToListAsync(); output = menus.Adapt>(); } return output.ToTree("-1"); } /// /// 获取用户菜单模块功能列表. /// /// 登录类型. /// [NonAction] public async Task GetUserModueList(string type) { var output = new List(); if (!_userManager.IsAdministrator) { var roles = _userManager.Roles; if (roles.Any()) { var items = await _repository.AsSugarClient().Queryable().In(a => a.ObjectId, roles).Where(a => a.ItemType == "module").GroupBy(it => new { it.ItemId }).Select(it => it.ItemId).ToListAsync(); output = await _repository.AsQueryable().Where(a => items.Contains(a.Id)) .Where(a => a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null).Select(a => new { Id = a.Id, FullName = a.FullName, SortCode = a.SortCode }) .MergeTable().OrderBy(o => o.SortCode).Select().ToListAsync(); } } else { output = await _repository.AsQueryable().Where(a => a.EnabledMark == 1 && a.Category.Equals(type) && a.DeleteMark == null) .Select(a => new { Id = a.Id, FullName = a.FullName, SortCode = a.SortCode }).MergeTable().OrderBy(o => o.SortCode).Select().ToListAsync(); } return output; } #endregion #region PrivateMethod /// /// 导入数据. /// /// /// private async Task ImportData(ModuleExportInput data) { data.id = SnowflakeIdHelper.NextId(); var idDic = new Dictionary(); if (data.buttonEntityList.Any()) { foreach (var item in data.buttonEntityList) { item.id = SnowflakeIdHelper.NextId(); item.moduleId = data.id; } var button = data.buttonEntityList.Adapt>(); await _repository.AsSugarClient().Insertable(button).ExecuteCommandAsync(); } if (data.columnEntityList.Any()) { foreach (var item in data.columnEntityList) { item.id = SnowflakeIdHelper.NextId(); item.moduleId = data.id; } var colum = data.columnEntityList.Adapt>(); await _repository.AsSugarClient().Insertable(colum).ExecuteCommandAsync(); } var dic = new Dictionary(); if (data.authorizeEntityList.Any()) { foreach (var item in data.authorizeEntityList) { var id = SnowflakeIdHelper.NextId(); dic[item.id] = id; item.id = id; item.moduleId = data.id; } var dataAuthorize = data.authorizeEntityList.Adapt>(); await _repository.AsSugarClient().Insertable(dataAuthorize).ExecuteCommandAsync(); } if (data.schemeEntityList.Any()) { foreach (var item in data.schemeEntityList) { item.id = SnowflakeIdHelper.NextId(); item.moduleId = data.id; if (item.conditionJson.IsNotEmptyOrNull()) { foreach (var key in dic.Keys) { item.conditionJson = item.conditionJson.Replace(key, dic[key]); } } } var dataAuthorizeScheme = data.schemeEntityList.Adapt>(); await _repository.AsSugarClient().Insertable(dataAuthorizeScheme).ExecuteCommandAsync(); } if (data.formEntityList.Any()) { foreach (var item in data.formEntityList) { item.id = SnowflakeIdHelper.NextId(); item.moduleId = data.id; } var form = data.formEntityList.Adapt>(); await _repository.AsSugarClient().Insertable(form).ExecuteCommandAsync(); } var module = data.Adapt(); var isOk = await _repository.AsSugarClient().Insertable(module).ExecuteCommandAsync(); if (isOk < 1) throw Oops.Oh(ErrorCode.D3008); } #endregion }