init commit
This commit is contained in:
100
20220330_Vote/Ewide.Core/Service/App/Dto/AppInput.cs
Normal file
100
20220330_Vote/Ewide.Core/Service/App/Dto/AppInput.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统应用参数
|
||||
/// </summary>
|
||||
public class AppInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public virtual string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标颜色
|
||||
/// </summary>
|
||||
public virtual string Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否默认激活(Y-是,N-否),只能有一个系统默认激活
|
||||
/// 用户登录后默认展示此系统菜单
|
||||
/// </summary>
|
||||
public bool Active { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public CommonStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
}
|
||||
|
||||
public class AddAppInput : AppInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用编码不能为空")]
|
||||
public override string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public override string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标颜色
|
||||
/// </summary>
|
||||
[RegularExpression("^#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}$", ErrorMessage = "颜色格式不正确")]
|
||||
public override string Color { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteAppInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateAppInput : AppInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryAppInput : DeleteAppInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class SetDefaultAppInput : DeleteAppInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
33
20220330_Vote/Ewide.Core/Service/App/Dto/AppOutput.cs
Normal file
33
20220330_Vote/Ewide.Core/Service/App/Dto/AppOutput.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统应用参数
|
||||
/// </summary>
|
||||
public class AppOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否默认
|
||||
/// </summary>
|
||||
public bool Active { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
}
|
||||
}
|
||||
18
20220330_Vote/Ewide.Core/Service/App/ISysAppService.cs
Normal file
18
20220330_Vote/Ewide.Core/Service/App/ISysAppService.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysAppService
|
||||
{
|
||||
Task AddApp(AddAppInput input);
|
||||
Task DeleteApp(DeleteAppInput input);
|
||||
Task<SysApp> GetApp([FromQuery] QueryAppInput input);
|
||||
Task<dynamic> GetAppList([FromQuery] AppInput input);
|
||||
Task<dynamic> GetLoginApps(string userId);
|
||||
Task<dynamic> QueryAppPageList([FromQuery] AppInput input);
|
||||
Task SetAsDefault(SetDefaultAppInput input);
|
||||
Task UpdateApp(UpdateAppInput input);
|
||||
Task ChangeUserAppStatus(UpdateAppInput input);
|
||||
}
|
||||
}
|
||||
204
20220330_Vote/Ewide.Core/Service/App/SysAppService.cs
Normal file
204
20220330_Vote/Ewide.Core/Service/App/SysAppService.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统应用服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "App", Order = 100)]
|
||||
public class SysAppService : ISysAppService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysApp> _sysAppRep; // 应用表仓储
|
||||
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ISysMenuService _sysMenuService;
|
||||
|
||||
public SysAppService(IRepository<SysApp> sysAppRep,
|
||||
IUserManager userManager,
|
||||
ISysMenuService sysMenuService)
|
||||
{
|
||||
_sysAppRep = sysAppRep;
|
||||
_userManager = userManager;
|
||||
_sysMenuService = sysMenuService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户应用相关信息
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<dynamic> GetLoginApps(string userId)
|
||||
{
|
||||
var apps = _sysAppRep.DetachedEntities.Where(u => u.Status == (int)CommonStatus.ENABLE);
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
var appCodeList = await _sysMenuService.GetUserMenuAppCodeList(userId);
|
||||
apps = apps.Where(u => appCodeList.Contains(u.Code));
|
||||
}
|
||||
var appList = await apps.OrderBy(u => u.Sort).Select(u => new AppOutput
|
||||
{
|
||||
Id = u.Id,
|
||||
Code = u.Code,
|
||||
Name = u.Name,
|
||||
Active = u.Active,
|
||||
Sort = u.Sort
|
||||
}).ToListAsync(); // .OrderByDescending(u => u.Active) // 将激活的放到第一个
|
||||
|
||||
//// 默认激活第一个应用
|
||||
if (appList != null && appList.Count > 0 && !appList[0].Active)
|
||||
appList[0].Active = true;
|
||||
return appList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询系统应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/page")]
|
||||
public async Task<dynamic> QueryAppPageList([FromBody] AppInput input)
|
||||
{
|
||||
var apps = await _sysAppRep.DetachedEntities
|
||||
.Where(
|
||||
!string.IsNullOrEmpty(input.Name?.Trim()),
|
||||
u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")
|
||||
)
|
||||
.Where(
|
||||
!string.IsNullOrEmpty(input.Code?.Trim()),
|
||||
u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")
|
||||
)
|
||||
.ToPageData(input);
|
||||
return PageDataResult<SysApp>.PageResult(apps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加系统应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/add")]
|
||||
public async Task AddApp(AddAppInput input)
|
||||
{
|
||||
var isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => u.Name == input.Name || u.Code == input.Code);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D5000);
|
||||
|
||||
if (input.Active)
|
||||
{
|
||||
isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => u.Active == input.Active);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D5001);
|
||||
}
|
||||
|
||||
var app = input.Adapt<SysApp>();
|
||||
await app.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除系统应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/delete")]
|
||||
public async Task DeleteApp(DeleteAppInput input)
|
||||
{
|
||||
var app = await _sysAppRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
// 该应用下是否有状态为正常的菜单
|
||||
var hasMenu = await _sysMenuService.HasMenu(app.Code);
|
||||
if (hasMenu)
|
||||
throw Oops.Oh(ErrorCode.D5002);
|
||||
|
||||
await app.DeleteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新系统应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/edit")]
|
||||
public async Task UpdateApp(UpdateAppInput input)
|
||||
{
|
||||
var isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D5000);
|
||||
|
||||
if (input.Active)
|
||||
{
|
||||
isExist = await _sysAppRep.DetachedEntities.AnyAsync(u => u.Active == input.Active && !u.Id.Equals(input.Id));
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D5001);
|
||||
}
|
||||
|
||||
var app = input.Adapt<SysApp>();
|
||||
await app.UpdateExcludeAsync(new[] { nameof(SysApp.Status) }, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysApp/detail")]
|
||||
public async Task<SysApp> GetApp([FromQuery] QueryAppInput input)
|
||||
{
|
||||
return await _sysAppRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统应用列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysApp/list")]
|
||||
public async Task<dynamic> GetAppList([FromQuery] AppInput input)
|
||||
{
|
||||
return await _sysAppRep.DetachedEntities.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设为默认应用
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/setAsDefault")]
|
||||
public async Task SetAsDefault(SetDefaultAppInput input)
|
||||
{
|
||||
var apps = await _sysAppRep.Where(u => u.Status == (int)CommonStatus.ENABLE).ToListAsync();
|
||||
apps.ForEach(u =>
|
||||
{
|
||||
u.Active = false;
|
||||
});
|
||||
|
||||
var app = await _sysAppRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
app.Active = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改用户状态
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysApp/changeStatus")]
|
||||
public async Task ChangeUserAppStatus(UpdateAppInput input)
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
|
||||
throw Oops.Oh(ErrorCode.D3005);
|
||||
|
||||
var app = await _sysAppRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
app.Status = input.Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
183
20220330_Vote/Ewide.Core/Service/Area/AreaCodeService.cs
Normal file
183
20220330_Vote/Ewide.Core/Service/Area/AreaCodeService.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Ewide.Core.Service.Area.Dto;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Area
|
||||
{
|
||||
public class AreaCodeService : IAreaCodeService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysAreaCode> _areaCodeRep;
|
||||
private readonly IRepository<SysOrg> _sysOrgRep;
|
||||
private readonly ISysCacheService _sysCacheService;
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
public AreaCodeService(IRepository<SysAreaCode> AreaCodeRep, ISysCacheService sysCacheService, IRepository<SysOrg> sysOrgRep, IUserManager userManager)
|
||||
{
|
||||
_areaCodeRep = AreaCodeRep;
|
||||
_sysCacheService = sysCacheService;
|
||||
_sysOrgRep = sysOrgRep;
|
||||
_userManager = userManager;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加一个区域
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task AddAreaCode(AreaCodeInput input)
|
||||
{
|
||||
CheckInput(input);
|
||||
CheckCode(input);
|
||||
CheckArea(input);
|
||||
await _areaCodeRep.InsertNowAsync(input.Adapt<SysAreaCode>());
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAreaCode(await _areaCodeRep.DetachedEntities.ToListAsync());
|
||||
#endif
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除一个区域
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteAreaCode(DeleteAreaCodeInput input)
|
||||
{
|
||||
var AreaCode = await _areaCodeRep.FirstOrDefaultAsync(p => p.Code == input.Code);
|
||||
if (await _sysOrgRep.DetachedEntities.AnyAsync(o => o.AreaCode == input.Code))
|
||||
{
|
||||
throw Oops.Oh("不能删除已包含区域的组织");
|
||||
}
|
||||
await AreaCode.DeleteNowAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAreaCode(await _areaCodeRep.DetachedEntities.ToListAsync());
|
||||
#endif
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据区域代码获取区域信息
|
||||
/// </summary>
|
||||
/// <param name="code">区域代码</param>
|
||||
/// <returns></returns>
|
||||
public async Task<SysAreaCode> GetAreaCode(string code)
|
||||
{
|
||||
var cachedAreaCodes = await _sysCacheService.GetAreaCode();
|
||||
if (cachedAreaCodes == null || cachedAreaCodes.Count < 0)
|
||||
{
|
||||
cachedAreaCodes = await _areaCodeRep.DetachedEntities.ToListAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAreaCode(cachedAreaCodes);
|
||||
#endif
|
||||
}
|
||||
return cachedAreaCodes.FirstOrDefault(a => a.Code == code);
|
||||
}
|
||||
|
||||
public async Task<List<SysAreaCode>> GetAreaCodeWithChildren(string code)
|
||||
{
|
||||
return await _areaCodeRep.DetachedEntities.Where(a => a.Code.StartsWith(code)).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<dynamic> QueryAreaCodePageList(AreaCodeInput input)
|
||||
{
|
||||
var AreaCodes = await _areaCodeRep.DetachedEntities
|
||||
.Where(input.LevelType.HasValue, a => a.LevelType == input.LevelType)
|
||||
.Where(!string.IsNullOrEmpty(input.Code), a => a.Code.Contains(input.Code))
|
||||
.Where(!string.IsNullOrEmpty(input.AdCode), a => a.AdCode.Contains(input.AdCode))
|
||||
.Where(!string.IsNullOrEmpty(input.Name), a => a.Name.Contains(input.Name))
|
||||
.Where(!string.IsNullOrEmpty(input.Pcode), a => a.Code.StartsWith(input.Pcode))
|
||||
.ToPageData(input);
|
||||
return PageDataResult<SysAreaCode>.PageResult(AreaCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新区域信息
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateAreaCode(AreaCodeInput input)
|
||||
{
|
||||
CheckInput(input);
|
||||
CheckArea(input);
|
||||
var area = input.Adapt<SysAreaCode>();
|
||||
await area.UpdateNowAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAreaCode(await _areaCodeRep.DetachedEntities.ToListAsync());
|
||||
#endif
|
||||
}
|
||||
private bool CheckInput(AreaCodeInput input)
|
||||
{
|
||||
//检查level和区域长度
|
||||
if (false)
|
||||
{
|
||||
throw Oops.Oh("数据异常");
|
||||
}
|
||||
//检查是否有子节点
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckArea(AreaCodeInput input)
|
||||
{
|
||||
var any = _areaCodeRep.DetachedEntities.Any(p => p.AdCode == input.AdCode && p.Code != input.Code);
|
||||
if (any)
|
||||
{
|
||||
throw Oops.Oh("区域编码重复");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckCode(AreaCodeInput input)
|
||||
{
|
||||
var any = _areaCodeRep.DetachedEntities.Any(p => p.Code == input.Code);
|
||||
if (any)
|
||||
{
|
||||
throw Oops.Oh("编码重复");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetAreaCodeListByOrgId(List<string> orgIdList)
|
||||
{
|
||||
return await _sysOrgRep.DetachedEntities.Where(p => orgIdList.Contains(p.Id)).Select(p => p.AreaCode).Distinct().ToListAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取区域目录树
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AreaTreeNode>> GetAreaCodeTree(int? level)
|
||||
{
|
||||
level = level.GetValueOrDefault(100);
|
||||
var cachedAreaCodes = await _sysCacheService.GetAreaCode();
|
||||
if (cachedAreaCodes == null || cachedAreaCodes.Count < 0)
|
||||
{
|
||||
cachedAreaCodes = await _areaCodeRep.DetachedEntities.ToListAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAreaCode(cachedAreaCodes);
|
||||
#endif
|
||||
}
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
var userAreaList = await _userManager.GetUserAllAreaList();
|
||||
cachedAreaCodes = cachedAreaCodes.Where(a => userAreaList.Contains(a.Code)).ToList();
|
||||
}
|
||||
|
||||
return new TreeBuildUtil<AreaTreeNode>().DoTreeBuild(cachedAreaCodes.Select(u => new AreaTreeNode
|
||||
{
|
||||
Code = u.Code,
|
||||
AdCode = u.AdCode,
|
||||
ParentCode = u.ParentCode,
|
||||
Name = u.Name,
|
||||
LevelType = u.LevelType,
|
||||
Note = u.Note
|
||||
}).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
33
20220330_Vote/Ewide.Core/Service/Area/Dto/AreaCodeInput.cs
Normal file
33
20220330_Vote/Ewide.Core/Service/Area/Dto/AreaCodeInput.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Area.Dto
|
||||
{
|
||||
public class AreaCodeInput : InputBase
|
||||
{
|
||||
public string Code { get; set; }
|
||||
public string AdCode { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int? LevelType { get; set; }
|
||||
public string Note { get; set; }
|
||||
public int Sort { get; set; }
|
||||
public string Pcode { get; set; }
|
||||
}
|
||||
public class UpdateAreaCodeInput
|
||||
{
|
||||
public string AdCode { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int? LevelType { get; set; }
|
||||
public string Note { get; set; }
|
||||
public int Sort { get; set; }
|
||||
}
|
||||
public class DeleteAreaCodeInput
|
||||
{
|
||||
[Required(ErrorMessage ="区域代码不可为空")]
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
33
20220330_Vote/Ewide.Core/Service/Area/Dto/AreaCodeOutput.cs
Normal file
33
20220330_Vote/Ewide.Core/Service/Area/Dto/AreaCodeOutput.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Area.Dto
|
||||
{
|
||||
public class AreaCodeOutput:AreaCodeInput
|
||||
{
|
||||
public string ParentCode { get; set; }
|
||||
}
|
||||
public class AreaTreeNode : AreaCodeOutput, ITreeNode
|
||||
{
|
||||
public List<AreaTreeNode> Children { get; set; } = new List<AreaTreeNode>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Code;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return ParentCode;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<AreaTreeNode>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
20220330_Vote/Ewide.Core/Service/Area/IAreaCodeService.cs
Normal file
25
20220330_Vote/Ewide.Core/Service/Area/IAreaCodeService.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Ewide.Core.Service.Area.Dto;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Area
|
||||
{
|
||||
public interface IAreaCodeService
|
||||
{
|
||||
Task AddAreaCode(AreaCodeInput input);
|
||||
Task DeleteAreaCode(DeleteAreaCodeInput input);
|
||||
Task UpdateAreaCode(AreaCodeInput input);
|
||||
Task<SysAreaCode> GetAreaCode(string code);
|
||||
Task<List<SysAreaCode>> GetAreaCodeWithChildren(string code);
|
||||
|
||||
Task<List<AreaTreeNode>> GetAreaCodeTree(int? level);
|
||||
|
||||
Task<dynamic> QueryAreaCodePageList([FromQuery] AreaCodeInput input);
|
||||
|
||||
Task<List<string>> GetAreaCodeListByOrgId(List<string> orgIdList);
|
||||
}
|
||||
}
|
||||
358
20220330_Vote/Ewide.Core/Service/Auth/AuthService.cs
Normal file
358
20220330_Vote/Ewide.Core/Service/Auth/AuthService.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using Ewide.Core.Attributes;
|
||||
using Ewide.Core.Util;
|
||||
using Furion;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DataEncryption;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using UAParser;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录授权相关服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Auth", Order = 160)]
|
||||
public class AuthService : IAuthService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysUser> _sysUserRep; // 用户表仓储
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IUserManager _userManager; // 用户管理
|
||||
|
||||
private readonly ISysUserService _sysUserService; // 系统用户服务
|
||||
private readonly ISysEmpService _sysEmpService; // 系统员工服务
|
||||
private readonly ISysRoleService _sysRoleService; // 系统角色服务
|
||||
private readonly ISysMenuService _sysMenuService; // 系统菜单服务
|
||||
private readonly ISysAppService _sysAppService; // 系统应用服务
|
||||
private readonly IClickWordCaptcha _captchaHandle;// 验证码服务
|
||||
private readonly ISysConfigService _sysConfigService; // 验证码服务
|
||||
|
||||
public AuthService(IRepository<SysUser> sysUserRep,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IUserManager userManager,
|
||||
ISysUserService sysUserService,
|
||||
ISysEmpService sysEmpService,
|
||||
ISysRoleService sysRoleService,
|
||||
ISysMenuService sysMenuService,
|
||||
ISysAppService sysAppService,
|
||||
IClickWordCaptcha captchaHandle,
|
||||
ISysConfigService sysConfigService)
|
||||
{
|
||||
_sysUserRep = sysUserRep;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userManager = userManager;
|
||||
_sysUserService = sysUserService;
|
||||
_sysEmpService = sysEmpService;
|
||||
_sysRoleService = sysRoleService;
|
||||
_sysMenuService = sysMenuService;
|
||||
_sysAppService = sysAppService;
|
||||
_captchaHandle = captchaHandle;
|
||||
_sysConfigService = sysConfigService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户登录
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <remarks>默认用户名/密码:admin/admin</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/loginswagger")]
|
||||
[AllowAnonymous]
|
||||
[Op(LogOpType.GRANT)]
|
||||
public async Task<LoginOutput> LoginSwaggerAsync([Required] LoginInput input)
|
||||
{
|
||||
input.Password = RSAHandler.RSAEncrypt(input.Password);
|
||||
return await LoginAsync(input);
|
||||
}
|
||||
/// <summary>
|
||||
/// 用户登录
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <remarks>默认用户名/密码:admin/admin</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/login")]
|
||||
[AllowAnonymous]
|
||||
[Op(LogOpType.GRANT)]
|
||||
public async Task<LoginOutput> LoginAsync([Required] LoginInput input)
|
||||
{
|
||||
#if !DEBUG
|
||||
var password = RSAHandler.RSADecrypt(input.Password);
|
||||
#endif
|
||||
|
||||
var user = await GetUser(input);
|
||||
|
||||
#if !DEBUG
|
||||
// 验证密码强度
|
||||
var pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value;
|
||||
if (!Regex.Match(password, pattern).Success)
|
||||
{
|
||||
return new LoginOutput
|
||||
{
|
||||
Passed = false,
|
||||
Pattern = pattern,
|
||||
Descriptions = App.Configuration.GetSection("SimplePassword:Descriptions").Value
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
return new LoginOutput
|
||||
{
|
||||
Passed = true,
|
||||
Token = await HandlerLoginAsync(user)
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/loginPass")]
|
||||
[AllowAnonymous]
|
||||
public async Task<LoginOutput> LoginPassAsync([Required] LoginPassInput input)
|
||||
{
|
||||
var user = await GetUser(input);
|
||||
|
||||
var newPassword = RSAHandler.RSADecrypt(input.NewPassword);
|
||||
// 验证新密码强度
|
||||
var pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value;
|
||||
if (!Regex.Match(newPassword, pattern).Success)
|
||||
{
|
||||
throw Oops.Oh("新密码强度不符合规则");
|
||||
}
|
||||
|
||||
newPassword = MD5Encryption.Encrypt(newPassword);
|
||||
if (newPassword.Equals(user.Password))
|
||||
throw Oops.Oh(ErrorCode.D10041);
|
||||
|
||||
user.Password = newPassword;
|
||||
|
||||
return new LoginOutput
|
||||
{
|
||||
Passed = true,
|
||||
Token = await HandlerLoginAsync(user)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private async Task<SysUser> GetUser(LoginInput input)
|
||||
{
|
||||
#if !DEBUG
|
||||
var password = RSAHandler.RSADecrypt(input.Password);
|
||||
// 获取加密后的密码
|
||||
var encryptPasswod = MD5Encryption.Encrypt(password);
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Account.Equals(input.Account) || u.Phone.Equals(input.Account) || u.Email.Equals(input.Account));
|
||||
#else
|
||||
// 判断用户名和密码是否正确
|
||||
var user = await _sysUserRep.FirstOrDefaultAsync(u => (u.Account.Equals(input.Account) || u.Phone.Equals(input.Account) || u.Email.Equals(input.Account)) && u.Password.Equals(encryptPasswod));
|
||||
_ = user ?? throw Oops.Oh(ErrorCode.D1000);
|
||||
#endif
|
||||
|
||||
// 验证账号是否被冻结
|
||||
if (user.Status == CommonStatus.DISABLE)
|
||||
throw Oops.Oh(ErrorCode.D1017);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
private async Task<string> HandlerLoginAsync(SysUser user)
|
||||
{
|
||||
// 生成Token令牌
|
||||
//var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
|
||||
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
|
||||
{
|
||||
{ ClaimConst.CLAINM_USERID, user.Id },
|
||||
{ ClaimConst.CLAINM_ACCOUNT, user.Account },
|
||||
{ ClaimConst.CLAINM_NAME, user.Name },
|
||||
{ ClaimConst.CLAINM_SUPERADMIN, user.AdminType },
|
||||
});
|
||||
|
||||
// 设置Swagger自动登录
|
||||
_httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
|
||||
|
||||
// 生成刷新Token令牌
|
||||
var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, 30);
|
||||
|
||||
// 设置刷新Token令牌
|
||||
_httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
|
||||
|
||||
// 增加登录日志
|
||||
var loginUserOutput = user.Adapt<LoginUserOutput>();
|
||||
var clent = Parser.GetDefault().Parse(App.GetService<IHttpContextAccessor>().HttpContext.Request.Headers["User-Agent"]);
|
||||
loginUserOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major;
|
||||
loginUserOutput.LastLoginOs = clent.OS.Family + clent.OS.Major;
|
||||
await new SysLogVis
|
||||
{
|
||||
Name = "登录",
|
||||
Success = true,
|
||||
Message = "登录成功",
|
||||
Ip = loginUserOutput.LastLoginIp,
|
||||
Browser = loginUserOutput.LastLoginBrowser,
|
||||
Os = loginUserOutput.LastLoginOs,
|
||||
VisType = 1,
|
||||
VisTime = loginUserOutput.LastLoginTime,
|
||||
Account = loginUserOutput.Account
|
||||
}.InsertAsync();
|
||||
|
||||
return accessToken;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前登录用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/getLoginUser")]
|
||||
public async Task<LoginUserOutput> GetLoginUserAsync()
|
||||
{
|
||||
var user = _userManager.User;
|
||||
var userId = user.Id;
|
||||
|
||||
var httpContext = App.GetService<IHttpContextAccessor>().HttpContext;
|
||||
var loginOutput = user.Adapt<LoginUserOutput>();
|
||||
|
||||
// 隐藏手机号/邮箱中间几位
|
||||
loginOutput.Phone = String.IsNullOrEmpty(loginOutput.Phone) ? loginOutput.Phone
|
||||
: loginOutput.Phone.Substring(0, 3) + "****" + loginOutput.Phone.Substring(7, 4);
|
||||
loginOutput.Email = String.IsNullOrEmpty(loginOutput.Email) ? loginOutput.Email
|
||||
: String.Join("@", loginOutput.Email.Split('@').Select((p, i) =>
|
||||
{
|
||||
return i == 0 ? (p.Length > 3 ? p.Substring(0, 3).PadRight(p.Length, '*') : "".PadRight(3, '*')) : p;
|
||||
}));
|
||||
|
||||
loginOutput.LastLoginTime = user.LastLoginTime = DateTime.Now;
|
||||
var ip = httpContext.Request.Headers["X-Real-IP"].FirstOrDefault();
|
||||
loginOutput.LastLoginIp = user.LastLoginIp = string.IsNullOrEmpty(user.LastLoginIp) ? httpContext.GetRemoteIpAddressToIPv4() : ip;
|
||||
///如果真实ip为空的话,就获取客户端主机IPv4地址
|
||||
if (string.IsNullOrEmpty(ip))
|
||||
{
|
||||
loginOutput.LastLoginIp = httpContext.GetRemoteIpAddressToIPv4();
|
||||
}
|
||||
//var ipInfo = IpTool.Search(loginOutput.LastLoginIp);
|
||||
//loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]";
|
||||
|
||||
var clent = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
|
||||
loginOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major;
|
||||
loginOutput.LastLoginOs = clent.OS.Family + clent.OS.Major;
|
||||
|
||||
// 员工信息
|
||||
loginOutput.LoginEmpInfo = await _sysEmpService.GetEmpInfo(userId);
|
||||
|
||||
// 角色信息
|
||||
loginOutput.Roles = await _sysRoleService.GetUserRoleList(userId);
|
||||
|
||||
// 权限信息
|
||||
loginOutput.Permissions = await _sysMenuService.GetLoginPermissionList(userId);
|
||||
|
||||
// 数据范围信息(机构Id集合)
|
||||
loginOutput.DataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
|
||||
// 具备应用信息(多系统,默认激活一个,可根据系统切换菜单),返回的结果中第一个为激活的系统
|
||||
loginOutput.Apps = await _sysAppService.GetLoginApps(userId);
|
||||
|
||||
// 菜单信息
|
||||
if (loginOutput.Apps.Count > 0)
|
||||
{
|
||||
//var defaultActiveAppCode = loginOutput.Apps.FirstOrDefault(u => u.Active == true).Code; // loginOutput.Apps[0].Code;
|
||||
//loginOutput.Menus = await _sysMenuService.GetLoginMenusAntDesign(userId, defaultActiveAppCode);
|
||||
foreach (var app in loginOutput.Apps)
|
||||
{
|
||||
loginOutput.Menus.AddRange(await _sysMenuService.GetLoginMenusAntDesign(userId, app.Code));
|
||||
}
|
||||
}
|
||||
|
||||
return loginOutput;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/logout")]
|
||||
public async Task LogoutAsync()
|
||||
{
|
||||
_httpContextAccessor.HttpContext.SignoutToSwagger();
|
||||
//_httpContextAccessor.HttpContext.Response.Headers["access-token"] = "invalid token";
|
||||
var user = _userManager.User;
|
||||
var userId = user.Id;
|
||||
|
||||
var httpContext = App.GetService<IHttpContextAccessor>().HttpContext;
|
||||
var loginOutput = user.Adapt<LoginUserOutput>();
|
||||
|
||||
|
||||
var ip = httpContext.Request.Headers["X-Real-IP"];
|
||||
var LastLoginIp = user.LastLoginIp = string.IsNullOrEmpty(user.LastLoginIp) ? httpContext.GetRemoteIpAddressToIPv4() : ip;
|
||||
var clent = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
|
||||
loginOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major;
|
||||
///如果真实ip为空的话,就获取客户端主机IPv4地址
|
||||
if (string.IsNullOrEmpty(ip))
|
||||
{
|
||||
LastLoginIp = httpContext.GetRemoteIpAddressToIPv4();
|
||||
}
|
||||
// 增加退出日志
|
||||
await new SysLogVis
|
||||
{
|
||||
Name = "退出",
|
||||
VisTime = DateTime.Now,
|
||||
Success = true,
|
||||
Message = "退出成功",
|
||||
VisType = 2,
|
||||
Browser = loginOutput.LastLoginBrowser,
|
||||
Os = loginOutput.LastLoginOs,
|
||||
Ip = LastLoginIp,
|
||||
Account = loginOutput.Account
|
||||
}.InsertAsync();
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证码开关
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/getCaptchaOpen")]
|
||||
[AllowAnonymous]
|
||||
public async Task<bool> GetCaptchaOpen()
|
||||
{
|
||||
return await _sysConfigService.GetCaptchaOpenFlag();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证码(默认点选模式)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/captcha/get")]
|
||||
[AllowAnonymous]
|
||||
[NonUnify]
|
||||
public async Task<dynamic> GetCaptcha()
|
||||
{
|
||||
// 图片大小要与前端保持一致(坐标范围)
|
||||
return await Task.FromResult(_captchaHandle.CreateCaptchaImage(_captchaHandle.RandomCode(6), 310, 155));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验验证码
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/captcha/check")]
|
||||
[AllowAnonymous]
|
||||
[NonUnify]
|
||||
public async Task<dynamic> VerificationCode(ClickWordCaptchaInput input)
|
||||
{
|
||||
return await Task.FromResult(_captchaHandle.CheckCode(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
20220330_Vote/Ewide.Core/Service/Auth/Dto/LoginInput.cs
Normal file
43
20220330_Vote/Ewide.Core/Service/Auth/Dto/LoginInput.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Furion;
|
||||
using Furion.DependencyInjection;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录输入参数
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public class LoginInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
/// <example>superAdmin</example>
|
||||
[Required(ErrorMessage = "用户名不能为空"), MinLength(3, ErrorMessage = "用户名不能少于3位字符")]
|
||||
public virtual string Account { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
/// <example>1234567</example>
|
||||
[Required(ErrorMessage = "密码不能为空"), MinLength(5, ErrorMessage = "密码不能少于5位字符")]
|
||||
public virtual string Password { get; set; }
|
||||
}
|
||||
|
||||
[SuppressSniffer]
|
||||
public class LoginPassInput : LoginInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 新密码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "新密码不能为空")]
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 确认密码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "确认密码不能为空"), Compare(nameof(NewPassword), ErrorMessage = "两次密码不一致")]
|
||||
public string Confirm { get; set; }
|
||||
}
|
||||
}
|
||||
177
20220330_Vote/Ewide.Core/Service/Auth/Dto/LoginOutput.cs
Normal file
177
20220330_Vote/Ewide.Core/Service/Auth/Dto/LoginOutput.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using Furion.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
[SuppressSniffer]
|
||||
public class LoginOutput
|
||||
{
|
||||
public bool Passed { get; set; }
|
||||
public string Pattern { get; set; }
|
||||
public string Descriptions { get; set; }
|
||||
public string Token { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户登录输出参数
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public class LoginUserOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 账号
|
||||
/// </summary>
|
||||
public string Account { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码安全级别
|
||||
/// </summary>
|
||||
public int SecurityLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
public string NickName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 姓名
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 头像
|
||||
/// </summary>
|
||||
public string Avatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生日
|
||||
/// </summary>
|
||||
public DateTime? Birthday { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 性别(字典 1男 2女)
|
||||
/// </summary>
|
||||
public int Sex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱
|
||||
/// </summary>
|
||||
public String Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 手机
|
||||
/// </summary>
|
||||
public String Phone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电话
|
||||
/// </summary>
|
||||
public String Tel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 管理员类型(0超级管理员 1非管理员)
|
||||
/// </summary>
|
||||
public int AdminType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登陆IP
|
||||
/// </summary>
|
||||
public string LastLoginIp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登陆时间
|
||||
/// </summary>
|
||||
public DateTime LastLoginTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登陆地址
|
||||
/// </summary>
|
||||
public string LastLoginAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登陆所用浏览器
|
||||
/// </summary>
|
||||
public string LastLoginBrowser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登陆所用系统
|
||||
/// </summary>
|
||||
public string LastLoginOs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 员工信息
|
||||
/// </summary>
|
||||
public EmpOutput LoginEmpInfo { get; set; } = new EmpOutput();
|
||||
|
||||
/// <summary>
|
||||
/// 具备应用信息
|
||||
/// </summary>
|
||||
public List<AppOutput> Apps { get; set; } = new List<AppOutput>();
|
||||
|
||||
/// <summary>
|
||||
/// 角色信息
|
||||
/// </summary>
|
||||
public List<RoleOutput> Roles { get; set; } = new List<RoleOutput>();
|
||||
|
||||
/// <summary>
|
||||
/// 权限信息
|
||||
/// </summary>
|
||||
public List<string> Permissions { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 登录菜单信息---AntDesign版本菜单
|
||||
/// </summary>
|
||||
public List<AntDesignTreeNode> Menus { get; set; } = new List<AntDesignTreeNode>();
|
||||
|
||||
/// <summary>
|
||||
/// 数据范围(机构)信息
|
||||
/// </summary>
|
||||
public List<string> DataScopes { get; set; } = new List<string>();
|
||||
|
||||
///// <summary>
|
||||
///// 租户信息
|
||||
///// </summary>
|
||||
//public List<long> Tenants { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 密码
|
||||
///// </summary>
|
||||
//public string Password { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 账户过期
|
||||
///// </summary>
|
||||
//public string AccountNonExpired { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 凭证过期
|
||||
///// </summary>
|
||||
//public string CredentialsNonExpired { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 账户锁定
|
||||
///// </summary>
|
||||
//public bool AccountNonLocked { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 用户名称
|
||||
///// </summary>
|
||||
//public string UserName { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 权限
|
||||
///// </summary>
|
||||
//public List<long> Authorities { get; set; } = new List<long>();
|
||||
|
||||
///// <summary>
|
||||
///// 是否启动
|
||||
///// </summary>
|
||||
//public bool Enabled { get; set; }
|
||||
}
|
||||
}
|
||||
15
20220330_Vote/Ewide.Core/Service/Auth/IAuthService.cs
Normal file
15
20220330_Vote/Ewide.Core/Service/Auth/IAuthService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface IAuthService
|
||||
{
|
||||
Task<dynamic> GetCaptcha();
|
||||
Task<bool> GetCaptchaOpen();
|
||||
Task<LoginUserOutput> GetLoginUserAsync();
|
||||
Task<LoginOutput> LoginAsync([Required] LoginInput input);
|
||||
Task LogoutAsync();
|
||||
Task<dynamic> VerificationCode(ClickWordCaptchaInput input);
|
||||
}
|
||||
}
|
||||
24
20220330_Vote/Ewide.Core/Service/Cache/ISysCacheService.cs
Normal file
24
20220330_Vote/Ewide.Core/Service/Cache/ISysCacheService.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysCacheService
|
||||
{
|
||||
Task<bool> DelAsync(string key);
|
||||
Task<bool> DelByPatternAsync(string key);
|
||||
List<string> GetAllCacheKeys();
|
||||
Task<List<string>> GetDataScope(string userId);
|
||||
Task<List<AntDesignTreeNode>> GetMenu(string userId, string appCode);
|
||||
Task<List<string>> GetPermission(string userId);
|
||||
Task SetDataScope(string userId, List<string> dataScopes);
|
||||
Task SetMenu(string userId, string appCode, List<AntDesignTreeNode> menus);
|
||||
Task SetPermission(string userId, List<string> permissions);
|
||||
Task<List<SysAreaCode>> GetAreaCode();
|
||||
Task SetAreaCode(List<SysAreaCode> areaCodes);
|
||||
Task<bool> SetAsync(string key, object value);
|
||||
Task<string> GetAsync(string key);
|
||||
Task<T> GetAsync<T>(string key);
|
||||
bool Exists(string cacheKey);
|
||||
}
|
||||
}
|
||||
189
20220330_Vote/Ewide.Core/Service/Cache/SysCacheService.cs
Normal file
189
20220330_Vote/Ewide.Core/Service/Cache/SysCacheService.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统缓存服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Cache", Order = 100)]
|
||||
public class SysCacheService : ISysCacheService, IDynamicApiController, ISingleton
|
||||
{
|
||||
private readonly ICache _cache;
|
||||
private readonly CacheOptions _cacheOptions;
|
||||
|
||||
public SysCacheService(IOptions<CacheOptions> cacheOptions, Func<string, ISingleton, object> resolveNamed)
|
||||
{
|
||||
_cacheOptions = cacheOptions.Value;
|
||||
_cache = resolveNamed(_cacheOptions.CacheType.ToString(), default) as ICache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据范围缓存(机构Id集合)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<string>> GetDataScope(string userId)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_DATASCOPE + $"{userId}";
|
||||
return await _cache.GetAsync<List<string>>(cacheKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存数据范围(机构Id集合)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="dataScopes"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task SetDataScope(string userId, List<string> dataScopes)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_DATASCOPE + $"{userId}";
|
||||
await _cache.SetAsync(cacheKey, dataScopes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取菜单缓存
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AntDesignTreeNode>> GetMenu(string userId, string appCode)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_MENU + $"{userId}-{appCode}";
|
||||
return await _cache.GetAsync<List<AntDesignTreeNode>>(cacheKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存菜单
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="appCode"></param>
|
||||
/// <param name="menus"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task SetMenu(string userId, string appCode, List<AntDesignTreeNode> menus)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_MENU + $"{userId}-{appCode}";
|
||||
await _cache.SetAsync(cacheKey, menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取权限缓存(按钮)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<string>> GetPermission(string userId)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_PERMISSION + $"{userId}";
|
||||
return await _cache.GetAsync<List<string>>(cacheKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存权限
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task SetPermission(string userId, List<string> permissions)
|
||||
{
|
||||
var cacheKey = CommonConst.CACHE_KEY_PERMISSION + $"{userId}";
|
||||
await _cache.SetAsync(cacheKey, permissions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有缓存关键字
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<string> GetAllCacheKeys()
|
||||
{
|
||||
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
var entries = _cache.GetType().GetField("_entries", flags).GetValue(_cache);
|
||||
if (entries.GetType().GetProperty("Keys").GetValue(entries) is not ICollection<object> cacheItems) return new List<string>();
|
||||
return cacheItems.Where(u => !u.ToString().StartsWith("mini-profiler"))
|
||||
.Select(u => u.ToString()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定关键字缓存
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> DelAsync(string key)
|
||||
{
|
||||
_cache.DelAsync(key);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除某特征关键字缓存
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> DelByPatternAsync(string key)
|
||||
{
|
||||
_cache.DelByPatternAsync(key);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置缓存
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> SetAsync(string key, object value)
|
||||
{
|
||||
return await _cache.SetAsync(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetAsync(string key)
|
||||
{
|
||||
return await _cache.GetAsync(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public Task<T> GetAsync<T>(string key)
|
||||
{
|
||||
return _cache.GetAsync<T>(key);
|
||||
}
|
||||
public Task<List<SysAreaCode>> GetAreaCode()
|
||||
{
|
||||
return _cache.GetAsync<List<SysAreaCode>>(CommonConst.CACHE_AREA_CODE);
|
||||
}
|
||||
|
||||
public async Task SetAreaCode(List<SysAreaCode> areaCodes)
|
||||
{
|
||||
await _cache.SetAsync(CommonConst.CACHE_AREA_CODE, areaCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查给定 key 是否存在
|
||||
/// </summary>
|
||||
/// <param name="cacheKey">键</param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public bool Exists(string cacheKey)
|
||||
{
|
||||
return _cache.Equals(cacheKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
207
20220330_Vote/Ewide.Core/Service/CodeGen/CodeGenConfigService.cs
Normal file
207
20220330_Vote/Ewide.Core/Service/CodeGen/CodeGenConfigService.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成详细配置服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "CodeGenConfig", Order = 100)]
|
||||
public class CodeGenConfigService : ICodeGenConfigService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysCodeGenConfig> _sysCodeGenConfigRep; // 代码生成详细配置仓储
|
||||
|
||||
public CodeGenConfigService(IRepository<SysCodeGenConfig> sysCodeGenConfigRep)
|
||||
{
|
||||
_sysCodeGenConfigRep = sysCodeGenConfigRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 代码生成详细配置列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[HttpGet("/sysCodeGenerateConfig/list")]
|
||||
public async Task<List<CodeGenConfig>> List([FromQuery] CodeGenConfig input)
|
||||
{
|
||||
return await _sysCodeGenConfigRep.DetachedEntities.Where(u => u.CodeGenId == input.CodeGenId && u.WhetherCommon != YesOrNot.Y.ToString())
|
||||
.Select(u => u.Adapt<CodeGenConfig>()).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task Add(CodeGenConfig input)
|
||||
{
|
||||
var codeGenConfig = input.Adapt<SysCodeGenConfig>();
|
||||
await codeGenConfig.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除
|
||||
/// </summary>
|
||||
/// <param name="codeGenId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task Delete(string codeGenId)
|
||||
{
|
||||
var codeGenConfigList = await _sysCodeGenConfigRep.Where(u => u.CodeGenId == codeGenId).ToListAsync();
|
||||
codeGenConfigList.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="inputList"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysCodeGenerateConfig/edit")]
|
||||
public async Task Update(List<CodeGenConfig> inputList)
|
||||
{
|
||||
if (inputList == null || inputList.Count < 1) return;
|
||||
inputList.ForEach(u =>
|
||||
{
|
||||
var codeGenConfig = u.Adapt<SysCodeGenConfig>();
|
||||
codeGenConfig.Update(true);
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysCodeGenerateConfig/detail")]
|
||||
public async Task<SysCodeGenConfig> Detail(CodeGenConfig input)
|
||||
{
|
||||
return await _sysCodeGenConfigRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量增加
|
||||
/// </summary>
|
||||
/// <param name="tableColumnOuputList"></param>
|
||||
/// <param name="codeGenerate"></param>
|
||||
[NonAction]
|
||||
public void AddList(List<TableColumnOuput> tableColumnOuputList, SysCodeGen codeGenerate)
|
||||
{
|
||||
if (tableColumnOuputList == null) return;
|
||||
|
||||
foreach (var tableColumn in tableColumnOuputList)
|
||||
{
|
||||
var codeGenConfig = new SysCodeGenConfig();
|
||||
|
||||
var YesOrNo = YesOrNot.Y.ToString();
|
||||
if (Convert.ToBoolean(tableColumn.ColumnKey))
|
||||
{
|
||||
YesOrNo = YesOrNot.N.ToString();
|
||||
}
|
||||
|
||||
if (IsCommonColumn(tableColumn.ColumnName))
|
||||
{
|
||||
codeGenConfig.WhetherCommon = YesOrNot.Y.ToString();
|
||||
YesOrNo = YesOrNot.N.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
codeGenConfig.WhetherCommon = YesOrNot.N.ToString();
|
||||
}
|
||||
|
||||
codeGenConfig.CodeGenId = codeGenerate.Id;
|
||||
codeGenConfig.ColumnName = tableColumn.ColumnName;
|
||||
codeGenConfig.ColumnComment = tableColumn.ColumnComment;
|
||||
codeGenConfig.NetType = ConvertDataType(tableColumn.DataType);
|
||||
codeGenConfig.WhetherRetract = YesOrNot.N.ToString();
|
||||
|
||||
codeGenConfig.WhetherRequired = YesOrNot.N.ToString();
|
||||
codeGenConfig.QueryWhether = YesOrNo;
|
||||
codeGenConfig.WhetherAddUpdate = YesOrNo;
|
||||
codeGenConfig.WhetherTable = YesOrNo;
|
||||
|
||||
codeGenConfig.ColumnKey = tableColumn.ColumnKey;
|
||||
|
||||
codeGenConfig.DataType = tableColumn.DataType;
|
||||
codeGenConfig.EffectType = DataTypeToEff(codeGenConfig.NetType);
|
||||
codeGenConfig.QueryType = "=="; // QueryTypeEnum.eq.ToString();
|
||||
|
||||
codeGenConfig.InsertAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据类型转显示类型
|
||||
/// </summary>
|
||||
/// <param name="dataType"></param>
|
||||
/// <returns></returns>
|
||||
private static string DataTypeToEff(string dataType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dataType)) return "";
|
||||
return dataType switch
|
||||
{
|
||||
"string" => "input",
|
||||
"int" => "inputnumber",
|
||||
"long" => "input",
|
||||
"float" => "input",
|
||||
"double" => "input",
|
||||
"decimal" => "input",
|
||||
"bool" => "switch",
|
||||
"Guid" => "input",
|
||||
"DateTime" => "datepicker",
|
||||
"DateTimeOffset" => "datepicker",
|
||||
_ => "input",
|
||||
};
|
||||
}
|
||||
|
||||
// 转换.NET数据类型
|
||||
[NonAction]
|
||||
public string ConvertDataType(string dataType)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dataType)) return "";
|
||||
if (dataType.StartsWith("System.Nullable"))
|
||||
dataType = new Regex(@"(?i)(?<=\[)(.*)(?=\])").Match(dataType).Value; // 中括号[]里面值
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case "System.Guid": return "Guid";
|
||||
case "System.String": return "string";
|
||||
case "System.Int32": return "int";
|
||||
case "System.Int64": return "long";
|
||||
case "System.Single": return "float";
|
||||
case "System.Double": return "double";
|
||||
case "System.Decimal": return "decimal";
|
||||
case "System.Boolean": return "bool";
|
||||
case "System.DateTime": return "DateTime";
|
||||
case "System.DateTimeOffset": return "DateTimeOffset";
|
||||
case "System.Byte": return "byte";
|
||||
case "System.Byte[]": return "byte[]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
// 是否通用字段
|
||||
private static bool IsCommonColumn(string columnName)
|
||||
{
|
||||
var columnList = new List<string>() { "CreatedTime", "UpdatedTime", "CreatedUserId", "CreatedUserName", "UpdatedUserId", "UpdatedUserName", "IsDeleted" };
|
||||
return columnList.Contains(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
348
20220330_Vote/Ewide.Core/Service/CodeGen/CodeGenService.cs
Normal file
348
20220330_Vote/Ewide.Core/Service/CodeGen/CodeGenService.cs
Normal file
@@ -0,0 +1,348 @@
|
||||
using Furion;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Furion.ViewEngine;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.CodeGen
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成器服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "CodeGen", Order = 100)]
|
||||
public class CodeGenService : ICodeGenService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysCodeGen> _sysCodeGenRep; // 代码生成器仓储
|
||||
private readonly ICodeGenConfigService _codeGenConfigService;
|
||||
private readonly IViewEngine _viewEngine;
|
||||
|
||||
private readonly IRepository<SysMenu> _sysMenuRep; // 菜单表仓储
|
||||
|
||||
public CodeGenService(IRepository<SysCodeGen> sysCodeGenRep,
|
||||
ICodeGenConfigService codeGenConfigService,
|
||||
IViewEngine viewEngine,
|
||||
IRepository<SysMenu> sysMenuRep)
|
||||
{
|
||||
_sysCodeGenRep = sysCodeGenRep;
|
||||
_codeGenConfigService = codeGenConfigService;
|
||||
_viewEngine = viewEngine;
|
||||
_sysMenuRep = sysMenuRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/codeGenerate/page")]
|
||||
public async Task<dynamic> QueryCodeGenPageList([FromBody] CodeGenInput input)
|
||||
{
|
||||
var tableName = !string.IsNullOrEmpty(input.TableName?.Trim());
|
||||
var codeGens = await _sysCodeGenRep.DetachedEntities
|
||||
.Where((tableName, u => EF.Functions.Like(u.TableName, $"%{input.TableName.Trim()}%")))
|
||||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||||
return PageDataResult<SysCodeGen>.PageResult(codeGens);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/codeGenerate/add")]
|
||||
public async Task AddCodeGen(AddCodeGenInput input)
|
||||
{
|
||||
var isExist = await _sysCodeGenRep.DetachedEntities.AnyAsync(u => u.TableName == input.TableName);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1400);
|
||||
|
||||
var codeGen = input.Adapt<SysCodeGen>();
|
||||
var newCodeGen = await codeGen.InsertNowAsync();
|
||||
|
||||
// 加入配置表中
|
||||
_codeGenConfigService.AddList(GetColumnList(input), newCodeGen.Entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除
|
||||
/// </summary>
|
||||
/// <param name="inputs"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/codeGenerate/delete")]
|
||||
public async Task DeleteCodeGen(List<DeleteCodeGenInput> inputs)
|
||||
{
|
||||
if (inputs == null || inputs.Count < 1) return;
|
||||
|
||||
var codeGenConfigTaskList = new List<Task>();
|
||||
inputs.ForEach(u =>
|
||||
{
|
||||
_sysCodeGenRep.Delete(u.Id);
|
||||
|
||||
// 删除配置表中
|
||||
codeGenConfigTaskList.Add(_codeGenConfigService.Delete(u.Id));
|
||||
});
|
||||
await Task.WhenAll(codeGenConfigTaskList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/codeGenerate/edit")]
|
||||
public async Task UpdateCodeGen(UpdateCodeGenInput input)
|
||||
{
|
||||
var isExist = await _sysCodeGenRep.DetachedEntities.AnyAsync(u => u.TableName == input.TableName && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1400);
|
||||
|
||||
var codeGen = input.Adapt<SysCodeGen>();
|
||||
await codeGen.UpdateAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/codeGenerate/detail")]
|
||||
public async Task<SysCodeGen> GetCodeGen([FromQuery] QueryCodeGenInput input)
|
||||
{
|
||||
return await _sysCodeGenRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库表(实体)集合
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
[HttpGet("/codeGenerate/InformationList")]
|
||||
public List<TableOutput> GetTableList()
|
||||
{
|
||||
return Db.GetDbContext().Model.GetEntityTypes().Select(u => new TableOutput
|
||||
{
|
||||
TableName = u.GetDefaultTableName(),
|
||||
TableComment = u.GetComment()
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据表列(实体属性)集合
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public List<TableColumnOuput> GetColumnList(AddCodeGenInput input)
|
||||
{
|
||||
var entityType = Db.GetDbContext().Model.GetEntityTypes().FirstOrDefault(u => u.ClrType.Name == input.TableName);
|
||||
if (entityType == null) return null;
|
||||
|
||||
return entityType.GetProperties().Select(u => new TableColumnOuput
|
||||
{
|
||||
ColumnName = u.Name,
|
||||
ColumnKey = u.IsKey().ToString(),
|
||||
DataType = u.PropertyInfo.PropertyType.ToString(),
|
||||
ColumnComment = u.GetComment()
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 代码生成_本地项目
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/codeGenerate/runLocal")]
|
||||
public async void RunLocal(SysCodeGen input)
|
||||
{
|
||||
var templatePathList = GetTemplatePathList();
|
||||
var targetPathList = GetTargetPathList(input);
|
||||
for (var i = 0; i < templatePathList.Count; i++)
|
||||
{
|
||||
var tContent = File.ReadAllText(templatePathList[i]);
|
||||
|
||||
var tableFieldList = await _codeGenConfigService.List(new CodeGenConfig() { CodeGenId = input.Id }); // 字段集合
|
||||
if (i >= 4) // 适应前端首字母小写
|
||||
{
|
||||
tableFieldList.ForEach(u =>
|
||||
{
|
||||
u.ColumnName = u.ColumnName.Substring(0, 1).ToLower() + u.ColumnName.Substring(1);
|
||||
});
|
||||
}
|
||||
var queryWhetherList = tableFieldList.Where(u => u.QueryWhether == YesOrNot.Y.ToString()).ToList(); // 前端查询集合
|
||||
var tResult = _viewEngine.RunCompileFromCached(tContent, new
|
||||
{
|
||||
input.AuthorName,
|
||||
input.BusName,
|
||||
input.NameSpace,
|
||||
ClassName = input.TableName,
|
||||
QueryWhetherList = queryWhetherList,
|
||||
TableField = tableFieldList
|
||||
});
|
||||
|
||||
var dirPath = new DirectoryInfo(targetPathList[i]).Parent.FullName;
|
||||
if (!Directory.Exists(dirPath))
|
||||
Directory.CreateDirectory(dirPath);
|
||||
File.WriteAllText(targetPathList[i], tResult, Encoding.UTF8);
|
||||
}
|
||||
|
||||
await AddMenu(input.TableName, input.BusName);
|
||||
}
|
||||
|
||||
private async Task AddMenu(string className, string busName)
|
||||
{
|
||||
// 先删除该表已生成的菜单列表
|
||||
var menus = await _sysMenuRep.DetachedEntities.Where(u => u.Code.StartsWith("dilon_" + className.ToLower())).ToListAsync();
|
||||
menus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
var emptyGuid = System.Guid.Empty.ToString();
|
||||
// 目录
|
||||
var menuType0 = new SysMenu
|
||||
{
|
||||
Pid = emptyGuid,
|
||||
Pids = "["+ emptyGuid + "],",
|
||||
Name = busName + "管理",
|
||||
Code = "dilon_" + className.ToLower(),
|
||||
Type = 1,
|
||||
Icon = "robot",
|
||||
Router = "/" + className.ToLower(),
|
||||
Component = "PageView",
|
||||
Application = "busapp"
|
||||
};
|
||||
var pid0 = _sysMenuRep.InsertNowAsync(menuType0).GetAwaiter().GetResult().Entity.Id;
|
||||
|
||||
// 菜单
|
||||
var menuType1 = new SysMenu
|
||||
{
|
||||
Pid = pid0,
|
||||
Pids = "[0],[" + pid0 + "],",
|
||||
Name = busName + "管理",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr",
|
||||
Type = 1,
|
||||
Router = "/" + className.ToLower(),
|
||||
Component = "main/" + className + "/index",
|
||||
Application = "busapp",
|
||||
OpenType = 1
|
||||
};
|
||||
var pid1 = _sysMenuRep.InsertNowAsync(menuType1).GetAwaiter().GetResult().Entity.Id;
|
||||
|
||||
// 按钮-page
|
||||
var menuType2 = new SysMenu
|
||||
{
|
||||
Pid = pid1,
|
||||
Pids = "[0],[" + pid0 + "],[" + pid1 + "],",
|
||||
Name = busName + "查询",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr_page",
|
||||
Type = 2,
|
||||
Permission = className + ":page",
|
||||
Application = "busapp",
|
||||
}.InsertAsync();
|
||||
|
||||
// 按钮-detail
|
||||
var menuType2_1 = new SysMenu
|
||||
{
|
||||
Pid = pid1,
|
||||
Pids = "[0],[" + pid0 + "],[" + pid1 + "],",
|
||||
Name = busName + "详情",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr_detail",
|
||||
Type = 2,
|
||||
Permission = className + ":detail",
|
||||
Application = "busapp",
|
||||
}.InsertAsync();
|
||||
|
||||
// 按钮-add
|
||||
var menuType2_2 = new SysMenu
|
||||
{
|
||||
Pid = pid1,
|
||||
Pids = "[0],[" + pid0 + "],[" + pid1 + "],",
|
||||
Name = busName + "增加",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr_add",
|
||||
Type = 2,
|
||||
Permission = className + ":add",
|
||||
Application = "busapp",
|
||||
}.InsertAsync();
|
||||
|
||||
// 按钮-delete
|
||||
var menuType2_3 = new SysMenu
|
||||
{
|
||||
Pid = pid1,
|
||||
Pids = "[0],[" + pid0 + "],[" + pid1 + "],",
|
||||
Name = busName + "删除",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr_delete",
|
||||
Type = 2,
|
||||
Permission = className + ":delete",
|
||||
Application = "busapp",
|
||||
}.InsertAsync();
|
||||
|
||||
// 按钮-edit
|
||||
var menuType2_4 = new SysMenu
|
||||
{
|
||||
Pid = pid1,
|
||||
Pids = "[0],[" + pid0 + "],[" + pid1 + "],",
|
||||
Name = busName + "编辑",
|
||||
Code = "dilon_" + className.ToLower() + "_mgr_edit",
|
||||
Type = 2,
|
||||
Permission = className + ":edit",
|
||||
Application = "busapp",
|
||||
}.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取模板文件路径集合
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<string> GetTemplatePathList()
|
||||
{
|
||||
var templatePath = App.WebHostEnvironment.WebRootPath + @"\Template\";
|
||||
return new List<string>() {
|
||||
templatePath + "Service.cs.vm",
|
||||
templatePath + "IService.cs.vm",
|
||||
templatePath + "Input.cs.vm",
|
||||
templatePath + "Output.cs.vm",
|
||||
templatePath + "index.vue.vm",
|
||||
templatePath + "addForm.vue.vm",
|
||||
templatePath + "editForm.vue.vm",
|
||||
templatePath + "manage.js.vm",
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置生成文件路径
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
private List<string> GetTargetPathList(SysCodeGen input)
|
||||
{
|
||||
var backendPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.FullName + @"\Ewide.Application\Service\" + input.TableName + @"\";
|
||||
var servicePath = backendPath + input.TableName + "Service.cs";
|
||||
var iservicePath = backendPath + "I" + input.TableName + "Service.cs";
|
||||
var inputPath = backendPath + @"Dto\" + input.TableName + "Input.cs";
|
||||
var outputPath = backendPath + @"Dto\" + input.TableName + "Output.cs";
|
||||
var frontendPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName + @"\frontend\src\views\main\";
|
||||
var indexPath = frontendPath + input.TableName + @"\index.vue";
|
||||
var addFormPath = frontendPath + input.TableName + @"\addForm.vue";
|
||||
var editFormPath = frontendPath + input.TableName + @"\editForm.vue";
|
||||
var apiJsPath = new DirectoryInfo(App.WebHostEnvironment.ContentRootPath).Parent.Parent.FullName + @"\frontend\src\api\modular\main\" + input.TableName + "Manage.js";
|
||||
|
||||
return new List<string>() {
|
||||
servicePath,
|
||||
iservicePath,
|
||||
inputPath,
|
||||
outputPath,
|
||||
indexPath,
|
||||
addFormPath,
|
||||
editFormPath,
|
||||
apiJsPath
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成详细配置参数
|
||||
/// </summary>
|
||||
public class CodeGenConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 代码生成主表ID
|
||||
/// </summary>
|
||||
public string CodeGenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库字段名
|
||||
/// </summary>
|
||||
public string ColumnName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字段描述
|
||||
/// </summary>
|
||||
public string ColumnComment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// .NET类型
|
||||
/// </summary>
|
||||
public string NetType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 作用类型(字典)
|
||||
/// </summary>
|
||||
public string EffectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字典code
|
||||
/// </summary>
|
||||
public string DictTypeCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列表是否缩进(字典)
|
||||
/// </summary>
|
||||
public string WhetherRetract { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否必填(字典)
|
||||
/// </summary>
|
||||
public string WhetherRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否是查询条件
|
||||
/// </summary>
|
||||
public string QueryWhether { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询方式
|
||||
/// </summary>
|
||||
public string QueryType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列表显示
|
||||
/// </summary>
|
||||
public string WhetherTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 增改
|
||||
/// </summary>
|
||||
public string WhetherAddUpdate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主外键
|
||||
/// </summary>
|
||||
public string ColumnKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库中类型(物理类型)
|
||||
/// </summary>
|
||||
public string DataType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否是通用字段
|
||||
/// </summary>
|
||||
public string WhetherCommon { get; set; }
|
||||
}
|
||||
}
|
||||
124
20220330_Vote/Ewide.Core/Service/CodeGen/Dto/CodeGenInput.cs
Normal file
124
20220330_Vote/Ewide.Core/Service/CodeGen/Dto/CodeGenInput.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成参数类
|
||||
/// </summary>
|
||||
public class CodeGenInput : InputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 作者姓名
|
||||
/// </summary>
|
||||
public virtual string AuthorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类名
|
||||
/// </summary>
|
||||
public virtual string ClassName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否移除表前缀
|
||||
/// </summary>
|
||||
public virtual string TablePrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成方式
|
||||
/// </summary>
|
||||
public virtual string GenerateType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库表名
|
||||
/// </summary>
|
||||
public virtual string TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间
|
||||
/// </summary>
|
||||
public virtual string NameSpace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务名(业务代码包名称)
|
||||
/// </summary>
|
||||
public virtual string BusName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能名(数据库表名称)
|
||||
/// </summary>
|
||||
public virtual string TableComment { get; set; }
|
||||
}
|
||||
|
||||
public class AddCodeGenInput : CodeGenInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库表名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "数据库表名不能为空")]
|
||||
public override string TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务名(业务代码包名称)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "业务名不能为空")]
|
||||
public override string BusName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命名空间
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "命名空间不能为空")]
|
||||
public override string NameSpace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 作者姓名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "作者姓名不能为空")]
|
||||
public override string AuthorName { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 类名
|
||||
///// </summary>
|
||||
//[Required(ErrorMessage = "类名不能为空")]
|
||||
//public override string ClassName { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 是否移除表前缀
|
||||
///// </summary>
|
||||
//[Required(ErrorMessage = "是否移除表前缀不能为空")]
|
||||
//public override string TablePrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成方式
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "生成方式不能为空")]
|
||||
public override string GenerateType { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 功能名(数据库表名称)
|
||||
///// </summary>
|
||||
//[Required(ErrorMessage = "数据库表名不能为空")]
|
||||
//public override string TableComment { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteCodeGenInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成器Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "代码生成器Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateCodeGenInput : CodeGenInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成器Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "代码生成器Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryCodeGenInput : DeleteCodeGenInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成参数类
|
||||
/// </summary>
|
||||
public class CodeGenOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 代码生成器Id
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 作者姓名
|
||||
/// </summary>
|
||||
public string AuthorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类名
|
||||
/// </summary>
|
||||
public string ClassName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否移除表前缀
|
||||
/// </summary>
|
||||
public string TablePrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成方式
|
||||
/// </summary>
|
||||
public string GenerateType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库表名
|
||||
/// </summary>
|
||||
public string TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包名
|
||||
/// </summary>
|
||||
public string PackageName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务名(业务代码包名称)
|
||||
/// </summary>
|
||||
public string BusName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 功能名(数据库表名称)
|
||||
/// </summary>
|
||||
public string TableComment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库表列
|
||||
/// </summary>
|
||||
public class TableColumnOuput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字段名
|
||||
/// </summary>
|
||||
public string ColumnName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库中类型
|
||||
/// </summary>
|
||||
public string DataType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字段描述
|
||||
/// </summary>
|
||||
public string ColumnComment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主外键
|
||||
/// </summary>
|
||||
public string ColumnKey { get; set; }
|
||||
}
|
||||
}
|
||||
28
20220330_Vote/Ewide.Core/Service/CodeGen/Dto/TableOutput.cs
Normal file
28
20220330_Vote/Ewide.Core/Service/CodeGen/Dto/TableOutput.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据库表列表参数
|
||||
/// </summary>
|
||||
public class TableOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 表名(字母形式的)
|
||||
/// </summary>
|
||||
public string TableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public string CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public string UpdateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 表名称描述(注释)(功能名)
|
||||
/// </summary>
|
||||
public string TableComment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ICodeGenConfigService
|
||||
{
|
||||
Task Add(CodeGenConfig input);
|
||||
void AddList(List<TableColumnOuput> tableColumnOuputList, SysCodeGen codeGenerate);
|
||||
string ConvertDataType(string dataType);
|
||||
Task Delete(string codeGenId);
|
||||
Task<SysCodeGenConfig> Detail(CodeGenConfig input);
|
||||
Task<List<CodeGenConfig>> List([FromQuery] CodeGenConfig input);
|
||||
Task Update(List<CodeGenConfig> inputList);
|
||||
}
|
||||
}
|
||||
18
20220330_Vote/Ewide.Core/Service/CodeGen/ICodeGenService.cs
Normal file
18
20220330_Vote/Ewide.Core/Service/CodeGen/ICodeGenService.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.CodeGen
|
||||
{
|
||||
public interface ICodeGenService
|
||||
{
|
||||
Task AddCodeGen(AddCodeGenInput input);
|
||||
Task DeleteCodeGen(List<DeleteCodeGenInput> inputs);
|
||||
Task<SysCodeGen> GetCodeGen([FromQuery] QueryCodeGenInput input);
|
||||
List<TableColumnOuput> GetColumnList(AddCodeGenInput input);
|
||||
List<TableOutput> GetTableList();
|
||||
Task<dynamic> QueryCodeGenPageList([FromQuery] CodeGenInput input);
|
||||
void RunLocal(SysCodeGen input);
|
||||
Task UpdateCodeGen(UpdateCodeGenInput input);
|
||||
}
|
||||
}
|
||||
83
20220330_Vote/Ewide.Core/Service/Config/Dto/ConfigInput.cs
Normal file
83
20220330_Vote/Ewide.Core/Service/Config/Dto/ConfigInput.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数配置
|
||||
/// </summary>
|
||||
public class ConfigInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 属性值
|
||||
/// </summary>
|
||||
public virtual string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否是系统参数(Y-是,N-否)
|
||||
/// </summary>
|
||||
public virtual string SysFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public virtual string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public virtual int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 常量所属分类的编码,来自于“常量的分类”字典
|
||||
/// </summary>
|
||||
public virtual string GroupCode { get; set; }
|
||||
}
|
||||
|
||||
public class AddConfigInput : ConfigInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "参数名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "参数编码不能为空")]
|
||||
public override string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteConfigInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "参数Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateConfigInput : AddConfigInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryConfigInput : DeleteConfigInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
18
20220330_Vote/Ewide.Core/Service/Config/ISysConfigService.cs
Normal file
18
20220330_Vote/Ewide.Core/Service/Config/ISysConfigService.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysConfigService
|
||||
{
|
||||
Task AddConfig(AddConfigInput input);
|
||||
Task DeleteConfig(DeleteConfigInput input);
|
||||
Task<SysConfig> GetConfig([FromQuery] QueryConfigInput input);
|
||||
Task<dynamic> GetConfigList([FromQuery] ConfigInput input);
|
||||
Task<dynamic> QueryConfigPageList([FromQuery] ConfigInput input);
|
||||
Task UpdateConfig(UpdateConfigInput input);
|
||||
Task<bool> GetDemoEnvFlag();
|
||||
Task<bool> GetCaptchaOpenFlag();
|
||||
Task UpdateConfigCache(string code, object value);
|
||||
}
|
||||
}
|
||||
175
20220330_Vote/Ewide.Core/Service/Config/SysConfigService.cs
Normal file
175
20220330_Vote/Ewide.Core/Service/Config/SysConfigService.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统参数配置服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Config", Order = 100)]
|
||||
public class SysConfigService : ISysConfigService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysConfig> _sysConfigRep; // 参数配置表仓储
|
||||
private readonly ISysCacheService _sysCacheService;
|
||||
|
||||
public SysConfigService(IRepository<SysConfig> sysConfigRep, ISysCacheService sysCacheService)
|
||||
{
|
||||
_sysConfigRep = sysConfigRep;
|
||||
_sysCacheService = sysCacheService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页获取系统参数配置
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysConfig/page")]
|
||||
public async Task<dynamic> QueryConfigPageList([FromBody] ConfigInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
var groupCode = !string.IsNullOrEmpty(input.GroupCode?.Trim());
|
||||
var configs = await _sysConfigRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
|
||||
(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")),
|
||||
(groupCode, u => EF.Functions.Like(u.Code, $"%{input.GroupCode.Trim()}%")))
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.GroupCode)
|
||||
.ToPageData(input);
|
||||
return PageDataResult<SysConfig>.PageResult(configs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统参数配置列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysConfig/list")]
|
||||
public async Task<dynamic> GetConfigList([FromQuery] ConfigInput input)
|
||||
{
|
||||
return await _sysConfigRep.DetachedEntities.Where(u => u.Status != CommonStatus.DELETED).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加系统参数配置
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysConfig/add")]
|
||||
public async Task AddConfig(AddConfigInput input)
|
||||
{
|
||||
var isExist = await _sysConfigRep.DetachedEntities.AnyAsync(u => u.Name == input.Name || u.Code == input.Code);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D9000);
|
||||
|
||||
var config = input.Adapt<SysConfig>();
|
||||
await config.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除系统参数配置
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysConfig/delete")]
|
||||
public async Task DeleteConfig(DeleteConfigInput input)
|
||||
{
|
||||
var config = await _sysConfigRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
// 禁止删除系统参数
|
||||
if (config.SysFlag == YesOrNot.Y.ToString())
|
||||
throw Oops.Oh(ErrorCode.D9001);
|
||||
|
||||
await config.DeleteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新系统参数配置
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysConfig/edit")]
|
||||
public async Task UpdateConfig(UpdateConfigInput input)
|
||||
{
|
||||
var isExist = await _sysConfigRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D9000);
|
||||
|
||||
var config = input.Adapt<SysConfig>();
|
||||
await config.UpdateAsync(ignoreNullValues: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统参数配置
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysConfig/detail")]
|
||||
public async Task<SysConfig> GetConfig([FromQuery] QueryConfigInput input)
|
||||
{
|
||||
return await _sysConfigRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置信息
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<dynamic> GetConfigCache(string code)
|
||||
{
|
||||
var value = await _sysCacheService.GetAsync(code);
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
var config = await _sysConfigRep.DetachedEntities.FirstOrDefaultAsync(u => u.Code == code);
|
||||
value = config != null ? config.Value : "";
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAsync(code, value);
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新配置缓存
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateConfigCache(string code, object value)
|
||||
{
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetAsync(code, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取演示环境开关是否开启,默认为false
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<bool> GetDemoEnvFlag()
|
||||
{
|
||||
var value = await GetConfigCache("DILON_DEMO_ENV_FLAG");
|
||||
return bool.Parse(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证码开关标识
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GetCaptchaOpenFlag()
|
||||
{
|
||||
var value = await GetConfigCache("DILON_CAPTCHA_OPEN");
|
||||
return bool.Parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictDataInput.cs
Normal file
99
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictDataInput.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using Furion.DataValidation;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典值参数
|
||||
/// </summary>
|
||||
public class DictDataInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型Id
|
||||
/// </summary>
|
||||
public virtual string TypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public virtual string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 扩展编码
|
||||
/// </summary>
|
||||
public virtual string ExtCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public virtual int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public virtual string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public virtual CommonStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public class QueryDictDataListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型Id不能为空")]
|
||||
public string TypeId { get; set; }
|
||||
}
|
||||
|
||||
public class AddDictDataInput : DictDataInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型Id不能为空")]
|
||||
public override string TypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典值不能为空")]
|
||||
public override string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典值编码不能为空")]
|
||||
public override string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteDictDataInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典值Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典值Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateDictDataInput : AddDictDataInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典值Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典值Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryDictDataInput : DeleteDictDataInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
13
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictDataOutput.cs
Normal file
13
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictDataOutput.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典值参数
|
||||
/// </summary>
|
||||
public class DictDataOutput : DictDataInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典Id
|
||||
/// </summary>
|
||||
public virtual string Id { get; set; }
|
||||
}
|
||||
}
|
||||
108
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictTreeOutput.cs
Normal file
108
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictTreeOutput.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型与字典值构造的树
|
||||
/// </summary>
|
||||
public class DictTreeOutput : ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string Pid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码-对应字典值的编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称-对应字典值的value
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { set; get; }
|
||||
/// <summary>
|
||||
/// 子节点集合
|
||||
/// </summary>
|
||||
public List<DictTreeOutput> Children { get; set; } = new List<DictTreeOutput>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return Pid;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<DictTreeOutput>)children;
|
||||
}
|
||||
}
|
||||
|
||||
public class DictTreeNode : ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序,越小优先级越高
|
||||
/// </summary>
|
||||
public int Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<DictTreeNode> Children { get; set; } = new List<DictTreeNode>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return ParentId;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<DictTreeNode>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
98
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictTypeInput.cs
Normal file
98
20220330_Vote/Ewide.Core/Service/Dict/Dto/DictTypeInput.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型参数
|
||||
/// </summary>
|
||||
public class DictTypeInput : PageInputBase
|
||||
{
|
||||
public string Pid { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
public int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public virtual int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public virtual string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public virtual CommonStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public class AddDictTypeInput : DictTypeInput
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string Pid { get; set; }
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public override string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteDictTypeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 编号Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateDictTypeInput : AddDictTypeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class DropDownDictTypeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型编码不能为空")]
|
||||
public string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DropDownDictTypesInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "字典类型编码不能为空")]
|
||||
public string[] Code { get; set; }
|
||||
}
|
||||
|
||||
public class QueryDictTypeInfoInput : DeleteDictTypeInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
23
20220330_Vote/Ewide.Core/Service/Dict/Dto/EnumDictOutput.cs
Normal file
23
20220330_Vote/Ewide.Core/Service/Dict/Dto/EnumDictOutput.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Dict.Dto
|
||||
{
|
||||
public class EnumDictOutput
|
||||
{
|
||||
public string FullName { get; set; }
|
||||
public string Desc { get; set; }
|
||||
public string Code { get; set; }
|
||||
public List<EnumDictData> Datas { get; set; }
|
||||
}
|
||||
|
||||
public class EnumDictData
|
||||
{
|
||||
public string Desc { get; set; }
|
||||
public string Code { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
20
20220330_Vote/Ewide.Core/Service/Dict/ISysDictDataService.cs
Normal file
20
20220330_Vote/Ewide.Core/Service/Dict/ISysDictDataService.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysDictDataService
|
||||
{
|
||||
Task AddDictData(AddDictDataInput input);
|
||||
Task ChangeDictDataStatus(UpdateDictDataInput input);
|
||||
Task DeleteByTypeId(string dictTypeId);
|
||||
Task DeleteDictData(DeleteDictDataInput input);
|
||||
Task<dynamic> GetDictData([FromQuery] QueryDictDataInput input);
|
||||
Task<dynamic> GetDictDataList([FromQuery] QueryDictDataListInput input);
|
||||
Task<dynamic> GetDictDataListByDictTypeId(string dictTypeId);
|
||||
Task<dynamic> GetDictDataListByDictTypeIds(SysDictType[] dictTypes);
|
||||
Task<dynamic> QueryDictDataPageList([FromQuery] DictDataInput input);
|
||||
Task DeleteDictDataBatch(string[] Ids);
|
||||
Task UpdateDictData(UpdateDictDataInput input);
|
||||
}
|
||||
}
|
||||
22
20220330_Vote/Ewide.Core/Service/Dict/ISysDictTypeService.cs
Normal file
22
20220330_Vote/Ewide.Core/Service/Dict/ISysDictTypeService.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Ewide.Core.Service.Dict.Dto;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysDictTypeService
|
||||
{
|
||||
Task AddDictType(AddDictTypeInput input);
|
||||
Task ChangeDictTypeStatus(UpdateDictTypeInput input);
|
||||
Task DeleteDictType(DeleteDictTypeInput input);
|
||||
Task<List<DictTreeNode>> GetDictTree();
|
||||
Task<dynamic> GetDictType([FromQuery] QueryDictTypeInfoInput input);
|
||||
Task<dynamic> GetDictTypeDropDown([FromQuery] DropDownDictTypeInput input);
|
||||
Task<dynamic> GetDictTypeDropDowns([FromQuery] DropDownDictTypesInput input);
|
||||
Task<dynamic> GetDictTypeList();
|
||||
Task<dynamic> QueryDictTypePageList([FromQuery] DictTypeInput input);
|
||||
Task UpdateDictType(UpdateDictTypeInput input);
|
||||
Task<List<EnumDictOutput>> GetEnumDictDataList([FromQuery] DictTypeInput input);
|
||||
}
|
||||
}
|
||||
231
20220330_Vote/Ewide.Core/Service/Dict/SysDictDataService.cs
Normal file
231
20220330_Vote/Ewide.Core/Service/Dict/SysDictDataService.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典值服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "DictData", Order = 100)]
|
||||
public class SysDictDataService : ISysDictDataService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysDictData> _sysDictDataRep; // 字典类型表仓储
|
||||
private readonly IRepository<SysDictType> _sysDictTypeRep;
|
||||
public SysDictDataService(IRepository<SysDictData> sysDictDataRep, IRepository<SysDictType> sysDictTypeRep)
|
||||
{
|
||||
_sysDictTypeRep = sysDictTypeRep;
|
||||
_sysDictDataRep = sysDictDataRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询字典值
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/page")]
|
||||
public async Task<dynamic> QueryDictDataPageList([FromBody] DictDataInput input)
|
||||
{
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
var value = !string.IsNullOrEmpty(input.Value?.Trim());
|
||||
var dictDatas = await _sysDictDataRep.DetachedEntities
|
||||
.Where(u => u.TypeId == input.TypeId)
|
||||
.Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")),
|
||||
(value, u => EF.Functions.Like(u.Value, $"%{input.Value.Trim()}%")))
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
|
||||
//.Select(u => u.Adapt<DictDataOutput>())
|
||||
// .ToPagedListAsync(input.PageNo, input.PageSize)
|
||||
.ToPageData<SysDictData, DictDataOutput>(input);
|
||||
return PageDataResult<DictDataOutput>.PageResult(dictDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取某个字典类型下字典值列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictData/list")]
|
||||
public async Task<dynamic> GetDictDataList([FromQuery] QueryDictDataListInput input)
|
||||
{
|
||||
return await _sysDictDataRep.DetachedEntities.Where(u => u.TypeId == input.TypeId).Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加字典值
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/add")]
|
||||
public async Task AddDictData(AddDictDataInput input)
|
||||
{
|
||||
var isExist = await _sysDictDataRep.AnyAsync(u => (u.Code == input.Code || u.Value == input.Value) && u.TypeId == input.TypeId, false);
|
||||
if (isExist) throw Oops.Oh(ErrorCode.D3003);
|
||||
//datatype 的code 为null 则不能添加
|
||||
var dataType = _sysDictTypeRep.Where(s => s.Id == input.TypeId).FirstOrDefault();
|
||||
if (string.IsNullOrEmpty(dataType.Code)) throw Oops.Oh("此处类型不能添加数据");
|
||||
|
||||
input.ExtCode = CheckExtCode(input.ExtCode);
|
||||
|
||||
var dictData = input.Adapt<SysDictData>();
|
||||
await _sysDictDataRep.InsertAsync(dictData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除字典值
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/delete")]
|
||||
public async Task DeleteDictData(DeleteDictDataInput input)
|
||||
{
|
||||
var dictData = await _sysDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (dictData == null) throw Oops.Oh(ErrorCode.D3004);
|
||||
|
||||
await dictData.DeleteAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除字典值 id数组传入
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/deleteBatch")]
|
||||
public async Task DeleteDictDataBatch([FromBody] string[] ids)
|
||||
{
|
||||
var dictDataList = await _sysDictDataRep.Where(s => ids.Contains(s.Id)).ToListAsync();
|
||||
if (dictDataList.Count == 0) throw Oops.Oh(ErrorCode.D3004);
|
||||
dictDataList.ForEach(s =>
|
||||
{
|
||||
s.DeleteAsync();
|
||||
});
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新字典值
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/edit")]
|
||||
public async Task UpdateDictData(UpdateDictDataInput input)
|
||||
{
|
||||
var isExist = await _sysDictDataRep.AnyAsync(u => u.Id == input.Id, false);
|
||||
if (!isExist) throw Oops.Oh(ErrorCode.D3004);
|
||||
|
||||
// 排除自己并且判断与其他是否相同
|
||||
isExist = await _sysDictDataRep.AnyAsync(u => (u.Value == input.Value || u.Code == input.Code) && u.TypeId == input.TypeId && u.Id != input.Id, false);
|
||||
if (isExist) throw Oops.Oh(ErrorCode.D3003);
|
||||
|
||||
input.ExtCode = CheckExtCode(input.ExtCode);
|
||||
|
||||
var dictData = input.Adapt<SysDictData>();
|
||||
await _sysDictDataRep.UpdateAsync(dictData, ignoreNullValues: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字典值详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictData/detail")]
|
||||
public async Task<dynamic> GetDictData([FromQuery] QueryDictDataInput input)
|
||||
{
|
||||
return await _sysDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改字典值状态
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictData/changeStatus")]
|
||||
public async Task ChangeDictDataStatus(UpdateDictDataInput input)
|
||||
{
|
||||
var dictData = await _sysDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (dictData == null) throw Oops.Oh(ErrorCode.D3004);
|
||||
|
||||
if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
|
||||
throw Oops.Oh(ErrorCode.D3005);
|
||||
dictData.Status = input.Status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据字典类型Id获取字典值集合
|
||||
/// </summary>
|
||||
/// <param name="dictTypeId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<dynamic> GetDictDataListByDictTypeId(string dictTypeId)
|
||||
{
|
||||
return await _sysDictDataRep.DetachedEntities.Where(u => u.SysDictType.Id == dictTypeId)
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
|
||||
.Select(u => new
|
||||
{
|
||||
u.Code,
|
||||
u.Value,
|
||||
ExtCode = String.IsNullOrEmpty(u.ExtCode) ? null : Newtonsoft.Json.JsonConvert.DeserializeObject<object>(u.ExtCode),
|
||||
u.Remark
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public async Task<dynamic> GetDictDataListByDictTypeIds(SysDictType[] dictTypes)
|
||||
{
|
||||
var dictTypeIds = dictTypes.Select(u => u.Id);
|
||||
var dictData = await _sysDictDataRep.DetachedEntities.Where(u => dictTypeIds.Contains(u.SysDictType.Id))
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
|
||||
.ToListAsync();
|
||||
var result = new Dictionary<string, dynamic>();
|
||||
foreach (var dictType in dictTypes)
|
||||
{
|
||||
result.Add(dictType.Code, dictData.Where(u => u.TypeId == dictType.Id)
|
||||
.Select(u => new
|
||||
{
|
||||
u.Code,
|
||||
u.Value,
|
||||
ExtCode = String.IsNullOrEmpty(u.ExtCode) ? null : Newtonsoft.Json.JsonConvert.DeserializeObject<object>(u.ExtCode),
|
||||
u.Remark
|
||||
}));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除字典下所有值
|
||||
/// </summary>
|
||||
/// <param name="dictTypeId"></param>
|
||||
[NonAction]
|
||||
public async Task DeleteByTypeId(string dictTypeId)
|
||||
{
|
||||
var dictDatas = await _sysDictDataRep.Where(u => u.TypeId == dictTypeId).ToListAsync();
|
||||
dictDatas.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
private string CheckExtCode(string extCode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(extCode))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (extCode.StartsWith('{') && extCode.EndsWith('}'))
|
||||
{
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject(Newtonsoft.Json.JsonConvert.DeserializeObject(extCode));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
250
20220330_Vote/Ewide.Core/Service/Dict/SysDictTypeService.cs
Normal file
250
20220330_Vote/Ewide.Core/Service/Dict/SysDictTypeService.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Ewide.Core.Service.Dict.Dto;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典类型服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "DictType", Order = 100)]
|
||||
public class SysDictTypeService : ISysDictTypeService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysDictType> _sysDictTypeRep; // 字典类型表仓储
|
||||
private readonly ISysDictDataService _sysDictDataService;
|
||||
|
||||
public SysDictTypeService(ISysDictDataService sysDictDataService,
|
||||
IRepository<SysDictType> sysDictTypeRep)
|
||||
{
|
||||
_sysDictDataService = sysDictDataService;
|
||||
_sysDictTypeRep = sysDictTypeRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询字典类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictType/page")]
|
||||
public async Task<dynamic> QueryDictTypePageList([FromBody] DictTypeInput input)
|
||||
{
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var pId = !string.IsNullOrEmpty(input.Pid?.Trim());
|
||||
var type = input.Type > 0;
|
||||
var dictTypes = await _sysDictTypeRep.DetachedEntities
|
||||
.Where(pId, u => EF.Functions.Like(u.Pids, $"%[{input.Pid.Trim()}]%") || u.Id == input.Pid.Trim())
|
||||
.Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")),
|
||||
(name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
|
||||
.Where(type, u => input.Type == 1 ? string.IsNullOrEmpty(u.Code) : !string.IsNullOrEmpty(u.Code))
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
|
||||
//.ToPagedListAsync(input.PageNo, input.PageSize);
|
||||
.ToPageData(input);
|
||||
return PageDataResult<SysDictType>.PageResult(dictTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字典类型列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictType/list")]
|
||||
public async Task<dynamic> GetDictTypeList()
|
||||
{
|
||||
return await _sysDictTypeRep.DetachedEntities.Where(u => u.Status != CommonStatus.DELETED).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取字典类型下所有字典值
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictType/dropDown")]
|
||||
public async Task<dynamic> GetDictTypeDropDown([FromQuery] DropDownDictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Code == input.Code, false);
|
||||
if (dictType == null) throw Oops.Oh(ErrorCode.D3000);
|
||||
return await _sysDictDataService.GetDictDataListByDictTypeId(dictType.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictType/dropDowns")]
|
||||
public async Task<dynamic> GetDictTypeDropDowns([FromQuery] DropDownDictTypesInput input)
|
||||
{
|
||||
var dictTypes = await _sysDictTypeRep.Where(u => input.Code.Contains(u.Code), false).ToArrayAsync();
|
||||
if (dictTypes.Length == 0) throw Oops.Oh(ErrorCode.D3000);
|
||||
return await _sysDictDataService.GetDictDataListByDictTypeIds(dictTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加字典类型
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictType/add")]
|
||||
public async Task AddDictType(AddDictTypeInput input)
|
||||
{
|
||||
var isExist = await _sysDictTypeRep.AnyAsync(u => u.Name == input.Name, false);
|
||||
if (isExist) throw Oops.Oh(ErrorCode.D3001);
|
||||
var dictTypeEntity = _sysDictTypeRep.Where(s => s.Id == input.Pid).FirstOrDefault();
|
||||
if (dictTypeEntity != null && dictTypeEntity.Code != null) throw new Exception("此类型下不能添加子类型");
|
||||
var dictType = input.Adapt<SysDictType>();
|
||||
dictType.Pids = await CreateNewPids(input.Pid);
|
||||
if (input.Code == string.Empty) dictType.Code = null;
|
||||
await _sysDictTypeRep.InsertAsync(dictType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除字典类型
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictType/delete")]
|
||||
public async Task DeleteDictType(DeleteDictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (dictType == null) throw Oops.Oh(ErrorCode.D3000);
|
||||
|
||||
var dictDatas = await _sysDictDataService.GetDictDataListByDictTypeId(input.Id); //_sysDictDataService.DeleteByTypeId(input.Id);
|
||||
if (dictDatas != null && dictDatas.Count > 0) throw Oops.Oh(ErrorCode.D3002);
|
||||
|
||||
await dictType.DeleteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新字典类型
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictType/edit"),]
|
||||
public async Task UpdateDictType(UpdateDictTypeInput input)
|
||||
{
|
||||
var isExist = await _sysDictTypeRep.AnyAsync(u => u.Id == input.Id, false);
|
||||
if (!isExist) throw Oops.Oh(ErrorCode.D3000);
|
||||
|
||||
if (input.Id == input.Pid) throw Oops.Oh(ErrorCode.D4006);
|
||||
|
||||
// 排除自己并且判断与其他是否相同
|
||||
isExist = await _sysDictTypeRep.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id, false);
|
||||
if (isExist) throw Oops.Oh(ErrorCode.D3001);
|
||||
|
||||
var dictType = input.Adapt<SysDictType>();
|
||||
dictType.Pids = await CreateNewPids(input.Pid);
|
||||
dictType.Code = input.Code == string.Empty ? null : input.Code;
|
||||
await dictType.UpdateIncludeAsync(new string[] { nameof(SysDictType.Pid), nameof(SysDictType.Pids), nameof(SysDictType.Name), nameof(SysDictType.Code), nameof(SysDictType.Sort), nameof(SysDictType.Remark) }, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字典类型详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysDictType/detail")]
|
||||
public async Task<dynamic> GetDictType([FromQuery] QueryDictTypeInfoInput input)
|
||||
{
|
||||
return await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新字典类型状态
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysDictType/changeStatus")]
|
||||
public async Task ChangeDictTypeStatus(UpdateDictTypeInput input)
|
||||
{
|
||||
var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (dictType == null) throw Oops.Oh(ErrorCode.D3000);
|
||||
|
||||
if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
|
||||
throw Oops.Oh(ErrorCode.D3005);
|
||||
dictType.Status = input.Status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字典类型与字典值构造的字典树
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpGet("/sysDictType/tree")]
|
||||
public async Task<List<DictTreeNode>> GetDictTree()
|
||||
{
|
||||
var DictTypeList = await _sysDictTypeRep.AsQueryable().Where(p => string.IsNullOrEmpty(p.Code)).ToListAsync();
|
||||
return new TreeBuildUtil<DictTreeNode>().DoTreeBuild(DictTypeList
|
||||
.OrderBy(s => s.Sort)
|
||||
.Select(u => new DictTreeNode
|
||||
{
|
||||
Title = u.Name,
|
||||
ParentId = u.Pid,
|
||||
Id = u.Id,
|
||||
Value = u.Id
|
||||
}).ToList());
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建Pids格式
|
||||
/// 如果pid是0顶级节点,pids就是 [0];
|
||||
/// 如果pid不是顶级节点,pids就是 pid菜单的 pids + [pid] + ,
|
||||
/// </summary>
|
||||
/// <param name="pid"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> CreateNewPids(string pid)
|
||||
{
|
||||
if (pid.Equals(System.Guid.Empty.ToString()))
|
||||
{
|
||||
return "[" + System.Guid.Empty + "],";
|
||||
}
|
||||
else
|
||||
{
|
||||
var dtype = await _sysDictTypeRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == pid);
|
||||
return dtype.Pids + "[" + pid + "],";
|
||||
}
|
||||
}
|
||||
[HttpGet("/sysDictType/enumDictList")]
|
||||
public Task<List<EnumDictOutput>> GetEnumDictDataList([FromQuery] DictTypeInput input)
|
||||
{
|
||||
var typeList = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsEnum);
|
||||
typeList = typeList.Concat(Assembly.Load("Ewide.Application").GetTypes().Where(t => t.IsEnum));
|
||||
var list = new List<EnumDictOutput>();
|
||||
foreach (var type in typeList)
|
||||
{
|
||||
var dictType = new EnumDictOutput
|
||||
{
|
||||
Desc = type.GetCustomAttribute<DescriptionAttribute>()?.Description,
|
||||
FullName = type.FullName,
|
||||
Code = type.Name,
|
||||
Datas = new List<EnumDictData>(),
|
||||
};
|
||||
var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var value = field.GetValue(null);
|
||||
var dictData = new EnumDictData
|
||||
{
|
||||
Desc = field.GetCustomAttribute<DescriptionAttribute>()?.Description,
|
||||
Code = field.Name,
|
||||
Value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())).ToString(),
|
||||
};
|
||||
dictType.Datas.Add(dictData);
|
||||
}
|
||||
list.Add(dictType);
|
||||
}
|
||||
return Task.FromResult(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 附属机构和职位参数
|
||||
/// </summary>
|
||||
public class EmpExtOrgPosOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 附属机构id
|
||||
/// </summary>
|
||||
public string OrgId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属机构编码
|
||||
/// </summary>
|
||||
public string OrgCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属机构名称
|
||||
/// </summary>
|
||||
public string OrgName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属职位id
|
||||
/// </summary>
|
||||
public string PosId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属职位编码
|
||||
/// </summary>
|
||||
public string PosCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属职位名称
|
||||
/// </summary>
|
||||
public string PosName { get; set; }
|
||||
}
|
||||
}
|
||||
35
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpOutput.cs
Normal file
35
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpOutput.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工信息参数
|
||||
/// </summary>
|
||||
public class EmpOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 工号
|
||||
/// </summary>
|
||||
public string JobNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构id
|
||||
/// </summary>
|
||||
public string OrgId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构名称
|
||||
/// </summary>
|
||||
public string OrgName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构与职位信息
|
||||
/// </summary>
|
||||
public List<EmpExtOrgPosOutput> ExtOrgPos { get; set; } = new List<EmpExtOrgPosOutput>();
|
||||
|
||||
/// <summary>
|
||||
/// 职位信息
|
||||
/// </summary>
|
||||
public List<EmpPosOutput> Positions { get; set; } = new List<EmpPosOutput>();
|
||||
}
|
||||
}
|
||||
40
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpOutput2.cs
Normal file
40
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpOutput2.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工信息参数2
|
||||
/// </summary>
|
||||
public class EmpOutput2
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工号
|
||||
/// </summary>
|
||||
public string JobNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构Id
|
||||
/// </summary>
|
||||
public string OrgId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构名称
|
||||
/// </summary>
|
||||
public string OrgName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附属机构
|
||||
/// </summary>
|
||||
public List<EmpExtOrgPosOutput> ExtIds { get; set; } = new List<EmpExtOrgPosOutput>();
|
||||
|
||||
/// <summary>
|
||||
/// 职位集合
|
||||
/// </summary>
|
||||
public List<string> PosIdList { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
23
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpPosOutput.cs
Normal file
23
20220330_Vote/Ewide.Core/Service/Emp/Dto/EmpPosOutput.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工职位参数
|
||||
/// </summary>
|
||||
public class EmpPosOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 职位Id
|
||||
/// </summary>
|
||||
public string PosId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 职位编码
|
||||
/// </summary>
|
||||
public string PosCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 职位名称
|
||||
/// </summary>
|
||||
public string PosName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysEmpExtOrgPosService
|
||||
{
|
||||
Task AddOrUpdate(string empId, List<EmpExtOrgPosOutput> extIdList);
|
||||
Task DeleteEmpExtInfoByUserId(string empId);
|
||||
Task<List<EmpExtOrgPosOutput>> GetEmpExtOrgPosList(string empId);
|
||||
Task<bool> HasExtOrgEmp(string orgId);
|
||||
Task<bool> HasExtPosEmp(string posId);
|
||||
}
|
||||
}
|
||||
13
20220330_Vote/Ewide.Core/Service/Emp/ISysEmpPosService.cs
Normal file
13
20220330_Vote/Ewide.Core/Service/Emp/ISysEmpPosService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysEmpPosService
|
||||
{
|
||||
Task AddOrUpdate(string empId, List<string> posIdList);
|
||||
Task DeleteEmpPosInfoByUserId(string empId);
|
||||
Task<List<EmpPosOutput>> GetEmpPosList(string empId);
|
||||
Task<bool> HasPosEmp(string posId);
|
||||
}
|
||||
}
|
||||
14
20220330_Vote/Ewide.Core/Service/Emp/ISysEmpService.cs
Normal file
14
20220330_Vote/Ewide.Core/Service/Emp/ISysEmpService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysEmpService
|
||||
{
|
||||
Task AddOrUpdate(EmpOutput2 sysEmpParam);
|
||||
Task DeleteEmpInfoByUserId(string empId);
|
||||
Task<EmpOutput> GetEmpInfo(string empId);
|
||||
Task<string> GetEmpOrgId(string empId);
|
||||
Task<bool> HasOrgEmp(string orgId);
|
||||
Task UpdateEmpOrgInfo(string orgId, string orgName);
|
||||
}
|
||||
}
|
||||
100
20220330_Vote/Ewide.Core/Service/Emp/SysEmpExtOrgPosService.cs
Normal file
100
20220330_Vote/Ewide.Core/Service/Emp/SysEmpExtOrgPosService.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工附属机构和职位服务
|
||||
/// </summary>
|
||||
public class SysEmpExtOrgPosService : ISysEmpExtOrgPosService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysEmpExtOrgPos> _sysEmpExtOrgPosRep; // 附属机构表仓储
|
||||
|
||||
public SysEmpExtOrgPosService(IRepository<SysEmpExtOrgPos> sysEmpExtOrgPosRep)
|
||||
{
|
||||
_sysEmpExtOrgPosRep = sysEmpExtOrgPosRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存或编辑附属机构相关信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task AddOrUpdate(string empId, List<EmpExtOrgPosOutput> extIdList)
|
||||
{
|
||||
// 先删除
|
||||
await DeleteEmpExtInfoByUserId(empId);
|
||||
|
||||
var tasks = new List<Task>();
|
||||
extIdList.ForEach(u =>
|
||||
{
|
||||
tasks.Add(new SysEmpExtOrgPos
|
||||
{
|
||||
SysEmpId = empId,
|
||||
SysOrgId = u.OrgId,
|
||||
SysPosId = u.PosId
|
||||
}.InsertAsync());
|
||||
});
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取附属机构和职位信息
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<EmpExtOrgPosOutput>> GetEmpExtOrgPosList(string empId)
|
||||
{
|
||||
return await _sysEmpExtOrgPosRep.DetachedEntities
|
||||
.Where(u => u.SysEmpId == empId)
|
||||
.Select(u => new EmpExtOrgPosOutput
|
||||
{
|
||||
OrgId = u.SysOrg.Id,
|
||||
OrgCode = u.SysOrg.Code,
|
||||
OrgName = u.SysOrg.Name,
|
||||
PosId = u.SysPos.Id,
|
||||
PosCode = u.SysPos.Code,
|
||||
PosName = u.SysPos.Name
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据机构Id判断该附属机构下是否有员工
|
||||
/// </summary>
|
||||
/// <param name="orgId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> HasExtOrgEmp(string orgId)
|
||||
{
|
||||
return await _sysEmpExtOrgPosRep.DetachedEntities.AnyAsync(u => u.SysOrgId == orgId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据职位Id判断该附属职位下是否有员工
|
||||
/// </summary>
|
||||
/// <param name="posId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> HasExtPosEmp(string posId)
|
||||
{
|
||||
return await _sysEmpExtOrgPosRep.DetachedEntities.AnyAsync(u => u.SysPosId == posId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据员工Id删除对应的员工-附属信息
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteEmpExtInfoByUserId(string empId)
|
||||
{
|
||||
var empExtOrgPos = await _sysEmpExtOrgPosRep.Where(u => u.SysEmpId == empId).ToListAsync();
|
||||
empExtOrgPos.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
85
20220330_Vote/Ewide.Core/Service/Emp/SysEmpPosService.cs
Normal file
85
20220330_Vote/Ewide.Core/Service/Emp/SysEmpPosService.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工职位服务
|
||||
/// </summary>
|
||||
public class SysEmpPosService : ISysEmpPosService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysEmpPos> _sysEmpPosRep; // 员工职位表仓储
|
||||
|
||||
public SysEmpPosService(IRepository<SysEmpPos> sysEmpPosRep)
|
||||
{
|
||||
_sysEmpPosRep = sysEmpPosRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加或编辑员工职位相关信息
|
||||
/// </summary>
|
||||
/// <param name="empId">员工Id(用户Id)</param>
|
||||
/// <param name="posIdList">职位id集合</param>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task AddOrUpdate(string empId, List<string> posIdList)
|
||||
{
|
||||
// 先删除
|
||||
await DeleteEmpPosInfoByUserId(empId);
|
||||
|
||||
posIdList.ForEach(u =>
|
||||
{
|
||||
new SysEmpPos
|
||||
{
|
||||
SysEmpId = empId,
|
||||
SysPosId = u
|
||||
}.Insert();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所属职位信息
|
||||
/// </summary>
|
||||
/// <param name="empId">员工Id(用户Id)</param>
|
||||
public async Task<List<EmpPosOutput>> GetEmpPosList(string empId)
|
||||
{
|
||||
return await _sysEmpPosRep.DetachedEntities
|
||||
.Where(u => u.SysEmpId == empId)
|
||||
.Select(u => new EmpPosOutput
|
||||
{
|
||||
PosId = u.SysPos.Id,
|
||||
PosCode = u.SysPos.Code,
|
||||
PosName = u.SysPos.Name
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据职位Id判断该职位下是否有员工
|
||||
/// </summary>
|
||||
/// <param name="posId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> HasPosEmp(string posId)
|
||||
{
|
||||
return await _sysEmpPosRep.DetachedEntities.AnyAsync(u => u.SysPosId == posId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据员工Id删除对用的员工-职位信息
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteEmpPosInfoByUserId(string empId)
|
||||
{
|
||||
var empPos = await _sysEmpPosRep.Where(u => u.SysEmpId == empId).ToListAsync();
|
||||
empPos.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
126
20220330_Vote/Ewide.Core/Service/Emp/SysEmpService.cs
Normal file
126
20220330_Vote/Ewide.Core/Service/Emp/SysEmpService.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 员工服务
|
||||
/// </summary>
|
||||
public class SysEmpService : ISysEmpService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysEmp> _sysEmpRep; // 员工表仓储
|
||||
|
||||
private readonly ISysEmpExtOrgPosService _sysEmpExtOrgPosService;
|
||||
private readonly ISysEmpPosService _sysEmpPosService;
|
||||
|
||||
public SysEmpService(IRepository<SysEmp> sysEmpRep,
|
||||
ISysEmpExtOrgPosService sysEmpExtOrgPosService,
|
||||
ISysEmpPosService sysEmpPosService)
|
||||
{
|
||||
_sysEmpRep = sysEmpRep;
|
||||
_sysEmpExtOrgPosService = sysEmpExtOrgPosService;
|
||||
_sysEmpPosService = sysEmpPosService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户员工相关信息(包括登录)
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<EmpOutput> GetEmpInfo(string empId)
|
||||
{
|
||||
var empInfoOutput = new EmpOutput();
|
||||
var sysEmp = await _sysEmpRep.FirstOrDefaultAsync(u => u.Id == empId, false);
|
||||
if (sysEmp == null) return empInfoOutput;
|
||||
|
||||
empInfoOutput = sysEmp.Adapt<EmpOutput>();
|
||||
empInfoOutput.ExtOrgPos = await _sysEmpExtOrgPosService.GetEmpExtOrgPosList(empId);
|
||||
empInfoOutput.Positions = await _sysEmpPosService.GetEmpPosList(empId);
|
||||
return empInfoOutput;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加或编辑员工相关信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task AddOrUpdate(EmpOutput2 sysEmpParam)
|
||||
{
|
||||
// 先删除员工信息
|
||||
var emps = await _sysEmpRep.Where(u => u.Id == sysEmpParam.Id).ToListAsync();
|
||||
emps.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
// 再新增新员工信息
|
||||
var emp = sysEmpParam.Adapt<SysEmp>();
|
||||
emp.OrgName = (await Db.GetRepository<SysOrg>().DetachedEntities.FirstOrDefaultAsync(p => p.Id.Equals(emp.OrgId))).Name;
|
||||
await _sysEmpRep.InsertAsync(emp);
|
||||
|
||||
// 更新附属机构职位信息
|
||||
await _sysEmpExtOrgPosService.AddOrUpdate(emp.Id, sysEmpParam.ExtIds);
|
||||
|
||||
// 更新职位信息
|
||||
await _sysEmpPosService.AddOrUpdate(emp.Id, sysEmpParam.PosIdList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改员工相关机构信息
|
||||
/// </summary>
|
||||
/// <param name="orgId"></param>
|
||||
/// <param name="orgName"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateEmpOrgInfo(string orgId, string orgName)
|
||||
{
|
||||
var emps = await _sysEmpRep.Where(u => u.OrgId == orgId).ToListAsync();
|
||||
emps.ForEach(u =>
|
||||
{
|
||||
u.OrgName = orgName;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据机构Id判断该机构下是否有员工
|
||||
/// </summary>
|
||||
/// <param name="orgId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> HasOrgEmp(string orgId)
|
||||
{
|
||||
return await _sysEmpRep.DetachedEntities.AnyAsync(u => u.OrgId == orgId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据员工Id删除对应的员工表信息
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task DeleteEmpInfoByUserId(string empId)
|
||||
{
|
||||
// 删除员工信息
|
||||
var emp = await _sysEmpRep.FirstOrDefaultAsync(u => u.Id == empId);
|
||||
await emp.DeleteAsync();
|
||||
|
||||
// 级联删除对应的员工-附属信息
|
||||
await _sysEmpExtOrgPosService.DeleteEmpExtInfoByUserId(empId);
|
||||
|
||||
// 级联删除对用的员工-职位信息
|
||||
await _sysEmpPosService.DeleteEmpPosInfoByUserId(empId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取员工机构Id
|
||||
/// </summary>
|
||||
/// <param name="empId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetEmpOrgId(string empId)
|
||||
{
|
||||
return (await _sysEmpRep.FirstOrDefaultAsync(u => u.Id == empId, false)).OrgId;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
20220330_Vote/Ewide.Core/Service/File/Dto/FileInput.cs
Normal file
64
20220330_Vote/Ewide.Core/Service/File/Dto/FileInput.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 上传文件参数
|
||||
/// </summary>
|
||||
public class FileInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件存储位置(1:阿里云,2:腾讯云,3:minio,4:本地)
|
||||
/// </summary>
|
||||
public int FileLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件仓库
|
||||
/// </summary>
|
||||
public string FileBucket { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称(上传时候的文件名)
|
||||
/// </summary>
|
||||
public string FileOriginName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件后缀
|
||||
/// </summary>
|
||||
public string FileSuffix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小kb
|
||||
/// </summary>
|
||||
public long FileSizeKb { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小信息,计算后的
|
||||
/// </summary>
|
||||
public string FileSizeInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 存储到bucket的名称(文件唯一标识id)
|
||||
/// </summary>
|
||||
public string FileObjectName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 存储路径
|
||||
/// </summary>
|
||||
public string FilePath { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteFileInfoInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "文件Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryFileInoInput : DeleteFileInfoInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
14
20220330_Vote/Ewide.Core/Service/File/Dto/FileOutput.cs
Normal file
14
20220330_Vote/Ewide.Core/Service/File/Dto/FileOutput.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 上传文件参数
|
||||
/// </summary>
|
||||
public class FileOutput : FileInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
public System.DateTime CreatedTime { get; set; }
|
||||
}
|
||||
}
|
||||
21
20220330_Vote/Ewide.Core/Service/File/ISysFileService.cs
Normal file
21
20220330_Vote/Ewide.Core/Service/File/ISysFileService.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysFileService
|
||||
{
|
||||
Task DeleteFileInfo(DeleteFileInfoInput input);
|
||||
Task<IActionResult> DownloadFileInfo([FromQuery] QueryFileInoInput input);
|
||||
Task<SysFile> GetFileInfo([FromQuery] QueryFileInoInput input);
|
||||
Task<List<SysFile>> GetFileInfoList([FromQuery] FileOutput input);
|
||||
Task<IActionResult> PreviewFileInfo([FromQuery] QueryFileInoInput input);
|
||||
Task<dynamic> QueryFileInfoPageList([FromQuery] FileInput input);
|
||||
Task<string> UploadFileAvatar(IFormFile file);
|
||||
Task<string> UploadFileDefault(IFormFile file);
|
||||
Task<string> UploadFileDocument(IFormFile file);
|
||||
Task<string> UploadFileShop(IFormFile file);
|
||||
}
|
||||
}
|
||||
207
20220330_Vote/Ewide.Core/Service/File/SysFileService.cs
Normal file
207
20220330_Vote/Ewide.Core/Service/File/SysFileService.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "File", Order = 100)]
|
||||
public class SysFileService : ISysFileService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysFile> _sysFileInfoRep; // 文件信息表仓储
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SysFileService(IRepository<SysFile> sysFileInfoRep, IConfiguration configuration)
|
||||
{
|
||||
_sysFileInfoRep = sysFileInfoRep;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页获取文件列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysFileInfo/page")]
|
||||
public async Task<dynamic> QueryFileInfoPageList([FromBody] FileInput input)
|
||||
{
|
||||
var fileBucket = !string.IsNullOrEmpty(input.FileBucket?.Trim());
|
||||
var fileOriginName = !string.IsNullOrEmpty(input.FileOriginName?.Trim());
|
||||
var files = await _sysFileInfoRep.DetachedEntities
|
||||
.Where(input.FileLocation > 0, u => u.FileLocation == input.FileLocation)
|
||||
.Where(fileBucket, u => EF.Functions.Like(u.FileBucket, $"%{input.FileBucket.Trim()}%"))
|
||||
.Where(fileOriginName, u => EF.Functions.Like(u.FileOriginName, $"%{input.FileOriginName.Trim()}%"))
|
||||
.ToPageData<SysFile, FileOutput>(input);
|
||||
return PageDataResult<FileOutput>.PageResult(files);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysFileInfo/list")]
|
||||
public async Task<List<SysFile>> GetFileInfoList([FromQuery] FileOutput input)
|
||||
{
|
||||
return await _sysFileInfoRep.DetachedEntities.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除文件
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysFileInfo/delete")]
|
||||
public async Task DeleteFileInfo(DeleteFileInfoInput input)
|
||||
{
|
||||
var file = await _sysFileInfoRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (file != null)
|
||||
{
|
||||
await file.DeleteAsync();
|
||||
|
||||
var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, file.FileBucket, file.FileObjectName);
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysFileInfo/detail")]
|
||||
public async Task<SysFile> GetFileInfo([FromQuery] QueryFileInoInput input)
|
||||
{
|
||||
var file = await _sysFileInfoRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (file == null)
|
||||
throw Oops.Oh(ErrorCode.D8000);
|
||||
return file;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 预览文件
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysFileInfo/preview")]
|
||||
public async Task<IActionResult> PreviewFileInfo([FromQuery] QueryFileInoInput input)
|
||||
{
|
||||
return await DownloadFileInfo(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysFileInfo/upload")]
|
||||
public async Task<string> UploadFileDefault(IFormFile file)
|
||||
{
|
||||
return await UploadFile(file, _configuration["UploadFile:Default:path"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysFileInfo/download")]
|
||||
public async Task<IActionResult> DownloadFileInfo([FromQuery] QueryFileInoInput input)
|
||||
{
|
||||
var file = await GetFileInfo(input);
|
||||
var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, file.FileBucket, file.FileObjectName);
|
||||
var fileName = HttpUtility.UrlEncode(file.FileOriginName, Encoding.GetEncoding("UTF-8"));
|
||||
return new FileStreamResult(new FileStream(filePath, FileMode.Open), Util.MimeMapping.GetMimeMapping(filePath)) { FileDownloadName = fileName };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传头像
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> UploadFileAvatar(IFormFile file)
|
||||
{
|
||||
return await UploadFile(file, _configuration["UploadFile:Avatar:path"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文档
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> UploadFileDocument(IFormFile file)
|
||||
{
|
||||
return await UploadFile(file, _configuration["UploadFile:Document:path"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传商店图片
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> UploadFileShop(IFormFile file)
|
||||
{
|
||||
return await UploadFile(file, _configuration["UploadFile:Shop:path"]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="pathType"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task<string> UploadFile(IFormFile file, string pathType)
|
||||
{
|
||||
var fileId = Guid.NewGuid().ToString();
|
||||
|
||||
var fileSizeKb = (long)(file.Length / 1024.0); // 文件大小KB
|
||||
var originalFilename = file.FileName; // 文件原始名称
|
||||
var fileSuffix = Path.GetExtension(file.FileName).ToLower(); // 文件后缀
|
||||
var finalName = fileId + fileSuffix; // 生成文件的最终名称
|
||||
|
||||
var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, pathType);
|
||||
if (!Directory.Exists(filePath))
|
||||
Directory.CreateDirectory(filePath);
|
||||
|
||||
using (var stream = File.Create(Path.Combine(filePath, finalName)))
|
||||
{
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var sysFileInfo = new SysFile
|
||||
{
|
||||
Id = fileId,
|
||||
FileLocation = (int)FileLocation.LOCAL,
|
||||
FileBucket = pathType,
|
||||
FileObjectName = finalName,
|
||||
FileOriginName = originalFilename,
|
||||
FileSuffix = fileSuffix.TrimStart('.'),
|
||||
FileSizeKb = fileSizeKb
|
||||
};
|
||||
await sysFileInfo.InsertAsync();
|
||||
|
||||
return fileId;
|
||||
}
|
||||
}
|
||||
}
|
||||
95
20220330_Vote/Ewide.Core/Service/Log/Dto/OpLogInput.cs
Normal file
95
20220330_Vote/Ewide.Core/Service/Log/Dto/OpLogInput.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求日志参数
|
||||
/// </summary>
|
||||
public class OpLogInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作类型(0其他 1增加 2删除 3编辑)(见LogAnnotionOpTypeEnum)
|
||||
/// </summary>
|
||||
public int? OpType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否执行成功(Y-是,N-否)
|
||||
/// </summary>
|
||||
public bool? Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 具体消息
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ip
|
||||
/// </summary>
|
||||
public string Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 浏览器
|
||||
/// </summary>
|
||||
public string Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作系统
|
||||
/// </summary>
|
||||
public string Os { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求地址
|
||||
/// </summary>
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类名称
|
||||
/// </summary>
|
||||
public string ClassName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方法名称
|
||||
/// </summary>
|
||||
public string MethodName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求方式(GET POST PUT DELETE)
|
||||
/// </summary>
|
||||
public string ReqMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求参数
|
||||
/// </summary>
|
||||
public string Param { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回结果
|
||||
/// </summary>
|
||||
public string Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 耗时(毫秒)
|
||||
/// </summary>
|
||||
public long ElapsedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作时间
|
||||
/// </summary>
|
||||
public DateTime OpTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人
|
||||
/// </summary>
|
||||
public string Account { get; set; }
|
||||
}
|
||||
}
|
||||
10
20220330_Vote/Ewide.Core/Service/Log/Dto/OpLogOutput.cs
Normal file
10
20220330_Vote/Ewide.Core/Service/Log/Dto/OpLogOutput.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求日志参数
|
||||
/// </summary>
|
||||
public class OpLogOutput : OpLogInput
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
||||
60
20220330_Vote/Ewide.Core/Service/Log/Dto/VisLogInput.cs
Normal file
60
20220330_Vote/Ewide.Core/Service/Log/Dto/VisLogInput.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 访问日志参数
|
||||
/// </summary>
|
||||
public class VisLogInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否执行成功(Y-是,N-否)
|
||||
/// </summary>
|
||||
public bool? Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 具体消息
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// IP
|
||||
/// </summary>
|
||||
public string Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 浏览器
|
||||
/// </summary>
|
||||
public string Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作系统
|
||||
/// </summary>
|
||||
public string Os { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访问类型(字典 1登入 2登出)
|
||||
/// </summary>
|
||||
public int? VisType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访问时间
|
||||
/// </summary>
|
||||
public DateTime VisTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访问人
|
||||
/// </summary>
|
||||
public string Account { get; set; }
|
||||
}
|
||||
}
|
||||
10
20220330_Vote/Ewide.Core/Service/Log/Dto/VisLogOutput.cs
Normal file
10
20220330_Vote/Ewide.Core/Service/Log/Dto/VisLogOutput.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 访问日志参数
|
||||
/// </summary>
|
||||
public class VisLogOutput : VisLogInput
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
||||
11
20220330_Vote/Ewide.Core/Service/Log/ISysOpLogService.cs
Normal file
11
20220330_Vote/Ewide.Core/Service/Log/ISysOpLogService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysOpLogService
|
||||
{
|
||||
Task ClearOpLog();
|
||||
Task<dynamic> QueryOpLogPageList([FromQuery] OpLogInput input);
|
||||
}
|
||||
}
|
||||
11
20220330_Vote/Ewide.Core/Service/Log/ISysVisLogService.cs
Normal file
11
20220330_Vote/Ewide.Core/Service/Log/ISysVisLogService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysVisLogService
|
||||
{
|
||||
Task ClearVisLog();
|
||||
Task<dynamic> QueryVisLogPageList([FromQuery] VisLogInput input);
|
||||
}
|
||||
}
|
||||
63
20220330_Vote/Ewide.Core/Service/Log/SysOpLogService.cs
Normal file
63
20220330_Vote/Ewide.Core/Service/Log/SysOpLogService.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Dapper;
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作日志服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "OpLog", Order = 100)]
|
||||
public class SysOpLogService : ISysOpLogService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysLogOp> _sysOpLogRep; // 操作日志表仓储
|
||||
private readonly IDapperRepository<SysLogOp> _dapperRepository;
|
||||
|
||||
public SysOpLogService(IRepository<SysLogOp> sysOpLogRep, IDapperRepository<SysLogOp> dapperRepository)
|
||||
{
|
||||
_sysOpLogRep = sysOpLogRep;
|
||||
_dapperRepository = dapperRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询操作日志
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOpLog/page")]
|
||||
public async Task<dynamic> QueryOpLogPageList([FromBody] OpLogInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var success = input.Success.HasValue;
|
||||
var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim());
|
||||
var opLogs = await _sysOpLogRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
|
||||
.Where(input.OpType > 0, u => u.OpType == input.OpType)
|
||||
.Where(success, u => u.Success == input.Success.Value)
|
||||
.Where(searchBeginTime, u => u.OpTime >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
|
||||
u.OpTime <= DateTime.Parse(input.SearchEndTime.Trim()))
|
||||
.ToPageData<SysLogOp, OpLogOutput>(input);
|
||||
return PageDataResult<OpLogOutput>.PageResult(opLogs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空操作日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOpLog/delete")]
|
||||
public async Task ClearOpLog()
|
||||
{
|
||||
await _dapperRepository.ExecuteAsync("DELETE FROM sys_log_op");
|
||||
}
|
||||
}
|
||||
}
|
||||
63
20220330_Vote/Ewide.Core/Service/Log/SysVisLogService.cs
Normal file
63
20220330_Vote/Ewide.Core/Service/Log/SysVisLogService.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 访问日志服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "VisLog", Order = 100)]
|
||||
public class SysVisLogService : ISysVisLogService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysLogVis> _sysVisLogRep; // 访问日志表仓储
|
||||
|
||||
public SysVisLogService(IRepository<SysLogVis> sysVisLogRep)
|
||||
{
|
||||
_sysVisLogRep = sysVisLogRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询访问日志
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysVisLog/page")]
|
||||
public async Task<dynamic> QueryVisLogPageList([FromBody] VisLogInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var success = input.Success.HasValue;
|
||||
var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim());
|
||||
var visLogs = await _sysVisLogRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
|
||||
.Where(input.VisType > 0, u => u.VisType == input.VisType)
|
||||
.Where(success, u => u.Success == input.Success.Value)
|
||||
.Where(searchBeginTime, u => u.VisTime >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
|
||||
u.VisTime <= DateTime.Parse(input.SearchEndTime.Trim()))
|
||||
.ToPageData<SysLogVis, VisLogOutput>(input);
|
||||
return PageDataResult<VisLogOutput>.PageResult(visLogs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空访问日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysVisLog/delete")]
|
||||
public async Task ClearVisLog()
|
||||
{
|
||||
var visLogs = await _sysVisLogRep.Entities.ToListAsync();
|
||||
visLogs.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录菜单-AntDesign菜单类型
|
||||
/// </summary>
|
||||
public class AntDesignTreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父id
|
||||
/// </summary>
|
||||
public string Pid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由名称, 必须设置,且不能重名
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件
|
||||
/// </summary>
|
||||
public string Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重定向地址, 访问这个路由时, 自定进行重定向
|
||||
/// </summary>
|
||||
public string Redirect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由元信息(路由附带扩展信息)
|
||||
/// </summary>
|
||||
public Meta Meta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路径
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 控制路由和子路由是否显示在 sidebar
|
||||
/// </summary>
|
||||
public bool Hidden { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式
|
||||
/// </summary>
|
||||
public int OpenType { get; set; }
|
||||
|
||||
public string Application { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路由元信息内部类
|
||||
/// </summary>
|
||||
public class Meta
|
||||
{
|
||||
/// <summary>
|
||||
/// 路由标题, 用于显示面包屑, 页面标题 *推荐设置
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可见
|
||||
/// </summary>
|
||||
public bool Show { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 如需外部打开,增加:_blank
|
||||
/// </summary>
|
||||
public string Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内链打开http链接
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
}
|
||||
}
|
||||
148
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuInput.cs
Normal file
148
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuInput.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单参数
|
||||
/// </summary>
|
||||
public class MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public virtual string Pid { get; set; } = System.Guid.Empty.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||
/// </summary>
|
||||
public virtual int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由地址
|
||||
/// </summary>
|
||||
public virtual string Router { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 组件地址
|
||||
/// </summary>
|
||||
public virtual string Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限标识
|
||||
/// </summary>
|
||||
public virtual string Permission { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用分类(应用编码)
|
||||
/// </summary>
|
||||
public virtual string Application { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||
/// </summary>
|
||||
public virtual int OpenType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可见(Y-是,N-否)
|
||||
/// </summary>
|
||||
public bool Visible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内链地址
|
||||
/// </summary>
|
||||
public string Link { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重定向地址
|
||||
/// </summary>
|
||||
public string Redirect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权重(字典 1系统权重 2业务权重)
|
||||
/// </summary>
|
||||
public string Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定上级菜单显示
|
||||
/// </summary>
|
||||
public bool VisibleParent { get; set; }
|
||||
}
|
||||
|
||||
public class AddMenuInput : MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单类型不能为空")]
|
||||
public override int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "打开方式不能为空")]
|
||||
public override int OpenType { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteMenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateMenuInput : AddMenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "菜单Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>DeleteMenuInput
|
||||
[Required(ErrorMessage = "父级菜单Id不能为空")]
|
||||
public override string Pid { get; set; }
|
||||
}
|
||||
|
||||
public class QueryMenuInput : DeleteMenuInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ChangeAppMenuInput : MenuInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用编码
|
||||
/// </summary>DeleteMenuInput
|
||||
[Required(ErrorMessage = "应用编码不能为空")]
|
||||
public override string Application { get; set; }
|
||||
}
|
||||
}
|
||||
36
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuOutput.cs
Normal file
36
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuOutput.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单树(列表形式)
|
||||
/// </summary>
|
||||
public class MenuOutput : MenuInput, ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<MenuOutput> Children { get; set; } = new List<MenuOutput>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return Pid;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<MenuOutput>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuTreeOutput.cs
Normal file
76
20220330_Vote/Ewide.Core/Service/Menu/Dto/MenuTreeOutput.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 菜单树---授权、新增编辑时选择
|
||||
/// </summary>
|
||||
public class MenuTreeOutput : ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单类型
|
||||
/// </summary>
|
||||
public int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联显示父级
|
||||
/// </summary>
|
||||
public bool VisibleParent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 权限标识
|
||||
/// </summary>
|
||||
public string Permission { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序,越小优先级越高
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<MenuTreeOutput> Children { get; set; } = new List<MenuTreeOutput>();
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return ParentId;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<MenuTreeOutput>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
20220330_Vote/Ewide.Core/Service/Menu/ISysMenuService.cs
Normal file
22
20220330_Vote/Ewide.Core/Service/Menu/ISysMenuService.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysMenuService
|
||||
{
|
||||
Task AddMenu(AddMenuInput input);
|
||||
Task<List<AntDesignTreeNode>> ChangeAppMenu(ChangeAppMenuInput input);
|
||||
Task DeleteMenu(DeleteMenuInput input);
|
||||
Task<List<AntDesignTreeNode>> GetLoginMenusAntDesign(string userId, string appCode);
|
||||
Task<List<string>> GetLoginPermissionList(string userId);
|
||||
Task<dynamic> GetMenu(QueryMenuInput input);
|
||||
Task<dynamic> GetMenuList([FromQuery] MenuInput input);
|
||||
Task<dynamic> GetMenuTree([FromQuery] MenuInput input);
|
||||
Task<List<string>> GetUserMenuAppCodeList(string userId);
|
||||
Task<bool> HasMenu(string appCode);
|
||||
Task<dynamic> TreeForGrant([FromQuery] MenuInput input);
|
||||
Task UpdateMenu(UpdateMenuInput input);
|
||||
}
|
||||
}
|
||||
494
20220330_Vote/Ewide.Core/Service/Menu/SysMenuService.cs
Normal file
494
20220330_Vote/Ewide.Core/Service/Menu/SysMenuService.cs
Normal file
@@ -0,0 +1,494 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统菜单服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Menu", Order = 146)]
|
||||
public class SysMenuService : ISysMenuService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysMenu> _sysMenuRep; // 菜单表仓储
|
||||
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ISysCacheService _sysCacheService;
|
||||
private readonly ISysUserRoleService _sysUserRoleService;
|
||||
private readonly ISysRoleMenuService _sysRoleMenuService;
|
||||
|
||||
public SysMenuService(IRepository<SysMenu> sysMenuRep,
|
||||
IUserManager userManager,
|
||||
ISysCacheService sysCacheService,
|
||||
ISysUserRoleService sysUserRoleService,
|
||||
ISysRoleMenuService sysRoleMenuService)
|
||||
{
|
||||
_sysMenuRep = sysMenuRep;
|
||||
_userManager = userManager;
|
||||
_sysCacheService = sysCacheService;
|
||||
_sysUserRoleService = sysUserRoleService;
|
||||
_sysRoleMenuService = sysRoleMenuService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户权限(按钮权限标识集合)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<string>> GetLoginPermissionList(string userId)
|
||||
{
|
||||
var permissions = await _sysCacheService.GetPermission(userId); // 先从缓存里面读取
|
||||
if (permissions == null || permissions.Count < 1)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Type == (int)MenuType.FUNCTION)
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Select(u => u.Permission).ToListAsync();
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetPermission(userId, permissions); // 缓存结果
|
||||
#endif
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户AntDesign菜单集合
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<AntDesignTreeNode>> GetLoginMenusAntDesign(string userId, string appCode)
|
||||
{
|
||||
var antDesignTreeNodes = await _sysCacheService.GetMenu(userId, appCode); // 先从缓存里面读取
|
||||
if (antDesignTreeNodes == null || antDesignTreeNodes.Count < 1)
|
||||
{
|
||||
var sysMenuList = new List<SysMenu>();
|
||||
// 管理员则展示所有系统权重菜单,不能展示业务权重菜单
|
||||
if (_userManager.SuperAdmin)
|
||||
{
|
||||
sysMenuList = await _sysMenuRep.DetachedEntities
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Application == appCode)
|
||||
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||
.Where(u => u.Weight != (int)MenuWeight.DEFAULT_WEIGHT)
|
||||
.OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非管理员则获取自己角色所拥有的菜单集合
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
sysMenuList = await _sysMenuRep.DetachedEntities
|
||||
.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Application == appCode)
|
||||
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||
.OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
// 转换成登录菜单
|
||||
antDesignTreeNodes = sysMenuList.Select(u => new AntDesignTreeNode
|
||||
{
|
||||
Id = u.Id,
|
||||
Pid = u.Pid,
|
||||
Name = u.Code,
|
||||
Component = u.Component,
|
||||
Redirect = u.Redirect,
|
||||
Link = u.Link,
|
||||
OpenType = u.OpenType,
|
||||
Meta = new Meta
|
||||
{
|
||||
Title = u.Name,
|
||||
Icon = u.Icon,
|
||||
Show = u.Visible,
|
||||
Link = u.Link,
|
||||
Target = u.OpenType == (int)MenuOpenType.OUTER ? "_blank" : ""
|
||||
},
|
||||
Application = u.Application
|
||||
}).ToList();
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
await _sysCacheService.SetMenu(userId, appCode, antDesignTreeNodes); // 缓存结果
|
||||
#endif
|
||||
}
|
||||
return antDesignTreeNodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户菜单所属的应用编码集合
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<string>> GetUserMenuAppCodeList(string userId)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
return await _sysMenuRep.DetachedEntities
|
||||
.Where(u => (u.Type == 2 && u.VisibleParent) || u.Type < 2)
|
||||
.Where(u => menuIdList.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Select(u => u.Application).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 系统菜单列表(树表)
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/list")]
|
||||
public async Task<dynamic> GetMenuList([FromQuery] MenuInput input)
|
||||
{
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities.Where((application, u => u.Application == input.Application.Trim()),
|
||||
(name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.Select(u => u.Adapt<MenuOutput>())
|
||||
.ToListAsync();
|
||||
return new TreeBuildUtil<MenuOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Pids格式
|
||||
/// 如果pid是0顶级节点,pids就是 [0];
|
||||
/// 如果pid不是顶级节点,pids就是 pid菜单的 pids + [pid] + ,
|
||||
/// </summary>
|
||||
/// <param name="pid"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> CreateNewPids(string pid)
|
||||
{
|
||||
if (pid.Equals(System.Guid.Empty.ToString()))
|
||||
{
|
||||
return "[" + System.Guid.Empty + "],";
|
||||
}
|
||||
else
|
||||
{
|
||||
var pmenu = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == pid);
|
||||
return pmenu.Pids + "[" + pid + "],";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加和编辑时检查参数
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
private async Task CheckMenuParam(MenuInput input)
|
||||
{
|
||||
var type = input.Type;
|
||||
var router = input.Router;
|
||||
var permission = input.Permission;
|
||||
var openType = input.OpenType;
|
||||
var isVisibleParent = input.VisibleParent;
|
||||
|
||||
if (type.Equals((int)MenuType.DIR))
|
||||
{
|
||||
//if (string.IsNullOrEmpty(router))
|
||||
// throw Oops.Oh(ErrorCode.D4001);
|
||||
}
|
||||
else if (type.Equals((int)MenuType.MENU))
|
||||
{
|
||||
//if (string.IsNullOrEmpty(router))
|
||||
// throw Oops.Oh(ErrorCode.D4001);
|
||||
//if (string.IsNullOrEmpty(openType))
|
||||
// throw Oops.Oh(ErrorCode.D4002);
|
||||
}
|
||||
else if (type.Equals((int)MenuType.FUNCTION))
|
||||
{
|
||||
if (string.IsNullOrEmpty(permission))
|
||||
throw Oops.Oh(ErrorCode.D4003);
|
||||
if (!permission.Contains(":"))
|
||||
throw Oops.Oh(ErrorCode.D4004);
|
||||
// 判断该资源是否存在
|
||||
//permission = ":" + permission;
|
||||
//var urlSet = resourceCache.getAllResources();
|
||||
//if (!urlSet.Contains(permission.Replace(":","/")))
|
||||
// throw Oops.Oh(ErrorCode.meu1005);
|
||||
}
|
||||
|
||||
// 检查上级菜单的类型是否正确
|
||||
var pid = input.Pid;
|
||||
var flag = true;
|
||||
var empty = System.Guid.Empty.ToString();
|
||||
switch(type)
|
||||
{
|
||||
// 目录必须在顶级下
|
||||
case (int)MenuType.DIR:
|
||||
flag = pid.Equals(empty);
|
||||
break;
|
||||
// 菜单必须在顶级或目录下
|
||||
case (int)MenuType.MENU:
|
||||
if (!pid.Equals(empty))
|
||||
{
|
||||
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||
flag = parent.Type.Equals((int)MenuType.DIR);
|
||||
}
|
||||
break;
|
||||
// 功能必须在菜单下
|
||||
case (int)MenuType.FUNCTION:
|
||||
{
|
||||
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||
flag = parent == null ? false : parent.Type.Equals((int)MenuType.MENU);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
throw Oops.Oh("父级菜单类型错误");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/add")]
|
||||
public async Task AddMenu(AddMenuInput input)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(input.Code))
|
||||
{
|
||||
var isExist = await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code); // u.Name == input.Name
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D4000);
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
await CheckMenuParam(input);
|
||||
|
||||
var menu = input.Adapt<SysMenu>();
|
||||
menu.Pids = await CreateNewPids(input.Pid);
|
||||
menu.Status = (int)CommonStatus.ENABLE;
|
||||
await menu.InsertAsync();
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/delete")]
|
||||
[UnitOfWork]
|
||||
public async Task DeleteMenu(DeleteMenuInput input)
|
||||
{
|
||||
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
||||
.Select(u => u.Id).ToListAsync();
|
||||
childIdList.Add(input.Id);
|
||||
|
||||
var menus = await _sysMenuRep.Where(u => childIdList.Contains(u.Id)).ToListAsync();
|
||||
menus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
// 级联删除该菜单及子菜单对应的角色-菜单表信息
|
||||
await _sysRoleMenuService.DeleteRoleMenuListByMenuIdList(childIdList);
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/edit"),]
|
||||
public async Task UpdateMenu(UpdateMenuInput input)
|
||||
{
|
||||
// Pid和Id不能一致,一致会导致无限递归
|
||||
if (input.Id == input.Pid)
|
||||
throw Oops.Oh(ErrorCode.D4006);
|
||||
|
||||
if (!string.IsNullOrEmpty(input.Code))
|
||||
{
|
||||
var isExist = await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Code == input.Code && u.Id != input.Id); // u.Name == input.Name
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D4000);
|
||||
}
|
||||
|
||||
// 校验参数
|
||||
await CheckMenuParam(input);
|
||||
// 如果是编辑,父id不能为自己的子节点
|
||||
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
||||
.Select(u => u.Id).ToListAsync();
|
||||
if (childIdList.Contains(input.Pid))
|
||||
throw Oops.Oh(ErrorCode.D4006);
|
||||
|
||||
var oldMenu = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
|
||||
// 生成新的pids
|
||||
var newPids = await CreateNewPids(input.Pid);
|
||||
|
||||
// 是否更新子应用的标识
|
||||
var updateSubAppsFlag = false;
|
||||
// 是否更新子节点的pids的标识
|
||||
var updateSubPidsFlag = false;
|
||||
|
||||
// 如果应用有变化
|
||||
if (input.Application != oldMenu.Application)
|
||||
{
|
||||
// 父节点不是根节点不能移动应用
|
||||
if (!oldMenu.Pid.Equals(System.Guid.Empty.ToString()))
|
||||
throw Oops.Oh(ErrorCode.D4007);
|
||||
updateSubAppsFlag = true;
|
||||
}
|
||||
// 父节点有变化
|
||||
if (input.Pid != oldMenu.Pid)
|
||||
updateSubPidsFlag = true;
|
||||
|
||||
// 开始更新所有子节点的配置
|
||||
if (updateSubAppsFlag || updateSubPidsFlag)
|
||||
{
|
||||
// 查找所有叶子节点,包含子节点的子节点
|
||||
var menuList = await _sysMenuRep.Where(u => EF.Functions.Like(u.Pids, $"%{oldMenu.Id}%")).ToListAsync();
|
||||
// 更新所有子节点的应用为当前菜单的应用
|
||||
if (menuList.Count > 0)
|
||||
{
|
||||
// 更新所有子节点的application
|
||||
if (updateSubAppsFlag)
|
||||
{
|
||||
menuList.ForEach(u =>
|
||||
{
|
||||
u.Application = input.Application;
|
||||
});
|
||||
}
|
||||
|
||||
// 更新所有子节点的pids
|
||||
if (updateSubPidsFlag)
|
||||
{
|
||||
menuList.ForEach(u =>
|
||||
{
|
||||
// 子节点pids组成 = 当前菜单新pids + 当前菜单id + 子节点自己的pids后缀
|
||||
var oldParentCodesPrefix = oldMenu.Pids + "[" + oldMenu.Id + "],";
|
||||
var oldParentCodesSuffix = u.Pids.Substring(oldParentCodesPrefix.Length);
|
||||
var menuParentCodes = newPids + "[" + oldMenu.Id + "]," + oldParentCodesSuffix;
|
||||
u.Pids = menuParentCodes;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新当前菜单
|
||||
oldMenu = input.Adapt<SysMenu>();
|
||||
oldMenu.Pids = newPids;
|
||||
await oldMenu.UpdateExcludeAsync(new[] { nameof(SysMenu.Type) }, ignoreNullValues: true);
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysMenu/detail")]
|
||||
public async Task<dynamic> GetMenu(QueryMenuInput input)
|
||||
{
|
||||
return await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单树,用于新增、编辑时选择上级节点
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/tree")]
|
||||
public async Task<dynamic> GetMenuTree([FromQuery] MenuInput input)
|
||||
{
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities
|
||||
.Where(application, u => u.Application == input.Application.Trim())
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(u => u.Type == (int)MenuType.DIR || u.Type == (int)MenuType.MENU)
|
||||
.OrderBy(u => u.Sort)
|
||||
.Select(u => new MenuTreeOutput
|
||||
{
|
||||
Id = u.Id,
|
||||
ParentId = u.Pid,
|
||||
Value = u.Id.ToString(),
|
||||
Title = u.Name,
|
||||
Type = u.Type,
|
||||
VisibleParent = u.VisibleParent,
|
||||
Sort = u.Sort
|
||||
}).ToListAsync();
|
||||
return new TreeBuildUtil<MenuTreeOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统菜单树,用于给角色授权时选择
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMenu/treeForGrant")]
|
||||
public async Task<dynamic> TreeForGrant([FromQuery] MenuInput input)
|
||||
{
|
||||
var menuIdList = new List<string>();
|
||||
if (_userManager.SuperAdmin)
|
||||
{
|
||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
|
||||
menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||
}
|
||||
|
||||
var application = !string.IsNullOrEmpty(input.Application?.Trim());
|
||||
var menus = await _sysMenuRep.DetachedEntities
|
||||
.Where(application, u => u.Application == input.Application.Trim())
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Where(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
|
||||
.OrderBy(u => u.Sort).Select(u => new MenuTreeOutput
|
||||
{
|
||||
Id = u.Id,
|
||||
ParentId = u.Pid,
|
||||
Value = u.Id.ToString(),
|
||||
Title = u.Name,
|
||||
Type = u.Type,
|
||||
VisibleParent = u.VisibleParent,
|
||||
Permission = u.Permission,
|
||||
Remark = u.Remark,
|
||||
Sort = u.Sort
|
||||
}).ToListAsync();
|
||||
return new TreeBuildUtil<MenuTreeOutput>().DoTreeBuild(menus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据应用编码判断该机构下是否有状态为正常的菜单
|
||||
/// </summary>
|
||||
/// <param name="appCode"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<bool> HasMenu(string appCode)
|
||||
{
|
||||
return await _sysMenuRep.DetachedEntities.AnyAsync(u => u.Application == appCode && u.Status != CommonStatus.DELETED);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据系统应用切换菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("/sysMenu/change")]
|
||||
public async Task<List<AntDesignTreeNode>> ChangeAppMenu(ChangeAppMenuInput input)
|
||||
{
|
||||
return await GetLoginMenusAntDesign(_userManager.UserId, input.Application);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
20220330_Vote/Ewide.Core/Service/Monitor/IMachineService.cs
Normal file
11
20220330_Vote/Ewide.Core/Service/Monitor/IMachineService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface IMachineService
|
||||
{
|
||||
Task<dynamic> GetMachineBaseInfo();
|
||||
Task<dynamic> GetMachineNetWorkInfo();
|
||||
Task<dynamic> GetMachineUseInfo();
|
||||
}
|
||||
}
|
||||
53
20220330_Vote/Ewide.Core/Service/Monitor/MachineService.cs
Normal file
53
20220330_Vote/Ewide.Core/Service/Monitor/MachineService.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 服务器信息服务
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
[ApiDescriptionSettings(Name = "Machine", Order = 100)]
|
||||
public class MachineService : IMachineService, IDynamicApiController, ITransient
|
||||
{
|
||||
public MachineService()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取服务器资源信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMachine/use")]
|
||||
public async Task<dynamic> GetMachineUseInfo()
|
||||
{
|
||||
var useInfo = MachineUtil.GetMachineUseInfo();
|
||||
return await Task.FromResult(useInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取服务器基本参数
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMachine/base")]
|
||||
public async Task<dynamic> GetMachineBaseInfo()
|
||||
{
|
||||
return await MachineUtil.GetMachineBaseInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态获取网络信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysMachine/network")]
|
||||
public async Task<dynamic> GetMachineNetWorkInfo()
|
||||
{
|
||||
var baseInfo = MachineUtil.GetMachineNetWorkInfo();
|
||||
return await Task.FromResult(baseInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
64
20220330_Vote/Ewide.Core/Service/Notice/Dto/NoticeBase.cs
Normal file
64
20220330_Vote/Ewide.Core/Service/Notice/Dto/NoticeBase.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知公告参数
|
||||
/// </summary>
|
||||
public class NoticeBase
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { set; get; }
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型(字典 1通知 2公告)
|
||||
/// </summary>
|
||||
public int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布人Id
|
||||
/// </summary>
|
||||
public string PublicUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布人姓名
|
||||
/// </summary>
|
||||
public string PublicUserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布机构Id
|
||||
/// </summary>
|
||||
public string PublicOrgId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布机构名称
|
||||
/// </summary>
|
||||
public string PublicOrgName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布时间
|
||||
/// </summary>
|
||||
public DateTime PublicTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 撤回时间
|
||||
/// </summary>
|
||||
public DateTime CancelTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0草稿 1发布 2撤回 3删除)
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统通知公告详情参数
|
||||
/// </summary>
|
||||
public class NoticeDetailOutput : NoticeBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知到的用户Id集合
|
||||
/// </summary>
|
||||
public List<string> NoticeUserIdList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通知到的用户阅读信息集合
|
||||
/// </summary>
|
||||
public List<NoticeUserRead> NoticeUserReadInfoList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件Id集合
|
||||
/// </summary>
|
||||
public string Attachments { set; get; }
|
||||
}
|
||||
|
||||
public class NoticeUserRead
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Id
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0未读 1已读)
|
||||
/// </summary>
|
||||
public int ReadStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅读时间
|
||||
/// </summary>
|
||||
public DateTime? ReadTime { get; set; }
|
||||
}
|
||||
}
|
||||
106
20220330_Vote/Ewide.Core/Service/Notice/Dto/NoticeInput.cs
Normal file
106
20220330_Vote/Ewide.Core/Service/Notice/Dto/NoticeInput.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知公告参数
|
||||
/// </summary>
|
||||
public class NoticeInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public virtual string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容
|
||||
/// </summary>
|
||||
public virtual string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型(字典 1通知 2公告)
|
||||
/// </summary>
|
||||
public virtual int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0草稿 1发布 2撤回 3删除)
|
||||
/// </summary>
|
||||
public virtual int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通知到的人
|
||||
/// </summary>
|
||||
public virtual List<string> NoticeUserIdList { get; set; }
|
||||
}
|
||||
|
||||
public class AddNoticeInput : NoticeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "标题不能为空")]
|
||||
public override string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "内容不能为空")]
|
||||
public override string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型(字典 1通知 2公告)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "类型不能为空")]
|
||||
public override int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0草稿 1发布 2撤回 3删除)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "状态不能为空")]
|
||||
public override int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通知到的人
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "通知到的人不能为空")]
|
||||
public override List<string> NoticeUserIdList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件集合
|
||||
/// </summary>
|
||||
public List<string> Attachments { set; get; }
|
||||
}
|
||||
|
||||
public class DeleteNoticeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "通知公告Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateNoticeInput : AddNoticeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "通知公告Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryNoticeInput : DeleteNoticeInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ChangeStatusNoticeInput : DeleteNoticeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态(字典 0草稿 1发布 2撤回 3删除)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "状态不能为空")]
|
||||
public int Status { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知公告接收参数
|
||||
/// </summary>
|
||||
public class NoticeReceiveOutput : NoticeBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 阅读状态(字典 0未读 1已读)
|
||||
/// </summary>
|
||||
public int ReadStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅读时间
|
||||
/// </summary>
|
||||
public DateTime ReadTime { get; set; }
|
||||
|
||||
public string Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
16
20220330_Vote/Ewide.Core/Service/Notice/ISysNoticeService.cs
Normal file
16
20220330_Vote/Ewide.Core/Service/Notice/ISysNoticeService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Notice
|
||||
{
|
||||
public interface ISysNoticeService
|
||||
{
|
||||
Task AddNotice(AddNoticeInput input);
|
||||
Task ChangeStatus(ChangeStatusNoticeInput input);
|
||||
Task DeleteNotice(DeleteNoticeInput input);
|
||||
Task<NoticeDetailOutput> GetNotice([FromQuery] QueryNoticeInput input);
|
||||
Task<dynamic> QueryNoticePageList([FromQuery] NoticeInput input);
|
||||
Task<dynamic> ReceivedNoticePageList([FromQuery] NoticeInput input);
|
||||
Task UpdateNotice(UpdateNoticeInput input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Notice
|
||||
{
|
||||
public interface ISysNoticeUserService
|
||||
{
|
||||
Task Add(string noticeId, List<string> noticeUserIdList, int noticeUserStatus);
|
||||
Task<List<SysNoticeUser>> GetNoticeUserListByNoticeId(string noticeId);
|
||||
Task Read(string noticeId, string userId, int status);
|
||||
Task Update(string noticeId, List<string> noticeUserIdList, int noticeUserStatus);
|
||||
}
|
||||
}
|
||||
277
20220330_Vote/Ewide.Core/Service/Notice/SysNoticeService.cs
Normal file
277
20220330_Vote/Ewide.Core/Service/Notice/SysNoticeService.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
using Dapper;
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Notice
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知公告服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Notice", Order = 100)]
|
||||
public class SysNoticeService : ISysNoticeService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysNotice> _sysNoticeRep; // 通知公告表仓储
|
||||
private readonly IRepository<SysNoticeUser> _sysNoticeUserRep; // 通知公告用户表仓储
|
||||
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly ISysNoticeUserService _sysNoticeUserService;
|
||||
|
||||
private readonly IDapperRepository _dapperRepository;
|
||||
|
||||
|
||||
public SysNoticeService(IRepository<SysNotice> sysNoticeRep,
|
||||
IRepository<SysNoticeUser> sysNoticeUserRep,
|
||||
IUserManager userManager,
|
||||
ISysNoticeUserService sysNoticeUserService, IDapperRepository dapperRepository)
|
||||
{
|
||||
_sysNoticeRep = sysNoticeRep;
|
||||
_sysNoticeUserRep = sysNoticeUserRep;
|
||||
_userManager = userManager;
|
||||
_sysNoticeUserService = sysNoticeUserService;
|
||||
|
||||
_dapperRepository = dapperRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询通知公告
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/page")]
|
||||
public async Task<dynamic> QueryNoticePageList([FromBody] NoticeInput input)
|
||||
{
|
||||
var searchValue = !string.IsNullOrEmpty(input.SearchValue?.Trim());
|
||||
var notices = await _sysNoticeRep.DetachedEntities
|
||||
.Where(searchValue, u => EF.Functions.Like(u.Title, $"%{input.SearchValue.Trim()}%") ||
|
||||
EF.Functions.Like(u.Content, $"%{input.SearchValue.Trim()}%"))
|
||||
.Where(input.Type > 0, u => u.Type == input.Type)
|
||||
.Where(u => u.Status != (int)NoticeStatus.DELETED)
|
||||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||||
return PageDataResult<SysNotice>.PageResult(notices);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加通知公告
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/add")]
|
||||
[UnitOfWork]
|
||||
public async Task AddNotice(AddNoticeInput input)
|
||||
{
|
||||
_sysNoticeRep.EnsureTransaction();
|
||||
if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC)
|
||||
throw Oops.Oh(ErrorCode.D7000);
|
||||
|
||||
var config = new TypeAdapterConfig().ForType<AddNoticeInput, SysNotice>()
|
||||
.Map(target => target.Attachments, src => String.Join(",", src.Attachments))
|
||||
.Config;
|
||||
var notice = input.Adapt<SysNotice>(config);
|
||||
var id = System.Guid.NewGuid().ToString().ToLower();
|
||||
notice.Id = id;
|
||||
await UpdatePublicInfo(notice);
|
||||
// 如果是发布,则设置发布时间
|
||||
if (input.Status == (int)NoticeStatus.PUBLIC)
|
||||
notice.PublicTime = DateTime.Now;
|
||||
await notice.InsertAsync();
|
||||
|
||||
// 通知到的人
|
||||
var noticeUserIdList = input.NoticeUserIdList;
|
||||
var noticeUserStatus = (int)NoticeUserStatus.UNREAD;
|
||||
await _sysNoticeUserService.Add(id, noticeUserIdList, noticeUserStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除通知公告
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/delete")]
|
||||
public async Task DeleteNotice(DeleteNoticeInput input)
|
||||
{
|
||||
var notice = await _sysNoticeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
if (notice.Status != (int)NoticeStatus.DRAFT && notice.Status != (int)NoticeStatus.CANCEL) // 只能删除草稿和撤回的
|
||||
throw Oops.Oh(ErrorCode.D7001);
|
||||
|
||||
//notice.Status = (int)NoticeStatus.DELETED;
|
||||
await notice.DeleteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新通知公告
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/edit")]
|
||||
public async Task UpdateNotice(UpdateNoticeInput input)
|
||||
{
|
||||
if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC)
|
||||
throw Oops.Oh(ErrorCode.D7000);
|
||||
|
||||
// 非草稿状态
|
||||
if (input.Status != (int)NoticeStatus.DRAFT)
|
||||
throw Oops.Oh(ErrorCode.D7002);
|
||||
|
||||
var notice = input.Adapt<SysNotice>();
|
||||
if (input.Attachments != null)
|
||||
notice.Attachments = string.Join(",", input.Attachments);
|
||||
if (input.Status == (int)NoticeStatus.PUBLIC)
|
||||
{
|
||||
notice.PublicTime = DateTime.Now;
|
||||
await UpdatePublicInfo(notice);
|
||||
}
|
||||
await notice.UpdateAsync(true);
|
||||
|
||||
// 通知到的人
|
||||
var noticeUserIdList = input.NoticeUserIdList;
|
||||
var noticeUserStatus = (int)NoticeUserStatus.UNREAD;
|
||||
await _sysNoticeUserService.Update(input.Id, noticeUserIdList, noticeUserStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取通知公告详情
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysNotice/detail")]
|
||||
public async Task<NoticeDetailOutput> GetNotice([FromQuery] QueryNoticeInput input)
|
||||
{
|
||||
var notice = await _sysNoticeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
|
||||
// 获取通知到的用户
|
||||
var noticeUserList = await _sysNoticeUserService.GetNoticeUserListByNoticeId(input.Id);
|
||||
var noticeUserIdList = new List<string>();
|
||||
var noticeUserReadInfoList = new List<NoticeUserRead>();
|
||||
if (noticeUserList != null)
|
||||
{
|
||||
noticeUserList.ForEach(u =>
|
||||
{
|
||||
noticeUserIdList.Add(u.UserId.ToString());
|
||||
var noticeUserRead = new NoticeUserRead
|
||||
{
|
||||
UserId = u.UserId,
|
||||
ReadStatus = u.ReadStatus,
|
||||
ReadTime = u.ReadTime
|
||||
};
|
||||
noticeUserReadInfoList.Add(noticeUserRead);
|
||||
});
|
||||
}
|
||||
var noticeResult = notice.Adapt<NoticeDetailOutput>();
|
||||
if (_userManager.SuperAdmin)
|
||||
{
|
||||
noticeResult.NoticeUserIdList = noticeUserIdList;
|
||||
noticeResult.NoticeUserReadInfoList = noticeUserReadInfoList;
|
||||
}
|
||||
// 如果该条通知公告为已发布,则将当前用户的该条通知公告设置为已读
|
||||
if (notice.Status == (int)NoticeStatus.PUBLIC)
|
||||
await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, (int)NoticeUserStatus.READ);
|
||||
return noticeResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改通知公告状态
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/changeStatus")]
|
||||
public async Task ChangeStatus(ChangeStatusNoticeInput input)
|
||||
{
|
||||
// 状态应为撤回或删除或发布
|
||||
if (input.Status != (int)NoticeStatus.CANCEL && input.Status != (int)NoticeStatus.DELETED && input.Status != (int)NoticeStatus.PUBLIC)
|
||||
throw Oops.Oh(ErrorCode.D7000);
|
||||
|
||||
var notice = await _sysNoticeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
notice.Status = input.Status;
|
||||
|
||||
if (input.Status == (int)NoticeStatus.CANCEL)
|
||||
{
|
||||
notice.CancelTime = DateTime.Now;
|
||||
}
|
||||
else if (input.Status == (int)NoticeStatus.PUBLIC)
|
||||
{
|
||||
notice.PublicTime = DateTime.Now;
|
||||
}
|
||||
await notice.UpdateAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取接收的通知公告
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysNotice/received")]
|
||||
public async Task<dynamic> ReceivedNoticePageList([FromBody] NoticeInput input)
|
||||
{
|
||||
var sql = @"SELECT
|
||||
SN.*,
|
||||
SU.Avatar,
|
||||
SNU.ReadStatus,
|
||||
SNU.ReadTime
|
||||
FROM sys_notice SN
|
||||
LEFT JOIN sys_notice_user SNU ON SN.Id = SNU.NoticeId
|
||||
LEFT JOIN sys_user SU ON SN.PublicUserId = SU.Id
|
||||
WHERE SNU.UserId = @UserId AND SN.Status = @Status";
|
||||
|
||||
var data = await _dapperRepository.QueryPageDataDynamic(
|
||||
sql,
|
||||
input,
|
||||
new
|
||||
{
|
||||
_userManager.UserId,
|
||||
Status = (int)NoticeStatus.PUBLIC
|
||||
},
|
||||
new[] { "Type", "Title", "ReadStatus" }
|
||||
);
|
||||
|
||||
data.Items = data.Items.Select(p =>
|
||||
{
|
||||
var r = p.Adapt<NoticeReceiveOutput>();
|
||||
var content = Regex.Replace(r.Content, @"<\/?.+?\/?>|[\r\n]", "");
|
||||
r.Content = content.Substring(0, content.Length > 50 ? 50 : content.Length);
|
||||
return r;
|
||||
});
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取接收到的通知公告总数
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysNotice/unread")]
|
||||
public async Task<int> GetUnreadCount()
|
||||
{
|
||||
//删除 或者 草稿 未发布 都不让显示
|
||||
var noticeList = await _sysNoticeRep.Where(u => u.Status == (int)NoticeStatus.PUBLIC).Select(s => s.Id).ToListAsync();
|
||||
return await _sysNoticeUserRep.Where(u => u.UserId == _userManager.UserId && noticeList.Contains(u.NoticeId) && u.ReadStatus == (int)NoticeUserStatus.UNREAD).CountAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新发布信息
|
||||
/// </summary>
|
||||
/// <param name="notice"></param>
|
||||
[NonAction]
|
||||
private async Task UpdatePublicInfo(SysNotice notice)
|
||||
{
|
||||
var emp = await _userManager.GetUserEmpInfo(_userManager.UserId);
|
||||
notice.PublicUserId = _userManager.UserId;
|
||||
notice.PublicUserName = _userManager.Name;
|
||||
notice.PublicOrgId = emp.OrgId;
|
||||
notice.PublicOrgName = emp.OrgName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Notice
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知公告用户
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "NoticeUser", Order = 100)]
|
||||
public class SysNoticeUserService : ISysNoticeUserService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysNoticeUser> _sysNoticeUserRep; // 通知公告用户表仓储
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IRepository<SysNotice> _sysNoticeRep;
|
||||
public SysNoticeUserService(IRepository<SysNoticeUser> sysNoticeUserRep, IUserManager userManager, IRepository<SysNotice> sysNoticeRep)
|
||||
{
|
||||
_sysNoticeUserRep = sysNoticeUserRep;
|
||||
_userManager = userManager;
|
||||
_sysNoticeRep = sysNoticeRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加
|
||||
/// </summary>
|
||||
/// <param name="noticeId"></param>
|
||||
/// <param name="noticeUserIdList"></param>
|
||||
/// <param name="noticeUserStatus"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public async Task Add(string noticeId, List<string> noticeUserIdList, int noticeUserStatus)
|
||||
{
|
||||
foreach (var u in noticeUserIdList)
|
||||
{
|
||||
await new SysNoticeUser
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
NoticeId = noticeId,
|
||||
UserId = u,
|
||||
ReadStatus = noticeUserStatus
|
||||
}.InsertAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="noticeId"></param>
|
||||
/// <param name="noticeUserIdList"></param>
|
||||
/// <param name="noticeUserStatus"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Update(string noticeId, List<string> noticeUserIdList, int noticeUserStatus)
|
||||
{
|
||||
var noticeUsers = await _sysNoticeUserRep.Where(u => u.NoticeId == noticeId).ToListAsync();
|
||||
noticeUsers.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
await Add(noticeId, noticeUserIdList, noticeUserStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取通知公告用户列表
|
||||
/// </summary>
|
||||
/// <param name="noticeId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SysNoticeUser>> GetNoticeUserListByNoticeId(string noticeId)
|
||||
{
|
||||
return await _sysNoticeUserRep.Where(u => u.NoticeId == noticeId).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置通知公告读取状态
|
||||
/// </summary>
|
||||
/// <param name="noticeId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Read(string noticeId, string userId, int status)
|
||||
{
|
||||
var noticeUser = await _sysNoticeUserRep.FirstOrDefaultAsync(u => u.NoticeId == noticeId && u.UserId == userId);
|
||||
if (noticeUser != null)
|
||||
{
|
||||
noticeUser.ReadStatus = status;
|
||||
noticeUser.ReadTime = DateTime.Now;
|
||||
await noticeUser.UpdateAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
20220330_Vote/Ewide.Core/Service/OAuth/ISysOauthService.cs
Normal file
12
20220330_Vote/Ewide.Core/Service/OAuth/ISysOauthService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.OAuth
|
||||
{
|
||||
public interface ISysOauthService
|
||||
{
|
||||
Task<dynamic> GetWechatUserInfo([FromQuery] string token, [FromQuery] string openId);
|
||||
Task WechatLogin();
|
||||
Task WechatLoginCallback([FromQuery] string code, [FromQuery] string state, [FromQuery] string error_description = "");
|
||||
}
|
||||
}
|
||||
68
20220330_Vote/Ewide.Core/Service/OAuth/SysOauthService.cs
Normal file
68
20220330_Vote/Ewide.Core/Service/OAuth/SysOauthService.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Ewide.Core.OAuth;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.OAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "OAuth", Order = 159)]
|
||||
[AllowAnonymous]
|
||||
public class SysOauthService : ISysOauthService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly HttpContext _httpContext;
|
||||
private readonly WechatOAuth _wechatOAuth;
|
||||
|
||||
public SysOauthService(IHttpContextAccessor httpContextAccessor, WechatOAuth wechatOAuth)
|
||||
{
|
||||
_httpContext = httpContextAccessor.HttpContext;
|
||||
_wechatOAuth = wechatOAuth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 微信登录授权
|
||||
/// </summary>
|
||||
[HttpGet("oauth/wechat")]
|
||||
public Task WechatLogin()
|
||||
{
|
||||
_httpContext.Response.Redirect(_wechatOAuth.GetAuthorizeUrl("Ewide"));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 微信登录授权回调
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="error_description"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("oauth/wechatcallback")]
|
||||
public async Task WechatLoginCallback([FromQuery] string code, [FromQuery] string state, [FromQuery] string error_description = "")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(error_description))
|
||||
throw Oops.Oh(error_description);
|
||||
|
||||
var accessTokenModel = await _wechatOAuth.GetAccessTokenAsync(code, state);
|
||||
//var userInfoModel = await _wechatOAuth.GetUserInfoAsync(accessTokenModel.AccessToken, accessTokenModel.OpenId);
|
||||
await _httpContext.Response.WriteAsJsonAsync(accessTokenModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取微信用户基本信息
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="openId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("oauth/wechat/user")]
|
||||
public async Task<dynamic> GetWechatUserInfo([FromQuery] string token, [FromQuery] string openId)
|
||||
{
|
||||
return await _wechatOAuth.GetUserInfoAsync(token, openId);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgInput.cs
Normal file
102
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgInput.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 组织机构参数
|
||||
/// </summary>
|
||||
public class OrgInput : InputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public virtual string Pid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Ids
|
||||
/// </summary>
|
||||
public string Pids { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构类型
|
||||
/// </summary>
|
||||
public virtual int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电话
|
||||
/// </summary>
|
||||
public virtual string Tel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
/// <summary>
|
||||
/// 机构所在区域
|
||||
/// </summary>
|
||||
public virtual string AreaCode { get; set; }
|
||||
}
|
||||
|
||||
public class AddOrgInput : OrgInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "机构名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机构所在区域
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "机构所在区域不能为空")]
|
||||
public override string AreaCode { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteOrgInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 机构Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "机构Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateOrgInput : AddOrgInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 机构Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "机构Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryOrgInput : DeleteOrgInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class PageOrgInput : OrgInput
|
||||
{
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
13
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgOutput.cs
Normal file
13
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgOutput.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 组织机构参数
|
||||
/// </summary>
|
||||
public class OrgOutput : OrgInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 机构Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
66
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgTreeNode.cs
Normal file
66
20220330_Vote/Ewide.Core/Service/Org/Dto/OrgTreeNode.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 组织机构树
|
||||
/// </summary>
|
||||
public class OrgTreeNode : ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父Id
|
||||
/// </summary>
|
||||
public string ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
public int Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序,越小优先级越高
|
||||
/// </summary>
|
||||
public int Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
/// </summary>
|
||||
public List<OrgTreeNode> Children { get; set; } = new List<OrgTreeNode>();
|
||||
|
||||
/// <summary>
|
||||
/// 上一级Id
|
||||
/// </summary>
|
||||
public long Pid { get; set; }
|
||||
|
||||
public string GetId()
|
||||
{
|
||||
return Id;
|
||||
}
|
||||
|
||||
public string GetPid()
|
||||
{
|
||||
return ParentId;
|
||||
}
|
||||
|
||||
public void SetChildren(IList children)
|
||||
{
|
||||
Children = (List<OrgTreeNode>)children;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
20220330_Vote/Ewide.Core/Service/Org/ISysOrgService.cs
Normal file
32
20220330_Vote/Ewide.Core/Service/Org/ISysOrgService.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysOrgService
|
||||
{
|
||||
Task AddOrg(AddOrgInput input);
|
||||
Task DeleteOrg(DeleteOrgInput input);
|
||||
Task<List<string>> GetDataScopeListByDataScopeType(int dataScopeType, string orgId);
|
||||
List<string> GetDataScopeList(List<string> dataScopes);
|
||||
Task<SysOrg> GetOrg([FromQuery] QueryOrgInput input);
|
||||
Task<List<OrgOutput>> GetOrgList([FromQuery] OrgInput input);
|
||||
Task<dynamic> GetOrgTree([FromQuery] OrgInput input);
|
||||
Task<dynamic> QueryOrgPageList([FromQuery] PageOrgInput input);
|
||||
Task UpdateOrg(UpdateOrgInput input);
|
||||
/// <summary>
|
||||
/// 根据区域信息获取单位id
|
||||
/// </summary>
|
||||
/// <param name="dataScopeType">代表区域范围的类型</param>
|
||||
/// <param name="areaNumberCode">区域代码</param>
|
||||
/// <returns></returns>
|
||||
Task<List<string>> GetAreaDataScopeIdList(int dataScopeType,string areaNumberCode);
|
||||
/// <summary>
|
||||
/// 当前区域信息不包括子区域
|
||||
/// </summary>
|
||||
/// <param name="areaNumberCode">区域代码</param>
|
||||
/// <returns></returns>
|
||||
Task<List<string>> GetAreaDataScopeIdListWithoutChildrenArea(string areaNumberCode);
|
||||
}
|
||||
}
|
||||
361
20220330_Vote/Ewide.Core/Service/Org/SysOrgService.cs
Normal file
361
20220330_Vote/Ewide.Core/Service/Org/SysOrgService.cs
Normal file
@@ -0,0 +1,361 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 组织机构服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Org", Order = 148)]
|
||||
public class SysOrgService : ISysOrgService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysOrg> _sysOrgRep; // 组织机构表仓储
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
private readonly ISysEmpService _sysEmpService;
|
||||
private readonly ISysEmpExtOrgPosService _sysEmpExtOrgPosService;
|
||||
private readonly ISysRoleDataScopeService _sysRoleDataScopeService;
|
||||
private readonly ISysUserDataScopeService _sysUserDataScopeService;
|
||||
|
||||
public SysOrgService(IRepository<SysOrg> sysOrgRep,
|
||||
IUserManager userManager,
|
||||
ISysEmpService sysEmpService,
|
||||
ISysEmpExtOrgPosService sysEmpExtOrgPosService,
|
||||
ISysRoleDataScopeService sysRoleDataScopeService,
|
||||
ISysUserDataScopeService sysUserDataScopeService)
|
||||
{
|
||||
_sysOrgRep = sysOrgRep;
|
||||
_userManager = userManager;
|
||||
_sysEmpService = sysEmpService;
|
||||
_sysEmpExtOrgPosService = sysEmpExtOrgPosService;
|
||||
_sysRoleDataScopeService = sysRoleDataScopeService;
|
||||
_sysUserDataScopeService = sysUserDataScopeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询组织机构
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOrg/page")]
|
||||
public async Task<dynamic> QueryOrgPageList([FromBody] PageOrgInput input)
|
||||
{
|
||||
var dataScopeList = GetDataScopeList(await _userManager.GetUserAllDataScopeList());
|
||||
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var id = !string.IsNullOrEmpty(input.Id?.Trim());
|
||||
var pId = !string.IsNullOrEmpty(input.Pid?.Trim());
|
||||
var orgs = await _sysOrgRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), // 根据机构名称模糊查询
|
||||
(id, u => u.Id == input.Id.Trim()), // 根据机构id查询
|
||||
(pId, u => input.TreeNodeDataScope.GetValueOrDefault(1) == 2 ? (EF.Functions.Like(u.Pids, $"%[{input.Pid.Trim()}]%")
|
||||
|| u.Id == input.Pid.Trim()) : u.Id == input.Pid.Trim() )) // 根据父机构id查询
|
||||
.Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id)) // 非管理员范围限制
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
|
||||
.ToPageData<SysOrg,OrgOutput>(input);
|
||||
//.Select(u => u.Adapt<OrgOutput>())
|
||||
//.ToPagedListAsync(input.PageNo, input.PageSize);
|
||||
return PageDataResult<OrgOutput>.PageResult(orgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (非管理员)获取当前用户数据范围(机构Id)
|
||||
/// </summary>
|
||||
/// <param name="dataScopes"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetDataScopeList(List<string> dataScopes)
|
||||
{
|
||||
var dataScopeList = new List<string>();
|
||||
// 如果是超级管理员则获取所有组织机构,否则只获取其数据范围的机构数据
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
if (dataScopes.Count < 1)
|
||||
return dataScopeList;
|
||||
|
||||
// 不需要去查找上级节点
|
||||
|
||||
// 此处获取所有的上级节点,用于构造完整树
|
||||
//dataScopes.ForEach(u =>
|
||||
//{
|
||||
// var sysOrg = _sysOrgRep.DetachedEntities.FirstOrDefault(c => c.Id == u);
|
||||
// var parentAndChildIdListWithSelf = sysOrg.Pids.TrimEnd(',').Replace("[", "").Replace("]", "")
|
||||
// .Split(",").ToList();
|
||||
// dataScopeList.AddRange(parentAndChildIdListWithSelf);
|
||||
//});
|
||||
|
||||
dataScopeList = dataScopes;
|
||||
}
|
||||
return dataScopeList.Distinct().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取组织机构列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysOrg/list")]
|
||||
public async Task<List<OrgOutput>> GetOrgList([FromQuery] OrgInput input)
|
||||
{
|
||||
var dataScopeList = GetDataScopeList(await _userManager.GetUserAllDataScopeList());
|
||||
|
||||
var pId = !string.IsNullOrEmpty(input.Pid?.Trim());
|
||||
var orgs = await _sysOrgRep.DetachedEntities
|
||||
.Where(pId, u => u.Pid == input.Pid)
|
||||
.Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id))
|
||||
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort).ToListAsync();
|
||||
return orgs.Adapt<List<OrgOutput>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加组织机构
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOrg/add")]
|
||||
public async Task AddOrg(AddOrgInput input)
|
||||
{
|
||||
var isExist = await _sysOrgRep.DetachedEntities
|
||||
.AnyAsync(u => (u.Pid == input.Pid && u.Name == input.Name) || (!string.IsNullOrEmpty(input.Code) && u.Code == input.Code));
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D2002);
|
||||
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
// 如果新增的机构父Id不是0,则进行数据权限校验
|
||||
if (input.Pid != "0" && !string.IsNullOrEmpty(input.Pid))
|
||||
{
|
||||
// 新增组织机构的父机构不在自己的数据范围内
|
||||
var dataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
if (dataScopes.Count < 1 || !dataScopes.Contains(input.Pid))
|
||||
throw Oops.Oh(ErrorCode.D2003);
|
||||
}
|
||||
else
|
||||
throw Oops.Oh(ErrorCode.D2003);
|
||||
}
|
||||
|
||||
var sysOrg = input.Adapt<SysOrg>();
|
||||
await FillPids(sysOrg);
|
||||
await sysOrg.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 填充父Ids字段
|
||||
/// </summary>
|
||||
/// <param name="sysOrg"></param>
|
||||
/// <returns></returns>
|
||||
private async Task FillPids(SysOrg sysOrg)
|
||||
{
|
||||
if (sysOrg.Pid.Equals(System.Guid.Empty.ToString()))
|
||||
{
|
||||
sysOrg.Pids = "[" + System.Guid.Empty + "],";
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == sysOrg.Pid);
|
||||
sysOrg.Pids = t.Pids + "[" + t.Id + "],";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除组织机构
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOrg/delete")]
|
||||
[UnitOfWork]
|
||||
public async Task DeleteOrg(DeleteOrgInput input)
|
||||
{
|
||||
var sysOrg = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
|
||||
// 检测数据范围能不能操作这个机构
|
||||
var dataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
if (!_userManager.SuperAdmin && (dataScopes.Count < 1 || !dataScopes.Contains(sysOrg.Id)))
|
||||
throw Oops.Oh(ErrorCode.D2003);
|
||||
|
||||
// 该机构下有员工,则不能删
|
||||
var hasOrgEmp = await _sysEmpService.HasOrgEmp(sysOrg.Id);
|
||||
if (hasOrgEmp)
|
||||
throw Oops.Oh(ErrorCode.D2004);
|
||||
|
||||
// 该附属机构下若有员工,则不能删
|
||||
var hasExtOrgEmp = await _sysEmpExtOrgPosService.HasExtOrgEmp(sysOrg.Id);
|
||||
if (hasExtOrgEmp)
|
||||
throw Oops.Oh(ErrorCode.D2005);
|
||||
|
||||
// 级联删除子节点
|
||||
var childIdList = await GetChildIdListWithSelfById(sysOrg.Id);
|
||||
var orgs = await _sysOrgRep.Where(u => childIdList.Contains(u.Id)).ToListAsync();
|
||||
orgs.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
// 级联删除该机构及子机构对应的角色-数据范围关联信息
|
||||
await _sysRoleDataScopeService.DeleteRoleDataScopeListByOrgIdList(childIdList);
|
||||
|
||||
// 级联删除该机构子机构对应的用户-数据范围关联信息
|
||||
await _sysUserDataScopeService.DeleteUserDataScopeListByOrgIdList(childIdList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新组织机构
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysOrg/edit")]
|
||||
[UnitOfWork]
|
||||
public async Task UpdateOrg(UpdateOrgInput input)
|
||||
{
|
||||
if (!input.Pid.Equals(System.Guid.Empty.ToString()) && !string.IsNullOrEmpty(input.Pid))
|
||||
{
|
||||
var org = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Pid);
|
||||
_ = org ?? throw Oops.Oh(ErrorCode.D2000);
|
||||
}
|
||||
if (input.Id == input.Pid)
|
||||
throw Oops.Oh(ErrorCode.D2001);
|
||||
|
||||
// 如果是编辑,父id不能为自己的子节点
|
||||
var childIdListById = await GetChildIdListWithSelfById(input.Id);
|
||||
if (childIdListById.Contains(input.Pid))
|
||||
throw Oops.Oh(ErrorCode.D2001);
|
||||
|
||||
var sysOrg = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
|
||||
// 检测数据范围能不能操作这个机构
|
||||
var dataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
if (!_userManager.SuperAdmin && (dataScopes.Count < 1 || !dataScopes.Contains(sysOrg.Id)))
|
||||
throw Oops.Oh(ErrorCode.D2003);
|
||||
|
||||
var isExist = await _sysOrgRep.DetachedEntities
|
||||
.AnyAsync(u => ((u.Pid == input.Pid && u.Name == input.Name) || (!string.IsNullOrEmpty(input.Code) && u.Code == input.Code)) && u.Id != sysOrg.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D2002);
|
||||
|
||||
// 如果名称有变化,则修改对应员工的机构相关信息
|
||||
if (!sysOrg.Name.Equals(input.Name))
|
||||
await _sysEmpService.UpdateEmpOrgInfo(sysOrg.Id, sysOrg.Name);
|
||||
|
||||
sysOrg = input.Adapt<SysOrg>();
|
||||
await FillPids(sysOrg);
|
||||
await sysOrg.UpdateAsync(ignoreNullValues: true);
|
||||
|
||||
//// 将所有子的父id进行更新
|
||||
//childIdListById.ForEach(u=> {
|
||||
// var child = _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == u.Id);
|
||||
// var newInput = child.Adapt<UpdateOrgInput>();
|
||||
// UpdateOrg(newInput).GetAwaiter();
|
||||
//});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取组织机构信息
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysOrg/detail")]
|
||||
public async Task<SysOrg> GetOrg([FromQuery] QueryOrgInput input)
|
||||
{
|
||||
return await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据节点Id获取所有子节点Id集合,包含自己
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<string>> GetChildIdListWithSelfById(string id)
|
||||
{
|
||||
var childIdList = await _sysOrgRep.DetachedEntities
|
||||
.Where(u => EF.Functions.Like(u.Pids, $"%{id}%"))
|
||||
.Select(u => u.Id).ToListAsync();
|
||||
childIdList.Add(id);
|
||||
return childIdList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取组织机构树
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysOrg/tree")]
|
||||
public async Task<dynamic> GetOrgTree([FromQuery] OrgInput input)
|
||||
{
|
||||
var dataScopeList = new List<string>();
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
var dataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
if (dataScopes.Count < 1)
|
||||
return dataScopeList;
|
||||
dataScopeList = GetDataScopeList(dataScopes);
|
||||
}
|
||||
var orgs = await _sysOrgRep.DetachedEntities.Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.Where(input.Type != 0 , u=>u.Type < input.Type)
|
||||
.Select(u => new OrgTreeNode
|
||||
{
|
||||
Id = u.Id,
|
||||
ParentId = u.Pid,
|
||||
Title = u.Name,
|
||||
Type = u.Type,
|
||||
Value = u.Id.ToString(),
|
||||
Weight = u.Sort
|
||||
}).ToListAsync();
|
||||
|
||||
return new TreeBuildUtil<OrgTreeNode>().DoTreeBuild(orgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据数据范围类型获取当前用户的数据范围(机构Id)集合
|
||||
/// </summary>
|
||||
/// <param name="dataScopeType"></param>
|
||||
/// <param name="orgId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<string>> GetDataScopeListByDataScopeType(int dataScopeType, string orgId)
|
||||
{
|
||||
var orgIdList = new List<string>();
|
||||
if (string.IsNullOrEmpty(orgId))
|
||||
return orgIdList;
|
||||
|
||||
// 如果是范围类型是全部数据,则获取当前所有的组织架构Id
|
||||
if (dataScopeType == (int)DataScopeType.ALL)
|
||||
{
|
||||
orgIdList = await _sysOrgRep.DetachedEntities.Where(u => u.Status == (int)CommonStatus.ENABLE).Select(u => u.Id).ToListAsync();
|
||||
}
|
||||
// 如果范围类型是本部门及以下部门,则查询本节点和子节点集合,包含本节点
|
||||
else if (dataScopeType == (int)DataScopeType.DEPT_WITH_CHILD)
|
||||
{
|
||||
orgIdList = await GetChildIdListWithSelfById(orgId);
|
||||
}
|
||||
// 如果数据范围是本部门,不含子节点,则直接返回本部门
|
||||
else if (dataScopeType == (int)DataScopeType.DEPT)
|
||||
{
|
||||
orgIdList.Add(orgId);
|
||||
}
|
||||
return orgIdList;
|
||||
}
|
||||
public async Task<List<string>> GetAreaDataScopeIdList(int dataScopeType, string orgId)
|
||||
{
|
||||
var org = await _sysOrgRep.FirstOrDefaultAsync(o => o.Id == orgId);
|
||||
if (dataScopeType == (int)DataScopeType.AREA_WITH_CHILD)
|
||||
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaCode.StartsWith(org.AreaCode)).Select(p => p.Id).ToListAsync();
|
||||
if (dataScopeType == (int)DataScopeType.AREA)
|
||||
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaCode == org.AreaCode).Select(p => p.Id).ToListAsync();
|
||||
return new List<string>();
|
||||
}
|
||||
public async Task<List<string>> GetAreaDataScopeIdListWithoutChildrenArea(string areaNumberCode)
|
||||
{
|
||||
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaCode == areaNumberCode).Select(p => p.Id).ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
83
20220330_Vote/Ewide.Core/Service/Pos/Dto/PosInput.cs
Normal file
83
20220330_Vote/Ewide.Core/Service/Pos/Dto/PosInput.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 职位参数
|
||||
/// </summary>
|
||||
public class PosInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态(字典 0正常 1停用 2删除)
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前页码
|
||||
/// </summary>
|
||||
public int PageNo { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 页码容量
|
||||
/// </summary>
|
||||
public int PageSize { get; set; } = 20;
|
||||
}
|
||||
|
||||
public class AddPosInput : PosInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage ="职位名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "职位编码不能为空")]
|
||||
public override string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DeletePosInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 职位Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "职位Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatePosInput : AddPosInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 职位Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "职位Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryPosInput : DeletePosInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
15
20220330_Vote/Ewide.Core/Service/Pos/ISysPosService.cs
Normal file
15
20220330_Vote/Ewide.Core/Service/Pos/ISysPosService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysPosService
|
||||
{
|
||||
Task AddPos(AddPosInput input);
|
||||
Task DeletePos(DeletePosInput input);
|
||||
Task<SysPos> GetPos([FromQuery] QueryPosInput input);
|
||||
Task<dynamic> GetPosList([FromQuery] PosInput input);
|
||||
Task<dynamic> QueryPosPageList([FromQuery] PosInput input);
|
||||
Task UpdatePos(UpdatePosInput input);
|
||||
}
|
||||
}
|
||||
132
20220330_Vote/Ewide.Core/Service/Pos/SysPosService.cs
Normal file
132
20220330_Vote/Ewide.Core/Service/Pos/SysPosService.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 职位服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Pos", Order = 147)]
|
||||
public class SysPosService : ISysPosService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysPos> _sysPosRep; // 职位表仓储
|
||||
|
||||
private readonly ISysEmpPosService _sysEmpPosService;
|
||||
private readonly ISysEmpExtOrgPosService _sysEmpExtOrgPosService;
|
||||
|
||||
public SysPosService(IRepository<SysPos> sysPosRep,
|
||||
ISysEmpPosService sysEmpPosService,
|
||||
ISysEmpExtOrgPosService sysEmpExtOrgPosService)
|
||||
{
|
||||
_sysPosRep = sysPosRep;
|
||||
_sysEmpPosService = sysEmpPosService;
|
||||
_sysEmpExtOrgPosService = sysEmpExtOrgPosService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页获取职位
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysPos/page")]
|
||||
public async Task<dynamic> QueryPosPageList([FromBody] PosInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
var pos = await _sysPosRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
|
||||
(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
|
||||
.Where(u => u.Status == CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.ToPageData(input);
|
||||
//.ToPagedListAsync(input.PageNo, input.PageSize);
|
||||
return PageDataResult<SysPos>.PageResult(pos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取职位列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysPos/list")]
|
||||
public async Task<dynamic> GetPosList([FromQuery] PosInput input)
|
||||
{
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
return await _sysPosRep.DetachedEntities.Where(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))
|
||||
.Where(u => u.Status != CommonStatus.DELETED)
|
||||
.OrderBy(u => u.Sort).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加职位
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysPos/add")]
|
||||
public async Task AddPos(AddPosInput input)
|
||||
{
|
||||
var isExist = await _sysPosRep.DetachedEntities.AnyAsync(u => u.Name == input.Name || u.Code == input.Code);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D6000);
|
||||
|
||||
var pos = input.Adapt<SysPos>();
|
||||
await pos.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除职位
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysPos/delete")]
|
||||
public async Task DeletePos(DeletePosInput input)
|
||||
{
|
||||
// 该职位下是否有员工
|
||||
var hasPosEmp = await _sysEmpPosService.HasPosEmp(input.Id);
|
||||
if (hasPosEmp)
|
||||
throw Oops.Oh(ErrorCode.D6001);
|
||||
|
||||
// 该附属职位下是否有员工
|
||||
var hasExtPosEmp = await _sysEmpExtOrgPosService.HasExtPosEmp(input.Id);
|
||||
if (hasExtPosEmp)
|
||||
throw Oops.Oh(ErrorCode.D6001);
|
||||
|
||||
var pos = await _sysPosRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
await pos.DeleteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新职位
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysPos/edit")]
|
||||
public async Task UpdatePos(UpdatePosInput input)
|
||||
{
|
||||
var isExist = await _sysPosRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D6000);
|
||||
|
||||
var pos = input.Adapt<SysPos>();
|
||||
await pos.UpdateAsync(ignoreNullValues: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取职位
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysPos/detail")]
|
||||
public async Task<SysPos> GetPos([FromQuery] QueryPosInput input)
|
||||
{
|
||||
return await _sysPosRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
20220330_Vote/Ewide.Core/Service/Role/Dto/RoleInput.cs
Normal file
91
20220330_Vote/Ewide.Core/Service/Role/Dto/RoleInput.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色参数
|
||||
/// </summary>
|
||||
public class RoleInput : InputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public virtual string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据范围类型(字典 1全部数据 2本部门及以下数据 3本部门数据 4仅本人数据 5自定义数据)
|
||||
/// </summary>
|
||||
public int DataScopeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
public class AddRoleInput : RoleInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceName = "角色名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceName = "角色编码不能为空")]
|
||||
public override string Code { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteRoleInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceName = "角色Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateRoleInput : AddRoleInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceName = "角色Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryRoleInput : DeleteRoleInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class GrantRoleMenuInput : RoleInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceName = "角色Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class GrantRoleDataInput : GrantRoleMenuInput
|
||||
{
|
||||
|
||||
}
|
||||
public class GrantAreaDataInput : GrantRoleMenuInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
23
20220330_Vote/Ewide.Core/Service/Role/Dto/RoleOutput.cs
Normal file
23
20220330_Vote/Ewide.Core/Service/Role/Dto/RoleOutput.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录用户角色参数
|
||||
/// </summary>
|
||||
public class RoleOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
16
20220330_Vote/Ewide.Core/Service/Role/ISysRoleAreaService.cs
Normal file
16
20220330_Vote/Ewide.Core/Service/Role/ISysRoleAreaService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysRoleAreaService
|
||||
{
|
||||
Task DeleteRoleAreaListByAreaCodeList(List<string> areaCodeList);
|
||||
Task DeleteRoleAreaListByRoleId(string roleId);
|
||||
Task<List<string>> GetRoleAreaCodeList(List<string> roleIdList);
|
||||
Task GrantArea(GrantAreaDataInput input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysRoleDataScopeService
|
||||
{
|
||||
Task DeleteRoleDataScopeListByOrgIdList(List<string> orgIdList);
|
||||
Task DeleteRoleDataScopeListByRoleId(string roleId);
|
||||
Task<List<string>> GetRoleDataScopeIdList(List<string> roleIdList);
|
||||
Task GrantDataScope(GrantRoleDataInput input);
|
||||
}
|
||||
}
|
||||
13
20220330_Vote/Ewide.Core/Service/Role/ISysRoleMenuService.cs
Normal file
13
20220330_Vote/Ewide.Core/Service/Role/ISysRoleMenuService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysRoleMenuService
|
||||
{
|
||||
Task DeleteRoleMenuListByMenuIdList(List<string> menuIdList);
|
||||
Task DeleteRoleMenuListByRoleId(string roleId);
|
||||
Task<List<string>> GetRoleMenuIdList(List<string> roleIdList);
|
||||
Task GrantMenu(GrantRoleMenuInput input);
|
||||
}
|
||||
}
|
||||
24
20220330_Vote/Ewide.Core/Service/Role/ISysRoleService.cs
Normal file
24
20220330_Vote/Ewide.Core/Service/Role/ISysRoleService.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysRoleService
|
||||
{
|
||||
Task AddRole(AddRoleInput input);
|
||||
Task DeleteRole(DeleteRoleInput input);
|
||||
Task<string> GetNameByRoleId(string roleId);
|
||||
Task<dynamic> GetRoleDropDown();
|
||||
Task<SysRole> GetRoleInfo([FromQuery] QueryRoleInput input);
|
||||
Task<dynamic> GetRoleList([FromQuery] RoleInput input);
|
||||
Task<List<RoleOutput>> GetUserRoleList(string userId);
|
||||
Task GrantData(GrantRoleDataInput input);
|
||||
Task GrantMenu(GrantRoleMenuInput input);
|
||||
Task<List<string>> OwnData([FromQuery] QueryRoleInput input);
|
||||
Task<List<string>> OwnMenu([FromQuery] QueryRoleInput input);
|
||||
Task<List<string>> OwnArea([FromQuery] QueryRoleInput input);
|
||||
Task<dynamic> QueryRolePageList([FromQuery] RoleInput input);
|
||||
Task UpdateRole(UpdateRoleInput input);
|
||||
}
|
||||
}
|
||||
64
20220330_Vote/Ewide.Core/Service/Role/SysRoleAreaService.cs
Normal file
64
20220330_Vote/Ewide.Core/Service/Role/SysRoleAreaService.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service.Role
|
||||
{
|
||||
public class SysRoleAreaService : ISysRoleAreaService,ITransient
|
||||
{
|
||||
public readonly IRepository<SysRoleArea> _sysRoleAreaRep;
|
||||
|
||||
public SysRoleAreaService(IRepository<SysRoleArea> sysRolleAreaRep)
|
||||
{
|
||||
_sysRoleAreaRep = sysRolleAreaRep;
|
||||
}
|
||||
|
||||
public async Task DeleteRoleAreaListByAreaCodeList(List<string> areaCodeList)
|
||||
{
|
||||
var dataScopes = await _sysRoleAreaRep.DetachedEntities.Where(u => areaCodeList.Contains(u.AreaCode)).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
public async Task DeleteRoleAreaListByRoleId(string roleId)
|
||||
{
|
||||
var dataScopes = await _sysRoleAreaRep.DetachedEntities.Where(u => roleId==u.SysRoleId).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetRoleAreaCodeList(List<string> roleIdList)
|
||||
{
|
||||
return await _sysRoleAreaRep.DetachedEntities.Where(u => roleIdList.Contains(u.SysRoleId)).Select(u=>u.AreaCode).Distinct().ToListAsync();
|
||||
|
||||
}
|
||||
|
||||
public async Task GrantArea(GrantAreaDataInput input)
|
||||
{
|
||||
var dataScopes = await _sysRoleAreaRep.Where(u => u.SysRoleId == input.Id).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
input.GrantAreaCodeList.ForEach(u =>
|
||||
{
|
||||
new SysRoleArea
|
||||
{
|
||||
SysRoleId = input.Id,
|
||||
AreaCode = u
|
||||
}.Insert();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Ewide.Core.Service.Role;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色数据范围服务
|
||||
/// </summary>
|
||||
public class SysRoleDataScopeService : ISysRoleDataScopeService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysRoleDataScope> _sysRoleDataScopeRep; // 角色数据范围表仓储
|
||||
private readonly ISysRoleAreaService _sysRoleAreaService;
|
||||
public SysRoleDataScopeService(IRepository<SysRoleDataScope> sysRoleDataScopeRep, ISysRoleAreaService sysRoleAreaService)
|
||||
{
|
||||
_sysRoleDataScopeRep = sysRoleDataScopeRep;
|
||||
_sysRoleAreaService = sysRoleAreaService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权角色数据范围
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task GrantDataScope(GrantRoleDataInput input)
|
||||
{
|
||||
if (new[] { (int)DataScopeType.AREA, (int)DataScopeType.AREA_WITH_CHILD }.Contains(input.DataScopeType))
|
||||
{
|
||||
await _sysRoleAreaService.GrantArea(input.Adapt<GrantAreaDataInput>());
|
||||
return;
|
||||
}
|
||||
var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => u.SysRoleId == input.Id).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
input.GrantOrgIdList.ForEach(u =>
|
||||
{
|
||||
new SysRoleDataScope
|
||||
{
|
||||
SysRoleId = input.Id,
|
||||
SysOrgId = u
|
||||
}.Insert();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据角色Id集合获取角色数据范围集合
|
||||
/// </summary>
|
||||
/// <param name="roleIdList"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<string>> GetRoleDataScopeIdList(List<string> roleIdList)
|
||||
{
|
||||
return await _sysRoleDataScopeRep.DetachedEntities
|
||||
.Where(u => roleIdList.Contains(u.SysRoleId))
|
||||
.Select(u => u.SysOrgId).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据机构Id集合删除对应的角色-数据范围关联信息
|
||||
/// </summary>
|
||||
/// <param name="orgIdList"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteRoleDataScopeListByOrgIdList(List<string> orgIdList)
|
||||
{
|
||||
var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => orgIdList.Contains(u.SysOrgId)).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据角色Id删除对应的角色-数据范围关联信息
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteRoleDataScopeListByRoleId(string roleId)
|
||||
{
|
||||
var dataScopes = await _sysRoleDataScopeRep.DetachedEntities.Where(u => u.SysRoleId == roleId).ToListAsync();
|
||||
dataScopes.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
93
20220330_Vote/Ewide.Core/Service/Role/SysRoleMenuService.cs
Normal file
93
20220330_Vote/Ewide.Core/Service/Role/SysRoleMenuService.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色菜单
|
||||
/// </summary>
|
||||
public class SysRoleMenuService : ISysRoleMenuService, ITransient
|
||||
{
|
||||
private readonly IRepository<SysRoleMenu> _sysRoleMenuRep; // 角色菜单表仓储
|
||||
private readonly ISysCacheService _sysCacheService;
|
||||
|
||||
public SysRoleMenuService(IRepository<SysRoleMenu> sysRoleMenuRep, ISysCacheService sysCacheService)
|
||||
{
|
||||
_sysRoleMenuRep = sysRoleMenuRep;
|
||||
_sysCacheService = sysCacheService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取角色的菜单Id集合
|
||||
/// </summary>
|
||||
/// <param name="roleIdList"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<string>> GetRoleMenuIdList(List<string> roleIdList)
|
||||
{
|
||||
return await _sysRoleMenuRep.DetachedEntities
|
||||
.Where(u => roleIdList.Contains(u.SysRoleId))
|
||||
.Select(u => u.SysMenuId).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权角色菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
public async Task GrantMenu(GrantRoleMenuInput input)
|
||||
{
|
||||
var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => u.SysRoleId == input.Id).ToListAsync();
|
||||
roleMenus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
input.GrantMenuIdList.ForEach(u =>
|
||||
{
|
||||
new SysRoleMenu
|
||||
{
|
||||
SysRoleId = input.Id,
|
||||
SysMenuId = u
|
||||
}.Insert();
|
||||
});
|
||||
|
||||
// 清除缓存
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_PERMISSION);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据菜单Id集合删除对应的角色-菜单表信息
|
||||
/// </summary>
|
||||
/// <param name="menuIdList"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteRoleMenuListByMenuIdList(List<string> menuIdList)
|
||||
{
|
||||
var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.SysMenuId)).ToListAsync();
|
||||
roleMenus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据角色Id删除对应的角色-菜单表关联信息
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task DeleteRoleMenuListByRoleId(string roleId)
|
||||
{
|
||||
var roleMenus = await _sysRoleMenuRep.DetachedEntities.Where(u => u.SysRoleId == roleId).ToListAsync();
|
||||
roleMenus.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
282
20220330_Vote/Ewide.Core/Service/Role/SysRoleService.cs
Normal file
282
20220330_Vote/Ewide.Core/Service/Role/SysRoleService.cs
Normal file
@@ -0,0 +1,282 @@
|
||||
using Ewide.Core.Extension;
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Role", Order = 149)]
|
||||
public class SysRoleService : ISysRoleService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysRole> _sysRoleRep; // 角色表仓储
|
||||
private readonly IRepository<SysUserRole> _sysUserRoleRep; // 用户角色表仓储
|
||||
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ISysRoleDataScopeService _sysRoleDataScopeService;
|
||||
private readonly ISysOrgService _sysOrgService;
|
||||
private readonly ISysRoleMenuService _sysRoleMenuService;
|
||||
|
||||
public SysRoleService(IRepository<SysRole> sysRoleRep,
|
||||
IRepository<SysUserRole> sysUserRoleRep,
|
||||
IUserManager userManager,
|
||||
ISysRoleDataScopeService sysRoleDataScopeService,
|
||||
ISysOrgService sysOrgService,
|
||||
ISysRoleMenuService sysRoleMenuService)
|
||||
{
|
||||
_sysRoleRep = sysRoleRep;
|
||||
_sysUserRoleRep = sysUserRoleRep;
|
||||
_userManager = userManager;
|
||||
_sysRoleDataScopeService = sysRoleDataScopeService;
|
||||
_sysOrgService = sysOrgService;
|
||||
_sysRoleMenuService = sysRoleMenuService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户角色相关信息(登录)
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<List<RoleOutput>> GetUserRoleList(string userId)
|
||||
{
|
||||
return await _sysRoleRep.DetachedEntities.Join(_sysUserRoleRep.DetachedEntities, u => u.Id, e => e.SysRoleId, (u, e) => new { u, e })
|
||||
.Where(x => x.e.SysUserId == userId)
|
||||
.Select(x => x.u.Adapt<RoleOutput>()).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页获取角色列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/page")]
|
||||
public async Task<dynamic> QueryRolePageList([FromBody] RoleInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
var roles = await _sysRoleRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
|
||||
(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.ToPageData(input);
|
||||
return PageDataResult<SysRole>.PageResult(roles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取角色列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<dynamic> GetRoleList([FromQuery] RoleInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var code = !string.IsNullOrEmpty(input.Code?.Trim());
|
||||
return await _sysRoleRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
|
||||
(code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE).OrderBy(u => u.Sort)
|
||||
.Select(u => new
|
||||
{
|
||||
u.Id,
|
||||
Name = u.Name + "[" + u.Code + "]"
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色下拉(用于授权角色时选择)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysRole/dropDown")]
|
||||
public async Task<dynamic> GetRoleDropDown()
|
||||
{
|
||||
// 如果不是超级管理员,则查询自己拥有的角色集合
|
||||
var roles = _userManager.SuperAdmin
|
||||
? await _sysUserRoleRep.Where(u => u.SysUserId == _userManager.UserId).Select(u => u.SysRoleId).ToListAsync()
|
||||
: new List<string>();
|
||||
|
||||
return await _sysRoleRep.DetachedEntities
|
||||
.Where(roles.Count > 0, u => roles.Contains(u.Id))
|
||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||
.Select(u => new
|
||||
{
|
||||
u.Id,
|
||||
u.Code,
|
||||
u.Name
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加角色
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/add")]
|
||||
public async Task AddRole(AddRoleInput input)
|
||||
{
|
||||
var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => u.Code == input.Code || u.Name == input.Name);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1006);
|
||||
|
||||
var role = input.Adapt<SysRole>();
|
||||
role.DataScopeType = 1; // 新角色默认全部数据范围
|
||||
await role.InsertAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除角色
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/delete")]
|
||||
[UnitOfWork]
|
||||
public async Task DeleteRole(DeleteRoleInput input)
|
||||
{
|
||||
var sysRole = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
await sysRole.DeleteAsync();
|
||||
|
||||
//级联删除该角色对应的角色-数据范围关联信息
|
||||
await _sysRoleDataScopeService.DeleteRoleDataScopeListByRoleId(sysRole.Id);
|
||||
|
||||
////级联删除该角色对应的用户-角色表关联信息
|
||||
//await _sysUserRoleService.DeleteUserRoleListByRoleId(sysRole.Id); // 避免循环引用,故用下面逻辑
|
||||
var userRoles = await _sysUserRoleRep.Where(u => u.SysRoleId == sysRole.Id).ToListAsync();
|
||||
userRoles.ForEach(u =>
|
||||
{
|
||||
u.Delete();
|
||||
});
|
||||
|
||||
//级联删除该角色对应的角色-菜单表关联信息
|
||||
await _sysRoleMenuService.DeleteRoleMenuListByRoleId(sysRole.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新角色
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/edit")]
|
||||
public async Task UpdateRole(UpdateRoleInput input)
|
||||
{
|
||||
var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1006);
|
||||
|
||||
var sysRole = input.Adapt<SysRole>();
|
||||
await sysRole.UpdateAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取角色
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysRole/detail")]
|
||||
public async Task<SysRole> GetRoleInfo([FromQuery] QueryRoleInput input)
|
||||
{
|
||||
return await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权角色菜单
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/grantMenu")]
|
||||
public async Task GrantMenu(GrantRoleMenuInput input)
|
||||
{
|
||||
await _sysRoleMenuService.GrantMenu(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权角色数据
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysRole/grantData")]
|
||||
public async Task GrantData(GrantRoleDataInput input)
|
||||
{
|
||||
var role = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
var dataScopeType = input.DataScopeType;
|
||||
if (!_userManager.SuperAdmin)
|
||||
{
|
||||
//如果授权的角色的数据范围类型为全部,则没权限,只有超级管理员有
|
||||
if ((int)DataScopeType.ALL == dataScopeType)
|
||||
throw Oops.Oh(ErrorCode.D1016);
|
||||
|
||||
//如果授权的角色数据范围类型为自定义,则要判断授权的数据范围是否在自己的数据范围内
|
||||
if ((int)DataScopeType.DEFINE == dataScopeType)
|
||||
{
|
||||
var dataScopes = await _userManager.GetUserAllDataScopeList();
|
||||
var grantOrgIdList = input.GrantOrgIdList; //要授权的数据范围列表
|
||||
if (grantOrgIdList.Count > 0)
|
||||
{
|
||||
if (dataScopes.Count < 1)
|
||||
throw Oops.Oh(ErrorCode.D1016);
|
||||
else if (!dataScopes.All(u => grantOrgIdList.Any(c => c == u)))
|
||||
throw Oops.Oh(ErrorCode.D1016);
|
||||
}
|
||||
}
|
||||
}
|
||||
role.DataScopeType = dataScopeType;
|
||||
await _sysRoleDataScopeService.GrantDataScope(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据角色Id获取角色名称
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<string> GetNameByRoleId(string roleId)
|
||||
{
|
||||
var role = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == roleId);
|
||||
if (role == null)
|
||||
throw Oops.Oh(ErrorCode.D1002);
|
||||
return role.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取角色拥有菜单Id集合
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysRole/ownMenu")]
|
||||
public async Task<List<string>> OwnMenu([FromQuery] QueryRoleInput input)
|
||||
{
|
||||
return await _sysRoleMenuService.GetRoleMenuIdList(new List<string> { input.Id });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取角色拥有数据Id集合
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysRole/ownData")]
|
||||
public async Task<List<string>> OwnData([FromQuery] QueryRoleInput input)
|
||||
{
|
||||
return await _userManager.GetRoleExtraDataScopeList(input.Id);
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取角色拥有区域Id集合
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysRole/ownArea")]
|
||||
public Task<List<string>> OwnArea([FromQuery] QueryRoleInput input)
|
||||
{
|
||||
return _userManager.GetRoleExtraAreaScopeList(input.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
20220330_Vote/Ewide.Core/Service/Tenant/Dto/TenantInput.cs
Normal file
94
20220330_Vote/Ewide.Core/Service/Tenant/Dto/TenantInput.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户参数
|
||||
/// </summary>
|
||||
public class TenantInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主机
|
||||
/// </summary>
|
||||
public virtual string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电子邮箱
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电话号码
|
||||
/// </summary>
|
||||
public string Phone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模式
|
||||
/// </summary>
|
||||
public string Schema { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库连接
|
||||
/// </summary>
|
||||
public virtual string Connection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public string CreatedTime { get; set; }
|
||||
}
|
||||
|
||||
public class AddTenantInput : TenantInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "租户名称不能为空")]
|
||||
public override string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主机名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "主机名称不能为空")]
|
||||
public override string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库连接
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "数据库连接不能为空")]
|
||||
public override string Connection { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteTenantInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "租户Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateTenantInput : TenantInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "租户Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class QueryTenantInput : DeleteTenantInput
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
53
20220330_Vote/Ewide.Core/Service/Tenant/Dto/TenantOutput.cs
Normal file
53
20220330_Vote/Ewide.Core/Service/Tenant/Dto/TenantOutput.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户参数
|
||||
/// </summary>
|
||||
public class TenantOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户Id
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主机
|
||||
/// </summary>
|
||||
public string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电子邮箱
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 电话号码
|
||||
/// </summary>
|
||||
public string Phone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模式
|
||||
/// </summary>
|
||||
public string Schema { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库连接
|
||||
/// </summary>
|
||||
public string Connection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public string CreatedTime { get; set; }
|
||||
}
|
||||
}
|
||||
14
20220330_Vote/Ewide.Core/Service/Tenant/ISysTenantService.cs
Normal file
14
20220330_Vote/Ewide.Core/Service/Tenant/ISysTenantService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
public interface ISysTenantService
|
||||
{
|
||||
Task AddTenant(AddTenantInput input);
|
||||
Task DeleteTenant(DeleteTenantInput input);
|
||||
Task<SysTenant> GetTenant([FromQuery] QueryTenantInput input);
|
||||
Task<dynamic> QueryTenantPageList([FromQuery] TenantInput input);
|
||||
Task UpdateTenant(UpdateTenantInput input);
|
||||
}
|
||||
}
|
||||
100
20220330_Vote/Ewide.Core/Service/Tenant/SysTenantService.cs
Normal file
100
20220330_Vote/Ewide.Core/Service/Tenant/SysTenantService.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Furion.DatabaseAccessor;
|
||||
using Furion.DatabaseAccessor.Extensions;
|
||||
using Furion.DependencyInjection;
|
||||
using Furion.DynamicApiController;
|
||||
using Furion.FriendlyException;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Name = "Tenant", Order = 100)]
|
||||
public class SysTenantService : ISysTenantService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly IRepository<SysTenant, MultiTenantDbContextLocator> _sysTenantRep; // 租户表仓储
|
||||
|
||||
public SysTenantService(IRepository<SysTenant, MultiTenantDbContextLocator> sysTenantRep)
|
||||
{
|
||||
_sysTenantRep = sysTenantRep;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询租户
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysTenant/page")]
|
||||
public async Task<dynamic> QueryTenantPageList([FromBody] TenantInput input)
|
||||
{
|
||||
var name = !string.IsNullOrEmpty(input.Name?.Trim());
|
||||
var host = !string.IsNullOrEmpty(input.Host?.Trim());
|
||||
var tenants = await _sysTenantRep.DetachedEntities
|
||||
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
|
||||
(host, u => EF.Functions.Like(u.Host, $"%{input.Host.Trim()}%")))
|
||||
.Select(u => u.Adapt<TenantOutput>())
|
||||
.ToPagedListAsync(input.PageIndex, input.PageSize);
|
||||
return PageDataResult<TenantOutput>.PageResult(tenants);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加租户
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysTenant/add")]
|
||||
public async Task AddTenant(AddTenantInput input)
|
||||
{
|
||||
var isExist = await _sysTenantRep.DetachedEntities.AnyAsync(u => u.Name == input.Name || u.Host == input.Host);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1300);
|
||||
|
||||
var tenant = input.Adapt<SysTenant>();
|
||||
await _sysTenantRep.InsertAsync(tenant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除租户
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysTenant/delete")]
|
||||
public async Task DeleteTenant(DeleteTenantInput input)
|
||||
{
|
||||
var tenant = await _sysTenantRep.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
await _sysTenantRep.DeleteAsync(tenant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新租户
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/sysTenant/edit")]
|
||||
public async Task UpdateTenant(UpdateTenantInput input)
|
||||
{
|
||||
var isExist = await _sysTenantRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Host == input.Host) && u.Id != input.Id);
|
||||
if (isExist)
|
||||
throw Oops.Oh(ErrorCode.D1300);
|
||||
|
||||
var tenant = input.Adapt<SysTenant>();
|
||||
await _sysTenantRep.UpdateAsync(tenant, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取租户
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/sysTenant/detail")]
|
||||
public async Task<SysTenant> GetTenant([FromQuery] QueryTenantInput input)
|
||||
{
|
||||
return await _sysTenantRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
230
20220330_Vote/Ewide.Core/Service/Timer/Dto/JobInput.cs
Normal file
230
20220330_Vote/Ewide.Core/Service/Timer/Dto/JobInput.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using Furion.DataValidation;
|
||||
using Furion.TaskScheduler;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务调度参数
|
||||
/// </summary>
|
||||
public class JobPageInput : PageInputBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
|
||||
public string JobName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
public bool DoOnce { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 立即执行(默认等待启动)
|
||||
/// </summary>
|
||||
public bool StartNow { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 执行类型(并行、列队)
|
||||
/// </summary>
|
||||
public SpareTimeExecuteTypes ExecuteType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔时间(单位秒)
|
||||
/// </summary>
|
||||
/// <example>5</example>
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cron表达式
|
||||
/// </summary>
|
||||
public string Cron { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器类型
|
||||
/// </summary>
|
||||
public SpareTimeTypes TimerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求url
|
||||
/// </summary>
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求参数(Post,Put请求用)
|
||||
/// </summary>
|
||||
public string RequestParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Headers(可以包含如:Authorization授权认证)
|
||||
/// 格式:{"Authorization":"userpassword.."}
|
||||
/// </summary>
|
||||
public string Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求类型
|
||||
/// </summary>
|
||||
public RequestTypeEnum RequestType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
public class AddJobInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
|
||||
public string JobName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
public bool DoOnce { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 立即执行(默认等待启动)
|
||||
/// </summary>
|
||||
public bool StartNow { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 执行类型(并行、列队)
|
||||
/// </summary>
|
||||
public SpareTimeExecuteTypes ExecuteType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔时间(单位秒)
|
||||
/// </summary>
|
||||
/// <example>5</example>
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cron表达式
|
||||
/// </summary>
|
||||
public string Cron { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器类型
|
||||
/// </summary>
|
||||
public SpareTimeTypes TimerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求url
|
||||
/// </summary>
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求参数(Post,Put请求用)
|
||||
/// </summary>
|
||||
public string RequestParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Headers(可以包含如:Authorization授权认证)
|
||||
/// 格式:{"Authorization":"userpassword.."}
|
||||
/// </summary>
|
||||
public string Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求类型
|
||||
/// </summary>
|
||||
public RequestTypeEnum RequestType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
public class StopJobInput
|
||||
{
|
||||
public string JobName { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteJobInput : QueryJobInput
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class UpdateJobInput : QueryJobInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
/// <example>dilon</example>
|
||||
[Required, MaxLength(20)]
|
||||
public string JobName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
public bool DoOnce { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 立即执行(默认等待启动)
|
||||
/// </summary>
|
||||
public bool StartNow { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 执行类型(并行、列队)
|
||||
/// </summary>
|
||||
public SpareTimeExecuteTypes ExecuteType { get; set; } = SpareTimeExecuteTypes.Parallel;
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔时间(单位秒)
|
||||
/// </summary>
|
||||
/// <example>5</example>
|
||||
public int? Interval { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Cron表达式
|
||||
/// </summary>
|
||||
/// <example></example>
|
||||
[MaxLength(20)]
|
||||
public string Cron { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器类型
|
||||
/// </summary>
|
||||
public SpareTimeTypes TimerType { get; set; } = SpareTimeTypes.Interval;
|
||||
|
||||
/// <summary>
|
||||
/// 请求url
|
||||
/// </summary>
|
||||
[MaxLength(200)]
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求参数(Post,Put请求用)
|
||||
/// </summary>
|
||||
public string RequestParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Headers(可以包含如:Authorization授权认证)
|
||||
/// 格式:{"Authorization":"userpassword.."}
|
||||
/// </summary>
|
||||
public string Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求类型
|
||||
/// </summary>
|
||||
/// <example>2</example>
|
||||
public RequestTypeEnum RequestType { get; set; } = RequestTypeEnum.Post;
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[MaxLength(100)]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
public class QueryJobInput
|
||||
{
|
||||
[Required(ErrorMessage = "Id不能为空")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
150
20220330_Vote/Ewide.Core/Service/Timer/Dto/JobOutput.cs
Normal file
150
20220330_Vote/Ewide.Core/Service/Timer/Dto/JobOutput.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using Furion.TaskScheduler;
|
||||
using Quartz;
|
||||
using System;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务信息---任务详情
|
||||
/// </summary>
|
||||
public class JobOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已执行次数
|
||||
/// </summary>
|
||||
public long? RunNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器状态
|
||||
/// </summary>
|
||||
public SpareTimeStatus TimerStatus { get; set; } = SpareTimeStatus.Stopped;
|
||||
|
||||
/// <summary>
|
||||
/// 异常信息
|
||||
/// </summary>
|
||||
public string Exception { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string JobName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
public bool DoOnce { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 立即执行(默认等待启动)
|
||||
/// </summary>
|
||||
public bool StartNow { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 执行类型(并行、列队)
|
||||
/// </summary>
|
||||
public SpareTimeExecuteTypes ExecuteType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔时间(单位秒)
|
||||
/// </summary>
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cron表达式
|
||||
/// </summary>
|
||||
public string Cron { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器类型
|
||||
/// </summary>
|
||||
public SpareTimeTypes TimerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求url
|
||||
/// </summary>
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求类型
|
||||
/// </summary>
|
||||
/// <example>2</example>
|
||||
public RequestTypeEnum RequestType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务方法信息
|
||||
/// </summary>
|
||||
public class TaskMethodInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 方法名
|
||||
/// </summary>
|
||||
public string MethodName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方法所属类的Type对象
|
||||
/// </summary>
|
||||
public Type DeclaringType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string JobName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
public bool DoOnce { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 立即执行(默认等待启动)
|
||||
/// </summary>
|
||||
public bool StartNow { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 执行类型(并行、列队)
|
||||
/// </summary>
|
||||
public SpareTimeExecuteTypes ExecuteType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行间隔时间(单位秒)
|
||||
/// </summary>
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cron表达式
|
||||
/// </summary>
|
||||
public string Cron { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时器类型
|
||||
/// </summary>
|
||||
public SpareTimeTypes TimerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求url
|
||||
/// </summary>
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求类型
|
||||
/// </summary>
|
||||
/// <example>2</example>
|
||||
public RequestTypeEnum RequestType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
}
|
||||
68
20220330_Vote/Ewide.Core/Service/Timer/HttpJob.cs
Normal file
68
20220330_Vote/Ewide.Core/Service/Timer/HttpJob.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Furion.JsonSerialization;
|
||||
using Furion.RemoteRequest.Extensions;
|
||||
using Quartz;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ewide.Core.Service
|
||||
{
|
||||
[DisallowConcurrentExecution]
|
||||
public class HttpJob : IJob
|
||||
{
|
||||
//protected readonly int _maxLogCount = 20; //最多保存日志数量
|
||||
//protected Stopwatch _stopwatch = new();
|
||||
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
// 获取相关参数
|
||||
var requestUrl = context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTURL)?.Trim();
|
||||
requestUrl = requestUrl?.IndexOf("http") == 0 ? requestUrl : "http://" + requestUrl;
|
||||
var requestParameters = context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTPARAMETERS);
|
||||
var headersString = context.JobDetail.JobDataMap.GetString(SchedulerDef.HEADERS);
|
||||
var headers = !string.IsNullOrWhiteSpace(headersString) ? JSON.GetJsonSerializer().Deserialize<Dictionary<string, string>>(headersString.Trim()) : null;
|
||||
var requestType = (RequestTypeEnum)int.Parse(context.JobDetail.JobDataMap.GetString(SchedulerDef.REQUESTTYPE));
|
||||
|
||||
// var response = new HttpResponseMessage();
|
||||
switch (requestType)
|
||||
{
|
||||
case RequestTypeEnum.Get:
|
||||
await requestUrl.SetHeaders(headers).GetAsync();
|
||||
break;
|
||||
case RequestTypeEnum.Post:
|
||||
await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PostAsync();
|
||||
break;
|
||||
case RequestTypeEnum.Put:
|
||||
await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PutAsync();
|
||||
break;
|
||||
case RequestTypeEnum.Delete:
|
||||
await requestUrl.SetHeaders(headers).DeleteAsync();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//_stopwatch.Restart(); // 开始监视代码运行时间
|
||||
//// var beginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
//Debug.WriteLine(DateTimeOffset.Now.ToString());
|
||||
|
||||
//// var endTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
//_stopwatch.Stop(); // 停止监视
|
||||
|
||||
////// 执行次数
|
||||
////var runNumber = context.JobDetail.JobDataMap.GetString(SchedulerDef.RUNNUMBER);
|
||||
////context.JobDetail.JobDataMap[SchedulerDef.RUNNUMBER] = runNumber;
|
||||
|
||||
//// 耗时
|
||||
//var seconds = _stopwatch.Elapsed.TotalSeconds; // 总秒数
|
||||
//var executeTime = seconds >= 1 ? seconds + "秒" : _stopwatch.Elapsed.TotalMilliseconds + "毫秒";
|
||||
|
||||
////// 只保留20条记录
|
||||
////var logs = context.JobDetail.JobDataMap[SchedulerDef.LOGLIST] as List<string> ?? new List<string>();
|
||||
////if (logs.Count >= _maxLogCount)
|
||||
//// logs.RemoveRange(0, logs.Count - _maxLogCount);
|
||||
|
||||
////logs.Add($"<p class='msgList'><span class='time'>{beginTime} 至 {endTime} 【耗时】{executeTime}</span></p>");
|
||||
////context.JobDetail.JobDataMap[SchedulerDef.LOGLIST] = logs;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user