ソースを参照

canHandle相关字段冗余至流程实体

xf 1 年間 前
コミット
7559ad858d

+ 1 - 1
src/Hotline.Api/Controllers/BsController.cs

@@ -142,7 +142,7 @@ namespace Hotline.Api.Controllers
 
 
             //area7
-            var query7 = await _orderRepository.Queryable(workflowFilter: false)
+            var query7 = await _orderRepository.Queryable(viewFilter: false)
                 .GroupBy(d => d.HotspotName)
                 .Select(d => new
                 {

+ 2 - 2
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -348,7 +348,7 @@ namespace Hotline.Api.Controllers
 			var knowledge = await _knowledgeDomainService.KnowledgeInfo(Id, HttpContext.RequestAborted);
 			if (knowledge is null)
 				throw UserFriendlyException.SameMessage("知识查询失败!");
-			if (knowledge.Workflow != null ) knowledge.IsCanHandle = knowledge.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+			if (knowledge.Workflow != null ) knowledge.IsCanHandle = knowledge.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
 			//转化
 			var knowledgeShowInfoDto = _mapper.Map<KnowledgeInfoDto>(knowledge);
 
@@ -638,7 +638,7 @@ namespace Hotline.Api.Controllers
 			foreach (var item in items)
 			{
 				if (item.Workflow != null)
-					item.CanHandle = item.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+					item.CanHandle = item.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
 
 			}
 			//处理是否可以办理

+ 15 - 33
src/Hotline.Api/Controllers/OrderController.cs

@@ -213,7 +213,7 @@ public class OrderController : BaseController
             .WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
             .WhereIF(dto.PubState == EPubState.NoPub, d => d.Status < EOrderStatus.Published)
             .WhereIF(!string.IsNullOrEmpty(dto.PubMan),
-                d => d.Acceptor.Name.Contains(dto.PubMan!) || d.Acceptor.StaffNo.Contains(dto.PubMan!))
+                d => d.AcceptorName.Contains(dto.PubMan!) || d.AcceptorStaffNo.Contains(dto.PubMan!))
             .WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState)
             .WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState)
             .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.ProcessType == EProcessType.Zhiban)
@@ -434,7 +434,6 @@ public class OrderController : BaseController
     public async Task<PublishOrderPageBaseDto> PublishOrderPageBase(string id)
     {
         var order = await _orderRepository.Queryable()
-            .Includes(d => d.Acceptor)
             .Includes(d => d.OrderExtension)
             .FirstAsync(d => d.Id == id);
 
@@ -1091,7 +1090,6 @@ public class OrderController : BaseController
     public async Task<PagedDto<OrderDto>> CanDelayOrderList([FromQuery] CanDelayOrderListDto dto)
     {
         var (total, items) = await _orderRepository.Queryable()
-            .Includes(d => d.Acceptor)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                 d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.Filed &&
@@ -1185,7 +1183,7 @@ public class OrderController : BaseController
     [HttpGet("delay")]
     public async Task<PagedDto<OrderDelayDto>> DelayList([FromQuery] DelayListDto dto)
     {
-        var (total, items) = await _orderDelayRepository.Queryable(workflowFilter: false)
+        var (total, items) = await _orderDelayRepository.Queryable(viewFilter: false)
             .Includes(x => x.Order)
             .Includes(x => x.Workflow)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
@@ -1207,7 +1205,9 @@ public class OrderController : BaseController
     [HttpGet("wait_delay")]
     public async Task<PagedDto<OrderDelayDto>> WaitDelayList([FromQuery] DelayListDto dto)
     {
-        var (total, items) = await _orderDelayRepository.Queryable()
+        var isHandled = dto.IsApply.HasValue && dto.IsApply.Value;
+        var (total, items) = await _orderDelayRepository
+            .Queryable(viewFilter: true, handlerFilter: !isHandled)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                 d => d.Order.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             .WhereIF(dto.IsApply == true, x => x.DelayState != EDelayState.Examining)
@@ -1228,12 +1228,12 @@ public class OrderController : BaseController
     [HttpGet("delay/{id}")]
     public async Task<OrderDelayDto> DelayEntity(string id)
     {
-        var model = await _orderDelayRepository.Queryable(workflowFilter: false)
+        var model = await _orderDelayRepository.Queryable()
             .Includes(x => x.Order)
             .Includes(x => x.Workflow)
             .FirstAsync(x => x.Id == id);
         var rspModel = _mapper.Map<OrderDelayDto>(model);
-        rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
         if (rspModel.FileJson != null && rspModel.FileJson.Any())
         {
             var ids = rspModel.FileJson.Select(x => x.Id).ToList();
@@ -1339,7 +1339,7 @@ public class OrderController : BaseController
     [HttpGet("screen")]
     public async Task<PagedDto<OrderScreenListDto>> ScreenList([FromQuery] ScreenListDto dto)
     {
-        var query = _orderScreenRepository.Queryable(workflowFilter: false)
+        var query = _orderScreenRepository.Queryable(viewFilter: false)
             .Includes(x => x.Order)
             .Includes(x => x.VisitDetail)
             .Includes(x => x.Visit, d => d.Order)
@@ -1509,13 +1509,13 @@ public class OrderController : BaseController
     [HttpGet("screen/{id}")]
     public async Task<OrderScreenListDto> ScreenEntity(string id)
     {
-        var model = await _orderScreenRepository.Queryable(workflowFilter: false)
+        var model = await _orderScreenRepository.Queryable(viewFilter: false)
             .Includes(x => x.Order)
             .Includes(x => x.Workflow)
             .Includes(x => x.Visit, d => d.Order)
             .FirstAsync(x => x.Id == id);
         var rspModel = _mapper.Map<OrderScreenListDto>(model);
-        rspModel.IsCanHandle = model.Workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
         rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, HttpContext.RequestAborted);
         if (rspModel.FileJson != null && rspModel.FileJson.Any())
         {
@@ -1909,7 +1909,7 @@ public class OrderController : BaseController
     [HttpGet]
     public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
     {
-        var (total, items) = await _orderRepository.Queryable(workflowFilter: false)
+        var (total, items) = await _orderRepository.Queryable()
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
             .WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
             .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
@@ -1975,8 +1975,7 @@ public class OrderController : BaseController
     [HttpGet("{id}")]
     public async Task<OrderDto> Get(string id)
     {
-        var order = await _orderRepository.Queryable(workflowFilter: false)
-            .Includes(d => d.Acceptor)
+        var order = await _orderRepository.Queryable()
             .Includes(d => d.OrderExtension)
             .Includes(d => d.OrderDelays)
             .Includes(d => d.OrderScreens)
@@ -2352,31 +2351,14 @@ public class OrderController : BaseController
     [HttpGet("waited")]
     public async Task<PagedDto<OrderDto>> QueryWaited([FromQuery] QueryOrderWaitedDto dto)
     {
-        var query = dto.IsHandled.HasValue && !dto.IsHandled.Value
-            ? _orderRepository.Queryable().Where(d =>
-                SqlFunc.JsonListObjectAny(d.Workflow.HandlerUsers, "Key", _sessionContext.RequiredUserId) ||
-                SqlFunc.JsonListObjectAny(d.Workflow.HandlerOrgs, "Key", _sessionContext.RequiredOrgId))
-            : _orderRepository.Queryable();
-
-        var (total, items) = await query
+        var (total, items) = await _orderRepository
+            .Queryable(viewFilter: true, handlerFilter: dto.IsHandled.HasValue && dto.IsHandled.Value)
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                 d => d.No.Contains(dto.Keyword) || d.Title.Contains(dto.Keyword))
             .OrderByDescending(d => d.StartTime)
             .ToPagedListAsync(dto, HttpContext.RequestAborted);
 
-
-        //var (total, items) = await _orderRepository.Queryable()
-        //     .Includes(d => d.Workflow, x => x.Steps)
-        //     .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
-        //     .WhereIF(dto.IsHandled.HasValue && dto.IsHandled.Value, d => d.Workflow.Steps.Any(x => x.Status == EWorkflowStepStatus.Handled))
-        //     .WhereIF(dto.IsHandled.HasValue && !dto.IsHandled.Value, d => d.Workflow.Steps.Any(x => x.Status != EWorkflowStepStatus.Handled))
-        //     .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
-        //         d => d.No.Contains(dto.Keyword) || d.Title.Contains(dto.Keyword))
-        //     .OrderByDescending(d => d.StartTime)
-        //     .ToPagedListAsync(dto, HttpContext.RequestAborted);
-
-
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
 
@@ -2393,7 +2375,7 @@ public class OrderController : BaseController
                     : d is EOrderStatus.WaitForAccept or EOrderStatus.BackToUnAccept)
             .ToArray();
 
-        var (total, items) = await _orderRepository.Queryable(workflowFilter: false)
+        var (total, items) = await _orderRepository.Queryable(viewFilter: false)
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(dto.IsHandled.HasValue, d => handleStatuses.Contains(d.Status))
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword),

+ 3 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -15,6 +15,7 @@ using MediatR;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
 using XF.Domain.Authentications;
+using XF.Domain.Entities;
 using XF.Domain.Repository;
 
 namespace Hotline.Application.Handlers.FlowEngine;
@@ -138,7 +139,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                 var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);
                 if (screen != null)
                 {
-                    screen.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                    screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                     if (isReviewPass)
                     {
                         screen.Status = EScreenStatus.End;
@@ -204,7 +205,7 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                 var delay = await _orderDelayRepository.GetAsync(workflow.ExternalId, cancellationToken);
                 if (delay != null)
                 {
-                    delay.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                    delay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                     if (isReviewPass)
                     {
                         delay.DelayState = isReviewPass ? EDelayState.Pass : EDelayState.NoPass;

+ 2 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -158,7 +158,7 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                 if (screen != null)
                 {
                     screen.Status = EScreenStatus.Approval;
-                    screen.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                    screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                     await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
                 }
 
@@ -207,7 +207,7 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                     .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
                 if (orderDelay != null)
                 {
-                    orderDelay.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                    orderDelay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                     await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
                 }
 

+ 2 - 2
src/Hotline.Application/Handlers/FlowEngine/WorkflowStartHandler.cs

@@ -112,7 +112,7 @@ namespace Hotline.Application.Handlers.FlowEngine
                     if (screen != null)
                     {
                         screen.WorkflowId = workflow.Id;
-                        screen.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                        screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                         await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
                     }
                     break;
@@ -122,7 +122,7 @@ namespace Hotline.Application.Handlers.FlowEngine
                     if (orderDelay != null)
                     {
                         orderDelay.WorkflowId = workflow.Id;
-                        orderDelay.Assign(workflow.FlowedOrgIds, workflow.FlowedUserIds);
+                        orderDelay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
                         await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
                     }
                     break;

+ 6 - 4
src/Hotline.Repository.SqlSugar/BaseRepositoryWorkflow.cs

@@ -17,18 +17,20 @@ public class BaseRepositoryWorkflow<TEntity> : BaseRepository<TEntity>, IReposit
         _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
     }
 
-    public ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool workflowFilter = true)
+    public ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool viewFilter = true, bool handlerFilter = true)
     {
         if (includeDeleted)
             Db.QueryFilter.Clear();
 
-        //return Db.Queryable<TEntity>().WorkflowDataFiltering(_dataPermissionFilterBuilder);
         var query = Db.Queryable<TEntity>();
         if (permissionVerify)
             query = query.DataPermissionFiltering(_dataPermissionFilterBuilder);
 
-        if (workflowFilter)
-            query = query.WorkflowDataFiltering(_dataPermissionFilterBuilder);
+        if (viewFilter)
+            query = query.WorkflowViewFiltering(_dataPermissionFilterBuilder);
+
+        if(handlerFilter)
+            query = query.WorkflowHandleFiltering(_dataPermissionFilterBuilder);
         return query;
     }
 

+ 18 - 52
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs

@@ -23,15 +23,13 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
 
     public Expression<Func<TEntity, bool>> Build<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, new()
     {
-        var userId = _sessionContext.RequiredUserId;
-        var orgId = _sessionContext.RequiredOrgId;
         var queryFilterType = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
         switch (queryFilterType)
         {
             case ETableAccessLevel.Creator:
-                return d => d.CreatorId == userId;
+                return d => d.CreatorId == _sessionContext.RequiredUserId;
             case ETableAccessLevel.Org:
-                return d => d.CreatorOrgId == orgId;
+                return d => d.CreatorOrgId == _sessionContext.RequiredOrgId;
             case ETableAccessLevel.OrgAndBelow:
                 return d => d.AreaId == _sessionContext.AreaId && _sessionContext.OrgLevel <= d.CreatorOrgLevel; //d.CreatorOrgId.StartsWith(orgId);
             case ETableAccessLevel.All:
@@ -42,16 +40,27 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
         }
     }
 
-    public Expression<Func<TEntity, bool>> BuildIncludeFlowData<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
+    public Expression<Func<TEntity, bool>> BuildWithFlowViewFilter<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
+    {
+        var roles = _sessionContext.Roles;
+        if (roles != null && roles.Contains(RoleSeedData.AdminRole))
+            return d => true;
+
+        return d => SqlFunc.JsonArrayAny(d.FlowedUserIds, _sessionContext.RequiredOrgId) ||
+                    SqlFunc.JsonArrayAny(d.FlowedOrgIds, _sessionContext.RequiredOrgId);
+    }
+
+    public Expression<Func<TEntity, bool>> BuildWithFlowHandleFilter<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
     {
-        var userId = _sessionContext.RequiredUserId;
-        var orgCode = _sessionContext.RequiredOrgId;
         var roles = _sessionContext.Roles;
         if (roles != null && roles.Contains(RoleSeedData.AdminRole))
             return d => true;
 
-        return d => SqlFunc.JsonArrayAny(d.FlowedUserIds, userId) ||
-                    SqlFunc.JsonArrayAny(d.FlowedOrgIds, orgCode);
+        return d =>
+            (SqlFunc.JsonArrayAny(d.FlowedUserIds, _sessionContext.RequiredOrgId) ||
+             SqlFunc.JsonArrayAny(d.FlowedOrgIds, _sessionContext.RequiredOrgId)) &&
+            (SqlFunc.JsonListObjectAny(d.HandlerUsers, "Key", _sessionContext.RequiredOrgId) ||
+             SqlFunc.JsonListObjectAny(d.HandlerOrgs, "Key", _sessionContext.RequiredOrgId));
     }
 
     public Expression<Func<TEntity, Workflow, bool>> BuildIncludeFlowData1<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
@@ -65,47 +74,4 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
         return (d, w) => SqlFunc.JsonArrayAny(w.FlowedUserIds, userId) ||
                          SqlFunc.JsonArrayAny(w.FlowedOrgIds, orgCode);
     }
-
-    //public Expression<Func<TEntity, bool>> BuildIncludeFlowData<TEntity>() where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
-    //{
-    //    var userId = _sessionContext.RequiredUserId;
-    //    var orgCode = _sessionContext.RequiredOrgCode;
-    //    var queryFilterType = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
-
-    //    switch (queryFilterType)
-    //    {
-    //        case EAuthorityType.Create:
-    //            return d => d.CreatorId == userId
-    //                        || d.AssignUserIds.Contains(userId)
-    //                        || d.AssignOrgCodes.Contains(orgCode);
-    //        case EAuthorityType.Org:
-    //            return d => d.CreatorOrgCode == orgCode
-    //                        || d.AssignUserIds.Contains(userId)
-    //                        || d.AssignOrgCodes.Contains(orgCode)
-    //                ;
-    //        case EAuthorityType.OrgAndBelow:
-    //            return d => d.CreatorOrgCode.StartsWith(orgCode)
-    //                        || d.AssignUserIds.Contains(userId)
-    //                        || d.AssignOrgCodes.Contains(orgCode);
-    //        case EAuthorityType.All:
-    //            return d => true;
-    //        default:
-    //            return d => d.AssignUserIds.Contains(userId) || d.AssignOrgCodes.Contains(orgCode);
-    //    }
-    //}
-
-    //private static bool FlowDataFiltering<TEntity>(TEntity entity, string userId, string orgCode, string[] roles) where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
-    //{
-    //    if (entity.AssignUserIds.Contains(userId)) return true;
-    //    foreach (var assignOrgCode in entity.AssignOrgCodes)
-    //    {
-    //        if (assignOrgCode == orgCode) return true;
-    //        var baseOrg = assignOrgCode.Substring(0, 3);
-    //        if (orgCode.StartsWith(baseOrg) && orgCode.Length < assignOrgCode.Length)
-    //            return true;
-    //    }
-
-    //    return false;
-    //    //return entity.AssignRoles.Intersect(roles).Any();
-    //}
 }

+ 4 - 1
src/Hotline.Repository.SqlSugar/DataPermissions/IDataPermissionFilterBuilder.cs

@@ -10,7 +10,10 @@ public interface IDataPermissionFilterBuilder
     Expression<Func<TEntity, bool>> Build<TEntity>()
         where TEntity : class, IEntity<string>, IDataPermission, new();
 
-    Expression<Func<TEntity, bool>> BuildIncludeFlowData<TEntity>()
+    Expression<Func<TEntity, bool>> BuildWithFlowViewFilter<TEntity>()
+        where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new();
+
+    Expression<Func<TEntity, bool>> BuildWithFlowHandleFilter<TEntity>()
         where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new();
 
     Expression<Func<TEntity, Workflow, bool>> BuildIncludeFlowData1<TEntity>()

+ 9 - 3
src/Hotline.Repository.SqlSugar/Extensions/DataPermissionExtensions.cs

@@ -14,12 +14,18 @@ namespace Hotline.Repository.SqlSugar.Extensions
             return queryable.Where(dataPermissionFilterBuilder.Build<TEntity>());
         }
 
-        public static ISugarQueryable<TEntity> WorkflowDataFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
+        public static ISugarQueryable<TEntity> WorkflowViewFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
             IDataPermissionFilterBuilder dataPermissionFilterBuilder)
             where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
         {
-            //return queryable.LeftJoin(dataPermissionFilterBuilder.BuildIncludeFlowData1<TEntity>());
-            return queryable.Where(dataPermissionFilterBuilder.BuildIncludeFlowData<TEntity>());
+            return queryable.Where(dataPermissionFilterBuilder.BuildWithFlowViewFilter<TEntity>());
+        }
+
+        public static ISugarQueryable<TEntity> WorkflowHandleFiltering<TEntity>(this ISugarQueryable<TEntity> queryable,
+            IDataPermissionFilterBuilder dataPermissionFilterBuilder)
+            where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
+        {
+            return queryable.Where(dataPermissionFilterBuilder.BuildWithFlowHandleFilter<TEntity>());
         }
 
         public static TEntity InitDatePermission<TEntity>(this TEntity entity,

+ 1 - 2
src/Hotline/FlowEngine/FlowAssignInfo.cs

@@ -1,5 +1,4 @@
-using Hotline.FlowEngine.Workflows;
-using Hotline.Share.Dtos;
+using Hotline.Share.Dtos;
 using XF.Domain.Entities;
 
 namespace Hotline.FlowEngine;

+ 0 - 14
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -831,18 +831,4 @@ public partial class Workflow
     }
 
     #endregion
-}
-
-/// <summary>
-/// 办理对象分组(以办理step分组,多人办理一个step为一组)
-/// </summary>
-public class HandlerGroupItem
-{
-    public string GroupId { get; set; }
-
-    public string Key { get; set; }
-
-    public string Value { get; set; }
-
-
 }

+ 6 - 7
src/Hotline/Orders/OrderDomainService.cs

@@ -29,7 +29,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     private readonly ILogger<OrderDomainService> _logger;
     private readonly IFileRepository _fileRepository;
 
-	public OrderDomainService(
+    public OrderDomainService(
         IOrderRepository orderRepository,
         IRepository<OrderRedo> orderRedoRepository,
         IRepository<OrderPublish> orderPublishRepository,
@@ -42,7 +42,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         IMapper mapper,
         ILogger<OrderDomainService> logger,
         IFileRepository fileRepository,
-		IRepository<WexCallRecord> wexCallRecordRepository)
+        IRepository<WexCallRecord> wexCallRecordRepository)
     {
         _orderRepository = orderRepository;
         _orderRedoRepository = orderRedoRepository;
@@ -57,7 +57,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         _logger = logger;
         _fileRepository = fileRepository;
 
-	}
+    }
 
     public async Task<Order> GetOrderAsync(string? orderId, bool withHotspot = false, bool withAcceptor = false,
         CancellationToken cancellationToken = default)
@@ -65,7 +65,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         if (string.IsNullOrEmpty(orderId))
             throw UserFriendlyException.SameMessage("无效工单编号");
 
-        var query = _orderRepository.Queryable();
+        var query = _orderRepository.Queryable(viewFilter: false, handlerFilter: false);
         if (withHotspot)
             query = query.Includes(d => d.Hotspot);
         if (withAcceptor)
@@ -158,7 +158,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         var complement = _mapper.Map<OrderComplement>(dto);
         complement.InitId();
         if (dto.Files.Any()) complement.FileJson = await _fileRepository.AddFileAsync(dto.Files, complement.Id, "", cancellationToken);
-		return await _orderComplementRepository.AddAsync(complement, cancellationToken);
+        return await _orderComplementRepository.AddAsync(complement, cancellationToken);
     }
 
     #endregion
@@ -171,7 +171,6 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
             throw UserFriendlyException.SameMessage("无效流程编号");
         var order = await _orderRepository.Queryable()
             .Includes(d => d.Hotspot)
-            .Includes(d => d.Acceptor)
             .FirstAsync(d => d.WorkflowId == workflowId);
         if (order == null)
             throw new UserFriendlyException($"无效流程编号, workflowId: {workflowId}", "无效流程编号");
@@ -184,7 +183,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         var cacheKey = today.ToString("yyyyMMdd");
         var cacheOrderNo = _cacheOrderNo.GetOrSet(cacheKey, f =>
         {
-            var todayOrderCount = _orderRepository.Queryable(includeDeleted: true, workflowFilter: false)
+            var todayOrderCount = _orderRepository.Queryable(includeDeleted: true, viewFilter: false)
                 .CountAsync(d => d.CreationTime.Date == today.Date)
                 .GetAwaiter()
                 .GetResult();

+ 103 - 6
src/XF.Domain.Repository/Entity.cs

@@ -151,8 +151,21 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
     [SugarColumn(ColumnDataType = "json", IsJson = true)]
     public List<string>? FlowedUserIds { get; set; } = new();
 
-    //[SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
-    //public List<string> AssignRoles { get; set; } = new();
+    #region 当前办理对象
+
+    /// <summary>
+    /// 办理人id
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public List<HandlerGroupItem> HandlerUsers { get; set; } = new();
+
+    /// <summary>
+    /// 办理部门id
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public List<HandlerGroupItem> HandlerOrgs { get; set; } = new();
+
+    #endregion
 
     public void Assign(EFlowAssignType type, string handler)
     {
@@ -192,6 +205,42 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
         }
     }
 
+    /// <summary>
+    /// 是否可查看
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    public bool CanView(string userId, string orgId)
+    {
+        return FlowedUserIds.Any(d => d == userId) ||
+               FlowedOrgIds.Any(d => d == orgId);
+    }
+
+    /// <summary>
+    /// 是否能办理
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    public bool CanHandle(string userId, string orgId)
+    {
+        return CanView(userId, orgId) &&
+            HandlerUsers.Any(d => d.Key == userId) ||
+            HandlerOrgs.Any(d => d.Key == orgId);
+    }
+
+    /// <summary>
+    /// 流程每次流转时更新待办对象及流经对象
+    /// </summary>
+    public void Flowed(List<string> flowedUserIds, List<string> flowedOrgIds, List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs)
+    {
+        FlowedUserIds = flowedUserIds;
+        FlowedOrgIds = flowedOrgIds;
+        HandlerUsers = handlerUsers;
+        HandlerOrgs = handlerOrgs;
+    }
+
     public void Assign(List<string> flowedOrgIds, List<string> flowedUserIds)
     {
         FlowedOrgIds = flowedOrgIds;
@@ -263,7 +312,7 @@ public abstract class PositionEntity : FullStateEntity
 
 public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
 {
-    [SugarColumn(IsNullable = true)] 
+    [SugarColumn(IsNullable = true)]
     public string? WorkflowId { get; set; }
 
     /// <summary>
@@ -278,8 +327,21 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
     [SugarColumn(ColumnDataType = "json", IsJson = true)]
     public List<string>? FlowedUserIds { get; set; } = new();
 
-    //[SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
-    //public List<string> AssignRoles { get; set; } = new();
+    #region 当前办理对象
+
+    /// <summary>
+    /// 办理人id
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public List<HandlerGroupItem> HandlerUsers { get; set; } = new();
+
+    /// <summary>
+    /// 办理部门id
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public List<HandlerGroupItem> HandlerOrgs { get; set; } = new();
+
+    #endregion
 
     public void Assign(EFlowAssignType type, string handler)
     {
@@ -319,5 +381,40 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
         }
     }
 
-    
+    /// <summary>
+    /// 是否可查看
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    public bool CanView(string userId, string orgId)
+    {
+        return FlowedUserIds.Any(d => d == userId) ||
+               FlowedOrgIds.Any(d => d == orgId);
+    }
+
+    /// <summary>
+    /// 是否能办理
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    public bool CanHandle(string userId, string orgId)
+    {
+        return CanView(userId, orgId) &&
+               HandlerUsers.Any(d => d.Key == userId) ||
+               HandlerOrgs.Any(d => d.Key == orgId);
+    }
+
+    /// <summary>
+    /// 流程每次流转时更新待办对象及流经对象
+    /// </summary>
+    public void Flowed(List<string> flowedUserIds, List<string> flowedOrgIds, List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs)
+    {
+        FlowedUserIds = flowedUserIds;
+        FlowedOrgIds = flowedOrgIds;
+        HandlerUsers = handlerUsers;
+        HandlerOrgs = handlerOrgs;
+    }
+
 }

+ 9 - 1
src/XF.Domain.Repository/IRepositoryWorkflow.cs

@@ -22,6 +22,14 @@ namespace XF.Domain.Repository
 
     public interface IRepositoryWorkflow<TEntity> : IRepositorySqlSugar<TEntity> where TEntity : class, IEntity<string>, new()
     {
-        ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool workflowFilter = true);
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="permissionVerify"></param>
+        /// <param name="includeDeleted"></param>
+        /// <param name="viewFilter">是否可查看过滤开关</param>
+        /// <param name="handlerFilter">是否可办理过滤开关</param>
+        /// <returns></returns>
+        ISugarQueryable<TEntity> Queryable(bool permissionVerify = false, bool includeDeleted = false, bool viewFilter = false, bool handlerFilter = false);
     }
 }

+ 47 - 4
src/XF.Domain/Entities/IWorkflow.cs

@@ -18,15 +18,46 @@ public interface IWorkflow
     /// 流经办理人
     /// </summary>
     List<string> FlowedUserIds { get; set; }
+    
+    #region 当前办理对象
 
-    ///// <summary>
-    ///// 指派角色名称
-    ///// </summary>
-    //List<string> AssignRoles { get; set; }
+    /// <summary>
+    /// 办理人id
+    /// </summary>
+    public List<HandlerGroupItem> HandlerUsers { get; set; }
+
+    /// <summary>
+    /// 办理部门id
+    /// </summary>
+    public List<HandlerGroupItem> HandlerOrgs { get; set; }
+
+    #endregion
 
     void Assign(EFlowAssignType type, string handler);
 
     void Assign(EFlowAssignType type, IEnumerable<string> handlers);
+
+    /// <summary>
+    /// 是否可查看
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    bool CanView(string userId, string orgId);
+
+    /// <summary>
+    /// 是否能办理
+    /// </summary>
+    /// <param name="userId"></param>
+    /// <param name="orgId"></param>
+    /// <returns></returns>
+    bool CanHandle(string userId, string orgId);
+
+    /// <summary>
+    /// 流程每次流转时更新待办对象及流经对象
+    /// </summary>
+    void Flowed(List<string> flowedUserIds, List<string> flowedOrgIds,
+        List<HandlerGroupItem> handlerUsers, List<HandlerGroupItem> handlerOrgs);
 }
 
 public enum EFlowAssignType
@@ -45,4 +76,16 @@ public enum EFlowAssignType
     ///// 指派到角色
     ///// </summary>
     //Role = 2,
+}
+
+/// <summary>
+/// 办理对象分组(以办理step分组,多人办理一个step为一组)
+/// </summary>
+public class HandlerGroupItem
+{
+    public string GroupId { get; set; }
+
+    public string Key { get; set; }
+
+    public string Value { get; set; }
 }