1. 程式人生 > >系統操作日誌表單形式構建

系統操作日誌表單形式構建

1.概述

     所謂操作日誌,就是某人對指定模組的指定物件進行操作的記錄,在某種情況下,可能會有顯示本次操作對哪些資料欄位進行啦了動,或者是操作前後該模型的資料比對情況。針對於這類需求,想要檢視某條操作記錄具體改動項資訊的時候,對於前端來講,他不需要知道這個物件的具體型別及各個欄位的意義的漢字描述,他們只需要迴圈遍歷,將所有的資料拼到一個div容器裡即可。後臺該如何去設計才能做到最簡化的操作那?第一種情況可以用列舉的形式,來標記每種模型的型別,在每次記錄日誌的時候,可以將當前列舉也記錄進去(資料庫/nosql),這樣的話,在檢視每種記錄變動的詳情時,就可以根據每種型別封裝不同的拼接資料的策略,最終以統一的格式返回給前端。但是,這種操作起來並不是很理想,沒實現一種模組的操作都要實現對應的表單項拼接策略,顯然以後維護起來並不是十分的完美。那麼,能不能通過反射的形式來根絕具體的模型名稱動態的獲取模型型別,並根據具體的型別和json資料來形成物件,從而完成表單項的構建那??答案是:可以的(c#中可以根據Type type = Type.GetType(FullTypeName);類實現)。下面我們就先實現一下獲取當前操作模型具體操作操作記錄。

2.需求分析及實現

    1.前端需要展示成這樣:

       2.後臺程式碼設定

     

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace ConsoleApp1.OpearorLog.Entity
9 { 10 public class ColumnRenark : Attribute 11 { 12 /// <summary> 13 /// 欄位名稱 14 /// </summary> 15 public string ColumnName { get; set; } 16 /// <summary> 17 /// 欄位型別 18 /// </summary> 19 public ColumnType ColumnType { get; set
; } 20 21 22 public ColumnRenark() { } 23 } 24 public enum ColumnType 25 { 26 [Description("基礎型別(int/string...)")] 27 Basic = 0, 28 [Description("類型別")] 29 Class = 1, 30 [Description("字典型別")] 31 Dic = 2, 32 [Description("列表型別")] 33 Lst = 3, 34 35 36 } 37 }
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1.OpearorLog.Entity
{
    /// <summary>
    ///行記錄
    /// </summary>
    public class RowRecord
    {
        /// <summary>
        /// 欄位語義
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 欄位對應值
        /// </summary>
        public string Value { get; set; }
        /// <summary>
        /// 所屬層級
        /// </summary>
        public int Lev { get; set; }
        /// <summary>
        /// 包含的子項
        /// </summary>
        public List<List<RowRecord>> Child { get; set; }

        public RowRecord()
        {
            Child = new List<List<RowRecord>>();
        }

    }
}
View Code
  1 using Newtonsoft.Json;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 using System.Runtime.InteropServices;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 
  9 namespace ConsoleApp1
 10 {
 11   public  class OperatorLogContext
 12     {
 13         #region attr
 14         private List<RowRecord> RowRecords { get; set; }
 15         private object Obj { get; set; }
 16         public string FullTypeName { get; set; }
 17         public string JsonStr { get; set; }
 18         #endregion
 19 
 20         public OperatorLogContext(string fullTypeName,string jsonStr)
 21         {
 22             FullTypeName = fullTypeName;
 23             JsonStr = jsonStr;
 24             RowRecords = new List<RowRecord>();
 25             Type type = Type.GetType(FullTypeName);
 26             Obj = JsonConvert.DeserializeObject(JsonStr,type);
 27         }
 28         public OperatorLogContext()
 29         {
 30             Type type = Type.GetType(FullTypeName);
 31             Obj = JsonConvert.DeserializeObject(JsonStr, type);
 32         }
 33         /// <summary>
 34         /// 構建表單項
 35         /// </summary>
 36         /// <returns></returns>
 37         public List<RowRecord> BuildForm()
 38         {
 39             return Build(Obj);
 40         }
 41         #region private
 42         private List<RowRecord> Build(object obj, RowRecord parentRow = null, List<RowRecord> childRow = null, int lev = 0)
 43         {
 44             //1.當前型別
 45             Type currentType = obj.GetType();
 46             //2.獲取當下模型的所有屬性欄位
 47             var props = currentType.GetProperties();
 48             foreach (var prop in props)
 49             {
 50                 RowRecord rowRecord = new RowRecord();
 51                 rowRecord.Lev = lev;   //設定當前樹形級別
 52                 //3.獲取當下屬性欄位下的所有自定義屬性
 53                 var attr = prop.CustomAttributes.FirstOrDefault(o => o.AttributeType == typeof(ColumnRenark));
 54                 if (attr == null)
 55                 {
 56                     continue;
 57                 }
 58                 else
 59                 {
 60                     foreach (var named in attr.NamedArguments)
 61                     {
 62                         if (named.MemberName == "ColumnName")
 63                         {
 64                             rowRecord.Key = named.TypedValue.Value.ToString();
 65                         }
 66                         else if (named.MemberName == "ColumnType")
 67                         {
 68                             ColumnType columnType = (ColumnType)Enum.Parse(typeof(ColumnType), named.TypedValue.Value.ToString());
 69                             switch (columnType)
 70                             {
 71                                 case ColumnType.Basic:
 72                                     rowRecord.Value = prop.GetValue(obj).ToString();
 73                                     break;
 74                                 case ColumnType.Class:
 75                                     Build(prop.GetValue(obj), rowRecord, new List<RowRecord>());
 76                                     break;
 77                                 case ColumnType.Lst:
 78                                     var currentLst = (IEnumerable<object>)prop.GetValue(obj);
 79 
 80                                     foreach (var opt in currentLst)
 81                                     {
 82 
 83                                         Build(opt, rowRecord, new List<RowRecord>());
 84                                     }
 85                                     break;
 86                             }
 87                         }
 88                     }
 89                 }
 90 
 91                 if (parentRow != null)
 92                 {
 93                     rowRecord.Lev = parentRow.Lev + 1;
 94                     childRow.Add(rowRecord);
 95                 }
 96                 else
 97                 {
 98                     RowRecords.Add(rowRecord);
 99                 }
100             }
101             if (childRow != null)
102             {
103                 parentRow.Child.Add(childRow);
104             }
105             return RowRecords;
106         }
107         #endregion
108 
109     }
110 }
View Code
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            user.Age = 20;
            user.Name = "lsh";
            user.Book = new Book()
            {
                Name = "c#從入門指南",
                Desc = "書籍描述"
            };
            user.Hobby = new List<Hobby>() {
                new Hobby() { Name = "讀書", Rate = "89%" },
                new Hobby() { Name = "旅遊", Rate = "33%" }
            };
            string json = JsonConvert.SerializeObject(user);
            var lst = new OperatorLogContext("ConsoleApp1.User", json).BuildForm();
            Console.ReadKey();
        }
    }
    public class User
    {
        [ColumnRenark(ColumnName = "姓名", ColumnType = ColumnType.Basic)]
        public string Name { get; set; }
        [ColumnRenark(ColumnName = "年齡", ColumnType = ColumnType.Basic)]
        public int Age { get; set; }
        [ColumnRenark(ColumnName = "書籍", ColumnType = ColumnType.Class)]
        public Book Book { get; set; }
        [ColumnRenark(ColumnName = "愛好", ColumnType = ColumnType.Lst)]
        public List<Hobby> Hobby { get; set; }

    }
    public class Hobby
    {
        [ColumnRenark(ColumnName = "愛好名", ColumnType = ColumnType.Basic)]
        public string Name { get; set; }
        [ColumnRenark(ColumnName = "比率", ColumnType = ColumnType.Basic)]
        public string Rate { get; set; }
    }
    /// <summary>
    /// 行元素
    /// </summary>
    public class RowRecord
    {
        public string Key { get; set; }
        public string Value { get; set; }
        public int Lev { get; set; }
        public List<List<RowRecord>> Child { get; set; }

        public RowRecord()
        {
            Child = new List<List<RowRecord>>();
        }
    }
    public class Book
    {
        [ColumnRenark(ColumnName = "書名", ColumnType = ColumnType.Basic)]
        public string Name { get; set; }
        [ColumnRenark(ColumnName = "書描述", ColumnType = ColumnType.Basic)]
        public string Desc { get; set; }
    }
    /// <summary>
    /// 欄位標記屬性
    /// </summary>
    public class ColumnRenark : Attribute
    {
        /// <summary>
        /// 欄位名稱
        /// </summary>
        public string ColumnName { get; set; }
        /// <summary>
        /// 欄位型別
        /// </summary>
        public ColumnType ColumnType { get; set; }


        public ColumnRenark() { }
    }

    public enum ColumnType
    {
        [Description("基礎型別(int/string...)")]
        Basic = 0,
        [Description("類型別")]
        Class = 1,
        [Description("字典型別")]
        Dic = 2,
        [Description("列表型別")]
        Lst = 3,


    }
}
View Code

3.測試結果