From 78b5e0a2e4c48239983e236c48f8c0b897d69f9e Mon Sep 17 00:00:00 2001
From: sunpengfei <i@angelzzz.com>
Date: 星期二, 09 九月 2025 09:38:00 +0800
Subject: [PATCH] feat:开发

---
 FlexJobApi.Core/Utils/DbUtils/DbUtils.cs |  569 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 485 insertions(+), 84 deletions(-)

diff --git a/FlexJobApi.Core/Utils/DbUtils/DbUtils.cs b/FlexJobApi.Core/Utils/DbUtils/DbUtils.cs
index 1547067..e8e12e3 100644
--- a/FlexJobApi.Core/Utils/DbUtils/DbUtils.cs
+++ b/FlexJobApi.Core/Utils/DbUtils/DbUtils.cs
@@ -1,72 +1,465 @@
-锘縰sing Furion;
+锘縰sing Consul.Filtering;
+using Furion;
 using Furion.DatabaseAccessor;
 using Furion.DistributedIDGenerator;
+using Furion.FriendlyException;
+using Mapster;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.ChangeTracking;
 using Microsoft.EntityFrameworkCore.Diagnostics;
 using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.Extensions.Configuration;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
 using System.Text;
+using System.Threading;
 using System.Threading.Tasks;
+using System.Timers;
 
 namespace FlexJobApi.Core
 {
+    /// <summary>
+    /// 鏁版嵁搴撳伐鍏�
+    /// </summary>
     public static class DbUtils
     {
         /// <summary>
-        /// 鐢熸垚瀹炰綋娉ㄩ噴
+        /// 鑾峰彇鏍戝舰鏁版嵁璺緞
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <param name="parentId"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<string> GetTreeDataPath<TEntity>(
+             Guid? parentId,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, ITreeData<TEntity>, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            if (parentId.HasValue)
+            {
+                var parent = await rep.AsQueryable().AsNoTracking()
+                    .Where(it => it.Id == parentId)
+                    .Select(it => new
+                    {
+                        it.Path,
+                        it.Code
+                    })
+                    .FirstOrDefaultAsync(cancellationToken);
+                var summary = typeof(TEntity).GetSummary();
+                if (parent == null) throw Oops.Oh(EnumErrorCodeType.s404, $"涓婄骇{summary}");
+                return $"{parent.Path}{parent.Code}/";
+            }
+            else
+            {
+                return "/";
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊鏍戝舰鏁版嵁涓嬬骇璺緞
+        /// </summary>
+        /// <param name="oldPath"></param>
+        /// <param name="newPath"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task UpdateTreeDataChildrenPath<TEntity>(
+            string oldPath,
+            string newPath,
+            CancellationToken cancellationToken)
+            where TEntity : CommonEntity, ITreeData<TEntity>, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var models = await rep.AsQueryable()
+                .Where(it => it.Path.StartsWith(oldPath))
+                .ToListAsync(cancellationToken);
+            if (models.IsNotNull())
+            {
+                foreach (var model in models)
+                {
+                    model.Path = model.Path.Replace(oldPath, newPath);
+                }
+                await rep.UpdateAsync(models);
+            }
+        }
+
+        /// <summary>
+        /// 鏌ヨ閫夋嫨鍣ㄦ暟鎹�
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <typeparam name="TValue"></typeparam>
+        /// <typeparam name="TData"></typeparam>
+        /// <param name="request"></param>
+        /// <param name="getValue"></param>
+        /// <param name="getLabel"></param>
+        /// <param name="query"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<List<SelectOption<TValue, TData>>> GetSelect<TEntity, TValue, TData>(
+            this SelectQuery<TValue, TData> request,
+            Func<TData, TValue> getValue,
+            Func<TData, string> getLabel,
+            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var q = rep.AsQueryable().AsNoTracking();
+            if (query != null) q = query(q);
+            else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
+            var models = await q
+                .ProjectToType<TData>()
+                .ToListAsync(cancellationToken);
+            var options = new List<SelectOption<TValue, TData>>();
+            foreach (var model in models)
+            {
+                var option = new SelectOption<TValue, TData>();
+                option.Data = model;
+                option.Value = getValue(model);
+                option.Label = getLabel(model);
+                options.Add(option);
+            }
+            return options;
+        }
+
+        /// <summary>
+        /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <typeparam name="TItem"></typeparam>
+        /// <param name="page"></param>
+        /// <param name="query"></param>
+        /// <param name="selector"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<PagedListQueryResult<TItem>> GetPagedListAsync<TEntity, TItem>(
+            this PagedListQueryPageModel page,
+            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+            Expression<Func<TEntity, TItem>> selector = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+            where TItem : class, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var q = rep.AsQueryable().AsNoTracking();
+            if (query != null) q = query(q);
+            else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
+            if (page.OrderInput.IsNotNull())
+                q = q.CustomOrderBy(page.OrderInput);
+            var s = selector == null
+                ? q.ProjectToType<TItem>()
+                : q.Select(selector);
+            var pagedList = await s.ToPagedListAsync(page.Page, page.Rows, cancellationToken);
+            var result = new PagedListQueryResult<TItem>();
+            result.PageModel = page.Adapt<PagedListQueryResultPageModel>();
+            result.PageModel.TotalCount = pagedList.TotalCount;
+            result.PageModel.TotalPage = pagedList.TotalPages;
+            result.Data = pagedList.Items.ToList();
+            return result;
+        }
+        /// <summary>
+        /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+        /// </summary>
+        /// <typeparam name="TResult"></typeparam>
+        /// <typeparam name="TItem"></typeparam>
+        /// <param name="page"></param>
+        /// <param name="q"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<TResult> GetPagedListAsync<TResult, TItem>(
+            this PagedListQueryPageModel page,
+            IQueryable<TItem> q,
+            CancellationToken cancellationToken = default)
+            where TItem : class, new()
+            where TResult : PagedListQueryResult<TItem>, new()
+        {
+            if (page.OrderInput.IsNotNull())
+                q = q.CustomOrderBy(page.OrderInput);
+            var pagedList = await q.ToPagedListAsync(page.Page, page.Rows, cancellationToken);
+            var result = new TResult();
+            result.PageModel = page.Adapt<PagedListQueryResultPageModel>();
+            result.PageModel.TotalCount = pagedList.TotalCount;
+            result.PageModel.TotalPage = pagedList.TotalPages;
+            result.Data = pagedList.Items.ToList();
+            return result;
+        }
+
+        /// <summary>
+        /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+        /// </summary>
+        /// <typeparam name="TItem"></typeparam>
+        /// <param name="page"></param>
+        /// <param name="q"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static Task<PagedListQueryResult<TItem>> GetPagedListAsync<TItem>(
+            this PagedListQueryPageModel page,
+            IQueryable<TItem> q,
+            CancellationToken cancellationToken = default)
+            where TItem : class, new()
+        {
+            return GetPagedListAsync<PagedListQueryResult<TItem>, TItem>(page, q, cancellationToken);
+        }
+
+        public static IOrderedQueryable<T> CustomOrderBy<T>(this IQueryable<T> q, List<PagedListQueryPageModelOrderInput> orders)
+        {
+            ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
+            PagedListQueryPageModelOrderInput orderInput = orders[0];
+            IOrderedQueryable<T> orderedQueryable = (orderInput.Order == EnumPagedListOrder.Asc)
+                ? OrderBy(q, orderInput.Property, parameter)
+                : OrderByDescending(q, orderInput.Property, parameter);
+            for (int i = 1; i < orders.Count; i++)
+            {
+                PagedListQueryPageModelOrderInput orderInput2 = orders[i];
+                orderedQueryable = (orderInput2.Order == EnumPagedListOrder.Asc)
+                    ? ThenBy(orderedQueryable, orderInput2.Property, parameter)
+                    : ThenByDescending(orderedQueryable, orderInput2.Property, parameter);
+            }
+
+            return orderedQueryable;
+        }
+
+        private static IOrderedQueryable<T> Ordering<T>(IQueryable<T> source, ParameterExpression parameter, string propertyName, string methodName)
+        {
+            Type typeFromHandle = typeof(T);
+            MemberExpression memberExpression = Expression.PropertyOrField(parameter, propertyName);
+            LambdaExpression expression = Expression.Lambda(memberExpression, parameter);
+            MethodCallExpression expression2 = Expression.Call(typeof(Queryable), methodName, [typeFromHandle, memberExpression.Type], source.Expression, Expression.Quote(expression));
+            return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(expression2);
+        }
+
+        public static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> source, string propertyName, ParameterExpression parameter)
+        {
+            return Ordering(source, parameter, propertyName, "OrderBy");
+        }
+
+        public static IOrderedQueryable<T> OrderByDescending<T>(IQueryable<T> source, string propertyName, ParameterExpression parameter)
+        {
+            return Ordering(source, parameter, propertyName, "OrderByDescending");
+        }
+
+        public static IOrderedQueryable<T> ThenBy<T>(IOrderedQueryable<T> source, string propertyName, ParameterExpression parameter)
+        {
+            return Ordering(source, parameter, propertyName, "ThenBy");
+        }
+
+        public static IOrderedQueryable<T> ThenByDescending<T>(IOrderedQueryable<T> source, string propertyName, ParameterExpression parameter)
+        {
+            return Ordering(source, parameter, propertyName, "ThenByDescending");
+        }
+
+        public static async Task<TResult> GetDetail<TEntity, TResult>(
+            this Guid id,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            return await rep.AsQueryable().AsNoTracking()
+                .Where(it => it.Id == id)
+                .GetDetail<TEntity, TResult>(cancellationToken);
+        }
+
+        public static async Task<TResult> GetDetail<TEntity, TResult>(
+            this IQueryable<TEntity> q,
+            CancellationToken cancellationToken = default)
+        {
+            var model = await q
+                .ProjectToType<TResult>()
+                .FirstOrDefaultAsync(cancellationToken);
+            if (model == null)
+            {
+                var summary = await typeof(TEntity).GetSummary();
+                throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+            }
+            return model;
+        }
+
+        /// <summary>
+        /// 璁剧疆鏄惁绂佺敤
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <param name="request"></param>
+        /// <param name="query"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<int> SetIsDisabled<TEntity>(
+            this SetIsDisabledCommand request,
+            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, IIsDisabled, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var q = rep.AsQueryable();
+            if (query != null) q = query(q);
+            var entities = await q
+                .Where(it => request.Ids.Contains(it.Id) && it.IsDisabled != request.IsDisabled)
+                .ToListAsync();
+            foreach (var entity in entities)
+            {
+                entity.IsDisabled = request.IsDisabled;
+            }
+            return entities.Count;
+        }
+
+        /// <summary>
+        /// 鍒犻櫎鏁版嵁
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <param name="request"></param>
+        /// <param name="query"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<int> DeleteData<TEntity>(
+            this DeleteDataCommand request, Func<IQueryable<TEntity>,
+            IQueryable<TEntity>> query = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var q = rep.AsQueryable();
+            if (query != null) q = query(q);
+            var entities = await q
+                .Where(it => request.Ids.Contains(it.Id))
+                .ToListAsync(cancellationToken);
+            return entities.Any()
+                ? await rep.DeleteNowAsync(entities, cancellationToken)
+                : 0;
+        }
+
+        public static async Task<Guid> UpdateData<TEntity, TRequest>(
+            this IQueryable<TEntity> q,
+            TRequest request,
+            Action<TEntity> update = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+        {
+            var rep = Db.GetRepository<TEntity>();
+            var entity = await q.FirstOrDefaultAsync();
+            if (entity == null)
+            {
+                var summary = await typeof(TEntity).GetSummary();
+                throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+            }
+
+            if (update != null) update(entity);
+            else request.Adapt(entity);
+            await rep.UpdateAsync(entity);
+            return entity.Id;
+        }
+
+        /// <summary>
+        /// 淇濆瓨鏁版嵁
+        /// </summary>
+        /// <typeparam name="TEntity"></typeparam>
+        /// <typeparam name="TRequest"></typeparam>
+        /// <param name="request"></param>
+        /// <param name="query"></param>
+        /// <param name="checkExist"></param>
+        /// <param name="update"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        public static async Task<TEntity> SaveData<TEntity, TRequest>(
+            this TRequest request,
+            Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+            Expression<Func<TEntity, bool>> checkExist = null,
+            Action<TEntity> update = null,
+            CancellationToken cancellationToken = default)
+            where TEntity : CommonEntity, new()
+            where TRequest : SaveDataCommand, new()
+        {
+            var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+            var summary = await typeof(TEntity).GetSummary(xmlDoc);
+            var rep = Db.GetRepository<TEntity>();
+            if (checkExist != null && await rep.AsQueryable().AsNoTracking().AnyAsync(checkExist))
+                throw Oops.Oh(EnumErrorCodeType.s405, $"{summary ?? "淇℃伅"}");
+            if (request.Id.HasValue)
+            {
+                var q = rep.AsQueryable();
+                if (query != null) q = query(q);
+                var entity = await q.FirstOrDefaultAsync(it => it.Id == request.Id, cancellationToken);
+                if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+                if (update != null) update(entity);
+                else request.Adapt(entity);
+                await rep.UpdateAsync(entity);
+                return entity;
+            }
+            else
+            {
+                var entity = new TEntity();
+                if (update != null) update(entity);
+                else request.Adapt(entity);
+                await rep.InsertAsync(entity);
+                return entity;
+            }
+        }
+
+        /// <summary>
+        /// 鐢熸垚瀹炰綋
         /// </summary>
         /// <param name="modelBuilder"></param>
         /// <param name="dbContextLocator"></param>
         /// <returns></returns>
-        public static async Task BuildEntityComment(ModelBuilder modelBuilder, Type dbContextLocator = null)
+        public static async Task BuildEntity(ModelBuilder modelBuilder, Type dbContextLocator = null)
         {
-            var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
-            var entityTypes = App.Assemblies
-                .Where(it => it.FullName.Contains("FlexJob"))
-                .SelectMany(it => it.GetTypes())
-                .Where(it =>
-                    it.IsClass
-                    && !it.IsAbstract
-                    && typeof(IPrivateEntity).IsAssignableFrom(it)
-                    && (dbContextLocator == null
-                    ? it.BaseType == typeof(CommonEntity)
-                    : it.BaseType.GenericTypeArguments.Any(it => it == dbContextLocator)))
-                .ToList();
-            foreach (var entityType in entityTypes)
+            if (App.GetService<IMigrator>() != null)
             {
-                Console.WriteLine($"姝e湪鐢熸垚琛細{entityType.Name}");
-                // 鑾峰彇瀹炰綋绫荤殑XML娉ㄩ噴锛屽苟璁剧疆涓鸿〃娉ㄩ噴
-                var entityBuilder = modelBuilder.Entity(entityType);
-                string typeComment = (await entityType.GetXmlDocMemberAsync(xmlDoc))?.Summary;
-                if (!string.IsNullOrEmpty(typeComment))
+                var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+                foreach (var entityType in modelBuilder.Model.GetEntityTypes())
                 {
-                    Console.WriteLine($"姝e湪鐢熸垚琛ㄦ敞閲婏細{entityType.Name}-{typeComment}");
-                    entityBuilder.ToTable(it => it.HasComment(typeComment));
-                }
-                // 鑾峰彇瀹炰綋灞炴�х殑XML娉ㄩ噴锛屽苟璁剧疆涓哄垪娉ㄩ噴
-                var properties = entityType.GetProperties()
-                    .Where(p =>
-                        p.CanRead
-                        && p.CanWrite
-                        && !typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType)
-                        && (p.PropertyType.IsClass ? p.PropertyType.FullName.Contains("System.") : true));
-                foreach (var property in properties)
-                {
-                    string propComment = (await property.GetXmlDocMemberAsync(xmlDoc))?.Summary;
-                    if (!string.IsNullOrEmpty(propComment))
+                    Console.WriteLine($"姝e湪鐢熸垚琛細{entityType.Name}");
+                    // 鑾峰彇瀹炰綋绫荤殑XML娉ㄩ噴锛屽苟璁剧疆涓鸿〃娉ㄩ噴
+                    var entityBuilder = modelBuilder.Entity(entityType.ClrType);
+                    string typeComment = (await entityType.ClrType.GetXmlDocMemberAsync(xmlDoc))?.Summary;
+                    if (!string.IsNullOrEmpty(typeComment))
                     {
-                        Console.WriteLine($"姝e湪鐢熸垚灞炴�ф敞閲婏細{property.Name}-{propComment}");
-                        entityBuilder.Property(property.Name).HasComment(propComment);
+                        Console.WriteLine($"姝e湪鐢熸垚琛ㄦ敞閲婏細{entityType.Name}-{typeComment}");
+                        entityBuilder.ToTable(it => it.HasComment(typeComment));
                     }
+                    // 鑾峰彇瀹炰綋灞炴�х殑XML娉ㄩ噴锛屽苟璁剧疆涓哄垪娉ㄩ噴
+                    var properties = entityType.ClrType.GetProperties()
+                        .Where(p =>
+                            p.CanRead
+                            && p.CanWrite
+                            && !typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType)
+                            && (p.PropertyType.IsClass ? p.PropertyType.FullName.Contains("System.") : true));
+                    foreach (var property in properties)
+                    {
+                        string propComment = (await property.GetXmlDocMemberAsync(xmlDoc))?.Summary;
+                        if (!string.IsNullOrEmpty(propComment))
+                        {
+                            Console.WriteLine($"姝e湪鐢熸垚灞炴�ф敞閲婏細{property.Name}-{propComment}");
+                            entityBuilder.Property(property.Name).HasComment(propComment);
+                        }
+                    }
+                }
+            }
+
+            foreach (var entityType in modelBuilder.Model.GetEntityTypes())
+            {
+                if (typeof(CommonEntity).IsAssignableFrom(entityType.ClrType))
+                {
+                    // 鏋勫缓绛涢�夋潯浠讹細IsDeleted == false
+                    var parameter = Expression.Parameter(entityType.ClrType, "e");
+                    var property = Expression.Property(parameter, "IsDeleted");
+                    var constant = Expression.Constant(false);
+                    var equal = Expression.Equal(property, constant);
+                    var lambda = Expression.Lambda(equal, parameter);
+
+                    // 娣诲姞鍏ㄥ眬绛涢�夊櫒
+                    modelBuilder.Entity(entityType.ClrType).HasQueryFilter(lambda);
                 }
             }
         }
 
+        /// <summary>
+        /// 鏁版嵁鍙樻洿浜嬩欢
+        /// </summary>
+        /// <param name="eventData"></param>
+        /// <param name="result"></param>
         public static void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
         {
             // 鑾峰彇褰撳墠浜嬩欢瀵瑰簲涓婁笅鏂�
@@ -88,6 +481,7 @@
 
             // 閫氳繃璇锋眰涓幏鍙栧綋鍓嶆搷浣滀汉
             var logier = JwtUtils.GetCurrentLogier();
+            var traceId = App.GetTraceId();
 
             // 鑾峰彇鎵�鏈夊凡鏇存敼鐨勫疄浣�
             foreach (var entity in entities)
@@ -113,33 +507,47 @@
                     }
 
                     // 璧嬪�肩敤鎴蜂俊鎭疘d
-                    prop = entity.Property(nameof(CommonEntity.CreatedUserInfoId));
+                    prop = entity.Property(nameof(CommonEntity.CreatedUserId));
                     if (prop != null && prop.CurrentValue == null)
                     {
-                        prop.CurrentValue = logier?.UserInfoId;
+                        prop.CurrentValue = logier?.Id;
+                    }
+
+                    // 璧嬪�间紒涓欼d
+                    prop = entity.Property(nameof(CommonEntity.CreatedEnterpriseId));
+                    if (prop != null && prop.CurrentValue == null)
+                    {
+                        prop.CurrentValue = logier?.EnterpriseId;
+                    }
+
+                    // 璧嬪�艰窡韪狪d
+                    prop = entity.Property(nameof(CommonEntity.TraceId));
+                    if (prop != null && prop.CurrentValue == null && traceId.IsNotNull())
+                    {
+                        prop.CurrentValue = traceId;
                     }
                 }
                 else
                 {
                     // 璧嬪�间慨鏀规棩鏈�
                     var prop = entity.Property(nameof(CommonEntity.UpdatedTime));
-                    if (prop != null && prop.CurrentValue?.ToDateTime() == null)
+                    if (prop != null)
                     {
                         prop.CurrentValue = DateTimeOffset.Now;
                     }
 
                     // 璧嬪�肩敤鎴蜂俊鎭疘d
-                    prop = entity.Property(nameof(CommonEntity.UpdatedUserInfoId));
-                    if (prop != null && prop.CurrentValue == null)
+                    prop = entity.Property(nameof(CommonEntity.UpdatedUserId));
+                    if (prop != null)
                     {
-                        prop.CurrentValue = logier?.UserInfoId;
+                        prop.CurrentValue = logier?.Id;
                     }
 
                     // 璧嬪�艰窡韪狪d
                     prop = entity.Property(nameof(CommonEntity.TraceId));
-                    if (prop != null && prop.CurrentValue == null)
+                    if (prop != null && traceId.IsNotNull())
                     {
-                        prop.CurrentValue = App.GetTraceId();
+                        prop.CurrentValue = traceId;
                     }
 
                     // 杞垹闄�
@@ -148,7 +556,7 @@
                         entity.State = EntityState.Modified;
 
                         prop = entity.Property(nameof(CommonEntity.IsDeleted));
-                        if (prop != null && prop.CurrentValue == null)
+                        if (prop != null)
                         {
                             prop.CurrentValue = true;
                         }
@@ -160,51 +568,44 @@
                     continue;
                 }
 
-                Db.GetRepository<DbAuditLog, LogDbContextLocator>().InsertNow(new DbAuditLog
+                var log = new DbAuditLog
                 {
                     Id = IDGen.NextID(),
                     TableName = entityType.Name,
                     PrimaryKey = (Guid)entity.Property("Id").CurrentValue,
-                    NewValues = entity.State == EntityState.Added || entity.State == EntityState.Modified
-                        ? GetPropertyValuesAsJson(entity)
-                        : null,
-                    OldValues = entity.State == EntityState.Deleted || entity.State == EntityState.Modified
-                        ? GetPropertyValuesAsJson(entity, entity.State == EntityState.Modified)
-                        : null,
-                    Operate = entity.State == EntityState.Added
-                        ? EnumDbAuditOperate.Added
-                        : entity.State == EntityState.Modified
-                        ? EnumDbAuditOperate.Modified
-                        : EnumDbAuditOperate.Deleted,
                     TraceId = App.GetTraceId(),
                     CreatedTime = DateTime.Now,
-                    CreatedUserInfoId = logier?.UserInfoId,
-                });
+                    CreatedUserId = logier?.Id,
+                    CreatedEnterpriseId = logier?.EnterpriseId
+                };
+                log.Operate =
+                    entity.State == EntityState.Added
+                    ? EnumDbAuditOperate.Added
+                    : entity.State == EntityState.Modified
+                    ? EnumDbAuditOperate.Modified
+                    : EnumDbAuditOperate.Deleted;
+                if (entity.Property(nameof(CommonEntity.IsDeleted)).CurrentValue is bool isDeleted && isDeleted == true)
+                {
+                    log.Operate = EnumDbAuditOperate.Deleted;
+                }
+                log.NewValues =
+                    log.Operate == EnumDbAuditOperate.Deleted
+                    ? null
+                    : JsonConvert.SerializeObject(entity.Properties
+                        .Where(p => log.Operate == EnumDbAuditOperate.Modified
+                            ? p.IsModified
+                            : true)
+                        .ToDictionary(p => p.Metadata.Name, p => p.CurrentValue));
+                log.OldValues =
+                    log.Operate == EnumDbAuditOperate.Added
+                    ? null
+                    : JsonConvert.SerializeObject(entity.Properties
+                        .Where(p => log.Operate == EnumDbAuditOperate.Modified
+                            ? p.IsModified
+                            : true)
+                        .ToDictionary(p => p.Metadata.Name, p => p.OriginalValue));
+                Db.GetRepository<DbAuditLog, LogDbContextLocator>().InsertNow(log);
             }
-        }
-
-        private static string GetPropertyValuesAsJson(EntityEntry entry, bool getOldValues = false)
-        {
-            var properties = entry.Properties
-                .Where(p => getOldValues ? p.IsModified : true)
-                .ToDictionary(p => p.Metadata.Name, p => getOldValues ? p.OriginalValue : p.CurrentValue);
-
-            return JsonConvert.SerializeObject(properties);
-        }
-
-        public static void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)
-        {
-            var metadata = entityBuilder.Metadata;
-
-            var parameter = Expression.Parameter(metadata.ClrType, "e");
-            var property = Expression.Property(parameter, nameof(CommonEntity.IsDeleted));
-            var falseConstant = Expression.Constant(false, typeof(bool));
-            var fakeDeleteQueryFilterExpression = Expression.Lambda(
-                Expression.Equal(property, falseConstant),
-                parameter
-            );
-            if (fakeDeleteQueryFilterExpression == null) return;
-            entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);
         }
     }
 }

--
Gitblit v1.9.1