Dun.Jason 11 месяцев назад
Родитель
Сommit
e3b9d632e3

+ 101 - 1
src/Hotline.Api/Controllers/AiController.cs

@@ -1,6 +1,7 @@
 
 using Consul;
 using DotNetCore.CAP;
+using Hotline.Ai.CallOut;
 using Hotline.Ai.Jths;
 using Hotline.Ai.Visit;
 using Hotline.Application.Quality;
@@ -45,8 +46,9 @@ namespace Hotline.Api.Controllers
         private readonly IOrderRepository _orderRepository;
         private readonly IQualityApplication _qualityApplication;
         private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
+        private readonly IRepository<CallOutTemplate> _callOutTemplateRepository;
 
-        public AiController(ISystemSettingCacheManager systemSettingCacheManager,IRepository<AiOrderVisit> aiOrderVisitRepository,IRepository<AiOrderVisitDetail>  aiOrderVisitDetailRepository,IRepository<OrderVisit> orderVisitRepository,IRepository<OrderVisitDetail> orderVisitDetailRepository,IMapper mapper, /*IOptionsSnapshot<AiVisitConfig> options,*/IAiVisitService aiVisitService, ILogger<AiController> logger,ICapPublisher capPublisher,IOrderRepository orderRepository,IQualityApplication qualityApplication, ISystemDicDataCacheManager sysDicDataCacheManager)
+        public AiController(ISystemSettingCacheManager systemSettingCacheManager,IRepository<AiOrderVisit> aiOrderVisitRepository,IRepository<AiOrderVisitDetail>  aiOrderVisitDetailRepository,IRepository<OrderVisit> orderVisitRepository,IRepository<OrderVisitDetail> orderVisitDetailRepository,IMapper mapper, /*IOptionsSnapshot<AiVisitConfig> options,*/IAiVisitService aiVisitService, ILogger<AiController> logger,ICapPublisher capPublisher,IOrderRepository orderRepository,IQualityApplication qualityApplication, ISystemDicDataCacheManager sysDicDataCacheManager,IRepository<CallOutTemplate> callOutTemplateRepository)
         {
            _systemSettingCacheManager = systemSettingCacheManager;
             _aiOrderVisitRepository = aiOrderVisitRepository;
@@ -61,6 +63,7 @@ namespace Hotline.Api.Controllers
             _orderRepository = orderRepository;
             _qualityApplication = qualityApplication;
             _sysDicDataCacheManager = sysDicDataCacheManager;
+            _callOutTemplateRepository = callOutTemplateRepository;
         }
 
 
@@ -99,7 +102,101 @@ namespace Hotline.Api.Controllers
             return IsOk;
         }
 
+        #region 批量外呼
 
+        #region 批量外呼模板
+
+        /// <summary>
+        /// 外呼模板列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("callout-template-list")]
+        public async Task<PagedDto<AiCallOutTemplateQueryRep>> AiCallOutTemplateQuery([FromQuery]AiCallOutTemplateQueryRequest dto)
+        {
+            var (total,items) =await _callOutTemplateRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.TemplateName), x => x.TemplateName.Contains(dto.TemplateName))
+                .WhereIF(dto.StartTime != null, x => x.CreationTime >= dto.StartTime)
+                .WhereIF(dto.EndTime != null, x => x.CreationTime <= dto.EndTime)
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<AiCallOutTemplateQueryRep>(total, _mapper.Map<IReadOnlyList<AiCallOutTemplateQueryRep>>(items));
+        }
+
+        /// <summary>
+        /// 新增外呼模板
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("add-callouttemplate")]
+        public async Task AddCallOutTemplate([FromBody]CallOutTemplateDto dto)
+        {
+            var callOutTemplate = _mapper.Map<CallOutTemplate>(dto);
+            callOutTemplate.IsEnable = true;
+            await _callOutTemplateRepository.AddAsync(callOutTemplate, HttpContext.RequestAborted);
+        }
+        /// <summary>
+        /// 修改外呼模板
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("update-callouttemplate")]
+        public async Task UpdateCallOutTemplate([FromBody] UpdateCallOutTemplateDto dto)
+        {
+            var model = await _callOutTemplateRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (model == null)
+                throw UserFriendlyException.SameMessage("无效模板");
+            //验证是否有待执行的外呼任务TODO
+
+            model.TemplateName = dto.TemplateName;
+            model.TemplateContent = dto.TemplateContent;
+
+            await _callOutTemplateRepository.UpdateAsync(model, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 删除外呼模板
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpDelete("del-callouttemplate")]
+        public async Task DelCallOutTemplate([FromQuery]string id)
+        {
+            var model = await _callOutTemplateRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (model == null)
+                throw UserFriendlyException.SameMessage("无效模板");
+
+            //验证是否有待执行的外呼任务TODO
+            await _callOutTemplateRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 外呼模板启用禁用
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("callouttemplate-enable-unenable")]
+        public async Task CallOutTemplateEnableAndUnEnable([FromQuery]string id)
+        {
+            var model = await _callOutTemplateRepository.GetAsync(id, HttpContext.RequestAborted);
+            if (model == null)
+                throw UserFriendlyException.SameMessage("无效模板");
+
+            //验证是否有待执行的外呼任务TODO
+
+            model.IsEnable = !model.IsEnable;
+
+            await _callOutTemplateRepository.UpdateAsync(model, HttpContext.RequestAborted);
+        }
+
+        #endregion
+
+
+        #region 批量外呼任务
+
+        #endregion
+
+        #endregion
 
         #region 智能回访
 
@@ -566,5 +663,8 @@ namespace Hotline.Api.Controllers
         }
 
         #endregion
+
+
+        
     }
 }

+ 94 - 5
src/Hotline.Api/Controllers/OrderController.cs

@@ -40,13 +40,11 @@ using Hotline.Tools;
 using Hotline.Users;
 using Hotline.YbEnterprise.Sdk;
 using MapsterMapper;
-using MathNet.Numerics.Distributions;
 using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using MiniExcelLibs;
 using SqlSugar;
-using System;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
 using XF.Domain.Constants;
@@ -114,6 +112,7 @@ public class OrderController : BaseController
     private readonly IRepository<OrderSpecialDetail> _orderSpecialDetailRepository;
     private readonly IOrderSecondaryHandlingApplication _orderSecondaryHandlingApplication;
     private readonly IRepository<OrderCopy> _orderCopyRepository;
+    private readonly IRepository<ExternalCitizens> _externalCitizensRepository;
 
 	public OrderController(
         IOrderDomainService orderDomainService,
@@ -167,8 +166,9 @@ public class OrderController : BaseController
         IRepository<TranspondCityRawData> transpondCityRawDataRepository,
         IRepository<OrderSpecialDetail> orderSpecialDetailRepository,
         IOrderSecondaryHandlingApplication orderSecondaryHandlingApplication,
-        IRepository<OrderCopy> orderCopyRepository
-		)
+        IRepository<OrderCopy> orderCopyRepository,
+        IRepository<ExternalCitizens> externalCitizensRepository
+        )
     {
         _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
@@ -222,6 +222,7 @@ public class OrderController : BaseController
         _orderSpecialDetailRepository = orderSpecialDetailRepository;
         _orderSecondaryHandlingApplication = orderSecondaryHandlingApplication;
         _orderCopyRepository = orderCopyRepository;
+        _externalCitizensRepository = externalCitizensRepository;
 
 	}
 
@@ -4990,5 +4991,93 @@ public class OrderController : BaseController
 		return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
 	}
 
-	#endregion
+    #endregion
+
+    #region 外部市民管理
+
+    /// <summary>
+    /// 下载外部市民导入模板
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("download-externalcitizens-template")]
+    public async Task<object> DownLoadCitizensTemplate()
+    {
+        List<ExternalCitizensExcelContent> list = new List<ExternalCitizensExcelContent>();
+        ExternalCitizensExcelContent excelContent = new ExternalCitizensExcelContent() { };
+        list.Add(excelContent);
+        return _exportApplication.ExportData(list, "demo.xlsx");
+    }
+
+    /// <summary>
+    /// 导入外部市民
+    /// </summary>
+    /// <param name="file"></param>
+    /// <returns></returns>
+    [HttpPost("import-externalcitizens")]
+    public async Task<object> ImportExternalcitizens(IFormFile file)
+    {
+        using (var stream = new MemoryStream())
+        {
+            file.CopyTo(stream);
+            var list = MiniExcel.Query<ExternalCitizensExcelContent>(stream).ToList();
+            int count = 0;
+            int errorCount = 0;
+            int addCount = 0;
+            //int modifyCount = 0;
+            if (list != null && list.Count > 0)
+            {
+                count = list.Count;
+                foreach (var item in list)
+                {
+                    try
+                    {
+                        var externalcitizens = await _externalCitizensRepository.GetAsync(x => x.PhoneNum == item.PhoneNum, HttpContext.RequestAborted);
+                        if (externalcitizens is null)
+                        {
+                            externalcitizens = _mapper.Map<ExternalCitizens>(item);
+                            var id = await _externalCitizensRepository.AddAsync(externalcitizens, HttpContext.RequestAborted);
+                            if (!string.IsNullOrEmpty(id))
+                            {
+                                addCount++;
+                            }
+                            else
+                            {
+                                errorCount++;
+                            }
+                        }
+                        else
+                        {
+                            //_mapper.Map(item, externalcitizens);
+                            //await _externalCitizensRepository.UpdateAsync(externalcitizens, HttpContext.RequestAborted);
+                            //modifyCount++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        errorCount++;
+                    }
+                }
+            }
+            return new { Count = count, ErrorCount = errorCount, AddCount = addCount/*, ModifyCount = modifyCount*/ };
+        }
+    }
+
+    /// <summary>
+    /// 外部市民列表
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("externalcitizens-list")]
+    public async Task<PagedDto<ExternalcitizensRep>> QueryExternalcitizens([FromQuery]QueryExternalcitizensRequest dto) 
+    {
+        var (total,items) = await _externalCitizensRepository.Queryable()
+            .WhereIF(!string.IsNullOrEmpty(dto.PhoneNum), x => x.PhoneNum.Contains(dto.PhoneNum))
+            .WhereIF(!string.IsNullOrEmpty(dto.Name),x=>x.Name.Contains(dto.Name))
+            .OrderByDescending(x => x.CreationTime)
+            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+
+        return new PagedDto<ExternalcitizensRep>(total, _mapper.Map<IReadOnlyList<ExternalcitizensRep>>(items));
+    }
+
+
+    #endregion
 }

+ 1 - 1
src/Hotline.Api/config/appsettings.Development.json

@@ -16,7 +16,7 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+    "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
     "Redis": "110.188.24.182:50179",
     "MongoDB": "mongodb://192.168.100.121:27017",
     "Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"

+ 1 - 1
src/Hotline.Api/config/appsettings.json

@@ -16,7 +16,7 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
+    "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;",
     "Redis": "110.188.24.182:50179,password=fengwo22@@",
     "MongoDB": "mongodb://192.168.100.121:27017",
     "Wex": "server=222.212.82.225;Port=4509;Database=fs_kft;Uid=root;Pwd=Wex@12345;"

+ 55 - 0
src/Hotline.Share/Dtos/Ai/AiDto.cs

@@ -10,6 +10,61 @@ using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Dtos.Ai
 {
+    public class CallOutTemplateDto
+    {
+        public string TemplateName { get; set; }
+
+        public string TemplateContent { get; set; }
+    }
+
+    public class UpdateCallOutTemplateDto:CallOutTemplateDto
+    {
+        public string Id { get; set; }
+    }
+
+    public record AiCallOutTemplateQueryRequest:PagedRequest
+    {
+        public string TemplateName { get; set; }
+
+        public DateTime? StartTime { get; set; }
+
+        public DateTime? EndTime { get; set; }
+    }
+
+    public record AiCallOutTemplateQueryRep
+    {
+        /// <summary>
+        /// 模板名称
+        /// </summary>
+        public string TemplateName { get; set; }
+        /// <summary>
+        /// 外呼任务数
+        /// </summary>
+        public int CallOutTaskCount { get; set;]}
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public DateTime CreationTime { get; set; }
+
+        /// <summary>
+        /// 是否启用
+        /// </summary>
+        public bool IsEnable { get; set; }
+
+        /// <summary>
+        /// 创建人
+        /// </summary>
+        public string? CreatorName { get; set; }
+
+        /// <summary>
+        /// 创建部门
+        /// </summary>
+        public string? CreatorOrgName { get; set; }
+    }
+
+
+
     public class AiVisitBackDto
     {
         public string BatchUid { get; set; }

+ 25 - 0
src/Hotline.Share/Dtos/Order/ExternalcitizensDto.cs

@@ -0,0 +1,25 @@
+using Hotline.Share.Requests;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Order
+{
+    public record QueryExternalcitizensRequest: PagedRequest
+    {
+        public string PhoneNum { get; set; }
+
+        public string Name { get; set; }
+    }
+
+    public class ExternalcitizensRep
+    {
+        public string PhoneNum { get; set;}
+
+        public string Name { get; set; }
+
+        public DateTime CreationTime { get; set; }
+    }
+}

+ 36 - 0
src/Hotline/Ai/CallOut/CallOutTask.cs

@@ -0,0 +1,36 @@
+
+using XF.Domain.Repository;
+
+namespace Hotline.Ai.CallOut
+{
+    public class CallOutTask: CreationEntity
+    {
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string TaskName { get; set; }
+        /// <summary>
+        /// 应回访数量
+        /// </summary>
+        public int HasVisitCount { get; set; }
+
+        /// <summary>
+        /// 已回访成功数量
+        /// </summary>
+        public int VisitedCount { get; set; }
+
+        /// <summary>
+        /// 已回访失败数量
+        /// </summary>
+        public int VisitedFailCount { get; set; }
+
+        /// <summary>
+        /// 节日禁呼 0:否 1:是
+        /// </summary>
+        public int FestivalBan { get; set; }
+
+        public DateTime BeginTime { get; set; }
+
+        public DateTime EndTime { get; set; }
+    }
+}

+ 14 - 0
src/Hotline/Ai/CallOut/CallOutTemplate.cs

@@ -0,0 +1,14 @@
+using XF.Domain.Repository;
+
+namespace Hotline.Ai.CallOut
+{
+    public class CallOutTemplate: CreationSoftDeleteEntity
+    {
+        public string TemplateName { get; set; }
+
+        public bool IsEnable { get; set; }
+
+        public string TemplateContent { get; set; }
+
+    }
+}

+ 16 - 0
src/Hotline/Import/ExternalCitizensExcelContent.cs

@@ -0,0 +1,16 @@
+using MiniExcelLibs.Attributes;
+
+namespace Hotline.Import
+{
+    public class ExternalCitizensExcelContent
+    {
+        [ExcelColumnName("电话")]
+        public string PhoneNum { get; set; }
+
+        /// <summary>
+		/// 姓名
+		/// </summary>
+		[ExcelColumnName("姓名")]
+        public string? Name { get; set; }
+    }
+}