xf 2 سال پیش
والد
کامیت
81e9c7ffd1

+ 33 - 0
build/docker-compose.yml

@@ -0,0 +1,33 @@
+version: '3.4'
+
+services:
+  hotline:
+    image: ${DOCKER_REGISTRY-fwt}/hotline:${TAG:-latest}
+    container_name: hotline
+    environment:
+      - "TZ=Asia/Shanghai"
+    ports:
+      - "50110:80"
+      - "50113:50001"
+      - "50112:3500"
+    networks:
+      - hotline
+
+  hotline-dapr:
+    image: "daprio/daprd:edge"
+    command: [ "./daprd", 
+    "-app-id", "hotline", 
+    "-app-port", "80",
+    "-components-path", "/components",
+    #"-config", "/configuration/config.yaml"
+    ]
+    volumes:
+    - "./dapr/components/:/components"
+    #- "./dapr/configuration/:/configuration"
+    depends_on:
+      - hotline
+    network_mode: "service:hotline"
+
+networks:
+  hotline:
+    external: true

+ 1 - 0
src/Hotline.Api/Controllers/CallController.cs

@@ -1,6 +1,7 @@
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
 using Hotline.Permissions;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Requests;

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

@@ -1,6 +1,6 @@
 using Hotline.Permissions;
 using Hotline.Settings;
-using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Role;
 using Identity.Admin.HttpClient;
 using Identity.Shared.Dtos.Identity;

+ 15 - 2
src/Hotline.Api/Controllers/TestController.cs

@@ -1,4 +1,6 @@
-using Hotline.CallCenter.BlackLists;
+using Conductor.Client;
+using Conductor.Domain.Models;
+using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Devices;
 using Hotline.CallCenter.Ivrs;
 using Hotline.Realtimes;
@@ -35,6 +37,7 @@ namespace Hotline.Api.Controllers
         private readonly IBlacklistDomainService _blacklistDomainService;
         private readonly IIvrDomainService _ivrDomainService;
         private readonly ISugarUnitOfWork<HotlineDbContext> _uow;
+        private readonly IWorkflowRemotingService _workflowRemotingService;
 
         //private readonly ITypedCache<List<User>> _cache;
         //private readonly ICacheManager<User> _cache;
@@ -65,7 +68,8 @@ namespace Hotline.Api.Controllers
             IRealtimeService realtimeService,
             IBlacklistDomainService blacklistDomainService,
             IIvrDomainService ivrDomainService,
-            ISugarUnitOfWork<HotlineDbContext> uow
+            ISugarUnitOfWork<HotlineDbContext> uow,
+            IWorkflowRemotingService workflowRemotingService
             )
         {
             _logger = logger;
@@ -78,6 +82,7 @@ namespace Hotline.Api.Controllers
             _blacklistDomainService = blacklistDomainService;
             _ivrDomainService = ivrDomainService;
             _uow = uow;
+            _workflowRemotingService = workflowRemotingService;
         }
 
 
@@ -104,6 +109,14 @@ namespace Hotline.Api.Controllers
             throw new UserFriendlyException(2001, "test");
         }
 
+        [AllowAnonymous]
+        [HttpGet("wfdefine")]
+        public async Task<IReadOnlyList<Definition>> GetWorkflowDefine()
+        {
+            var a = await _workflowRemotingService.QueryDefinitionAsync(HttpContext.RequestAborted);
+            return a.Result;
+        }
+
         [ApiExplorerSettings(IgnoreApi = true)]
         [AllowAnonymous]
         [HttpGet("cdb")]

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

@@ -2,7 +2,6 @@
 using Hotline.Caches;
 using Hotline.CallCenter.Tels;
 using Hotline.Permissions;
-using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.User;
 using Hotline.Users;
 using Identity.Admin.HttpClient;
@@ -20,6 +19,7 @@ using XF.Utility.UnifyResponse;
 using Hotline.Settings;
 using Microsoft.AspNetCore.Mvc.Formatters;
 using Microsoft.AspNetCore.Authorization;
+using Hotline.Share.Dtos;
 
 namespace Hotline.Api.Controllers;
 

+ 107 - 0
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -0,0 +1,107 @@
+using Conductor.Client;
+using Conductor.Domain.Models;
+using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.Workflow;
+using Hotline.Share.Requests;
+using MapsterMapper;
+using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Exceptions;
+
+namespace Hotline.Api.Controllers;
+
+/// <summary>
+/// 工作流管理
+/// </summary>
+public class WorkflowController : BaseController
+{
+    private readonly IWorkflowRemotingService _workflowRemotingService;
+    private readonly IMapper _mapper;
+
+    public WorkflowController(
+        IWorkflowRemotingService workflowRemotingService,
+        IMapper mapper)
+    {
+        _workflowRemotingService = workflowRemotingService;
+        _mapper = mapper;
+    }
+
+    /// <summary>
+    /// 分页查询流程模板
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("definition")]
+    public async Task<PagedDto<WorkflowDefinitionDto>> QueryDefinitions([FromQuery] PagedRequest dto)
+    {
+        var presRsp = await _workflowRemotingService.QueryPreDefinitionAsync(HttpContext.RequestAborted);
+        if (!presRsp.IsSuccess)
+            throw new UserFriendlyException(presRsp.Error ?? string.Empty, "流程模板草稿查询失败");
+        var definesRsp = await _workflowRemotingService.QueryDefinitionAsync(HttpContext.RequestAborted);
+        if (!definesRsp.IsSuccess)
+            throw new UserFriendlyException(definesRsp.Error ?? string.Empty, "流程模板查询失败");
+        var dtos = _mapper.Map<List<WorkflowDefinitionDto>>(presRsp.Result);
+        dtos.AddRange(_mapper.Map<List<WorkflowDefinitionDto>>(definesRsp.Result));
+        var items = dtos.OrderByDescending(d => d.IsPreDefinition)
+            .ThenByDescending(d => d.Id)
+            .Skip(dto.Skip())
+            .Take(dto.PageSize)
+            .ToList();
+
+        return new PagedDto<WorkflowDefinitionDto>(dtos.Count, items);
+    }
+
+    /// <summary>
+    /// 新增流程模板草稿
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    /// <exception cref="UserFriendlyException"></exception>
+    [HttpPost("predefinition")]
+    public async Task<string> AddPreDefinition([FromBody] PreDefinition dto)
+    {
+        var addPreRsp = await _workflowRemotingService.AddPreDefinitionAsync(dto, HttpContext.RequestAborted);
+        if (!addPreRsp.IsSuccess) throw new UserFriendlyException(addPreRsp.Error ?? string.Empty, "新增流程模板草稿失败");
+        return addPreRsp.Result;
+    }
+
+    /// <summary>
+    /// 更新流程模板草稿
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    /// <exception cref="UserFriendlyException"></exception>
+    [HttpPut("predefinition")]
+    public async Task UpdatePreDefinition([FromBody] PreDefinition dto)
+    {
+        var updatePreRsp = await _workflowRemotingService.UpdatePreDefinitionAsync(dto, HttpContext.RequestAborted);
+        if (!updatePreRsp.IsSuccess) throw new UserFriendlyException(updatePreRsp.Error ?? string.Empty, "更新流程模板草稿失败");
+    }
+
+    /// <summary>
+    /// 发布(将草稿发布为正式模板)
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("publish/{id}")]
+    public async Task Publish(string id)
+    {
+        var pubRsp = await _workflowRemotingService.PublishAsync(id, HttpContext.RequestAborted);
+        if (!pubRsp.IsSuccess) throw new UserFriendlyException(pubRsp.Error ?? string.Empty, "发布流程模板失败");
+    }
+
+    /// <summary>
+    /// 发布(将草稿发布为正式模板)
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("publish")]
+    public async Task Publish([FromBody] PreDefinition dto)
+    {
+        var pubRsp = await _workflowRemotingService.PublishAsync(dto, HttpContext.RequestAborted);
+        if (!pubRsp.IsSuccess) throw new UserFriendlyException(pubRsp.Error ?? string.Empty, "发布流程模板失败");
+    }
+
+    [HttpPost("")]
+    public async Task Enable(string workflowId)
+    {
+
+    }
+}

+ 9 - 1
src/Hotline.Api/StartupExtensions.cs

@@ -24,6 +24,7 @@ using Microsoft.OpenApi.Models;
 using Serilog;
 using XF.Domain.Dependency;
 using XF.Domain.Filters;
+using Conductor.Client;
 
 namespace Hotline.Api;
 
@@ -49,6 +50,7 @@ internal static class StartupExtensions
         services
             .BatchInjectServices()
             .AddApplication()
+            .AddWorkflowConductor()
             ;
 
         var identityConfigs = configuration.GetSection(nameof(IdentityConfigs)).Get<IdentityConfigs>();
@@ -102,7 +104,13 @@ internal static class StartupExtensions
         {
             options.Filters.Add<UnifyResponseFilter>();
             options.Filters.Add<UserFriendlyExceptionFilter>();
-        });
+        })
+            .AddDapr(d =>
+            {
+#if DEBUG
+                d.UseHttpEndpoint("http://192.168.100.223:50122");
+#endif
+            });
         // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
         services.AddEndpointsApiExplorer();
         services.AddSwaggerGen(c =>

+ 2 - 4
src/Hotline.Application.Contracts/AppContractsStartupExtensions.cs

@@ -1,6 +1,4 @@
-using Hotline.Application.Contracts.Mappers;
-using Mapster;
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
 
 namespace Hotline.Application.Contracts
 {
@@ -8,7 +6,7 @@ namespace Hotline.Application.Contracts
     {
         public static IServiceCollection AddAppContracts(this IServiceCollection services)
         {
-            TypeAdapterConfig.GlobalSettings.Scan(typeof(MapperConfigs).Assembly);
+            
             return services;
         }
     }

+ 3 - 0
src/Hotline.Application/ApplicationStartupExtensions.cs

@@ -1,4 +1,6 @@
 using Hotline.Application.Contracts;
+using Hotline.Application.Mappers;
+using Mapster;
 using Microsoft.Extensions.DependencyInjection;
 
 namespace Hotline.Application
@@ -7,6 +9,7 @@ namespace Hotline.Application
     {
         public static IServiceCollection AddApplication(this IServiceCollection services)
         {
+            TypeAdapterConfig.GlobalSettings.Scan(typeof(MapperConfigs).Assembly);
             return services.AddAppContracts();
         }
     }

+ 2 - 0
src/Hotline.Application/Hotline.Application.csproj

@@ -7,6 +7,8 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Conductor.Client" Version="1.0.9" />
+    <PackageReference Include="Dapr.AspNetCore" Version="1.9.0" />
     <PackageReference Include="Identity.Admin.HttpClient" Version="1.0.20" />
   </ItemGroup>
 

+ 10 - 2
src/Hotline.Application.Contracts/Mappers/MapperConfigs.cs → src/Hotline.Application/Mappers/MapperConfigs.cs

@@ -1,10 +1,12 @@
-using Hotline.CallCenter.BlackLists;
+using Conductor.Domain.Models;
+using Hotline.CallCenter.BlackLists;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.User;
+using Hotline.Share.Dtos.Workflow;
 using Hotline.Users;
 using Mapster;
 
-namespace Hotline.Application.Contracts.Mappers
+namespace Hotline.Application.Mappers
 {
     public class MapperConfigs : IRegister
     {
@@ -16,6 +18,12 @@ namespace Hotline.Application.Contracts.Mappers
 
             config.NewConfig<AddUserDto, User>()
                 .Map(d => d.Name, x => x.Name ?? x.UserName);
+
+            config.NewConfig<PreDefinition, WorkflowDefinitionDto>()
+                .Map(d => d.IsPreDefinition, x => true);
+
+            config.NewConfig<Definition, WorkflowDefinitionDto>()
+                .Map(d => d.LastModificationTime, x => x.CreationTime);
         }
     }
 }

+ 1 - 1
src/Hotline.Share/Dtos/CallCenter/PagedDto.cs → src/Hotline.Share/Dtos/PagedDto.cs

@@ -1,4 +1,4 @@
-namespace Hotline.Share.Dtos.CallCenter
+namespace Hotline.Share.Dtos
 {
     public record PagedDto<T>
     {

+ 50 - 0
src/Hotline.Share/Dtos/Workflow/WorkflowDefinitionDto.cs

@@ -0,0 +1,50 @@
+namespace Hotline.Share.Dtos.Workflow;
+
+public class WorkflowDefinitionDto
+{
+    public bool IsPreDefinition { get; set; }
+
+    /// <summary>
+    /// 模板编码
+    /// </summary>
+    public string Id { get; set; }
+
+    public int Version { get; set; }
+
+    public string Description { get; set; }
+
+    //public string DataType { get; set; }
+
+    //public WorkflowErrorHandling DefaultErrorBehavior { get; set; }
+
+    public TimeSpan? DefaultErrorRetryInterval { get; set; }
+
+    //public List<Step> Steps { get; set; } = new List<Step>();
+
+    /// <summary>
+    /// 业务模块
+    /// </summary>
+    public string Module { get; set; }
+
+    /// <summary>
+    /// 业务模块编码
+    /// </summary>
+    public string ModuleCode { get; set; }
+
+    /// <summary>
+    /// 模板名称
+    /// </summary>
+    public string Name { get; set; }
+
+    /// <summary>
+    /// 启用/禁用
+    /// </summary>
+    public bool Enable { get; set; }
+
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 最近更新时间
+    /// </summary>
+    public DateTime LastModificationTime { get; }
+}

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

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

+ 2 - 0
src/Hotline.Share/Requests/PagedRequest.cs

@@ -5,5 +5,7 @@ namespace Hotline.Share.Requests
     {
         public int PageIndex { get; set; } = 1;
         public int PageSize { get; set; } = 10;
+
+        public int Skip() => (PageIndex - 1) * PageSize;
     }
 }

+ 0 - 4
src/Hotline/Hotline.csproj

@@ -18,8 +18,4 @@
     <ProjectReference Include="..\XF.Domain.Repository\XF.Domain.Repository.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="WorkOrders\" />
-  </ItemGroup>
-
 </Project>

+ 13 - 0
src/Hotline/Orders/IOrderDomainService.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Orders
+{
+    public interface IOrderDomainService
+    {
+        
+    }
+}

+ 15 - 0
src/Hotline/Orders/Order.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Orders
+{
+    /// <summary>
+    /// 工单
+    /// </summary>
+    public class Order
+    {
+    }
+}