532 lines
21 KiB
C#
532 lines
21 KiB
C#
//------------------------------------------------------------------------------
|
||
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
|
||
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
|
||
// 源代码使用协议遵循本仓库的开源协议及附加协议
|
||
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
|
||
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
|
||
// 使用文档:https://thingsgateway.cn/
|
||
// QQ群:605534569
|
||
//------------------------------------------------------------------------------
|
||
|
||
using BootstrapBlazor.Components;
|
||
|
||
using ThingsGateway.Extension.Generic;
|
||
using ThingsGateway.FriendlyException;
|
||
using ThingsGateway.SqlSugar;
|
||
|
||
namespace ThingsGateway.Admin.Application;
|
||
|
||
internal sealed class SysOrgService : BaseService<SysOrg>, ISysOrgService
|
||
{
|
||
private ISysUserService _sysUserService;
|
||
private ISysUserService SysUserService
|
||
{
|
||
get
|
||
{
|
||
if (_sysUserService == null)
|
||
{
|
||
_sysUserService = App.GetService<ISysUserService>();
|
||
}
|
||
return _sysUserService;
|
||
}
|
||
}
|
||
private IDispatchService<SysOrg> _dispatchService;
|
||
public SysOrgService(IDispatchService<SysOrg> dispatchService)
|
||
{
|
||
_dispatchService = dispatchService;
|
||
}
|
||
|
||
[OperDesc("CopyOrg")]
|
||
public async Task CopyAsync(SysOrgCopyInput input)
|
||
{
|
||
var orgList = await GetAllAsync().ConfigureAwait(false);//获取所有
|
||
var positionList = await App.GetService<ISysPositionService>().GetAllAsync().ConfigureAwait(false);//获取所有职位
|
||
var ids = new HashSet<long>();//定义不重复Id集合
|
||
var addOrgList = new List<SysOrg>();//添加机构列表
|
||
var addPositionList = new List<SysPosition>();//添加职位列表
|
||
var alreadyIds = new HashSet<long>();//定义已经复制过得组织Id
|
||
ids.AddRange(input.Ids);//加到集合
|
||
if (ids.Contains(input.TargetId))
|
||
throw Oops.Bah(Localizer["CanotContainsSelf"]);
|
||
//获取目标组织
|
||
var target = orgList.Where(it => it.Id == input.TargetId).FirstOrDefault();
|
||
if (target != null || input.TargetId == 0)
|
||
{
|
||
//需要复制的组织名称列表
|
||
var orgNames = orgList.Where(it => ids.Contains(it.Id)).Select(it => it.Name).ToList();
|
||
//目标组织的一级子组织名称列表
|
||
var targetChildNames = orgList.Where(it => it.ParentId == input.TargetId).Select(it => it.Name).ToList();
|
||
orgNames.ForEach(it =>
|
||
{
|
||
if (targetChildNames.Contains(it)) throw Oops.Bah(Localizer["TargetNameDup", it]);
|
||
});
|
||
foreach (var id in input.Ids)
|
||
{
|
||
var org = orgList.Where(o => o.Id == id).FirstOrDefault();//获取组织
|
||
if (org != null && !alreadyIds.Contains(id))
|
||
{
|
||
alreadyIds.Add(id);//添加到已复制列表
|
||
SysOrgService.RedirectOrg(org);//生成新的实体
|
||
org.ParentId = input.TargetId;//父id为目标Id
|
||
addOrgList.Add(org);
|
||
//是否包含职位
|
||
if (input.ContainsPosition)
|
||
{
|
||
var positions = positionList.Where(p => p.OrgId == id).ToList();//获取机构下的职位
|
||
positions.ForEach(p =>
|
||
{
|
||
p.OrgId = org.Id;//赋值新的机构ID
|
||
p.Id = CommonUtils.GetSingleId();//生成新的ID
|
||
p.Code = RandomHelper.CreateRandomString(10);//生成新的Code
|
||
addPositionList.Add(p);//添加到职位列表
|
||
});
|
||
}
|
||
//是否包含下级
|
||
if (input.ContainsChild)
|
||
{
|
||
var childIds = await GetOrgChildIdsAsync(id, false).ConfigureAwait(false);//获取下级id列表
|
||
alreadyIds.AddRange(childIds);//添加到已复制id
|
||
var childList = orgList.Where(c => childIds.Contains(c.Id)).ToList();//获取下级
|
||
var sysOrgChildren = CopySysOrgChildren(childList, id, org.Id, input.ContainsPosition,
|
||
positionList);//赋值下级组织
|
||
addOrgList.AddRange(sysOrgChildren.Item1);//添加到组织列表
|
||
addPositionList.AddRange(sysOrgChildren.Item2);//添加到职位列表
|
||
}
|
||
}
|
||
}
|
||
orgList.AddRange(addOrgList);//要添加的组织添加到组织列表
|
||
//遍历机构重新赋值全称和父Id列表
|
||
addOrgList.ForEach(it =>
|
||
{
|
||
it.Names = it.Name;
|
||
if (it.ParentId != 0)
|
||
{
|
||
var parentIdList = GetNames(orgList, it.ParentId, it.Name, out var names);
|
||
it.Names = names;
|
||
it.ParentIdList = parentIdList;
|
||
}
|
||
});
|
||
|
||
using var db = GetDB();
|
||
//事务
|
||
var result = await db.UseTranAsync(async () =>
|
||
{
|
||
await db.Insertable(addOrgList).ExecuteCommandAsync().ConfigureAwait(false);//插入组织
|
||
if (addPositionList.Count > 0)
|
||
{
|
||
await db.Insertable(addPositionList).ExecuteCommandAsync().ConfigureAwait(false);
|
||
}
|
||
}).ConfigureAwait(false);
|
||
if (result.IsSuccess)//如果成功了
|
||
{
|
||
RefreshCache();//刷新缓存
|
||
}
|
||
else
|
||
{
|
||
throw new(result.ErrorMessage, result.ErrorException);
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
[OperDesc("DeleteOrg")]
|
||
public async Task<bool> DeleteOrgAsync(IEnumerable<long> ids)
|
||
{
|
||
//获取所有ID
|
||
if (ids.Any())
|
||
{
|
||
using var db = GetDB();
|
||
var sysOrgList = await GetAllAsync().ConfigureAwait(false);//获取所有组织
|
||
var sysDeleteOrgList = new List<long>();//需要删除的组织ID集合
|
||
foreach (var it in ids)
|
||
{
|
||
var children = SysOrgService.GetSysOrgChildren(sysOrgList, it);//查找下级组织
|
||
sysDeleteOrgList.AddRange(children.Select(it => it.Id).ToList());
|
||
sysDeleteOrgList.Add(it);
|
||
}
|
||
//如果组织下有用户则不能删除
|
||
if (await db.Queryable<SysUser>().AnyAsync(it => sysDeleteOrgList.Contains(it.OrgId)).ConfigureAwait(false))
|
||
{
|
||
throw Oops.Bah(Localizer["DeleteUserFirst"]);
|
||
}
|
||
//判断组织下是否有角色
|
||
var hasRole = await db.Queryable<SysRole>().Where(it => sysDeleteOrgList.Contains(it.OrgId)).CountAsync().ConfigureAwait(false) > 0;
|
||
if (hasRole)
|
||
throw Oops.Bah(Localizer["DeleteRoleFirst"]);
|
||
// 判断组织下是否有职位
|
||
var hasPosition = await db.Queryable<SysPosition>().Where(it => sysDeleteOrgList.Contains(it.OrgId)).CountAsync().ConfigureAwait(false) > 0;
|
||
if (hasPosition)
|
||
throw Oops.Bah(Localizer["DeletePositionFirst"]);
|
||
//删除组织
|
||
var result = await base.DeleteAsync(ids).ConfigureAwait(false);
|
||
if (result)
|
||
RefreshCache();
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 从缓存/数据库获取系统配置列表
|
||
/// </summary>
|
||
public async Task<List<SysOrg>> GetAllAsync(bool showDisabled = true)
|
||
{
|
||
var key = $"{CacheConst.Cache_SysOrg}";//系统配置key
|
||
var sysOrgs = App.CacheService.Get<List<SysOrg>>(key);
|
||
if (sysOrgs == null)
|
||
{
|
||
using var db = GetDB();
|
||
sysOrgs = (await db.Queryable<SysOrg>().ToListAsync().ConfigureAwait(false));
|
||
App.CacheService.Set(key, sysOrgs);
|
||
}
|
||
if (!showDisabled)
|
||
{
|
||
sysOrgs = sysOrgs.Where(it => it.Status).ToList();
|
||
}
|
||
return sysOrgs;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<SysOrg> GetSysOrgByIdAsync(long id)
|
||
{
|
||
var sysOrg = await GetAllAsync().ConfigureAwait(false);
|
||
var result = sysOrg.FirstOrDefault(it => it.Id == id);
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表格查询
|
||
/// </summary>
|
||
public async Task<QueryData<SysOrg>> PageAsync(QueryPageOptions option, Func<ISugarQueryable<SysOrg>, ISugarQueryable<SysOrg>>? queryFunc = null)
|
||
{
|
||
var dataScope = await SysUserService.GetCurrentUserDataScopeAsync().ConfigureAwait(false);
|
||
queryFunc += a =>
|
||
a.WhereIF(dataScope != null && dataScope?.Count > 0, u => dataScope.Contains(u.Id))//在指定机构列表查询
|
||
.WhereIF(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId);
|
||
return await QueryAsync(option, queryFunc).ConfigureAwait(false);
|
||
}
|
||
|
||
/// <inheritdoc/>
|
||
public async Task<List<SysOrg>> SelectorAsync()
|
||
{
|
||
var sysOrgList = await GetAllAsync().ConfigureAwait(false);//获取所有组织
|
||
var dataScope = await SysUserService.GetCurrentUserDataScopeAsync().ConfigureAwait(false);
|
||
sysOrgList = sysOrgList
|
||
.WhereIf(dataScope != null && dataScope?.Count > 0, b => dataScope.Contains(b.Id))
|
||
.WhereIf(dataScope?.Count == 0, u => u.CreateUserId == UserManager.UserId)
|
||
.ToList();//在指定组织列表查询
|
||
|
||
return sysOrgList;
|
||
}
|
||
[OperDesc("SaveOrg")]
|
||
public async Task<bool> SaveOrgAsync(SysOrg input, ItemChangedType type)
|
||
{
|
||
await CheckInput(input).ConfigureAwait(false);//检查参数
|
||
var reuslt = await base.SaveAsync(input, type).ConfigureAwait(false);
|
||
|
||
if (reuslt)
|
||
{
|
||
if (type == ItemChangedType.Update)
|
||
{
|
||
if (!input.Status)
|
||
{
|
||
var orgIds = await GetOrgChildIdsAsync(input.Id, true).ConfigureAwait(false);//获取所有下级
|
||
await ClearTokenUtil.DeleteUserTokenByOrgIds(orgIds).ConfigureAwait(false);//清除用户token
|
||
}
|
||
}
|
||
RefreshCache();
|
||
}
|
||
|
||
return reuslt;
|
||
}
|
||
|
||
|
||
/// <inheritdoc />
|
||
public async Task<HashSet<long>> GetOrgChildIdsAsync(long orgId, bool isContainOneself = true, List<SysOrg> sysOrgList = null)
|
||
{
|
||
var orgIds = new HashSet<long>();//组织列表
|
||
if (orgId > 0)//如果orgId有值
|
||
{
|
||
//获取所有子集
|
||
var childList = await GetChildListByIdAsync(orgId, isContainOneself, sysOrgList).ConfigureAwait(false);
|
||
orgIds = childList.Select(x => x.Id).ToHashSet();//提取ID列表
|
||
}
|
||
return orgIds;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<List<SysOrg>> GetChildListByIdAsync(long orgId, bool isContainOneself = true, List<SysOrg> sysOrgList = null)
|
||
{
|
||
//获取所有组织
|
||
sysOrgList ??= await GetAllAsync().ConfigureAwait(false);
|
||
//查找下级
|
||
var childList = SysOrgService.GetSysOrgChildren(sysOrgList, orgId);
|
||
if (isContainOneself)//如果包含自己
|
||
{
|
||
//获取自己的组织信息
|
||
var self = sysOrgList.Where(it => it.Id == orgId).FirstOrDefault();
|
||
if (self != null) childList.Insert(0, self);//如果组织不为空就插到第一个
|
||
}
|
||
return childList;
|
||
}
|
||
|
||
|
||
|
||
/// <inheritdoc />
|
||
public async Task<List<SysOrg>> GetTenantListAsync()
|
||
{
|
||
var key = $"{CacheConst.Cache_SysTenant}";
|
||
|
||
var tenantList = App.CacheService.Get<List<SysOrg>>(key);
|
||
if (tenantList == null)
|
||
{
|
||
var orgList = await GetAllAsync(false).ConfigureAwait(false);
|
||
tenantList = orgList.Where(it => it.Category == OrgEnum.COMPANY).OrderBy(x => x.SortCode).ToList();
|
||
if (tenantList.Count > 0)
|
||
{
|
||
//插入Redis
|
||
App.CacheService.Set(key, tenantList);
|
||
}
|
||
}
|
||
return tenantList;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task<long?> GetTenantIdByOrgIdAsync(long orgId, List<SysOrg> sysOrgList = null)
|
||
{
|
||
var key = $"{CacheConst.Cache_SysOrgTenant}";
|
||
//先从缓存拿租户Id
|
||
var tenantId = App.CacheService.HashGetOne<long?>(key, orgId.ToString());
|
||
if (tenantId == null)
|
||
{
|
||
//获取所有组织
|
||
sysOrgList ??= await GetAllAsync().ConfigureAwait(false);
|
||
var userOrg = sysOrgList.FirstOrDefault(it => it.Id == orgId);
|
||
if (userOrg != null)
|
||
{
|
||
//如果是公司直接返回
|
||
if (userOrg.Category == OrgEnum.COMPANY)
|
||
{
|
||
tenantId = userOrg.Id;
|
||
}
|
||
else
|
||
{
|
||
var parentIds = userOrg.ParentIdList;//获取父级ID列表
|
||
//从最后一个往前遍历,取第一个公司ID为租户ID
|
||
for (var i = parentIds.Count - 1; i >= 0; i--)
|
||
{
|
||
var parentId = parentIds[i];
|
||
var org = sysOrgList.FirstOrDefault(it => it.Id == parentId);
|
||
if (org.Category == OrgEnum.COMPANY)
|
||
{
|
||
tenantId = org.Id;//租户ID
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (tenantId != null)
|
||
App.CacheService.HashAdd(key, orgId.ToString(), tenantId);//插入缓存
|
||
}
|
||
}
|
||
return tenantId;
|
||
}
|
||
|
||
#region 方法
|
||
/// <summary>
|
||
/// 赋值组织的所有下级
|
||
/// </summary>
|
||
/// <param name="orgList">组织列表</param>
|
||
/// <param name="parentId">父Id</param>
|
||
/// <param name="newParentId">新父Id</param>
|
||
/// <param name="isCopyPosition"></param>
|
||
/// <param name="positions"></param>
|
||
/// <returns></returns>
|
||
private static Tuple<List<SysOrg>, List<SysPosition>> CopySysOrgChildren(List<SysOrg> orgList, long parentId, long newParentId, bool isCopyPosition, List<SysPosition> positions)
|
||
{
|
||
//找下级组织列表
|
||
var orgInfos = orgList.Where(it => it.ParentId == parentId).ToList();
|
||
if (orgInfos.Count > 0)//如果数量大于0
|
||
{
|
||
var result = new Tuple<List<SysOrg>, List<SysPosition>>(
|
||
new List<SysOrg>(), new List<SysPosition>()
|
||
);
|
||
foreach (var item in orgInfos)//遍历组织
|
||
{
|
||
var oldId = item.Id;//获取旧Id
|
||
SysOrgService.RedirectOrg(item);//实体重新赋值
|
||
var children = CopySysOrgChildren(orgList, oldId, item.Id, isCopyPosition,
|
||
positions);//获取子节点
|
||
item.ParentId = newParentId;//赋值新的父Id
|
||
result.Item1.AddRange(children.Item1);//添加下级组织;
|
||
if (isCopyPosition)//如果包含职位
|
||
{
|
||
var positionList = positions.Where(it => it.OrgId == oldId).ToList();//获取职位列表
|
||
positionList.ForEach(it =>
|
||
{
|
||
it.OrgId = item.Id;//赋值新的机构ID
|
||
it.Id = CommonUtils.GetSingleId();//生成新的ID
|
||
it.Code = RandomHelper.CreateRandomString(10);//生成新的Code
|
||
});
|
||
result.Item2.AddRange(positionList);//添加职位列表
|
||
}
|
||
}
|
||
return result;//返回结果
|
||
}
|
||
return new Tuple<List<SysOrg>, List<SysPosition>>(
|
||
new List<SysOrg>(), new List<SysPosition>()
|
||
);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取组织所有下级
|
||
/// </summary>
|
||
/// <param name="orgList"></param>
|
||
/// <param name="parentId"></param>
|
||
/// <returns></returns>
|
||
private static List<SysOrg> GetSysOrgChildren(List<SysOrg> orgList, long parentId)
|
||
{
|
||
//找下级组织ID列表
|
||
var orgInfos = orgList.Where(it => it.ParentId == parentId).ToList();
|
||
if (orgInfos.Count > 0)//如果数量大于0
|
||
{
|
||
var data = new List<SysOrg>();
|
||
foreach (var item in orgInfos)//遍历组织
|
||
{
|
||
var children = SysOrgService.GetSysOrgChildren(orgList, item.Id);//获取子节点
|
||
data.AddRange(children);//添加子节点);
|
||
data.Add(item);//添加到列表
|
||
}
|
||
return data;//返回结果
|
||
}
|
||
return new List<SysOrg>();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 重新生成组织实体
|
||
/// </summary>
|
||
/// <param name="org"></param>
|
||
private static void RedirectOrg(SysOrg org)
|
||
{
|
||
//重新生成ID并赋值
|
||
var newId = CommonUtils.GetSingleId();
|
||
org.Id = newId;
|
||
org.Code = RandomHelper.CreateRandomString(10);
|
||
org.CreateTime = DateTime.Now;
|
||
org.CreateUser = UserManager.UserAccount;
|
||
org.CreateUserId = UserManager.UserId;
|
||
}
|
||
/// <summary>
|
||
/// 检查输入参数
|
||
/// </summary>
|
||
private async Task CheckInput(SysOrg input)
|
||
{
|
||
|
||
if (!(await SysUserService.GetUserByIdAsync(UserManager.UserId).ConfigureAwait(false)).IsGlobal)
|
||
{
|
||
if (input.ParentId == 0)
|
||
{
|
||
throw Oops.Bah(Localizer["RootOrg"]);
|
||
}
|
||
}
|
||
var sysOrgList = await GetAllAsync().ConfigureAwait(false);//获取全部
|
||
if (sysOrgList.Any(it => it.ParentId == input.ParentId && it.Name == input.Name && it.Id != input.Id))//判断同级是否有名称重复的
|
||
throw Oops.Bah(Localizer["NameDup", input.Name]);
|
||
input.Names = input.Name;//全称默认自己
|
||
if (input.ParentId != 0)
|
||
{
|
||
//获取父级,判断父级ID正不正确
|
||
var parent = sysOrgList.Where(it => it.Id == input.ParentId).FirstOrDefault();
|
||
if (parent != null)
|
||
{
|
||
if (parent.Id == input.Id)
|
||
throw Oops.Bah(Localizer["ParentChoiceSelf"]);
|
||
}
|
||
else
|
||
{
|
||
throw Oops.Bah(Localizer["ParentNull", input.Id]);
|
||
}
|
||
var parentIdList = GetNames(sysOrgList, input.ParentId, input.Name, out var names);
|
||
input.Names = names;
|
||
input.ParentIdList = parentIdList;
|
||
}
|
||
//如果code没填
|
||
if (string.IsNullOrEmpty(input.Code))
|
||
{
|
||
input.Code = RandomHelper.CreateRandomString(10);
|
||
}
|
||
else
|
||
{
|
||
//判断是否有相同的Code
|
||
if (sysOrgList.Any(it => it.Code == input.Code && it.Id != input.Id))
|
||
throw Oops.Bah(Localizer["CodeDup", input.Code]);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 刷新缓存
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private void RefreshCache()
|
||
{
|
||
App.CacheService.Remove($"{CacheConst.Cache_SysOrg}");
|
||
App.CacheService.Remove($"{CacheConst.Cache_SysUser}");
|
||
App.CacheService.Remove($"{CacheConst.Cache_SysTenant}");
|
||
App.CacheService.Remove($"{CacheConst.Cache_SysOrgTenant}");
|
||
|
||
_dispatchService.Dispatch(null);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取全称
|
||
/// </summary>
|
||
/// <param name="sysOrgList">组织列表</param>
|
||
/// <param name="parentId">父Id</param>
|
||
/// <param name="orgName">组织名称</param>
|
||
/// <param name="names">组织全称</param>
|
||
/// <returns>组织父Id列表</returns>
|
||
private static List<long> GetNames(List<SysOrg> sysOrgList, long parentId, string orgName, out string names)
|
||
{
|
||
names = string.Empty;
|
||
//获取父级菜单
|
||
var parents = SysOrgService.GetOrgParents(sysOrgList, parentId);
|
||
foreach (var item in parents)
|
||
{
|
||
names += $"{item.Name}/";
|
||
}
|
||
names += orgName;//赋值全称
|
||
var parentIdList = parents.Select(it => it.Id).ToList();//赋值父Id列表
|
||
return parentIdList;
|
||
}
|
||
|
||
|
||
/// <inheritdoc />
|
||
private static List<SysOrg> GetOrgParents(List<SysOrg> allOrgList, long orgId, bool includeSelf = true)
|
||
{
|
||
//找到组织
|
||
var sysOrgList = allOrgList.Where(it => it.Id == orgId).FirstOrDefault();
|
||
if (sysOrgList != null)//如果组织不为空
|
||
{
|
||
var data = new List<SysOrg>();
|
||
var parents = SysOrgService.GetOrgParents(allOrgList, sysOrgList.ParentId, includeSelf);//递归获取父节点
|
||
data.AddRange(parents);//添加父节点;
|
||
if (includeSelf)
|
||
data.Add(sysOrgList);//添加到列表
|
||
return data;//返回结果
|
||
}
|
||
return new List<SysOrg>();
|
||
}
|
||
|
||
#endregion 方法
|
||
}
|