Parcourir la source

Merge branch 'test' into lib/test

libin il y a 3 mois
Parent
commit
3c31b583ef

+ 11 - 1
src/Hotline.Api/Controllers/ExportData/ExportDataController.cs

@@ -9,6 +9,16 @@ using XF.Domain.Exceptions;
 
 namespace Hotline.Api.Controllers.ExportData;
 
+/// <summary>
+/// 只要URL结尾是 export_excel 的请求都会进入这个控制器
+/// 逻辑:
+///     1. 通过URL找到对应的Controller和Action
+///     2. 通过Controller和Action找到对应的ApplicationService
+///        比如: RedPackController.GetRedPackList 就会去查找 RedPackApplication.GetRedPackList 方法
+///     3. 通过反射调用对应的方法
+///     4. ApplicationService 的方法返回的必须是 ISugarQueryable
+///     5. ApplicationService 中方法的Description 属性会作为导出的文件名
+/// </summary>
 [ApiController]
 [Route("{*path:regex(.*export_excel$)}")]
 public class ExportDataController : BaseController
@@ -86,7 +96,7 @@ public class ExportDataController : BaseController
         var result = method.Invoke(serviceInstance, [queryDto]);
 
         var returnType = method.ReturnType.GetGenericArguments()[0];
-        var description = method.GetCustomAttribute<DescriptionAttribute>()?.Description;
+        var description = method.GetCustomAttribute<DescriptionAttribute>()?.Description + "_";
         if (pageIndex == null || pageSize == null)
         {
             isExportAll = true;

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

@@ -749,7 +749,7 @@ namespace Hotline.Api.Controllers
             }
 
             var info = await _knowledgeRepository.GetAsync(dto.Ids[0]) ?? throw UserFriendlyException.SameMessage("知识不存在");
-            return info.Content.HtmlToStream(dto.FileType).GetFileStreamResult(dto.FileType, info.Title, false);
+            return info.Content.HtmlToStream(dto.FileType, info.Title, _pdfManager).GetFileStreamResult(dto.FileType, info.Title, false);
         }
 
         /// <summary>
@@ -846,7 +846,7 @@ namespace Hotline.Api.Controllers
             //return _baseDataApplication
             //    .FileType(EFileType.excel | EFileType.pdf)
             //    .Build();
-            var ignoreFileType = EFileType.excel | EFileType.pdf;
+            var ignoreFileType = EFileType.excel;//| EFileType.pdf;
             var items = EnumExts.GetDescriptions<EFileType>();
             var filteredDictionary = items
                  .Where(kvp => (ignoreFileType & (EFileType)kvp.Key) == 0)

+ 1 - 1
src/Hotline.Application/CallCenter/TianRunCallApplication.cs

@@ -111,7 +111,7 @@ namespace Hotline.Application.CallCenter
 
         public override async Task<string> PublishVisitRelevanceCallIdAsync(OrderRelevanceCallIdDto dto, CancellationToken cancellationToken)
         {
-            return null;
+            return await Task.FromResult(dto.CallId);
         }
 
         public override async Task OrderVisitRelevanceCallIdAsync(VisitDto dto, CancellationToken cancellationToken)

+ 2 - 0
src/Hotline.Application/Jobs/XingTangCallsSyncJob.cs

@@ -132,6 +132,7 @@ namespace Hotline.Application.Jobs
                         //推省上
                         await _capPublisher.PublishAsync(EventNames.HotlineCallAdd, calls.Adapt<List<CallNativeDto>>());
                     }
+                    _logger.LogInformation($"旧方法同步通话记录成功,数量:{calls.Count}");
                 }
                 else
                 {
@@ -177,6 +178,7 @@ namespace Hotline.Application.Jobs
                         //推省上
                         await _capPublisher.PublishAsync(EventNames.HotlineCallAdd, calls.Adapt<List<CallNativeDto>>());
                     }
+                    _logger.LogInformation($"新方法同步通话记录成功,数量:{calls.Count}");
                 }
             }
             catch (Exception e)

+ 2 - 0
src/Hotline.Application/Jobs/XingTangTelOperationSyncJob.cs

@@ -90,6 +90,7 @@ namespace Hotline.Application.Jobs
 
                     }
                     await _telOperationRepository.AddRangeAsync(operations, context.CancellationToken);
+                    _logger.LogInformation($"旧方法同步分机操作记录成功,数量:{operations.Count}");
                 }
                 else
                 {
@@ -107,6 +108,7 @@ namespace Hotline.Application.Jobs
                         operations.Add(operation);
                     }
                     await _telOperationRepository.AddRangeAsync(operations, context.CancellationToken);
+                    _logger.LogInformation($"新方法同步分机操作记录成功,数量:{operations.Count}");
                 }
             }
             catch (Exception e)

+ 6 - 2
src/Hotline.Application/Orders/Handles/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs

@@ -77,8 +77,12 @@ public class OrderScreenNextWorkflowHandler : INotificationHandler<NextStepNotif
                                     screenDto.Content = notification.Dto.Opinion;
                                     screenDto.Files = new List<Share.Dtos.File.FileDto>();
                                 }
-                                //推省上
-                                _capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto()
+								if (_appOptions.Value.IsLuZhou)
+								{
+									screenDto.Content = notification.Dto.Opinion;
+								}
+								//推省上
+								_capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto()
                                 {
                                     Order = screenOrderDto,
                                     Screen = screenDto,

+ 0 - 106
src/Hotline.Application/Orders/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs

@@ -1,106 +0,0 @@
-using DotNetCore.CAP;
-using Hotline.Configurations;
-using Hotline.FlowEngine.Notifications;
-using Hotline.FlowEngine.WorkflowModules;
-using Hotline.Orders;
-using Hotline.Share.Dtos.Order;
-using Hotline.Share.Enums.Order;
-using Hotline.Share.Mq;
-using MapsterMapper;
-using MediatR;
-using Microsoft.Extensions.Options;
-using XF.Domain.Authentications;
-using XF.Domain.Repository;
-
-namespace Hotline.Application.Orders.OrderScreenHandler;
-public class OrderScreenNextWorkflowHandler : INotificationHandler<NextStepNotify>
-{
-	private readonly ICapPublisher _capPublisher;
-	private readonly IMapper _mapper;
-	private readonly IOrderScreenRepository _orderScreenRepository;
-	private readonly ISessionContext _sessionContext;
-	private readonly IRepository<OrderScreenDetail> _orderScreenDetailRepository;
-	private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
-
-	public OrderScreenNextWorkflowHandler(
-		ICapPublisher capPublisher,
-		IMapper mapper,
-		IOrderScreenRepository orderScreenRepository,
-		ISessionContext sessionContext,
-		IOptionsSnapshot<AppConfiguration> appOptions,
-		IRepository<OrderScreenDetail> orderScreenDetailRepository)
-	{
-		_capPublisher = capPublisher;
-		_mapper = mapper;
-		_orderScreenRepository = orderScreenRepository;
-		_sessionContext = sessionContext;
-		_orderScreenDetailRepository = orderScreenDetailRepository;
-		_appOptions = appOptions;
-	}
-
-	/// <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)
-	{
-		if (notification.Workflow.ModuleCode == WorkflowModuleConsts.OrderScreen) 
-		{
-			var workflow = notification.Workflow;
-			var nextTag = string.IsNullOrEmpty(notification.NextStepDefine.Tag)
-				? null
-				: System.Text.Json.JsonSerializer.Deserialize<DefinitionTag>(notification.NextStepDefine.Tag);
-			var screen = await _orderScreenRepository.Queryable().Includes(x => x.Order)
-				.Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
-			if (screen != null)
-			{
-				screen.Status = EScreenStatus.Approval;
-				screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
-				//如果下个节点是省审批,则修改为省甄别
-				if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org && nextTag.Value == TagDefaults.TagValue.Province)
-					screen.IsProScreen = true;
-				await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
-			}
-
-			if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org)
-			{
-				switch (nextTag.Value)
-				{
-					case TagDefaults.TagValue.Province:
-						if (screen != null)
-						{
-							var screenDto = _mapper.Map<OrderScreenListDto>(screen);
-							if (screen.Order != null && screen.Order.Source == ESource.ProvinceStraight)
-							{
-								var screenOrderDto = _mapper.Map<OrderDto>(screen.Order);
-								//省件甄别--以省审批前一个节点整理的甄别意见为准推送省上 宜宾
-								if (_appOptions.Value.IsYiBin)
-								{
-                                    screenDto.Content = notification.Dto.Opinion;
-                                    screenDto.Files = new List<Share.Dtos.File.FileDto>();
-								}
-								if (_appOptions.Value.IsLuZhou)
-								{
-									screenDto.Content = notification.Dto.Opinion;
-								}
-								//推省上
-								_capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto()
-								{
-									Order = screenOrderDto,
-									Screen = screenDto,
-									ClientGuid = ""
-								});
-							}
-						}
-
-						break;
-				}
-			}
-			OrderScreenDetail detail = new OrderScreenDetail
-			{
-				ScreenId = screen.Id
-			};
-			detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName, 1);
-			await _orderScreenDetailRepository.AddAsync(detail, cancellationToken);
-		}
-	}
-}

+ 1 - 0
src/Hotline.Application/Snapshot/IndustryApplication.cs

@@ -379,6 +379,7 @@ public class IndustryApplication : IIndustryApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [Description("志愿者上报")]
     public ISugarQueryable<VolunteerReportItemsOutDto> GetVolunteerReportItems(VolunteerReportItemsInDto dto)
     {
         var query = _volunteerReportRepository.Queryable()

+ 2 - 0
src/Hotline.Application/Snapshot/InviteCodeApplication.cs

@@ -7,6 +7,7 @@ using Mapster;
 using SqlSugar;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -64,6 +65,7 @@ public class InviteCodeApplication : IInviteCodeApplication, IScopeDependency
         return _inviteCodeRepository.Queryable();
     }
 
+    [Description("邀请码统计")]
     public ISugarQueryable<InviteCodeStatisticOutDto> GetInviteCodeStatisticAsync(GetInviteCodeStatisticInDto dto)
     {
         dto.ValidateObject();

+ 48 - 3
src/Hotline.Application/Tools/StringExtensions.cs

@@ -1,5 +1,8 @@
-using Hotline.Application.ExportWord;
+using System.Text;
+using Hotline.Application.ExportWord;
+using Hotline.Pdf;
 using Hotline.Share.Enums.Article;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Tools;
 public static class StringExtensions
@@ -14,9 +17,51 @@ public static class StringExtensions
         return WordHelper.ConvertHtmlToPdf(value);
     }
 
-    public static Stream HtmlToStream(this string value, EFileType fileType)
+    public static Stream HtmlToPDF(this string value, string? title, IPdfManager? pdfManager)
     {
-        if (fileType == EFileType.pdf) return value.HtmlToPDF();
+        if (pdfManager is null)
+            throw new UserFriendlyException($"非法参数: {nameof(pdfManager)}");
+        var content = value
+                .Replace("&nbsp;", " ")
+                .Replace("&amp;", "&")
+                .Replace("&quot;", "\"")
+                .Replace("&gt;", ">")
+                .Replace("&lt;", "<")
+            ;
+
+        //去除html标签
+        var sb = new StringBuilder();
+        while (!string.IsNullOrEmpty(content) && (content.StartsWith('<') || content.EndsWith('>')))
+        {
+            var indexright = content.IndexOf('>');
+            var indexSecLeft = content.IndexOf('<', indexright);
+            if (indexSecLeft < indexright)
+            {
+                content = content.Remove(0, indexright + 1);
+            }
+            else
+            {
+                var startIndex = indexright + 1;
+                var str = content.Substring(startIndex, indexSecLeft - startIndex);
+                if (!string.IsNullOrEmpty(str)) sb.AppendLine(str);
+                content = content.Remove(0, indexSecLeft);
+            }
+        }
+
+        var sbStr = sb.ToString();
+        if (!string.IsNullOrEmpty(sbStr))
+            content = sbStr;
+
+        var stream = new MemoryStream();
+        pdfManager.GeneratePdf(title, content, stream);
+        stream.Seek(0, SeekOrigin.Begin);
+        return stream;
+    }
+
+    public static Stream HtmlToStream(this string value, EFileType fileType, string? title = null, IPdfManager? pdfManager = null)
+    {
+        //if (fileType == EFileType.pdf) return value.HtmlToPDF();
+        if (fileType == EFileType.pdf) return value.HtmlToPDF(title, pdfManager);
         if (fileType == EFileType.word) return value.HtmlToWord();
         throw new NotImplementedException($"无效的 fileType 入参: {fileType}");
     }

+ 4 - 1
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -103,7 +103,10 @@ public class AddSnapshotOrderInDto : Position
     public string IndustryId { get; set; }
 
     /// <summary>
-    /// 作业类型
+    /// 作业类型;
+    /// 0: 电焊;
+    /// 1: 气割;
+    /// 2: 其他;
     /// </summary>
     public EJobType? JobType { get; set; }
 

+ 2 - 0
src/Hotline.Share/Dtos/Snapshot/RedPackRecordDto.cs

@@ -4,6 +4,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using XF.Utility.EnumExtensions;
 
@@ -47,6 +48,7 @@ public class SnapshotRedPackRecordSendOutDto
     /// <summary>
     /// OpenId
     /// </summary>
+    [JsonPropertyName("wXOpenId")]
     public string WXOpenId { get; set; }
 
     /// <summary>