Kaynağa Gözat

Merge branch 'master' into tangj-knowledge

TANG JIANG 2 yıl önce
ebeveyn
işleme
27c48eeca9
25 değiştirilmiş dosya ile 337 ekleme ve 159 silme
  1. 22 18
      src/Hotline.Api/Controllers/OrderController.cs
  2. 2 1
      src/Hotline.Api/Controllers/SysController.cs
  3. 9 1
      src/Hotline.Application/FlowEngine/IWorkflowApplication.cs
  4. 32 1
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  5. 13 6
      src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs
  6. 15 4
      src/Hotline.Application/Handlers/FlowEngine/StartWorkflowHandler.cs
  7. 3 21
      src/Hotline.Application/Orders/IOrderApplication.cs
  8. 24 0
      src/Hotline.Application/Orders/OrderApplication.cs
  9. 21 17
      src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs
  10. 13 11
      src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionManager.cs
  11. 0 2
      src/Hotline.Share/Dtos/Dic/DicDto.cs
  12. 1 1
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  13. 6 6
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  14. 48 0
      src/Hotline.Share/Dtos/PositionDto.cs
  15. 30 1
      src/Hotline.Share/Enums/Order/EComplainType.cs
  16. 0 17
      src/Hotline/FlowEngine/Definitions/StepDefine.cs
  17. 22 0
      src/Hotline/FlowEngine/FlowAssignMode.cs
  18. 5 4
      src/Hotline/FlowEngine/Notifies/WorkflowNotify.cs
  19. 2 0
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  20. 3 5
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  21. 3 3
      src/Hotline/Orders/IOrderDomainService.cs
  22. 6 4
      src/Hotline/Orders/OrderDomainService.cs
  23. 17 28
      src/XF.Domain.Repository/Entity.cs
  24. 8 8
      src/XF.Domain/Entities/IDataPermission.cs
  25. 32 0
      src/XF.Domain/Extensions/OrgExtensions.cs

+ 22 - 18
src/Hotline.Api/Controllers/OrderController.cs

@@ -58,25 +58,23 @@ public class OrderController : BaseController
     public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
     {
         var (total, items) = await _orderRepository.Queryable()
-            //.Includes(d => d.Employee)
-            //.Includes(d => d.Workflow, d => d.Assigns)
             .Where(d => d.Workflows.Any(x => x.ModuleCode == WorkflowModuleConsts.OrderManage))
             .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.AcceptType.HasValue, d => d.AcceptType == dto.AcceptType)
-            .WhereIF(dto.Channel.HasValue, d => d.Channel == dto.Channel)
-            .WhereIF(!string.IsNullOrEmpty(dto.HotspotId), d => d.HotspotId == dto.HotspotId)
+            .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
+            .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.Channel))
+            .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
             .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone))
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), d => d.Workflows.Any(x => x.Assigns.Any(s => s.OrgCode == dto.OrgCode)))
+            .WhereIF(dto.OrgCodes.Any(), d => d.Workflows.Any(x => x.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode))))
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.Employee.Name.Contains(dto.NameOrNo) || d.Employee.StaffNo.Contains(dto.NameOrNo))
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
             .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
-            .WhereIF(dto.EmergencyLevel.HasValue, d => d.EmergencyLevel == dto.EmergencyLevel)
+            .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))
             .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo) || d.Contact.Contains(dto.PhoneNo))
             .WhereIF(dto.PushType.HasValue, d => d.PushType == dto.PushType)
             .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart)
             .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd)
-            .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)
+            .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
@@ -95,6 +93,11 @@ public class OrderController : BaseController
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
 
+    /// <summary>
+    /// 查询工单详情
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
     [HttpGet("{id}")]
     public async Task<OrderDto> Get(string id)
     {
@@ -131,6 +134,11 @@ public class OrderController : BaseController
         await _orderRepository.RemoveAsync(order);
     }
 
+    /// <summary>
+    /// 更新工单信息
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
     [HttpPut]
     public async Task Update([FromBody] UpdateOrderDto dto)
     {
@@ -176,15 +184,12 @@ public class OrderController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data")]
-    public async Task<object> BaseData()
+    public dynamic BaseData()
     {
-        var baseHotspots = await _hotSpotTypeRepository.Queryable().Where(d => string.IsNullOrEmpty(d.ParentId))
-            .ToListAsync();
         return new
         {
             AcceptTypeOptions = EnumExts.GetDescriptions<EAcceptType>(),
             ChannelOptions = EnumExts.GetDescriptions<EChannel>(),
-            BaseHotspots = baseHotspots.Select(d => new KeyValuePair<string, string>(d.ProvinceCode, d.HotSpotName)).ToList(),
             OrgsOptions = _organizeRepository.GetOrgJson(),
             EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
             PushTypeOptions = EnumExts.GetDescriptions<EPushType>(),
@@ -193,14 +198,12 @@ public class OrderController : BaseController
     }
 
     /// <summary>
-    /// 新增页面
+    /// 新增页面基础数据
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data-add")]
-    public async Task<object> BaseDataAdd()
+    public dynamic BaseDataAdd()
     {
-        var baseHotspots = await _hotSpotTypeRepository.Queryable().Where(d => string.IsNullOrEmpty(d.ParentId))
-            .ToListAsync();
         return new
         {
             ChannelOptions = EnumExts.GetDescriptions<EChannel>(),
@@ -211,13 +214,13 @@ public class OrderController : BaseController
             OrderTypeOptions = EnumExts.GetDescriptions<EOrderType>(),
             AcceptTypeOptions = EnumExts.GetDescriptions<EAcceptType>(),
             EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
-            BaseHotspots = baseHotspots.Select(d => new KeyValuePair<string, string>(d.ProvinceCode, d.HotSpotName)).ToList(),
             PushTypeOptions = EnumExts.GetDescriptions<EPushType>(),
+            //todo 是否重复
         };
     }
 
     /// <summary>
-    /// 扩展信息新增页面
+    /// 扩展信息新增页面基础数据
     /// </summary>
     /// <returns></returns>
     [HttpGet("base-data-ext")]
@@ -227,6 +230,7 @@ public class OrderController : BaseController
         return new
         {
             //LicenceTypeOptions = SysDicTypeConsts.LicenceType,
+            ComplainTypeOptions = EnumExts.GetDescriptions<EComplainType>()
         };
     }
 

+ 2 - 1
src/Hotline.Api/Controllers/SysController.cs

@@ -276,7 +276,8 @@ namespace Hotline.Api.Controllers
         [HttpGet("dictdata-type")]
         public async Task<List<SysDicData>> GetSysDicData([FromQuery] GetSysDicDataDto dto)
         {
-            return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeId == dto.typeid).WhereIF(!string.IsNullOrEmpty(dto.datavalue),x=>x.DicDataValue.Contains(dto.datavalue)).ToTreeAsync(x=>x.Children,x=>x.ParentId,"");
+            return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeId == dto.typeid)/*.WhereIF(!string.IsNullOrEmpty(dto.datavalue),x=>x.DicDataValue.Contains(dto.datavalue))*/.ToTreeAsync(x=>x.Children,x=>x.ParentId,"");
+            //return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeId == dto.typeid).WhereIF(!string.IsNullOrEmpty(dto.datavalue), x => x.DicDataValue.Contains(dto.datavalue)).WhereIF(!string.IsNullOrEmpty(dto.ParentId), x => x.ParentId == dto.ParentId).ToListAsync();
         }
 
         /// <summary>

+ 9 - 1
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -1,5 +1,8 @@
-using Hotline.FlowEngine.Workflows;
+using Hotline.FlowEngine;
+using Hotline.FlowEngine.Definitions;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Enums.FlowEngine;
 
 namespace Hotline.Application.FlowEngine
 {
@@ -24,5 +27,10 @@ namespace Hotline.Application.FlowEngine
         Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(string moduleCode, string externalId, CancellationToken cancellationToken);
 
         Task<IReadOnlyList<NextStepOptions>> GetNextStepOptionsAsync(Workflow workflow, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 查询指派办理人的处理方式及实际办理人
+        /// </summary>
+        Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine StepDefine, List<string> Handlers, CancellationToken cancellationToken);
     }
 }

+ 32 - 1
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -1,4 +1,5 @@
-using Hotline.FlowEngine.Definitions;
+using Hotline.FlowEngine;
+using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
@@ -10,6 +11,7 @@ using Hotline.Users;
 using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
+using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 
 namespace Hotline.Application.FlowEngine;
@@ -163,6 +165,35 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return items;
     }
 
+    /// <summary>
+    /// 查询指派办理人的处理方式及实际办理人
+    /// </summary>
+    public async Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine stepDefine, List<string> handlers, CancellationToken cancellationToken)
+    {
+        switch (stepDefine.HandlerType)
+        {
+            case EHandlerType.Role:
+                if (!handlers.Any())
+                {
+                    var roles = await _roleRepository.Queryable()
+                        .Includes(d => d.Accounts)
+                        .Where(d => stepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name))
+                        .ToListAsync();
+                    handlers = roles.SelectMany(d => d.Accounts).Select(d => d.Id).ToList();
+                }
+
+                return new FlowAssignMode(EFlowAssignType.User, handlers);
+            case EHandlerType.OrgLevel:
+            case EHandlerType.OrgType:
+            case EHandlerType.AssignOrg:
+                return new FlowAssignMode(EFlowAssignType.Org, handlers);
+            case EHandlerType.AssignUser:
+                return new FlowAssignMode(EFlowAssignType.User, handlers);
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+    }
+
 
     #region private
 

+ 13 - 6
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -1,4 +1,5 @@
-using Hotline.FlowEngine.Notifies;
+using Hotline.Application.FlowEngine;
+using Hotline.FlowEngine.Notifies;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Settings;
@@ -12,10 +13,14 @@ namespace Hotline.Application.Handlers.FlowEngine;
 
 public class NextStepHandler : INotificationHandler<NextStepNotify>
 {
+    private readonly IWorkflowApplication _workflowApplication;
     private readonly IOrderDomainService _orderDomainService;
 
-    public NextStepHandler(IOrderDomainService orderDomainService)
+    public NextStepHandler(
+        IWorkflowApplication workflowApplication,
+        IOrderDomainService orderDomainService)
     {
+        _workflowApplication = workflowApplication;
         _orderDomainService = orderDomainService;
     }
 
@@ -26,13 +31,15 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
     {
         var workflow = notification.Workflow;
         var data = notification.Dto;
+        var assignMode = await _workflowApplication.GetFlowAssignModeAsync(notification.StepDefine,
+            data.Handlers.Select(d => d.Id).ToList(), cancellationToken);
+
         switch (workflow.ModuleCode)
         {
             case WorkflowModuleConsts.OrderManage:
-                await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, 
-                    notification.FlowAssignType, notification.IsCountersignEnd, notification.IsCountersignStart,
-                    workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName, 
-                    data.Handlers.Select(d => d.Id), cancellationToken);
+                await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign,
+                    assignMode, notification.IsCountersignEnd, notification.IsCountersignStart,
+                    workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName, cancellationToken);
                 break;
         }
     }

+ 15 - 4
src/Hotline.Application/Handlers/FlowEngine/StartWorkflowHandler.cs

@@ -3,21 +3,31 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Application.FlowEngine;
 using Hotline.FlowEngine.Notifies;
 using Hotline.Orders;
 using Hotline.Settings;
 using Hotline.Share.Enums.Order;
 using MediatR;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Handlers.FlowEngine
 {
     public class StartWorkflowHandler : INotificationHandler<StartWorkflowNotify>
     {
+        private readonly IWorkflowApplication _workflowApplication;
         private readonly IOrderDomainService _orderDomainService;
+        private readonly IOrderRepository _orderRepository;
 
-        public StartWorkflowHandler(IOrderDomainService orderDomainService)
+        public StartWorkflowHandler(
+            IWorkflowApplication workflowApplication,
+            IOrderDomainService orderDomainService,
+            IOrderRepository orderRepository
+            )
         {
+            _workflowApplication = workflowApplication;
             _orderDomainService = orderDomainService;
+            _orderRepository = orderRepository;
         }
 
         /// <summary>Handles a notification</summary>
@@ -27,14 +37,15 @@ namespace Hotline.Application.Handlers.FlowEngine
         {
             var workflow = notification.Workflow;
             var data = notification.Dto;
+            var assignMode = await _workflowApplication.GetFlowAssignModeAsync(notification.StepDefine,
+                data.Handlers.Select(d => d.Id).ToList(), cancellationToken);
 
             switch (workflow.ModuleCode)
             {
                 case WorkflowModuleConsts.OrderManage:
-                    await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, notification.FlowAssignType, 
+                    await _orderDomainService.OrderManageAsync(EOrderStatus.WaitForSign, assignMode,
                         false, notification.IsCountersignStart,
-                        workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName,
-                        data.Handlers.Select(d => d.Id), cancellationToken);
+                        workflow.ExternalId, workflow.CurrentStepTime, workflow.CurrentStepName, cancellationToken);
                     break;
             }
         }

+ 3 - 21
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -3,31 +3,13 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using Hotline.FlowEngine.Workflows;
-using Hotline.Orders;
-using XF.Domain.Dependency;
+using Hotline.Share.Enums.Order;
+using XF.Domain.Entities;
 
 namespace Hotline.Application.Orders
 {
     public interface IOrderApplication
     {
-        Task<Order> GetAsync(string id);
-    }
-
-    public class OrderApplication : IOrderApplication, IScopeDependency
-    {
-        private readonly IWorkflowDomainService _workflowDomainService;
-
-        public OrderApplication(IWorkflowDomainService workflowDomainService)
-        {
-            _workflowDomainService = workflowDomainService;
-        }
-
-        public async Task<Order> GetAsync(string id)
-        {
-            //var order = 
-
-            throw new NotImplementedException();
-        }
+       
     }
 }

+ 24 - 0
src/Hotline.Application/Orders/OrderApplication.cs

@@ -0,0 +1,24 @@
+using Hotline.FlowEngine.Workflows;
+using Hotline.Orders;
+using Hotline.Share.Enums.Order;
+using Hotline.Users;
+using XF.Domain.Dependency;
+using XF.Domain.Entities;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Application.Orders;
+
+public class OrderApplication : IOrderApplication, IScopeDependency
+{
+    private readonly IWorkflowDomainService _workflowDomainService;
+    private readonly IOrderRepository _orderRepository;
+
+    public OrderApplication(
+        IWorkflowDomainService workflowDomainService,
+        IOrderRepository orderRepository
+        )
+    {
+        _workflowDomainService = workflowDomainService;
+        _orderRepository = orderRepository;
+    }
+}

+ 21 - 17
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs

@@ -44,39 +44,43 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
         var roles = _sessionContext.Roles;
         var orgCode = _sessionContext.RequiredOrgCode;
         var scheme = DataPermissionManager.GetQueryFilter<TEntity>(_sessionContext);
-        //var (_, orgCode, _, _) = DataPermissionManager.GetDataPermissionOptions();
 
         switch (scheme.QueryFilter)
         {
             case EAuthorityType.Create:
-                return d => d.CreatorId == userId || FlowDataFiltering(d, userId, orgCode, roles);
+                return d => d.CreatorId == userId
+                            || d.AssignUserIds.Contains(userId)
+                            || d.AssignOrgCodes.Contains(orgCode);
             case EAuthorityType.Org:
                 return d => d.CreatorOrgCode == scheme.OrgCode
                             || d.AssignUserIds.Contains(userId)
                             || d.AssignOrgCodes.Contains(orgCode)
-                            
+
                             //todo 扩展sqlfunc || d.AssignRoles.Intersect(roles).Any()
                             ;
             case EAuthorityType.OrgAndBelow:
-                return d => d.CreatorOrgCode.StartsWith(scheme.OrgCode) || FlowDataFiltering(d, userId, orgCode, roles);
+                return d => d.CreatorOrgCode.StartsWith(scheme.OrgCode)
+                            || d.AssignUserIds.Contains(userId)
+                            || d.AssignOrgCodes.Contains(orgCode);
             case EAuthorityType.All:
                 return d => true;
             default:
-                return d => FlowDataFiltering(d, userId, orgCode, roles);
+                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;
-        }
+    //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 entity.AssignRoles.Intersect(roles).Any();
-    }
+    //    return false;
+    //    //return entity.AssignRoles.Intersect(roles).Any();
+    //}
 }

+ 13 - 11
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionManager.cs

@@ -28,17 +28,19 @@ public class DataPermissionManager : IDataPermissionManager, IScopeDependency
 
     public (string orgId, string orgCode, string creatorId, string? areaId) GetDataPermissionOptions()
     {
-        using var scope = _serviceScopeFactory.CreateScope();
-        var userRepository = scope.ServiceProvider.GetRequiredService<IUserRepository>();
-        var user = userRepository.GetAsync(_sessionContext.RequiredUserId).GetAwaiter().GetResult();
-        if (!string.IsNullOrEmpty(user!.OrgId))
-        {
-            var orgRepository = scope.ServiceProvider.GetRequiredService<ISystemOrganizeRepository>();
-            var org = orgRepository!.GetAsync(user!.OrgId).GetAwaiter().GetResult();
-
-            return (org!.Id, org.OrgCode, _sessionContext.RequiredUserId, org.OrgCode);
-        }
-        return ("", "", _sessionContext.RequiredUserId, "");
+        //using var scope = _serviceScopeFactory.CreateScope();
+        //var userRepository = scope.ServiceProvider.GetRequiredService<IUserRepository>();
+        //var user = userRepository.GetAsync(_sessionContext.RequiredUserId).GetAwaiter().GetResult();
+        //if (!string.IsNullOrEmpty(user!.OrgId))
+        //{
+        //    var orgRepository = scope.ServiceProvider.GetRequiredService<ISystemOrganizeRepository>();
+        //    var org = orgRepository!.GetAsync(user!.OrgId).GetAwaiter().GetResult();
+
+        //    return (org!.Id, org.OrgCode, _sessionContext.RequiredUserId, org.OrgCode);
+        //}
+        //return ("", "", _sessionContext.RequiredUserId, "");
+        return (_sessionContext.RequiredOrgId, _sessionContext.RequiredOrgCode, 
+            _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
     }
 
     private EAuthorityType GetCurrentQueryFilter(string[] roles, string entityName)

+ 0 - 2
src/Hotline.Share/Dtos/Dic/DicDto.cs

@@ -23,7 +23,5 @@ namespace Hotline.Share.Dtos.Dic
     public record GetSysDicDataDto
     {
         public string typeid { get; set; }
-
-        public string datavalue { get; set; }
     }
 }

+ 1 - 1
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -99,7 +99,7 @@ namespace Hotline.Share.Dtos.Order
         public string Id { get; set; }
     }
 
-    public class AddOrderDto
+    public class AddOrderDto : PositionDto
     {
         #region 来电信息
 

+ 6 - 6
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -19,12 +19,12 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 受理类型
         /// </summary>
-        public EAcceptType? AcceptType { get; set; }
+        public List<EAcceptType> AcceptTypes { get; set; } = new();
 
         /// <summary>
         /// 来源渠道
         /// </summary>
-        public EChannel? Channel { get; set; }
+        public List<EChannel> Channels { get; set; } = new();
 
         /// <summary>
         /// 转接号码(转接来源)
@@ -34,12 +34,12 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 热点分类
         /// </summary>
-        public string? HotspotId { get; set; }
+        public List<string> HotspotIds { get; set; } = new();
 
         /// <summary>
         /// 接办部门
         /// </summary>
-        public string? OrgCode { get; set; }
+        public List<string> OrgCodes { get; set; } = new();
 
         /// <summary>
         /// 受理坐席名字或工号
@@ -55,7 +55,7 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 紧急程度
         /// </summary>
-        public EEmergencyLevel? EmergencyLevel { get; set; }
+        public List<EEmergencyLevel> EmergencyLevels { get; set; } = new();
 
         /// <summary>
         /// 来电或联系电话
@@ -76,6 +76,6 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 工单状态
         /// </summary>
-        public EOrderStatus? Status { get; set; }
+        public List<EOrderStatus> Statuses { get; set; } = new();
     }
 }

+ 48 - 0
src/Hotline.Share/Dtos/PositionDto.cs

@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos
+{
+    public class PositionDto
+    {
+        /// <summary>
+        /// 经度
+        /// </summary>
+        public double? Longitude { get; set; }
+
+        /// <summary>
+        /// 维度
+        /// </summary>
+        public double? Latitude { get; set; }
+
+        /// <summary>
+        /// 行政区划编码
+        /// </summary>
+        public string? AreaCode { get; set; }
+
+        /// <summary>
+        /// 省
+        /// </summary>
+        public string? Province { get; set; }
+
+        /// <summary>
+        /// 市
+        /// </summary>
+        public string? City { get; set; }
+
+        /// <summary>
+        /// 区/县
+        /// </summary>
+        public string? County { get; set; }
+
+        /// <summary>
+        /// 街道/详细地址
+        /// </summary>
+        public string? Street { get; set; }
+
+        public string Address => $"{Province ?? string.Empty}{City ?? string.Empty}{County ?? string.Empty}{Street ?? string.Empty}";
+    }
+}

+ 30 - 1
src/Hotline.Share/Enums/Order/EComplainType.cs

@@ -1,7 +1,36 @@
-namespace Hotline.Share.Enums.Order;
+using System.ComponentModel;
+
+namespace Hotline.Share.Enums.Order;
 
 [Flags]
 public enum EComplainType
 {
     //修理、重做、更换、退货、补足商品数量、退赔费用、赔偿损失、停止侵权、核定侵权责任
+
+    [Description("修理")]
+    Repair = 1,
+
+    [Description("重做")]
+    Redo = 1 << 1,
+
+    [Description("更换")]
+    Change = 1 << 2,
+
+    [Description("退货")]
+    ReturnGoods = 1 << 3,
+
+    [Description("补足商品数量")]
+    Complement = 1 << 4,
+
+    [Description("退赔费用")]
+    Refund = 1 << 5,
+
+    [Description("赔偿损失")]
+    Compensation = 1 << 6,
+
+    [Description("停止侵权")]
+    StopInfringement = 1 << 7,
+
+    [Description("核定侵权责任")]
+    AuthorizedInfringement = 1 << 8
 }

+ 0 - 17
src/Hotline/FlowEngine/Definitions/StepDefine.cs

@@ -22,21 +22,4 @@ public class StepDefine : StepBasic
         if (HandlerType is EHandlerType.Role) return false;
         return handlerCount > 1;
     }
-
-    public (EFlowAssignType assignType, List<IdName> handlers) GetFlowAssignMode(List<IdName> handlers)
-    {
-        switch (HandlerType)
-        {
-            case EHandlerType.Role:
-                return handlers.Any() ? (EFlowAssignType.User, handlers) : (EFlowAssignType.Role, HandlerClassifies);
-            case EHandlerType.OrgLevel:
-            case EHandlerType.OrgType:
-            case EHandlerType.AssignOrg:
-                return (EFlowAssignType.Org, handlers);
-            case EHandlerType.AssignUser:
-                return (EFlowAssignType.User, handlers);
-            default:
-                throw new ArgumentOutOfRangeException();
-        }
-    }
 }

+ 22 - 0
src/Hotline/FlowEngine/FlowAssignMode.cs

@@ -0,0 +1,22 @@
+using XF.Domain.Entities;
+
+namespace Hotline.FlowEngine;
+
+public class FlowAssignMode
+{
+    public FlowAssignMode(EFlowAssignType flowAssignType, List<string> handlers)
+    {
+        FlowAssignType = flowAssignType;
+        Handlers = handlers;
+    }
+
+    /// <summary>
+    /// 流程指派类型
+    /// </summary>
+    public EFlowAssignType FlowAssignType { get; set; }
+
+    /// <summary>
+    /// 办理人/办理部门(UserIds/OrgCodes)
+    /// </summary>
+    public List<string> Handlers { get; set; }
+}

+ 5 - 4
src/Hotline/FlowEngine/Notifies/WorkflowNotify.cs

@@ -1,15 +1,16 @@
-using Hotline.FlowEngine.Workflows;
+using Hotline.FlowEngine.Definitions;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Share.Dtos.FlowEngine;
 using MediatR;
 using XF.Domain.Entities;
 
 namespace Hotline.FlowEngine.Notifies;
 
-public record WorkflowNotify(Workflow Workflow, EFlowAssignType FlowAssignType, List<IdName> Handlers) : INotification;
+public record WorkflowNotify(Workflow Workflow, StepDefine StepDefine, BasicWorkflowDto Dto) : INotification;
 
-public record StartWorkflowNotify(Workflow Workflow, EFlowAssignType FlowAssignType, List<IdName> Handlers, BasicWorkflowDto Dto, bool IsCountersignStart) : WorkflowNotify(Workflow, FlowAssignType, Handlers);
+public record StartWorkflowNotify(Workflow Workflow, StepDefine StepDefine, BasicWorkflowDto Dto, bool IsCountersignStart) : WorkflowNotify(Workflow, StepDefine, Dto);
 
-public record NextStepNotify(Workflow Workflow, EFlowAssignType FlowAssignType, List<IdName> Handlers, BasicWorkflowDto Dto, bool IsCountersignStart, bool IsCountersignEnd) : WorkflowNotify(Workflow, FlowAssignType, Handlers);
+public record NextStepNotify(Workflow Workflow, StepDefine StepDefine, BasicWorkflowDto Dto, bool IsCountersignStart, bool IsCountersignEnd) : WorkflowNotify(Workflow, StepDefine, Dto);
 
 public record AcceptWorkflowNotify(Workflow Workflow) : INotification;
 

+ 2 - 0
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -1,5 +1,7 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Enums.FlowEngine;
+using XF.Domain.Entities;
 
 namespace Hotline.FlowEngine.Workflows
 {

+ 3 - 5
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -9,6 +9,7 @@ using MediatR;
 using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
+using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Utility.SequentialId;
 
@@ -95,8 +96,7 @@ namespace Hotline.FlowEngine.Workflows
             await CreateStepAsync(workflow, nextStepBoxDefine, dto, cancellationToken: cancellationToken);
 
             //publish
-            var assignMode = nextStepBoxDefine.GetFlowAssignMode(dto.Handlers);
-            _mediator.Publish(new StartWorkflowNotify(workflow, assignMode.assignType, assignMode.handlers, dto, isStartCountersign), cancellationToken);
+            _mediator.Publish(new StartWorkflowNotify(workflow, nextStepBoxDefine, dto, isStartCountersign), cancellationToken);
         }
 
         public async Task<Workflow> GetWorkflowAsync(string workflowId,
@@ -301,9 +301,7 @@ namespace Hotline.FlowEngine.Workflows
 
             #endregion
 
-            var assignMode = nextStepBoxDefine.GetFlowAssignMode(dto.Handlers);
-            _mediator.Publish(new NextStepNotify(workflow, assignMode.assignType, assignMode.handlers, dto,
-                isStartCountersign, isCountersignOver));
+            _mediator.Publish(new NextStepNotify(workflow, nextStepBoxDefine, dto, isStartCountersign, isCountersignOver));
         }
 
         /// <summary>

+ 3 - 3
src/Hotline/Orders/IOrderDomainService.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.FlowEngine;
 using Hotline.Share.Enums.Order;
 using XF.Domain.Entities;
 
@@ -20,8 +21,7 @@ namespace Hotline.Orders
         /// <summary>
         /// 工单办理(每个节点都会触发)
         /// </summary>
-        Task OrderManageAsync(EOrderStatus status, EFlowAssignType assignType, bool isCountersignEnd, bool isCountersignStart,
-            string orderId, DateTime currentStepTime, string CurrentStepName,
-            IEnumerable<string> handlers, CancellationToken cancellationToken);
+        Task OrderManageAsync(EOrderStatus status, FlowAssignMode assignMode, bool isCountersignEnd, bool isCountersignStart,
+            string orderId, DateTime currentStepTime, string CurrentStepName, CancellationToken cancellationToken);
     }
 }

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

@@ -1,4 +1,5 @@
-using Hotline.Share.Enums.Order;
+using Hotline.FlowEngine;
+using Hotline.Share.Enums.Order;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
 using XF.Domain.Dependency;
@@ -52,10 +53,9 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     /// <summary>
     /// 工单办理(每个节点都会触发)
     /// </summary>
-    public async Task OrderManageAsync(EOrderStatus status, EFlowAssignType assignType,
+    public async Task OrderManageAsync(EOrderStatus status, FlowAssignMode assignMode,
         bool isCountersignEnd, bool isCountersignStart,
         string orderId, DateTime currentStepTime, string CurrentStepName,
-        IEnumerable<string> handlers,
         CancellationToken cancellationToken)
     {
         var order = await _orderRepository.GetAsync(orderId, cancellationToken);
@@ -63,7 +63,9 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
             throw new UserFriendlyException($"无效工单编号, orderId: {orderId}", "无效工单编号");
         if (order.Status is EOrderStatus.Filed) return;
 
-        order.Assign(assignType, handlers);
+        //更新指派信息
+        order.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+
         //1.如果order未处于会签中,则判断是否发起会签(isstartCountersign) 2.如果处于会签中,则判断会签是否结束(isCountersignEnd)
         if (order.Status is EOrderStatus.Countersigning && isCountersignEnd)
         {

+ 17 - 28
src/XF.Domain.Repository/Entity.cs

@@ -1,6 +1,7 @@
 using SqlSugar;
 using XF.Domain.Entities;
 using XF.Domain.Events;
+using XF.Domain.Extensions;
 
 namespace XF.Domain.Repository;
 
@@ -142,28 +143,25 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
     [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> AssignOrgCodes { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "longtext", IsJson = true)]
     public List<string> AssignUserIds { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
-    public List<string> AssignRoles { get; set; } = new();
+    //[SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
+    //public List<string> AssignRoles { get; set; } = new();
 
     public void Assign(EFlowAssignType type, string handler)
     {
         switch (type)
         {
             case EFlowAssignType.Org:
-                if (!AssignOrgCodes.Exists(d => d == handler))
-                    AssignOrgCodes.Add(handler);
+                var orgCodes = handler.GetHigherOrgCodes(true).ToList();
+                AssignOrgCodes.AddRange(orgCodes);
+                AssignOrgCodes = AssignOrgCodes.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
                 if (!AssignUserIds.Exists(d => d == handler))
                     AssignUserIds.Add(handler);
                 break;
-            case EFlowAssignType.Role:
-                if (!AssignRoles.Exists(d => d == handler))
-                    AssignRoles.Add(handler);
-                break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(type), type, null);
         }
@@ -174,17 +172,14 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
         switch (type)
         {
             case EFlowAssignType.Org:
-                AssignOrgCodes.AddRange(handlers);
+                var orgCodes = handlers.SelectMany(d => d.GetHigherOrgCodes(true)).ToList();
+                AssignOrgCodes.AddRange(orgCodes);
                 AssignOrgCodes = AssignOrgCodes.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
                 AssignUserIds.AddRange(handlers);
                 AssignUserIds = AssignUserIds.Distinct().ToList();
                 break;
-            case EFlowAssignType.Role:
-                AssignRoles.AddRange(handlers);
-                AssignRoles = AssignRoles.Distinct().ToList();
-                break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(type), type, null);
         }
@@ -235,28 +230,25 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
     [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
     public List<string> AssignOrgCodes { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "longtext", IsJson = true)]
     public List<string> AssignUserIds { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
-    public List<string> AssignRoles { get; set; } = new();
+    //[SugarColumn(ColumnDataType = "varchar(600)", IsJson = true)]
+    //public List<string> AssignRoles { get; set; } = new();
 
     public void Assign(EFlowAssignType type, string handler)
     {
         switch (type)
         {
             case EFlowAssignType.Org:
-                if (!AssignOrgCodes.Exists(d => d == handler))
-                    AssignOrgCodes.Add(handler);
+                var orgCodes = handler.GetHigherOrgCodes(true).ToList();
+                AssignOrgCodes.AddRange(orgCodes);
+                AssignOrgCodes = AssignOrgCodes.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
                 if (!AssignUserIds.Exists(d => d == handler))
                     AssignUserIds.Add(handler);
                 break;
-            case EFlowAssignType.Role:
-                if (!AssignRoles.Exists(d => d == handler))
-                    AssignRoles.Add(handler);
-                break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(type), type, null);
         }
@@ -267,17 +259,14 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
         switch (type)
         {
             case EFlowAssignType.Org:
-                AssignOrgCodes.AddRange(handlers);
+                var orgCodes = handlers.SelectMany(d => d.GetHigherOrgCodes(true)).ToList();
+                AssignOrgCodes.AddRange(orgCodes);
                 AssignOrgCodes = AssignOrgCodes.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
                 AssignUserIds.AddRange(handlers);
                 AssignUserIds = AssignUserIds.Distinct().ToList();
                 break;
-            case EFlowAssignType.Role:
-                AssignRoles.AddRange(handlers);
-                AssignRoles = AssignRoles.Distinct().ToList();
-                break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(type), type, null);
         }

+ 8 - 8
src/XF.Domain/Entities/IDataPermission.cs

@@ -28,10 +28,10 @@ namespace XF.Domain.Entities
         /// </summary>
         List<string> AssignUserIds { get; set; }
 
-        /// <summary>
-        /// 指派角色名称
-        /// </summary>
-        List<string> AssignRoles { get; set; }
+        ///// <summary>
+        ///// 指派角色名称
+        ///// </summary>
+        //List<string> AssignRoles { get; set; }
 
         void Assign(EFlowAssignType type, string handler);
 
@@ -50,9 +50,9 @@ namespace XF.Domain.Entities
         /// </summary>
         User = 1,
 
-        /// <summary>
-        /// 指派到角色
-        /// </summary>
-        Role = 2,
+        ///// <summary>
+        ///// 指派到角色
+        ///// </summary>
+        //Role = 2,
     }
 }

+ 32 - 0
src/XF.Domain/Extensions/OrgExtensions.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Exceptions;
+
+namespace XF.Domain.Extensions
+{
+    public static class OrgExtensions
+    {
+        public static List<string> GetHigherOrgCodes(this string orgCode, bool withSelf = false)
+        {
+            if (string.IsNullOrEmpty(orgCode))
+                return new();
+            var length = orgCode.Length;
+            if (length % 3 != 0)
+                throw new UserFriendlyException($"非法OrgCode, code: {orgCode}");
+
+            var rsp = new List<string>();
+            if (withSelf)
+                rsp.Add(orgCode);
+            var code = orgCode.Substring(0, length - 3);
+            while (code.Length > 0)
+            {
+                rsp.Add(code);
+                code = code.Substring(0, code.Length - 3);
+            }
+            return rsp;
+        }
+    }
+}