Эх сурвалжийг харах

Merge branch 'master' of http://git.fwt.com/Hotline/hotline

dss 2 жил өмнө
parent
commit
63e4992116
25 өөрчлөгдсөн 561 нэмэгдсэн , 384 устгасан
  1. 24 14
      src/Hotline.Api/Controllers/WorkflowController.cs
  2. 1 4
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  3. 23 2
      src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs
  4. 1 1
      src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs
  5. 2 1
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  6. 0 19
      src/Hotline.Repository.SqlSugar/System/WorkflowBusinessRepository.cs
  7. 4 0
      src/Hotline.Share/Dtos/FlowEngine/DefinitionDto.cs
  8. 22 0
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  9. 0 4
      src/Hotline.Share/Hotline.Share.csproj
  10. 6 3
      src/Hotline/FlowEngine/Definitions/Definition.cs
  11. 17 1
      src/Hotline/FlowEngine/Definitions/StepDefine.cs
  12. 0 39
      src/Hotline/FlowEngine/Notifies/NextStepNotify.cs
  13. 18 0
      src/Hotline/FlowEngine/Notifies/WorkflowNotify.cs
  14. 2 2
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  15. 11 3
      src/Hotline/FlowEngine/Workflows/Workflow.cs
  16. 31 19
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  17. 11 12
      src/Hotline/Orders/Order.cs
  18. 4 233
      src/Hotline/Orders/OrderComplain.cs
  19. 2 2
      src/Hotline/Orders/OrderDomainService.cs
  20. 242 0
      src/Hotline/Orders/OrderExtensionEntity.cs
  21. 25 0
      src/Hotline/Orders/OrderReport.cs
  22. 0 13
      src/Hotline/Settings/IWorkflowBusinessRepository.cs
  23. 26 5
      src/Hotline/Settings/WorkflowModule.cs
  24. 66 6
      src/XF.Domain.Repository/Entity.cs
  25. 23 1
      src/XF.Domain/Entities/IDataPermission.cs

+ 24 - 14
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -10,6 +10,7 @@ using Hotline.Share.Requests;
 using Hotline.Users;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 
@@ -60,17 +61,26 @@ public class WorkflowController : BaseController
     [HttpGet("definition")]
     public async Task<PagedDto<DefinitionDto>> QueryDefinitions([FromQuery] PagedRequest dto)
     {
-        var result = await _definitionRepository.Queryable()
+        //todo 数据量大需重构
+        var query1 = await _definitionRepository.Queryable()
             .Where(d => d.Status == EDefinitionStatus.Temporary)
+            .ToListAsync();
+        var query2 = await _definitionRepository.Queryable()
+            .Select(d => new { i = SqlFunc.RowNumber($"{d.Version} desc", d.Code), d })
             .MergeTable()
-            .Where(d => d.Status != EDefinitionStatus.Temporary)
-            .GroupBy(d => d.Code)
-            .OrderByDescending(d => d.Version)
-            .Take(1)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            .Where(d => d.i == 1)
+            .ToListAsync();
 
-        var items = _mapper.Map<IReadOnlyList<DefinitionDto>>(result.Items);
-        return new PagedDto<DefinitionDto>(result.Total, items);
+        var query = query1.Union(query2.Select(d => d.d));
+        var total = query.Count();
+        var items = query
+            .OrderBy(d => d.Status)
+            .ThenByDescending(d => d.CreationTime)
+            .Skip(dto.Skip())
+            .Take(dto.PageSize)
+            .ToList();
+
+        return new PagedDto<DefinitionDto>(total, _mapper.Map<IReadOnlyList<DefinitionDto>>(items));
     }
 
     /// <summary>
@@ -207,7 +217,7 @@ public class WorkflowController : BaseController
     [HttpGet("nextsteps")]
     public async Task<IReadOnlyList<NextStepOptions>> GetNextStepOptions(string workflowId)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, HttpContext.RequestAborted);
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: HttpContext.RequestAborted);
         var nextStepDefines = _workflowDomainService.GetNextStepOptions(workflow, HttpContext.RequestAborted);
 
         //todo 性能问题
@@ -269,7 +279,7 @@ public class WorkflowController : BaseController
     [HttpPost("jump")]
     public async Task Jump([FromBody] RecallDto dto)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, HttpContext.RequestAborted);
+        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, cancellationToken: HttpContext.RequestAborted);
         await _workflowDomainService.JumpAsync(workflow, dto, HttpContext.RequestAborted);
     }
 
@@ -290,9 +300,9 @@ public class WorkflowController : BaseController
     /// <param name="workflowId"></param>
     /// <returns></returns>
     [HttpGet("jump")]
-    public async Task<IReadOnlyList<StepDefineDto>> GetJumpTargets(string workflowId)
+    public async Task<IReadOnlyList<StepDefineDto>> GetJumpOptions(string workflowId)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, HttpContext.RequestAborted);
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: HttpContext.RequestAborted);
         return _mapper.Map<IReadOnlyList<StepDefineDto>>(workflow.Definition.Steps);
     }
 
@@ -302,9 +312,9 @@ public class WorkflowController : BaseController
     /// <param name="workflowId"></param>
     /// <returns></returns>
     [HttpGet("recall")]
-    public async Task<IReadOnlyList<StepDefineDto>> GetRecallTargets(string workflowId)
+    public async Task<IReadOnlyList<StepDefineDto>> GetRecallOptions(string workflowId)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, HttpContext.RequestAborted);
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: HttpContext.RequestAborted);
         return _mapper.Map<IReadOnlyList<StepDefineDto>>(workflow.StepBoxes);
     }
 

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

@@ -18,7 +18,6 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IWorkflowRepository _workflowRepository;
     private readonly IUserRepository _userRepository;
-    private readonly IWorkflowBusinessRepository _workflowBusinessRepository;
     private readonly ISessionContext _sessionContext;
 
     public WorkflowApplication(
@@ -26,14 +25,12 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         IWorkflowDomainService workflowDomainService,
         IWorkflowRepository workflowRepository,
         IUserRepository userRepository,
-        IWorkflowBusinessRepository workflowBusinessRepository,
         ISessionContext sessionContext)
     {
         _definitionDomainService = definitionDomainService;
         _workflowDomainService = workflowDomainService;
         _workflowRepository = workflowRepository;
         _userRepository = userRepository;
-        _workflowBusinessRepository = workflowBusinessRepository;
         _sessionContext = sessionContext;
     }
 
@@ -58,7 +55,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <returns></returns>
     public async Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken)
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, cancellationToken);
+        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, cancellationToken: cancellationToken);
         var nextStepBoxDefine = _workflowDomainService.GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
         var isOutOfCallCenter =
             await CheckIfFlowOutOfCallCenterAsync(nextStepBoxDefine, dto.NextMainHandler, cancellationToken);

+ 23 - 2
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -1,16 +1,37 @@
 using Hotline.FlowEngine.Notifies;
+using Hotline.Orders;
+using Hotline.Settings;
 using MediatR;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Handlers.FlowEngine;
 
 public class NextStepHandler : INotificationHandler<NextStepNotify>
 {
+    private readonly IOrderRepository _orderRepository;
+
+    public NextStepHandler(IOrderRepository orderRepository)
+    {
+        _orderRepository = orderRepository;
+    }
+
     /// <summary>Handles a notification</summary>
     /// <param name="notification">The notification</param>
     /// <param name="cancellationToken">Cancellation token</param>
     public async Task Handle(NextStepNotify notification, CancellationToken cancellationToken)
     {
-        //todo 1.query order 2.add depcode to assignDepCodes, userId
-        throw new NotImplementedException();
+        var workflow = notification.Workflow;
+        var data = notification.Dto;
+        switch (workflow.ModuleCode)
+        {
+            case WorkflowModuleConsts.Order:
+                var order = await _orderRepository.GetAsync(d => d.WorkflowId == workflow.Id, cancellationToken);
+                if (order == null)
+                    throw new UserFriendlyException($"工单审批流程Id无效, workflowId: {workflow.Id}", "无效流程编号");
+                order.Assign(notification.FlowAssignType, data.Handlers);
+
+                //todo business logic
+                break;
+        }
     }
 }

+ 1 - 1
src/Hotline.Repository.SqlSugar/DataPermissions/DataPermissionFilterBuilder.cs

@@ -61,7 +61,7 @@ public class DataPermissionFilterBuilder : IDataPermissionFilterBuilder, IScopeD
     private static bool FlowDataFiltering<TEntity>(TEntity entity, string userId, string depCode) where TEntity : class, IEntity<string>, IDataPermission, IWorkflow, new()
     {
         if (entity.AssignUserIds.Contains(userId)) return true;
-        foreach (var assignDepCode in entity.AssignDepCodes)
+        foreach (var assignDepCode in entity.AssignOrgCodes)
         {
             if (assignDepCode == depCode) return true;
             var baseDep = assignDepCode.Substring(0, 3);

+ 2 - 1
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -6,10 +6,11 @@ using System.Threading.Tasks;
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using SqlSugar;
+using XF.Domain.Dependency;
 
 namespace Hotline.Repository.SqlSugar.Orders
 {
-    public class OrderRepository : BaseRepositoryWorkflow<Order>, IOrderRepository
+    public class OrderRepository : BaseRepositoryWorkflow<Order>, IOrderRepository, IScopeDependency
     {
         public OrderRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
         {

+ 0 - 19
src/Hotline.Repository.SqlSugar/System/WorkflowBusinessRepository.cs

@@ -1,19 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Hotline.Repository.SqlSugar.DataPermissions;
-using Hotline.Settings;
-using SqlSugar;
-using XF.Domain.Dependency;
-
-namespace Hotline.Repository.SqlSugar.System
-{
-    public class WorkflowBusinessRepository : BaseRepository<WorkflowModule>, IWorkflowBusinessRepository, IScopeDependency
-    {
-        public WorkflowBusinessRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
-        {
-        }
-    }
-}

+ 4 - 0
src/Hotline.Share/Dtos/FlowEngine/DefinitionDto.cs

@@ -39,10 +39,14 @@ namespace Hotline.Share.Dtos.FlowEngine
         
         public string ExternalData { get; set; }
 
+        public string ModuleId { get; set; }
+
         /// <summary>
         /// 业务模块名称
         /// </summary>
         public string ModuleName { get; set; }
+
+        public string ModuleCode { get; set; }
     }
 
     public class StepDefineDto : StepBasicDto

+ 22 - 0
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Order
+{
+    public class OrderDto : UpdateOrderDto
+    {
+        public string CreationTime { get; set; }
+    }
+
+    public class UpdateOrderDto : AddOrderDto
+    {
+        public string Id { get; set; }
+    }
+
+    public class AddOrderDto
+    {
+    }
+}

+ 0 - 4
src/Hotline.Share/Hotline.Share.csproj

@@ -11,8 +11,4 @@
     <PackageReference Include="XF.Utility.EnumExtensions" Version="1.0.2" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Dtos\Order\" />
-  </ItemGroup>
-
 </Project>

+ 6 - 3
src/Hotline/FlowEngine/Definitions/Definition.cs

@@ -33,14 +33,17 @@ public class Definition : CreationEntity
 
     public EDefinitionStatus Status { get; set; }
 
-    public string ModuleId { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleId { get; set; }
 
     /// <summary>
     /// 业务模块名称
     /// </summary>
-    public string ModuleName { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleName { get; set; }
 
-    public string ModuleCode { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleCode { get; set; }
 
     #region Method
 

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

@@ -1,4 +1,7 @@
-namespace Hotline.FlowEngine.Definitions;
+using Hotline.Share.Enums.FlowEngine;
+using XF.Domain.Entities;
+
+namespace Hotline.FlowEngine.Definitions;
 
 /// <summary>
 /// 模板定义节点
@@ -6,4 +9,17 @@
 public class StepDefine : StepBasic
 {
     public List<NextStepDefine> NextSteps { get; set; }
+
+    public EFlowAssignType GFlowAssignType()
+    {
+        return HandlerType switch
+        {
+            EHandlerType.Role => EFlowAssignType.User,
+            EHandlerType.OrgLevel => EFlowAssignType.Org,
+            EHandlerType.OrgType => EFlowAssignType.Org,
+            EHandlerType.AssignUser => EFlowAssignType.User,
+            EHandlerType.AssignOrg => EFlowAssignType.Org,
+            _ => throw new ArgumentOutOfRangeException()
+        };
+    }
 }

+ 0 - 39
src/Hotline/FlowEngine/Notifies/NextStepNotify.cs

@@ -1,39 +0,0 @@
-using Hotline.FlowEngine.Workflows;
-using Hotline.Share.Dtos.FlowEngine;
-using MediatR;
-
-namespace Hotline.FlowEngine.Notifies
-{
-    public class WorkflowNotify : INotification
-    {
-        public Workflow Workflow { get; set; }
-    }
-
-    public class StartWorkflowNotify : WorkflowNotify
-    {
-        public BasicWorkflowDto Dto { get; set; }
-    }
-
-    public class AcceptWorkflowNotify : WorkflowNotify
-    {
-
-    }
-
-    public class NextStepNotify : WorkflowNotify
-    {
-        public BasicWorkflowDto Dto { get; set; }
-    }
-
-    /// <summary>
-    /// 汇总节点可接办
-    /// </summary>
-    public class CountersignEndAssigned : WorkflowNotify
-    {
-
-    }
-
-
-
-    public record PreviousStepNotify(PreviousWorkflowDto Data) : INotification;
-
-}

+ 18 - 0
src/Hotline/FlowEngine/Notifies/WorkflowNotify.cs

@@ -0,0 +1,18 @@
+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) : INotification;
+
+public record StartWorkflowNotify(Workflow Workflow, EFlowAssignType FlowAssignType, BasicWorkflowDto Dto) : WorkflowNotify(Workflow, FlowAssignType);
+
+public record NextStepNotify(Workflow Workflow, EFlowAssignType FlowAssignType, BasicWorkflowDto Dto) : WorkflowNotify(Workflow, FlowAssignType);
+
+public record AcceptWorkflowNotify(Workflow Workflow) : INotification;
+
+public record CountersignEndAssigned(Workflow Workflow) : INotification;
+
+public record PreviousStepNotify(PreviousWorkflowDto Data) : INotification;

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

@@ -13,9 +13,9 @@ namespace Hotline.FlowEngine.Workflows
         Task StartAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken);
 
         /// <summary>
-        /// 有definition,steps,无traces
+        /// 查询工作流
         /// </summary>
-        Task<Workflow> GetWorkflowAsync(string workflowId, CancellationToken cancellationToken);
+        Task<Workflow> GetWorkflowAsync(string workflowId, bool withDefine = false, bool withSteps = false, bool withTraces = false, bool withSupplements = false, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 受理,接办

+ 11 - 3
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -9,9 +9,17 @@ public class Workflow : CreationEntity
 {
     public string DefinitionId { get; set; }
 
-    public string ModuleId { get; set; }
-    public string ModuleName { get; set; }
-    public string ModuleCode { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleId { get; set; }
+
+    /// <summary>
+    /// 业务模块名称
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleName { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? ModuleCode { get; set; }
 
     public string Title { get; set; }
 

+ 31 - 19
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -85,28 +85,40 @@ namespace Hotline.FlowEngine.Workflows
             await CreateStepAsync(workflow, nextStepBoxDefine, dto, cancellationToken: cancellationToken);
 
             //publish
-            await _mediator.Publish(new StartWorkflowNotify { Workflow = workflow, Dto = dto }, cancellationToken);
+            await _mediator.Publish(new StartWorkflowNotify(workflow, nextStepBoxDefine.GFlowAssignType(), dto), cancellationToken);
         }
 
-        public async Task<Workflow> GetWorkflowAsync(string workflowId, CancellationToken cancellationToken)
+        public async Task<Workflow> GetWorkflowAsync(string workflowId,
+            bool withDefine = false, bool withSteps = false,
+            bool withTraces = false, bool withSupplements = false,
+            CancellationToken cancellationToken = default)
         {
-            var workflow = await _workflowRepository.Queryable()
-                .Includes(d => d.Definition)
-                .FirstAsync(d => d.Id == workflowId);
+            var query = _workflowRepository.Queryable();
+            if (withDefine)
+                query = query.Includes(d => d.Definition);
+            if (withSupplements)
+                query = query.Includes(d => d.Supplements);
+
+            var workflow = await query.FirstAsync(d => d.Id == workflowId);
             if (workflow is null)
                 throw new UserFriendlyException("无效workflowId");
 
-            var steps = await _workflowStepRepository.Queryable()
-                .Where(d => d.WorkflowId == workflowId)
-                .OrderBy(d => d.CreationTime)
-                .ToTreeAsync(d => d.Steps, d => d.ParentId, null);
-
-            //var traces = await _workflowTraceRepository.Queryable()
-            //    .Where(d => d.WorkflowId == workflowId)
-            //    .ToTreeAsync(d => d.Traces, d => d.ParentId, null);
+            if (withSteps)
+            {
+                var steps = await _workflowStepRepository.Queryable()
+                    .Where(d => d.WorkflowId == workflowId)
+                    .OrderBy(d => d.CreationTime)
+                    .ToTreeAsync(d => d.Steps, d => d.ParentId, null);
+                workflow.StepBoxes = steps;
+            }
 
-            workflow.StepBoxes = steps;
-            //workflow.Traces = traces;
+            if (withTraces)
+            {
+                var traces = await _workflowTraceRepository.Queryable()
+                    .Where(d => d.WorkflowId == workflowId)
+                    .ToTreeAsync(d => d.Traces, d => d.ParentId, null);
+                workflow.Traces = traces;
+            }
 
             return workflow;
         }
@@ -141,7 +153,7 @@ namespace Hotline.FlowEngine.Workflows
 
             await AcceptTraceAsync(workflow, currentStepBox, currentStep, cancellationToken);
 
-            await _mediator.Publish(new AcceptWorkflowNotify { Workflow = workflow }, cancellationToken);
+            await _mediator.Publish(new AcceptWorkflowNotify(workflow), cancellationToken);
         }
 
         /// <summary>
@@ -244,14 +256,14 @@ namespace Hotline.FlowEngine.Workflows
                     if (canHandle)
                     {
                         await UpdateNextCountersignEndAssignedAsync(nextStepBox, currentStep, cancellationToken);
-                        await _mediator.Publish(new CountersignEndAssigned { Workflow = workflow }, cancellationToken);
+                        await _mediator.Publish(new CountersignEndAssigned(workflow), cancellationToken);
                     }
 
                 }
                 else
                 {
                     await UpdateNextCountersignEndAssignedAsync(nextStepBox, currentStep, cancellationToken);
-                    await _mediator.Publish(new CountersignEndAssigned { Workflow = workflow }, cancellationToken);
+                    await _mediator.Publish(new CountersignEndAssigned(workflow), cancellationToken);
                 }
             }
 
@@ -268,7 +280,7 @@ namespace Hotline.FlowEngine.Workflows
 
             #endregion
 
-            await _mediator.Publish(new NextStepNotify { Workflow = workflow, Dto = dto }, cancellationToken);
+            await _mediator.Publish(new NextStepNotify(workflow, nextStepBoxDefine.GFlowAssignType(), dto), cancellationToken);
         }
 
         /// <summary>

+ 11 - 12
src/Hotline/Orders/Order.cs

@@ -157,8 +157,17 @@ namespace Hotline.Orders
         public string Content { get; set; }
 
         #endregion
+        
 
-        public string CurrentStep { get; set; }
+        /// <summary>
+        /// 当前节点名称
+        /// </summary>
+        public string CurrentStepName { get; set; }
+
+        /// <summary>
+        /// 到达当前节点时间
+        /// </summary>
+        public DateTime CurrentStepTime { get; set; }
 
         /// <summary>
         /// 工单状态
@@ -173,7 +182,7 @@ namespace Hotline.Orders
         /// <summary>
         /// 过期时间
         /// </summary>
-        public DateTime? EndTime { get; set; }
+        public DateTime? ExpiredTime { get; set; }
     }
 
     /// <summary>
@@ -186,15 +195,5 @@ namespace Hotline.Orders
         /// </summary>
         [Navigate(NavigateType.OneToOne, nameof(Id))]
         public OrderComplain OrderComplain { get; set; }
-
-
-    }
-
-    /// <summary>
-    /// 工单扩展信息 12315-举报
-    /// </summary>
-    public class OrderExt1
-    {
-
     }
 }

+ 4 - 233
src/Hotline/Orders/OrderComplain.cs

@@ -6,143 +6,15 @@ namespace Hotline.Orders;
 /// <summary>
 /// 工单扩展信息(12315-投诉)
 /// </summary>
-public class OrderComplain : FullStateEntity
+public class OrderComplain : OrderExtensionEntity
 {
-    #region 投诉人信息
-
-    /// <summary>
-    /// 证件类型
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? LicenceTypeCode { get; set; }
-    [SugarColumn(IsNullable = true)]
-    public string? LicenceType { get; set; }
-
-    /// <summary>
-    /// 证件号码, 证件类型已选的情况为必填,否则非必填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? LicenceNo { get; set; }
-
-    /// <summary>
-    /// 提供方类型(投诉人类型)
-    /// </summary>
-    public EProviderType? ProviderType { get; set; }
-
-    /// <summary>
-    /// 提供方身份(投诉人身份)
-    /// </summary>
-    public ECitizenStatus1? ProviderStatus { get; set; }
-
-    /// <summary>
-    /// 国籍或地区
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public ENationality? Nationality { get; set; }
-
-    /// <summary>
-    /// 民族
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? NationCode { get; set; }
-    [SugarColumn(IsNullable = true)]
-    public string? Nation { get; set; }
-
-    /// <summary>
-    /// 邮政编码
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? PostalCode { get; set; }
-
-    /// <summary>
-    /// 邮箱
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? Email { get; set; }
-
-    /// <summary>
-    /// 其他联系方式
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? OtherContact { get; set; }
-
-    #endregion
-
-    #region 投诉对象信息
-
-    /// <summary>
-    /// 企业名称
-    /// </summary>
-    public string EnterpriseName { get; set; }
-
-    /// <summary>
-    /// 统一社会信用代码
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? UnifiedSocialCreditCode { get; set; }
-
-    /// <summary>
-    /// 注册地址
-    /// </summary>
-    public string RegisterAddress { get; set; }
-
-    /// <summary>
-    /// 注册号
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? RegisterNumber { get; set; }
-
-    /// <summary>
-    /// 企业联系人
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? EnterpriseContact { get; set; }
-
-    /// <summary>
-    /// 市场主体类型
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? MarketTypeCode { get; set; }
-    [SugarColumn(IsNullable = true)]
-    public string? MarketType { get; set; }
-
-    /// <summary>
-    /// 行业分类
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? IndustryClassifyCode { get; set; }
-    [SugarColumn(IsNullable = true)]
-    public string? IndustryClassify { get; set; }
-
-    #endregion
-
     #region 投诉详情
 
-    /// <summary>
-    /// 商品品牌编码
-    /// </summary>
-    public string BrandCode { get; set; }
-
-    /// <summary>
-    /// 商品分类/品牌
-    /// </summary>
-    public string Brand { get; set; }
-
-    /// <summary>
-    /// 消费金额,只能填写数字,且只能填写非负数
-    /// </summary>
-    public decimal Amount { get; set; }
-
-    /// <summary>
-    /// 客体类别
-    /// </summary>
-    public string ObjectClassifyCode { get; set; }
-    public string ObjectClassify { get; set; }
-
     /// <summary>
     /// 投诉问题类别
     /// </summary>
     public string ComplainClassifyCode { get; set; }
+
     public string ComplainClassify { get; set; }
 
     /// <summary>
@@ -150,29 +22,10 @@ public class OrderComplain : FullStateEntity
     /// </summary>
     public DateTime OccurrenceTime { get; set; }
 
-    /// <summary>
-    /// 销售方式
-    /// </summary>
-    public ESalesMode SalesMode { get; set; }
-
     /// <summary>
     /// 投诉目标,销售方式为“网购”时展示该字段且必填
     /// </summary>
-    public EComplainTarget? ComplainTarget { get; set; }
-
-    /// <summary>
-    /// 电商平台,销售方式为“网购”时展示该字段且必填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ECommercePlatformCode { get; set; }
-    [SugarColumn(IsNullable = true)]
-    public string? ECommercePlatform { get; set; }
-
-    /// <summary>
-    /// 外部订单号,销售方式为“ 网购”时展示该字段且必填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ExternalOrderNo { get; set; }
+    public EOrderTarget? ComplainTarget { get; set; }
 
     /// <summary>
     /// 经营地址,销售方式为“现场”时必填
@@ -183,88 +36,6 @@ public class OrderComplain : FullStateEntity
     [SugarColumn(IsNullable = true)]
     public string? BussinessAddress { get; set; }
 
-    /// <summary>
-    /// 具体渠道
-    /// <remarks>
-    /// 销售方式为“电视购物”“电话购物”“邮购”时展示该字段,且必填
-    /// 电视购物:请填写购物的电视频道
-    /// 电话购物:请填写商品销售者的热线号码
-    /// 邮购:请填写宣传商品的邮政公司或来件地址
-    /// </remarks>
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? Channel { get; set; }
-
-    /// <summary>
-    /// 专利权人,“投诉问题类别”为“专利”时展示该字段,选填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? Patentee { get; set; }
-
-    /// <summary>
-    /// 专利名称,“投诉问题类别”为“专利”时展示该字段,选填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? PatentName { get; set; }
-
-    /// <summary>
-    /// 专利类型,“投诉问题类别”为“专利”时展示该字段,选填
-    /// </summary>
-    public EPatentType? PatentType { get; set; }
-
-    /// <summary>
-    /// 专利号,“投诉问题类别”为“专利”时展示该字段,选填
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? PatentNo { get; set; }
-
-    /// <summary>
-    /// 产品名称
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ProductName { get; set; }
-
-    /// <summary>
-    /// 批准文号
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ApprovalNumber { get; set; }
-
-    /// <summary>
-    /// 产品批号
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ProductBatchNo { get; set; }
-
-    /// <summary>
-    /// 产品规格
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ProductStandard { get; set; }
-
-    /// <summary>
-    /// 产品有效期
-    /// </summary>
-    public DateTime ProductExpriedTime { get; set; }
-
-    /// <summary>
-    /// 生产厂家
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? Manufacturer { get; set; }
-
-    /// <summary>
-    /// 销售企业
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? SalesEnterprise { get; set; }
-
-    /// <summary>
-    /// 消费者地址
-    /// </summary>
-    [SugarColumn(IsNullable = true)]
-    public string? ConsumerAddress { get; set; }
-
     /// <summary>
     /// 诉求类型,多选
     /// </summary>
@@ -299,7 +70,7 @@ public enum EProviderType
     //生产企业、销售企业、服务企业、其他企业、个体工商户、自然人、群诉、其他类型
 }
 
-public enum EComplainTarget
+public enum EOrderTarget
 {
     //平台、入驻商家
 }

+ 2 - 2
src/Hotline/Orders/OrderDomainService.cs

@@ -23,12 +23,12 @@ public class OrderDomainService : IOrderDomainService
         if (!string.IsNullOrEmpty(order.Contact))
             order.ContactMask = order.Contact.MaskPhoneNumber();
 
-        order.No = GetNewOrderNo();
+        order.No = GenerateNewOrderNo();
 
         return await _orderRepository.AddAsync(order, cancellationToken);
     }
 
-    private string GetNewOrderNo()
+    private string GenerateNewOrderNo()
     {
         var today = DateTime.Today;
         var cacheKey = $"{OrderNoPrefix}{today:yyyyMMdd}";

+ 242 - 0
src/Hotline/Orders/OrderExtensionEntity.cs

@@ -0,0 +1,242 @@
+using SqlSugar;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders;
+
+public class OrderExtensionEntity : FullStateEntity
+{
+    #region 投诉人信息
+
+    /// <summary>
+    /// 证件类型
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? LicenceTypeCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? LicenceType { get; set; }
+
+    /// <summary>
+    /// 证件号码, 证件类型已选的情况为必填,否则非必填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? LicenceNo { get; set; }
+
+    /// <summary>
+    /// 提供方类型(投诉人类型)
+    /// </summary>
+    public EProviderType? ProviderType { get; set; }
+
+    /// <summary>
+    /// 提供方身份(投诉人身份)
+    /// </summary>
+    public ECitizenStatus1? ProviderStatus { get; set; }
+
+    /// <summary>
+    /// 国籍或地区
+    /// </summary>
+    public ENationality? Nationality { get; set; }
+
+    /// <summary>
+    /// 民族
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? NationCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? Nation { get; set; }
+
+    /// <summary>
+    /// 邮政编码
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? PostalCode { get; set; }
+
+    /// <summary>
+    /// 邮箱
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? Email { get; set; }
+
+    /// <summary>
+    /// 其他联系方式
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? OtherContact { get; set; }
+
+    #endregion
+
+    #region 投诉对象信息
+
+    /// <summary>
+    /// 企业名称
+    /// </summary>
+    public string EnterpriseName { get; set; }
+
+    /// <summary>
+    /// 统一社会信用代码
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? UnifiedSocialCreditCode { get; set; }
+
+    /// <summary>
+    /// 注册地址
+    /// </summary>
+    public string RegisterAddress { get; set; }
+
+    /// <summary>
+    /// 注册号
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? RegisterNumber { get; set; }
+
+    /// <summary>
+    /// 企业联系人
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? EnterpriseContact { get; set; }
+
+    /// <summary>
+    /// 市场主体类型
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? MarketTypeCode { get; set; }
+
+    [SugarColumn(IsNullable = true)]
+    public string? MarketType { get; set; }
+
+    /// <summary>
+    /// 行业分类
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? IndustryClassifyCode { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? IndustryClassify { get; set; }
+
+    #endregion
+
+    #region 投诉/举报 详情
+
+
+    /// <summary>
+    /// 商品分类/品牌
+    /// </summary>
+    public string BrandCode { get; set; }
+
+    public string Brand { get; set; }
+
+    /// <summary>
+    /// 消费金额,只能填写数字,且只能填写非负数
+    /// </summary>
+    public decimal Amount { get; set; }
+
+    /// <summary>
+    /// 客体类别
+    /// </summary>
+    public string ObjectClassifyCode { get; set; }
+
+    public string ObjectClassify { get; set; }
+
+    /// <summary>
+    /// 销售方式
+    /// </summary>
+    public ESalesMode SalesMode { get; set; }
+
+    /// <summary>
+    /// 电商平台,销售方式为“网购”时展示该字段且必填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ECommercePlatformCode { get; set; }
+    [SugarColumn(IsNullable = true)]
+    public string? ECommercePlatform { get; set; }
+
+    /// <summary>
+    /// 外部订单号,销售方式为“ 网购”时展示该字段且必填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ExternalOrderNo { get; set; }
+
+    /// <summary>
+    /// 具体渠道
+    /// <remarks>
+    /// 销售方式为“电视购物”“电话购物”“邮购”时展示该字段,且必填
+    /// 电视购物:请填写购物的电视频道
+    /// 电话购物:请填写商品销售者的热线号码
+    /// 邮购:请填写宣传商品的邮政公司或来件地址
+    /// </remarks>
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? Channel { get; set; }
+
+    /// <summary>
+    /// 专利权人,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? Patentee { get; set; }
+
+    /// <summary>
+    /// 专利名称,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? PatentName { get; set; }
+
+    /// <summary>
+    /// 专利类型,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    public EPatentType? PatentType { get; set; }
+
+    /// <summary>
+    /// 专利号,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? PatentNo { get; set; }
+
+    /// <summary>
+    /// 产品名称
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ProductName { get; set; }
+
+    /// <summary>
+    /// 批准文号
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ApprovalNumber { get; set; }
+
+    /// <summary>
+    /// 产品批号
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ProductBatchNo { get; set; }
+
+    /// <summary>
+    /// 产品规格
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ProductStandard { get; set; }
+
+    /// <summary>
+    /// 产品有效期
+    /// </summary>
+    public DateTime ProductExpriedTime { get; set; }
+
+    /// <summary>
+    /// 生产厂家
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? Manufacturer { get; set; }
+
+    /// <summary>
+    /// 销售企业
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? SalesEnterprise { get; set; }
+
+    /// <summary>
+    /// 消费者地址
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ConsumerAddress { get; set; }
+
+    #endregion
+}

+ 25 - 0
src/Hotline/Orders/OrderReport.cs

@@ -0,0 +1,25 @@
+using SqlSugar;
+
+namespace Hotline.Orders;
+
+/// <summary>
+/// 工单扩展信息 12315-举报
+/// </summary>
+public class OrderReport : OrderExtensionEntity
+{
+    #region 举报详情
+
+    /// <summary>
+    /// 举报问题类别
+    /// </summary>
+    public string ReportClassifyCode { get; set; }
+
+    public string ReportClassify { get; set; }
+
+    /// <summary>
+    /// 举报目标,销售方式为“网购”时展示该字段且必填
+    /// </summary>
+    public EOrderTarget? ReportTarget { get; set; }
+
+    #endregion
+}

+ 0 - 13
src/Hotline/Settings/IWorkflowBusinessRepository.cs

@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using XF.Domain.Repository;
-
-namespace Hotline.Settings
-{
-    public interface IWorkflowBusinessRepository : IRepository<WorkflowModule>
-    {
-    }
-}

+ 26 - 5
src/Hotline/Settings/WorkflowModule.cs

@@ -13,12 +13,33 @@ namespace Hotline.Settings;
 /// <summary>
 /// 工作流业务模块
 /// </summary>
-[SugarIndex("unique_account_username", nameof(WorkflowModule.Code), OrderByType.Asc, true)]
-public class WorkflowModule : CreationEntity
+//[SugarIndex("unique_account_username", nameof(WorkflowModule.Code), OrderByType.Asc, true)]
+//public class WorkflowModule : CreationEntity
+//{
+//    public string Name { get; set; }
+
+//    public string Code { get; set; }
+
+//    public string DefinitionCode { get; set; }
+//}
+
+public class WorkflowModule
 {
-    public string Name { get; set; }
+    public WorkflowModule()
+    {
+        Modules = new Dictionary<string, string>
+        {
+            { WorkflowModuleConsts.Order, "工单审批" },
+        };
+    }
 
-    public string Code { get; set; }
+    public Dictionary<string, string> Modules { get; init; }
+}
 
-    public string DefinitionCode { get; set; }
+public class WorkflowModuleConsts
+{
+    /// <summary>
+    /// 工单审批
+    /// </summary>
+    public const string Order = "Order";
 }

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

@@ -139,11 +139,41 @@ public abstract class WorkflowEntity : FullStateEntity, IWorkflow
     [SugarColumn(IsNullable = true)]
     public string? WorkflowId { get; set; }
 
-    [SugarColumn(ColumnDataType = "varchar(4000)", IsJson = true)]
-    public List<string> AssignDepCodes { get; set; } = new();
+    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    public List<string> AssignOrgCodes { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(4000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
     public List<string> AssignUserIds { get; set; } = new();
+
+    public void Assign(EFlowAssignType type, string id)
+    {
+        switch (type)
+        {
+            case EFlowAssignType.Org:
+                AssignOrgCodes.Add(id);
+                break;
+            case EFlowAssignType.User:
+                AssignUserIds.Add(id);
+                break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(type), type, null);
+        }
+    }
+
+    public void Assign(EFlowAssignType type, IEnumerable<string> ids)
+    {
+        switch (type)
+        {
+            case EFlowAssignType.Org:
+                AssignOrgCodes.AddRange(ids);
+                break;
+            case EFlowAssignType.User:
+                AssignUserIds.AddRange(ids);
+                break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(type), type, null);
+        }
+    }
 }
 
 public abstract class PositionEntity : FullStateEntity
@@ -187,9 +217,39 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
     [SugarColumn(IsNullable = true)]
     public string? WorkflowId { get; set; }
 
-    [SugarColumn(ColumnDataType = "varchar(3000)", IsJson = true)]
-    public List<string> AssignDepCodes { get; set; } = new();
+    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+    public List<string> AssignOrgCodes { get; set; } = new();
 
-    [SugarColumn(ColumnDataType = "varchar(3000)", IsJson = true)]
+    [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
     public List<string> AssignUserIds { get; set; } = new();
+
+    public void Assign(EFlowAssignType type, string id)
+    {
+        switch (type)
+        {
+            case EFlowAssignType.Org:
+                AssignOrgCodes.Add(id);
+                break;
+            case EFlowAssignType.User:
+                AssignUserIds.Add(id);
+                break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(type), type, null);
+        }
+    }
+
+    public void Assign(EFlowAssignType type, IEnumerable<string> ids)
+    {
+        switch (type)
+        {
+            case EFlowAssignType.Org:
+                AssignOrgCodes.AddRange(ids);
+                break;
+            case EFlowAssignType.User:
+                AssignUserIds.AddRange(ids);
+                break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(type), type, null);
+        }
+    }
 }

+ 23 - 1
src/XF.Domain/Entities/IDataPermission.cs

@@ -17,10 +17,32 @@ namespace XF.Domain.Entities
     public interface IWorkflow
     {
         string? WorkflowId { get; set; }
+
         /// <summary>
         /// 指派部门编码
         /// </summary>
-        List<string> AssignDepCodes { get; set; }
+        List<string> AssignOrgCodes { get; set; }
+
+        /// <summary>
+        /// 指派用户Id
+        /// </summary>
         List<string> AssignUserIds { get; set; }
+
+        void Assign(EFlowAssignType type, string id);
+
+        void Assign(EFlowAssignType type, IEnumerable<string> ids);
+    }
+
+    public enum EFlowAssignType
+    {
+        /// <summary>
+        /// 指派到部门
+        /// </summary>
+        Org = 0,
+
+        /// <summary>
+        /// 指派到用户
+        /// </summary>
+        User = 1,
     }
 }