Skip to content

Commit

Permalink
[improv]菜单移动,仅交换位置,不要给所有菜单重新计算排序数字
Browse files Browse the repository at this point in the history
  • Loading branch information
nnhy committed Sep 4, 2024
1 parent eea309c commit 0b24d1f
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 79 deletions.
136 changes: 82 additions & 54 deletions XCode/Tree/EntityTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,45 +37,45 @@ static EntityTree()
}

/// <summary>实体树操作者</summary>
protected static IEntityTreeSetting Setting;
public static IEntityTreeSetting Setting;
#endregion

#region 扩展属性
/// <summary>排序值</summary>
private Int32 Sort
{
get { return String.IsNullOrEmpty(Setting.Sort) ? 0 : (Int32)this[Setting.Sort]; }
set { if (!String.IsNullOrEmpty(Setting.Sort) && (Int32)this[Setting.Sort] != value) SetItem(Setting.Sort, value); }
get { return String.IsNullOrEmpty(Setting.Sort) ? 0 : (Int32)this[Setting.Sort]!; }
set { if (!String.IsNullOrEmpty(Setting.Sort) && (Int32)this[Setting.Sort]! != value) SetItem(Setting.Sort, value); }
}

/// <summary>子节点</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual IList<TEntity> Childs => Extends.Get(nameof(Childs), e => FindChilds());
public virtual IList<TEntity> Childs => Extends.Get(nameof(Childs), e => FindChilds())!;

/// <summary>子节点</summary>
protected virtual IList<TEntity> FindChilds() => FindAllByParent((TKey)this[Setting.Key]);
protected virtual IList<TEntity> FindChilds() => FindAllByParent((TKey)this[Setting.Key]!);

/// <summary>父节点</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual TEntity Parent => Extends.Get(nameof(Parent), e => FindParent());
public virtual TEntity? Parent => Extends.Get(nameof(Parent), e => FindParent());

/// <summary>父节点</summary>
protected virtual TEntity FindParent() => FindByKeyWithCache((TKey)this[Setting.Parent]);
protected virtual TEntity FindParent() => FindByKeyWithCache((TKey)this[Setting.Parent]!);

/// <summary>在缓存中查找节点</summary>
protected static TEntity FindByKeyWithCache(TKey key) => Meta.Session.Cache.Find(e => Equals(e[Setting.Key], key));

/// <summary>子孙节点</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual IList<TEntity> AllChilds => Extends.Get(nameof(AllChilds), e => FindAllChilds(this));
public virtual IList<TEntity> AllChilds => Extends.Get(nameof(AllChilds), e => FindAllChilds(this))!;

/// <summary>子孙节点,包含自己</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual IList<TEntity> MyAllChilds => Extends.Get(nameof(MyAllChilds), e => FindAllChilds(this, true));
public virtual IList<TEntity> MyAllChilds => Extends.Get(nameof(MyAllChilds), e => FindAllChilds(this, true))!;

/// <summary>父节点集合</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual IList<TEntity> AllParents => Extends.Get(nameof(AllParents), e => FindAllParents(this));
public virtual IList<TEntity> AllParents => Extends.Get(nameof(AllParents), e => FindAllParents(this))!;

/// <summary>深度</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
Expand All @@ -92,7 +92,7 @@ public virtual Int32 Deepth
}
}

private static TEntity _Root;
private static TEntity _Root = null!;
/// <summary>根</summary>
public static TEntity Root
{
Expand All @@ -101,29 +101,29 @@ public static TEntity Root
if (_Root == null)
{
_Root = new TEntity();
Meta.Session.OnDataChange += delegate { _Root = null; };
Meta.Session.OnDataChange += delegate { _Root = null!; };
}
return _Root;
}
set { _Root = null; }
set { _Root = null!; }
}

/// <summary>节点名</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual String NodeName
public virtual String? NodeName
{
get
{
var key = Setting.Name;
if (String.IsNullOrEmpty(key)) return String.Empty;

return (String)this[key];
return (String?)this[key];
}
}

/// <summary>父级节点名</summary>
[XmlIgnore, ScriptIgnore, IgnoreDataMember]
public virtual String ParentNodeName
public virtual String? ParentNodeName
{
get
{
Expand All @@ -133,7 +133,7 @@ public virtual String ParentNodeName
var parent = Parent;
if (parent == null) return String.Empty;

return (String)parent[key];
return (String?)parent[key];
}
}

Expand Down Expand Up @@ -225,7 +225,7 @@ public static IList<TEntity> FindAllByParent(TKey parentKey)
if (item1.Sort != item2.Sort)
return -n * item1.Sort.CompareTo(item2.Sort);
else
return (item1[Setting.Key] as IComparable).CompareTo(item2[Setting.Key]);
return (item1[Setting.Key] as IComparable)!.CompareTo(item2[Setting.Key]);
});
}
return list;
Expand All @@ -236,7 +236,7 @@ public static IList<TEntity> FindAllByParent(TKey parentKey)
public static IList<TEntity> FindAllNoParent()
{
// 有父节点的跳过,父节点为空的跳过
return Meta.Session.Cache.FindAll(e => !IsNull((TKey)e[Setting.Parent]) && e.Parent == null);
return Meta.Session.Cache.FindAll(e => !IsNull((TKey)e[Setting.Parent]!) && e.Parent == null);
}

/// <summary>查找指定键的所有子节点,以深度层次树结构输出,包括当前节点作为根节点。空父节点返回顶级列表,无效父节点返回空列表</summary>
Expand All @@ -246,7 +246,7 @@ public static IList<TEntity> FindAllNoParent()
public static IList<TEntity> FindAllChildsByParent(TKey parentKey)
{
var entity = IsNull(parentKey) ? Root : FindByKeyWithCache(parentKey);
if (entity == null) return new List<TEntity>();
if (entity == null) return [];

return FindAllChilds(entity, true);
}
Expand All @@ -258,7 +258,7 @@ public static IList<TEntity> FindAllChildsByParent(TKey parentKey)
public static IList<TEntity> FindAllChildsNoParent(TKey parentKey)
{
var entity = IsNull(parentKey) ? Root : FindByKeyWithCache(parentKey);
if (entity == null) return new List<TEntity>();
if (entity == null) return [];

return FindAllChilds(entity, false);
}
Expand All @@ -274,10 +274,10 @@ public static IList<TEntity> FindAllChildsNoParent(TKey parentKey)
[DataObjectMethod(DataObjectMethodType.Select)]
public static IList<TEntity> FindAllParentsByKey(TKey key)
{
if (IsNull(key)) return new List<TEntity>();
if (IsNull(key)) return [];

var entity = FindByKeyWithCache(key);
if (entity == null) return new List<TEntity>();
if (entity == null) return [];

return FindAllParents(entity);
}
Expand All @@ -289,17 +289,17 @@ public static IList<TEntity> FindAllParentsByKey(TKey key)
/// <param name="includeSelf">返回列表是否包含根节点,默认false</param>
/// <param name="exclude">要排除的节点</param>
/// <returns></returns>
protected static IList<TEntity> FindAllChilds(IEntityTree entity, Boolean includeSelf = false, IEntityTree exclude = null)
protected static IList<TEntity> FindAllChilds(IEntityTree entity, Boolean includeSelf = false, IEntityTree? exclude = null)
{
if (entity == null) return new List<TEntity>();
if (entity == null) return [];
var childlist = entity.Childs;
if (childlist == null) return new List<TEntity>();
if (childlist == null) return [];

var list = new List<TEntity>();
// 不使用递归,避免死循环
// 使用堆栈而不使用队列,因为树的构造一般是深度搜索而不是广度搜索
var stack = new Stack<TEntity>();
stack.Push(entity as TEntity);
stack.Push((entity as TEntity)!);

while (stack.Count > 0)
{
Expand Down Expand Up @@ -337,7 +337,7 @@ protected static IList<TEntity> FindAllChilds(IEntityTree entity, Boolean includ
protected static IList<TEntity> FindAllParents(IEntityTree entity, Boolean includeSelf = false)
{
var pkey = Setting.Parent;
if (entity == null || pkey.IsNullOrEmpty() || IsNull((TKey)entity[pkey]) || entity.Parent == null) return new List<TEntity>();
if (entity == null || pkey.IsNullOrEmpty() || IsNull((TKey)entity[pkey]!) || entity.Parent == null) return [];

var list = new List<TEntity>();
var item = entity as TEntity;
Expand All @@ -363,7 +363,7 @@ protected static IList<TEntity> FindAllParents(IEntityTree entity, Boolean inclu
/// <param name="path">层次路径</param>
/// <param name="keys">用于在每一层匹配实体的键值,默认是NameKeyName</param>
/// <returns></returns>
public TEntity FindByPath(String path, params String[] keys)
public TEntity? FindByPath(String path, params String[] keys)
{
if (String.IsNullOrEmpty(path)) return null;

Expand All @@ -386,11 +386,11 @@ public TEntity FindByPath(String path, params String[] keys)
if (ss == null || ss.Length <= 0) return null;

// 找第一级
TEntity entity = null;
TEntity? entity = null;
foreach (var item in keys)
{
//entity = list.Find(item, ss[0]);
entity = list.FirstOrDefault(e => (String)e[item] == ss[0]);
entity = list.FirstOrDefault(e => (String?)e[item] == ss[0]);
if (entity != null) break;
}
if (entity == null) return null;
Expand All @@ -413,7 +413,7 @@ public Boolean Contains(TKey key)
if (IsNull(key)) return false;

// 自身
if (Equals((TKey)this[Setting.Key], key)) return true;
if (Equals((TKey)this[Setting.Key]!, key)) return true;

// 子级
var list = Childs;
Expand All @@ -433,7 +433,7 @@ public Boolean Contains(TKey key)
/// <param name="separator">分隔符</param>
/// <param name="func">回调</param>
/// <returns></returns>
public String GetFullPath(Boolean includeSelf = true, String separator = @"\", Func<TEntity, String> func = null)
public String? GetFullPath(Boolean includeSelf = true, String separator = @"\", Func<TEntity, String>? func = null)
{
var list = FindAllParents(this, includeSelf);
if (list == null || list.Count <= 0) return null;
Expand Down Expand Up @@ -502,41 +502,69 @@ public virtual void ClearRelation()
/// <summary>排序上升</summary>
public void Up()
{
var list = FindAllByParent((TKey)this[Setting.Parent]);
var list = FindAllByParent((TKey)this[Setting.Parent]!);
if (list == null || list.Count <= 0) return;

var n = Setting.BigSort ? 1 : -1;
//var n = Setting.BigSort ? 1 : -1;

//for (var i = 0; i < list.Count; i++)
//{
// var s = list.Count - i;
// // 当前项,排序增加。原来比较实体相等有问题,也许新旧实体类不对应,现在改为比较主键值
// if (EqualTo(list[i])) s += n;
// // 下一项是当前项,排序减少
// if (i < list.Count - 1 && EqualTo(list[i + 1])) s -= n;
// list[i].Sort = s;
//}
//list.Save();

// 跟前一个交换位置
for (var i = 0; i < list.Count; i++)
{
var s = list.Count - i;
// 当前项,排序增加。原来比较实体相等有问题,也许新旧实体类不对应,现在改为比较主键值
if (EqualTo(list[i])) s += n;
// 下一项是当前项,排序减少
if (i < list.Count - 1 && EqualTo(list[i + 1])) s -= n;
list[i].Sort = s;
var cur = list[i];
if (i > 1 && EqualTo(cur))
{
var prev = list[i - 1];
(prev.Sort, cur.Sort) = (cur.Sort, prev.Sort);

cur.Update();
prev.Update();
}
}
list.Save();
}

/// <summary>排序下降</summary>
public void Down()
{
var list = FindAllByParent((TKey)this[Setting.Parent]);
var list = FindAllByParent((TKey)this[Setting.Parent]!);
if (list == null || list.Count <= 0) return;

var n = Setting.BigSort ? 1 : -1;
//var n = Setting.BigSort ? 1 : -1;

//for (var i = 0; i < list.Count; i++)
//{
// var s = list.Count - i;
// // 当前项,排序减少
// if (EqualTo(list[i])) s -= n;
// // 上一项是当前项,排序增加
// if (i >= 1 && EqualTo(list[i - 1])) s += n;
// list[i].Sort = s;
//}
//list.Save();

// 跟前一个交换位置
for (var i = 0; i < list.Count; i++)
{
var s = list.Count - i;
// 当前项,排序减少
if (EqualTo(list[i])) s -= n;
// 上一项是当前项,排序增加
if (i >= 1 && EqualTo(list[i - 1])) s += n;
list[i].Sort = s;
var cur = list[i];
if (i < list.Count - 1 && EqualTo(cur))
{
var next = list[i + 1];
(next.Sort, cur.Sort) = (cur.Sort, next.Sort);

cur.Update();
next.Update();
}
}
list.Save();
}

Boolean EqualTo(IEntity entity)
Expand All @@ -560,8 +588,8 @@ public override Boolean Valid(DataMethod method)

if (!base.Valid(method)) return false;

var key = (TKey)this[Setting.Key];
var pkey = (TKey)this[Setting.Parent];
var key = (TKey)this[Setting.Key]!;
var pkey = (TKey)this[Setting.Parent]!;

var isnull = IsNull(key);
var pisnull = IsNull(pkey);
Expand Down Expand Up @@ -624,7 +652,7 @@ private static Boolean IsNull(TKey value)

#region IEntityTree 成员
/// <summary>父实体</summary>
IEntity IEntityTree.Parent => Parent;
IEntity? IEntityTree.Parent => Parent;

/// <summary>子实体集合</summary>
IList<IEntity> IEntityTree.Childs => Childs.Cast<IEntity>().ToList();
Expand Down
46 changes: 21 additions & 25 deletions XCode/Tree/IEntityTree.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
using System;
using System.Collections.Generic;
namespace XCode;

namespace XCode
/// <summary>实体树接口</summary>
public interface IEntityTree : IEntity
{
/// <summary>实体树接口</summary>
public interface IEntityTree : IEntity
{
#region 属性
/// <summary>父实体</summary>
IEntity Parent { get; }
#region 属性
/// <summary>父实体</summary>
IEntity? Parent { get; }

/// <summary>子实体集合</summary>
IList<IEntity> Childs { get; }
/// <summary>子实体集合</summary>
IList<IEntity> Childs { get; }

/// <summary>子孙实体集合。以深度层次树结构输出</summary>
IList<IEntity> AllChilds { get; }
/// <summary>子孙实体集合。以深度层次树结构输出</summary>
IList<IEntity> AllChilds { get; }

/// <summary>父亲实体集合。以深度层次树结构输出</summary>
IList<IEntity> AllParents { get; }
/// <summary>父亲实体集合。以深度层次树结构输出</summary>
IList<IEntity> AllParents { get; }

/// <summary>深度</summary>
Int32 Deepth { get; }
/// <summary>深度</summary>
Int32 Deepth { get; }

/// <summary>树形节点名,根据深度带全角空格前缀</summary>
String TreeNodeText { get; }
/// <summary>树形节点名,根据深度带全角空格前缀</summary>
String TreeNodeText { get; }

/// <summary>获取完整树,包含根节点,排除指定分支。多用于树节点父级选择</summary>
/// <param name="exclude"></param>
/// <returns></returns>
IList<IEntity> FindAllChildsExcept(IEntityTree exclude);
#endregion
}
/// <summary>获取完整树,包含根节点,排除指定分支。多用于树节点父级选择</summary>
/// <param name="exclude"></param>
/// <returns></returns>
IList<IEntity> FindAllChildsExcept(IEntityTree exclude);
#endregion
}

0 comments on commit 0b24d1f

Please sign in to comment.