• C#之组织树生成之道


           最近公司来了一个小的项目。项目组成员就六个。几个新人,项目经理也不知道看没有看式样。就把一个权限设置页面分给了一个新人来做。那个新人能力不是太好,项目经理也不管。分Task,也不管别人会不会。二话不说,上来就开工。

           这个新人做了两天都没有做出来。于是来求助我。花了一个多小时,总算搞定了。看了看代码,有些地方还是很值得对C#和JSON不了解的童鞋们借鉴的。今天把代码分享出来。

           先说说这个权限生成的几个需求。

           数据源是从数据库读出来的。数据的结构是这样的。有个treePath,里面的存的数据是这样的。

           通过“/”表明数据的组织层次结构,也就是说如果没有“/”就表明是根节点,如果有一个“/”就表明是第二层结构。这样以此类推。每一个“/”前数据表明其父节点是哪一个。就好比这样的一对数据:

           10001

           10001/10002 

           10001/10002/1003

           10001/10003/1003

           20001

           20001/20002

           组织结构就如下了:

           

            相信大家都明白了,接下来看看我们最后要生成的结果图:

                    

               好了生成的图大家也明白了。就是这样的树状图。

               下面我来说说我们实现的代码思路。首先把数据从库里面读出来。然后分析数据,最后生成JOSN对象文件,然后前台进行分析这个JSON对象数据。最后生成我们的树状图。

                我们直接来看看代码:

                代码中我定义了一个两个类,用来存储数据的。请看这两个类:

               

     1 /// <summary>
     2 /// 组织数据
     3 /// </summary>
     4 public class Organization
     5 {
     6     public string OrganKey { get; set; }
     7 
     8     public string OrganName { get; set; }
     9 
    10     public string TreePath { get; set; }
    11 
    12     public Organization(string organKey, string organName, string treePath)
    13     {
    14         this.OrganKey = organKey;
    15         this.OrganName = organName;
    16         this.TreePath = treePath;
    17     }
    18 }
    19 
    20 /// <summary>
    21 /// 最终的数据结构类型
    22 /// </summary>
    23 public class OrganizationResult
    24 {
    25 
    26     private List<OrganizationResult> lstChildren = new List<OrganizationResult>();
    27 
    28     /// <summary>
    29     /// 主键KEY
    30     /// </summary>
    31     public string Key { get; set; }
    32 
    33     /// <summary>
    34     /// 主键Name
    35     /// </summary>
    36     public string Name { get; set; }
    37 
    38     /// <summary>
    39     /// 获取字节点的个数
    40     /// </summary>
    41     /// <returns></returns>
    42     public int GetChildNodesCount()
    43     {
    44         return lstChildren.Count;
    45     }
    46 
    47     public string levelKey { get; set; }
    48 
    49     /// <summary>
    50     /// 构造初始化
    51     /// </summary>
    52     /// <param name="key"></param>
    53     /// <param name="name"></param>
    54     /// <param name="levelKey"></param>
    55     public OrganizationResult(string key, string name, string levelKey)
    56     {
    57         this.Key = key;
    58         this.Name = name;
    59         this.levelKey = levelKey;
    60     }
    61 
    62     /// <summary>
    63     /// 添加子节点
    64     /// </summary>
    65     /// <param name="child"></param>
    66     public void AddChildNodes(OrganizationResult child)
    67     {
    68         this.lstChildren.Add(child);
    69     }
    70 
    71     /// <summary>
    72     /// 根据路径获取节点
    73     /// </summary>
    74     /// <param name="index"></param>
    75     /// <returns></returns>
    76     public OrganizationResult GetChildNodesByIndex(int index)
    77     {
    78         if (this.GetChildNodesCount() < index)
    79         {
    
    80             return null;
    81         }
    82         else
    83         {
    84             return lstChildren[index];
    85         }
    86     }
    87 
    88     /// <summary>
    89     /// 获取所有的子节点
    90     /// </summary>
    91     /// <returns></returns>
    92     public List<OrganizationResult> GetChildNodes()
    93     {
    94         return lstChildren;
    95     }
    96 }

                  这个OrganizationResult是最终存放我们要的数据类。
                  下面是我们的数据处理方法:(请看代码)

    View Code
      1 public partial class Index : System.Web.UI.Page
      2 {
      3     /// <summary>
      4     /// 数据集合
      5     /// </summary>
      6     private List<Organization> lstData;
      7 
      8     protected void Page_Load(object sender, EventArgs e)
      9     {
     10         if (!IsPostBack)
     11         {
     12             this.SetOrganziationData();
     13 
     14             List<OrganizationResult> lstResult = this.ResolveOrganization(lstData);
     15 
     16             this.CreateJsonFile(this.CreateJson(lstResult));
     17         }
     18     }
     19 
     20     #region 组织架构的分析
     21     /// <summary>
     22     /// 解析组织架构
     23     /// </summary>
     24     /// <param name="lstData"></param>
     25     /// <returns></returns>
     26     private List<OrganizationResult> ResolveOrganization(List<Organization> lstData)
     27     {
     28         List<OrganizationResult> lstOrganizationResult = new List<OrganizationResult>();
     29 
     30         Dictionary<int, List<Organization>> dicLevelData = new Dictionary<int, List<Organization>>();
     31 
     32         foreach (Organization item in lstData)
     33         {
     34             int level = item.TreePath.Split('/').Length;
     35 
     36             if (dicLevelData.ContainsKey(level))
     37             {
     38                 dicLevelData[level].Add(item);
     39             }
     40             else
     41             {
     42                 dicLevelData.Add(level, new List<Organization>() { item });
     43             }
     44         }
     45 
     46         // 根据键值排序
     47         dicLevelData = dicLevelData.OrderBy(c => c.Key).ToDictionary(k => k.Key, k => k.Value);
     48 
     49         foreach (int key in dicLevelData.Keys)
     50         {
     51             foreach (Organization item in dicLevelData[key])
     52             {
     53                 this.InsertOrganizationResult(key, item, lstOrganizationResult);
     54             }
     55         }
     56 
     57         return lstOrganizationResult;
     58     }
     59 
     60     /// <summary>
     61     /// 设置组织结构
     62     /// </summary>
     63     /// <param name="organizationLevel"></param>
     64     /// <param name="item"></param>
     65     /// <param name="lstOrganizaitonResult"></param>
     66     private void InsertOrganizationResult(int organizationLevel, Organization item, List<OrganizationResult> lstOrganizaitonResult)
     67     {
     68         // 如果属于根目录
     69         if (organizationLevel == 1)
     70         {
     71             lstOrganizaitonResult.Add(this.InitOrganizationResult(item));
     72             return;
     73         }
     74 
     75         // 如果不属于根目录
     76         string[] treePath = item.TreePath.Split('/');
     77         List<int> lstLevel = new List<int>();
     78         this.FindParentPath(lstOrganizaitonResult, lstLevel, treePath);
     79         List<OrganizationResult> lstChildrenTemp = lstOrganizaitonResult;
     80         foreach (int level in lstLevel)
     81         {
     82             if (lstOrganizaitonResult[level].GetChildNodesCount() == 0)
     83             {
     84                 lstChildrenTemp = lstOrganizaitonResult[level].GetChildNodes();
     85             }
     86             else
     87             {
     88                 lstChildrenTemp = lstChildrenTemp[level].GetChildNodes();
     89             }
     90         }
     91 
     92         lstChildrenTemp.Add(this.InitOrganizationResult(item));
     93     }
     94 
     95     /// <summary>
     96     /// 获取根目录父节点和父节点的位置
     97     /// </summary>
     98     /// <param name="lstOrganizaitonResult"></param>
     99     /// <param name="parentIndex"></param>
    100     /// <param name="childIndex"></param>
    101     /// <param name="treePath"></param>
    102     private void FindParentPath(List<OrganizationResult> lstOrganizaitonResult, List<int> lstLevel, string[] treePath)
    103     {
    104         for (int rootIndex = 0; rootIndex < lstOrganizaitonResult.Count; rootIndex++)
    105         {
    106             string levelKey = lstOrganizaitonResult[rootIndex].levelKey;
    107 
    108             // 找到第一任父节点继续往下找
    109             if (treePath[0] == levelKey)
    110             {
    111                 lstLevel.Add(rootIndex);
    112 
    113                 if (treePath.Length == 1)
    114                 {
    115                     return;
    116                 }
    117 
    118                 // 如果不存在子节点,则直接添加
    119                 if (lstOrganizaitonResult[rootIndex].GetChildNodesCount() == 0)
    120                 {
    121                     return;
    122                 }
    123 
    124                 string[] tempLevel = new string[treePath.Length - 1];
    125                 Array.Copy(treePath, 1, tempLevel, 0, tempLevel.Length);
    126                 this.FindParentPath(lstOrganizaitonResult[rootIndex].GetChildNodes(), lstLevel, tempLevel);
    127                 return;
    128             }
    129             else
    130             {
    131                 continue;
    132             }
    133         }
    134     }
    135 
    136     /// <summary>
    137     /// 初始化一个组织结果数据
    138     /// </summary>
    139     /// <param name="key"></param>
    140     /// <param name="name"></param>
    141     /// <returns></returns>
    142     private OrganizationResult InitOrganizationResult(string key, string name, string parentKey)
    143     {
    144         return new OrganizationResult(key, name, parentKey);
    145     }
    146 
    147     /// <summary>
    148     /// 初始化一个组织结果数据
    149     /// </summary>
    150     /// <param name="key"></param>
    151     /// <param name="name"></param>
    152     /// <returns></returns>
    153     private OrganizationResult InitOrganizationResult(Organization organ)
    154     {
    155         string levelKey = null;
    156         string[] tempArr = organ.TreePath.Split('/');
    157 
    158         // 设置自己属于哪一个节点
    159         if (tempArr.Length == 1)
    160         {
    161             levelKey = tempArr[0];
    162         }
    163         else
    164         {
    165             levelKey = tempArr[tempArr.Length - 1];
    166         }
    167 
    168         return new OrganizationResult(organ.OrganKey, organ.OrganName, levelKey);
    169     }
    170 
    171     /// <summary>
    172     /// 初始化数据信息
    173     /// </summary>
    174     private void SetOrganziationData()
    175     {
    176         if (lstData == null)
    177         {
    178             lstData = new List<Organization>();
    179         }
    180 
    181         lstData.AddRange(
    182             new Organization[]{
    183 
    184                     new Organization("001","年级一","00001"),
    185 
    186                     // 班级一的学生信息(年级一)
    187                     new Organization("002","班级一","00001/10001"),
    188                     new Organization("003","学生A","00001/10001/11001"),
    189                     new Organization("004","学生B","00001/10001/11002"), 
    190                    
    191                     // 班级二的学生信息(年级一)
    192                     new Organization("005","班级二","00001/10002"),
    193                     new Organization("006","学生C", "00001/10002/12001"),
    194 
    195                     new Organization("007","年级二","00002"),
    196 
    197                     // 班级一的学生信息(年级二)
    198                     new Organization("008","班级一","00002/20001"),
    199                     new Organization("009","学生D","00002/20001/12001"),
    200                     new Organization("010","学生E","00002/20001/12002"),
    201                     
    202                     // 班级二的学生信息(年级二)
    203                     new Organization("011","班级二","00002/20002"),
    204                     new Organization("012","学生F","00002/20002/20001")
    205                 }
    206         );
    207     }
    208     #endregion 组织架构的分析
    209 
    210     #region 生成JSON对象
    211 
    212     /// <summary>
    213     /// 生成JSON对象
    214     /// </summary>
    215     /// <param name="lstResult"></param>
    216     /// <returns></returns>
    217     private string CreateJson(List<OrganizationResult> lstResult)
    218     {
    219         StringBuilder strBuild = new StringBuilder("[");
    220 
    221         int index = 0;
    222 
    223         foreach (OrganizationResult item in lstResult)
    224         {
    225             if (index == 0)
    226             {
    227                 strBuild.Append(this.CreateElement(item));
    228                 strBuild.Append("\r\n");
    229             }
    230             else {
    231                 strBuild.Append(","+this.CreateElement(item));
    232                 strBuild.AppendLine("\r\n");
    233             }
    234             index++;
    235            
    236         }
    237         strBuild.AppendLine("]");
    238         return strBuild.ToString();
    239     }
    240 
    241     /// <summary>
    242     /// 创建一个对象
    243     /// </summary>
    244     /// <param name="item"></param>
    245     /// <returns></returns>
    246     private string CreateElement(OrganizationResult item)
    247     {
    248         StringBuilder strBuild = new StringBuilder("");
    249 
    250         if (item.GetChildNodesCount() != 0)
    251         {
    252             strBuild.AppendLine("{\"id\":" + "\"" + item.Key + "\",");
    253             strBuild.AppendLine("\"text\":" + "\"" + item.Name + "\",");
    254             strBuild.AppendLine("\"children\":[");
    255             bool isFirst = true;
    256 
    257             foreach (OrganizationResult element in item.GetChildNodes())
    258             {
    259                 if (isFirst)
    260                 {
    261                     strBuild.Append(this.CreateElement(element));
    262                  
    263                     isFirst = false;
    264                 }
    265                 else
    266                 {
    267                     strBuild.AppendLine("," + this.CreateElement(element));
    268                 }
    269             }
    270 
    271             strBuild.AppendLine("]}");
    272         }
    273         else
    274         {
    275             strBuild.AppendLine("{\"text\":" + "\"" + item.Name + "\"}");
    276 
    277             return strBuild.ToString();
    278         }
    279 
    280         return strBuild.ToString();
    281     }
    282     #endregion
    283 
    284     #region 创建JSON文件
    285     /// <summary>
    286     /// 创建JSON文件 
    287     /// </summary>
    288     /// <param name="fileData"></param>
    289     private void CreateJsonFile(String fileData)
    290     {
    291         string filePath = System.AppDomain.CurrentDomain.BaseDirectory + "data/tree_data.json";
    292 
    293         if (File.Exists(filePath))
    294         {
    295             File.Delete(filePath);
    296         }
    297 
    298         using (StreamWriter sw = new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write), System.Text.Encoding.UTF8))
    299         {
    300             sw.WriteLine(fileData);
    301         }
    302     }
    303     #endregion
    304 }
    305 
    306 /// <summary>
    307 /// 组织数据
    308 /// </summary>
    309 public class Organization
    310 {
    311     public string OrganKey { get; set; }
    312 
    313     public string OrganName { get; set; }
    314 
    315     public string TreePath { get; set; }
    316 
    317     public Organization(string organKey, string organName, string treePath)
    318     {
    319         this.OrganKey = organKey;
    320         this.OrganName = organName;
    321         this.TreePath = treePath;
    322     }
    323 }


                  上面的代码就是我们主要的逻辑代码。在上面代码中采用了Linq数据排序,函数递归等一些常用的开发技巧。相信大家看看注释应该就明白了。如果有不明白的地方,可以来拍砖,我会给大家解释。

                   关于前台部分就是利用JQuery进行分析JSON,大家可以按照自己的想法去实现。

                   好了,今晚就到这里,还有其他的东西要弄。下次见,我的朋友。

                 

          

  • 相关阅读:
    jquery几款不错的插件
    jQuery 闭包
    SQL高手篇:精典SQL FAQ收藏
    完美解决Excel的连接字符串与上传方法
    文件流高级压缩文件和解压缩
    jquery弹窗插件jqueryimpromptu.4.0.js
    SQL Server 2008删除行出现错误“已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行”
    那些天我们经历的实时错误—StudentMis小结
    基础很重要,查询如何“组合”!谈谈组合查询
    探究Null、Empty、VbNullstring、Nothing的异同
  • 原文地址:https://www.cnblogs.com/heardawn/p/2700871.html
Copyright © 2020-2023  润新知