更新项目配置,新增设备同步模块,优化WebSocket和Swagger配置,增强SCADA系统的免登录接口,支持数据字典项和登录日志的免登录查询与记录。调整Java编译设置,确保更好的开发体验。
This commit is contained in:
114
yy-admin-master/YY.Admin.Core/Extension/EnumerableExtension.cs
Normal file
114
yy-admin-master/YY.Admin.Core/Extension/EnumerableExtension.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YY.Admin.Core.Extension;
|
||||
|
||||
namespace YY.Admin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据集合拓展类
|
||||
/// </summary>
|
||||
public static class EnumerableExtension
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, PropertyInfo> PropertyCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// 查询有父子关系的数据集
|
||||
/// </summary>
|
||||
/// <param name="list">数据集</param>
|
||||
/// <param name="idExpression">主键ID字段</param>
|
||||
/// <param name="parentIdExpression">父级字段</param>
|
||||
/// <param name="topParentIdValue">顶级节点父级字段值</param>
|
||||
/// <param name="isContainOneself">是否包含顶级节点本身</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> ToChildList<T, P>(this IEnumerable<T> list,
|
||||
Expression<Func<T, P>> idExpression,
|
||||
Expression<Func<T, P>> parentIdExpression,
|
||||
object topParentIdValue,
|
||||
bool isContainOneself = true)
|
||||
{
|
||||
if (list == null || !list.Any()) return Enumerable.Empty<T>();
|
||||
|
||||
var propId = GetPropertyInfo(idExpression);
|
||||
var propParentId = GetPropertyInfo(parentIdExpression);
|
||||
|
||||
// 查找所有顶级节点
|
||||
var topNodes = list.Where(item => Equals(propId.GetValue(item), topParentIdValue)).ToList();
|
||||
|
||||
return TraverseHierarchy(list, propId, propParentId, topNodes, isContainOneself);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询有父子关系的数据集
|
||||
/// </summary>
|
||||
/// <param name="list">数据集</param>
|
||||
/// <param name="idExpression">主键ID字段</param>
|
||||
/// <param name="parentIdExpression">父级字段</param>
|
||||
/// <param name="topLevelPredicate">顶级节点的选择条件</param>
|
||||
/// <param name="isContainOneself">是否包含顶级节点本身</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> ToChildList<T, P>(this IEnumerable<T> list,
|
||||
Expression<Func<T, P>> idExpression,
|
||||
Expression<Func<T, P>> parentIdExpression,
|
||||
Expression<Func<T, bool>> topLevelPredicate,
|
||||
bool isContainOneself = true)
|
||||
{
|
||||
if (list == null || !list.Any()) return Enumerable.Empty<T>();
|
||||
|
||||
// 获取顶级节点
|
||||
var topNodes = list.Where(topLevelPredicate.Compile()).ToList();
|
||||
|
||||
if (!topNodes.Any()) return Enumerable.Empty<T>();
|
||||
|
||||
var idPropertyInfo = GetPropertyInfo(idExpression);
|
||||
var parentPropertyInfo = GetPropertyInfo(parentIdExpression);
|
||||
|
||||
return TraverseHierarchy(list, idPropertyInfo, parentPropertyInfo, topNodes, isContainOneself);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 辅助方法,从表达式中提取属性信息并使用临时缓存
|
||||
/// </summary>
|
||||
private static PropertyInfo GetPropertyInfo<T, P>(Expression<Func<T, P>> expression)
|
||||
{
|
||||
// 使用 ConcurrentDictionary 确保线程安全
|
||||
return PropertyCache.GetOrAdd(typeof(T).FullName + "." + ((MemberExpression)expression.Body).Member.Name, k =>
|
||||
{
|
||||
if (expression.Body is UnaryExpression { Operand: MemberExpression member }) return (PropertyInfo)member.Member;
|
||||
if (expression.Body is MemberExpression memberExpression) return (PropertyInfo)memberExpression.Member;
|
||||
throw new Exception("表达式必须是一个属性访问: " + expression);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用队列遍历层级结构
|
||||
/// </summary>
|
||||
private static IEnumerable<T> TraverseHierarchy<T>(IEnumerable<T> list,
|
||||
PropertyInfo idPropertyInfo,
|
||||
PropertyInfo parentPropertyInfo,
|
||||
List<T> topNodes,
|
||||
bool isContainOneself)
|
||||
{
|
||||
var queue = new Queue<T>(topNodes);
|
||||
var result = new HashSet<T>(topNodes);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var currentNode = queue.Dequeue();
|
||||
var children = list.Where(item => Equals(parentPropertyInfo.GetValue(item), idPropertyInfo.GetValue(currentNode))).ToList();
|
||||
children.Where(child => result.Add(child)).ForEach(child => queue.Enqueue(child));
|
||||
}
|
||||
if (isContainOneself) return result;
|
||||
|
||||
// 如果不需要包含顶级节点本身,则移除它们
|
||||
topNodes.ForEach(e => result.Remove(e));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user