Forráskód Böngészése

Merge branch 'test' into lib/test

libin 1 hete
szülő
commit
a0256914db
22 módosított fájl, 827 hozzáadás és 17 törlés
  1. 74 0
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  2. 95 0
      src/Hotline.Api/Controllers/Exam/OfflineExamAnalysisController.cs
  3. 1 1
      src/Hotline.Api/Controllers/Exam/QuestionController.cs
  4. 3 1
      src/Hotline.Api/Controllers/Exam/UserExamController.cs
  5. 14 0
      src/Hotline.Application/Exam/Constants/ApiRoutes/OfflineExamAnalysisApiRoute.cs
  6. 6 0
      src/Hotline.Application/Exam/Constants/Messages/ExamSystemConstants.cs
  7. 28 0
      src/Hotline.Application/Exam/Interface/ExamManages/IOfflineExamAnalysisService.cs
  8. 29 0
      src/Hotline.Application/Exam/QueryExtensions/ExamManages/OfflineExamQueryExtensions.cs
  9. 148 0
      src/Hotline.Application/Exam/Service/ExamManages/OfflineExamAnalysisService.cs
  10. 41 14
      src/Hotline.Application/OrderApp/OrderDelayApp/OrderDelayApplication.cs
  11. 20 0
      src/Hotline.Repository.SqlSugar/Exam/Interfaces/ExamManages/IOfflineExamAnalysisRepository.cs
  12. 22 0
      src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamManages/OfflineExamAnalysisRepository.cs
  13. 63 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/OfflineExamAnalysisValidator.cs
  14. 2 0
      src/Hotline.Share/Dtos/CallCenter/BiSeatCallsDto.cs
  15. 75 0
      src/Hotline.Share/Dtos/ExamManages/OfflineExamAnalysisDto.cs
  16. 1 0
      src/Hotline.Share/Dtos/Order/OrderDelay/DelayWithStepId.cs
  17. 6 1
      src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs
  18. 6 0
      src/Hotline.Share/Requests/Exam/OfflineExamAnalysisPagedRequest.cs
  19. 10 0
      src/Hotline.Share/ViewResponses/Exam/OfflineExamAnalysisPageViewResponse.cs
  20. 52 0
      src/Hotline.Share/ViewResponses/Exam/OfflineExamAnalysisViewResponse.cs
  21. 69 0
      src/Hotline/Exams/ExamManages/ExamOfflineExamAnalysis.cs
  22. 62 0
      src/Hotline/Exams/ExamManages/OfflineExamAnalysisExcel.cs

+ 74 - 0
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -29,6 +29,7 @@ using Hotline.Application.StatisticalReport.CallReport;
 using DocumentFormat.OpenXml.Spreadsheet;
 using DocumentFormat.OpenXml.Wordprocessing;
 using NPOI.SS.Formula.Functions;
+using static System.Runtime.InteropServices.JavaScript.JSType;
 
 namespace Hotline.Api.Controllers.Bi;
 
@@ -470,6 +471,79 @@ public class BiCallController : BaseController
             "坐席话务统计分析明细");
     }
 
+    /// <summary>
+    /// 小休统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("restsday")]
+    [AllowAnonymous]
+    public async Task<IReadOnlyList<BiSeatRestDto>> QuerySeatRestDay([FromQuery] QuerySeatRestRequest dto)
+    {
+        return await _telRestRepository.Queryable()
+            .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
+            .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), x => x.StaffNo.Contains(dto.StaffNo))
+            .Where(x => x.CreationTime >= dto.StartTime)
+            .Where(x => x.CreationTime <= dto.EndTime)
+            .GroupBy(x => new { DayTime = x.CreationTime.ToString("yyyy-MM-dd"), x.UserId, x.StaffNo, x.UserName })
+            .Select(x => new BiSeatRestDto
+            {
+                DayTime= x.CreationTime.ToString("yyyy-MM-dd"),
+                UserId = x.UserId,
+                StaffNo = x.StaffNo,
+                UserName = x.UserName,
+                RestCount = SqlFunc.AggregateCount(x.Id),
+                RestDuration = SqlFunc.AggregateSum(x.RestDuration / 60) / SqlFunc.AggregateCount(x.Id),
+                CumulativeDuration = SqlFunc.AggregateSum(x.RestDuration / 60)
+            })
+            .OrderByDescending(x=>x.DayTime)
+            .OrderByIF(dto.SortRule is 0, a => a.RestDuration, OrderByType.Asc)
+            .OrderByIF(dto.SortRule is 1, a => a.RestDuration, OrderByType.Desc)
+            //.MergeTable()
+            .ToListAsync(HttpContext.RequestAborted);
+    }
+
+    /// <summary>
+    /// 小休统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("restsday/export")]
+    [LogFilterAlpha("导出日志")]
+    public async Task<FileStreamResult> QuerySeatRestDayExport([FromBody] ExportExcelDto<QuerySeatRestRequest> dto)
+    {
+        var query = await _telRestRepository.Queryable()
+            .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.UserName), x => x.UserName.Contains(dto.QueryDto.UserName))
+            .WhereIF(!string.IsNullOrEmpty(dto.QueryDto.StaffNo), x => x.StaffNo.Contains(dto.QueryDto.StaffNo))
+            .Where(x => x.CreationTime >= dto.QueryDto.StartTime)
+            .Where(x => x.CreationTime <= dto.QueryDto.EndTime)
+             .GroupBy(x => new { DayTime = x.CreationTime.ToString("yyyy-MM-dd"), x.UserId, x.StaffNo, x.UserName })
+            .Select(x => new BiSeatRestDto
+            {
+                DayTime = x.CreationTime.ToString("yyyy-MM-dd"),
+                UserId = x.UserId,
+                StaffNo = x.StaffNo,
+                UserName = x.UserName,
+                RestCount = SqlFunc.AggregateCount(x.Id),
+                RestDuration = SqlFunc.AggregateSum(x.RestDuration / 60) / SqlFunc.AggregateCount(x.Id),
+                CumulativeDuration = SqlFunc.AggregateSum(x.RestDuration / 60)
+            })
+             .OrderByDescending(x => x.DayTime)
+            .OrderByIF(dto.QueryDto.SortRule is 0, a => a.RestDuration, OrderByType.Asc)
+            .OrderByIF(dto.QueryDto.SortRule is 1, a => a.RestDuration, OrderByType.Desc)
+           // .MergeTable()
+            .ToListAsync(HttpContext.RequestAborted);
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<BiSeatRestDto>(dto.ColumnInfos);
+
+        var dtos = _mapper.Map<ICollection<BiSeatRestDto>>(query)
+                          .Select(stu => _mapper.Map(stu, typeof(BiSeatRestDto), dynamicClass))
+                          .Cast<object>()
+                          .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+        return ExcelStreamResult(stream, "座席小休统计表");
+    }
 
     /// <summary>
     /// 小休统计

+ 95 - 0
src/Hotline.Api/Controllers/Exam/OfflineExamAnalysisController.cs

@@ -0,0 +1,95 @@
+using Exam.Infrastructure.Data.Entity;
+using Exam.Share.ViewResponses.Exam;
+using Exam.Share.ViewResponses.Question;
+using Hotline.Application.Exam.Constants.ApiRoutes;
+using Hotline.Application.Exam.Interface.ExamManages;
+using Hotline.Application.Exam.Service.ExamManages;
+using Hotline.Application.ExportExcel;
+using Hotline.Exams.ExamManages;
+using Hotline.Exams.Questions;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Requests.Exam;
+using Hotline.Share.Requests.Question;
+using Hotline.Share.ViewResponses.Exam;
+using Hotline.Tools;
+using MapsterMapper;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Hotline.Api.Controllers.Exam
+{
+    public class OfflineExamAnalysisController : BaseController
+    {
+        private readonly IOfflineExamAnalysisService _offineExamAnalysisService;
+        private readonly IMapper _mapper;
+        private readonly IExportApplication _exportApplication;
+
+        public OfflineExamAnalysisController(IOfflineExamAnalysisService offineExamAnalysisService,IMapper mapper, IExportApplication exportApplication)
+        {
+            _offineExamAnalysisService = offineExamAnalysisService;
+            this._mapper = mapper;
+            this._exportApplication = exportApplication;
+        }
+
+        /// <summary>
+        /// 获取线下考试分页列表
+        /// </summary>
+        /// <param name="offlineExamAnalysisPagedRequest"></param>
+        /// <returns></returns>
+        [HttpPost(OfflineExamAnalysisApiRoute.GetPagedList)]
+        public async Task<PageViewResponse<OfflineExamAnalysisViewResponse>> GetPagedList([FromBody] OfflineExamAnalysisPagedRequest offlineExamAnalysisPagedRequest)
+        {
+            var offlineExamAnalysisPageViewResponse = await _offineExamAnalysisService.GetPagedListAsync(offlineExamAnalysisPagedRequest);            
+
+            return offlineExamAnalysisPageViewResponse;
+        }
+
+        /// <summary>
+        /// 导入Excel
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost(OfflineExamAnalysisApiRoute.ImportExcel)]
+        public async Task ImportExcel(IFormFile file)
+        {
+            await _offineExamAnalysisService.ImportExcel(file, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 导出线下考试成绩
+        /// </summary>
+        /// <param name="exportExcelDto"></param>
+        /// <returns></returns>
+        [HttpPost(OfflineExamAnalysisApiRoute.ExportOfflineExamAnalysis)]
+        public async Task<FileStreamResult> ExportOfflineExamAnalysis([FromBody] ExportExcelDto<OfflineExamAnalysisPagedRequest> exportExcelDto)
+        {
+            if (exportExcelDto.IsExportAll)
+            {
+                exportExcelDto.QueryDto.IsPaged = false;
+            }
+            var result = await _offineExamAnalysisService.GetPagedListAsync(exportExcelDto.QueryDto);
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<OfflineExamAnalysisViewResponse>(exportExcelDto.ColumnInfos ?? new List<ColumnInfo>());
+
+            var dtos = result.Items
+                .Select(stu => _mapper.Map(stu, typeof(OfflineExamAnalysisViewResponse), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "导出线下考试成绩");
+
+        }
+
+        /// <summary>
+        /// 下载Excel模版
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet(OfflineExamAnalysisApiRoute.Download)]
+        public FileStreamResult Download()
+        {
+            var list = new List<OfflineExamAnalysisExcel>();
+            return _exportApplication.ExportData(list, "线下考试成绩统计表.xlsx");
+        }
+    }
+}

+ 1 - 1
src/Hotline.Api/Controllers/Exam/QuestionController.cs

@@ -130,7 +130,7 @@ namespace Hotline.Api.Controllers.Exam
         public FileStreamResult Download()
         {
             var list = new List<QuestionExcel>();
-            return _exportApplication.ExportData(list, "Template.xlsx");
+            return _exportApplication.ExportData(list, "题库.xlsx");
         }
     }
 }

+ 3 - 1
src/Hotline.Api/Controllers/Exam/UserExamController.cs

@@ -40,7 +40,9 @@ namespace Hotline.Api.Controllers.Exam
         {
             await _examManageService.UpdateExamStatus(new EntityQueryRequest(), HttpContext.RequestAborted);
 
-            return await _userExamService.GetPagedListAsync(userExamPagedRequest) as UserExamResultPageViewResponse;
+            var userExamResultPageViewResponse = await _userExamService.GetPagedListAsync(userExamPagedRequest);
+
+            return userExamResultPageViewResponse as UserExamResultPageViewResponse;
         }
 
         /// <summary>

+ 14 - 0
src/Hotline.Application/Exam/Constants/ApiRoutes/OfflineExamAnalysisApiRoute.cs

@@ -0,0 +1,14 @@
+using Hotline.Application.Exam.Core.Constants;
+
+namespace Hotline.Application.Exam.Constants.ApiRoutes
+{
+    public class OfflineExamAnalysisApiRoute:ApiRoute
+    {
+        public const string ImportExcel = "ImportExcel";
+
+        public const string Download = "Download";
+
+        public const string ExportOfflineExamAnalysis = "ExportOfflineExamAnalysis";
+
+    }
+}

+ 6 - 0
src/Hotline.Application/Exam/Constants/Messages/ExamSystemConstants.cs

@@ -6,4 +6,10 @@
 
         public static string[] ColumnNames = ["题型","试题标签","难度级别","正式可用","模拟可用", "题干", "选项A", "选项B", "选项C", "选项D", "选项E", "选项F", "选项G", "选项H", "选项I", "选项J", "答案"];
     }
+
+    public class OfflineExamSystemConstants
+    {
+        public static string[] ColumnNames = ["参考人员", "部门名称", "考试标题", "开始时间", "结束时间", "考试总分", "合格分数", "考试分数"];
+
+    }
 }

+ 28 - 0
src/Hotline.Application/Exam/Interface/ExamManages/IOfflineExamAnalysisService.cs

@@ -0,0 +1,28 @@
+using Hotline.Exams.ExamManages;
+using Hotline.Exams.Questions;
+using Hotline.Repository.SqlSugar.Exam.Interface;
+using Hotline.Share.Dtos.ExamManages;
+using Hotline.Share.Requests.Exam;
+using Hotline.Share.ViewResponses.Exam;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.Interface.ExamManages
+{
+    public interface IOfflineExamAnalysisService : IQueryService<OfflineExamAnalysisViewResponse, OfflineExamAnalysisDto, OfflineExamAnalysisPagedRequest>, IApiService<AddOfflineExamAnalysisDto, UpdateOfflineExamAnalysisDto, ExamOfflineExamAnalysis>
+    {
+
+        /// <summary>
+        /// 导入Excel
+        /// </summary>
+        /// <param name="file"></param>
+        /// <param name="requestAborted"></param>
+        /// <returns></returns>
+        Task ImportExcel(IFormFile file, CancellationToken requestAborted);
+    }
+}

+ 29 - 0
src/Hotline.Application/Exam/QueryExtensions/ExamManages/OfflineExamQueryExtensions.cs

@@ -0,0 +1,29 @@
+using Hotline.Application.Exam.Core.Utilities;
+using Hotline.Exams.ExamManages;
+using Hotline.Share.Requests.Exam;
+using JiebaNet.Segmenter.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.QueryExtensions.ExamManages
+{
+    public static class OfflineExamQueryExtensions
+    {
+        public static Expression<Func<ExamOfflineExamAnalysis, bool>> GetExpression(this OfflineExamAnalysisPagedRequest offlineExamAnalysisPagedRequest)
+        {
+            Expression<Func<ExamOfflineExamAnalysis, bool>> expression = m => m.Id != null;
+
+            expression = ExpressionableUtility.CreateExpression<ExamOfflineExamAnalysis>()
+            .AndIF(offlineExamAnalysisPagedRequest.StartTime.IsNotNull(), x => x.StartTime >= offlineExamAnalysisPagedRequest.StartTime)
+            .AndIF(offlineExamAnalysisPagedRequest.EndTime.IsNotNull(), x => x.StartTime <= offlineExamAnalysisPagedRequest.EndTime)
+            .AndIF(offlineExamAnalysisPagedRequest.Keyword.IsNotNull(), x => x.ExamName.Contains(offlineExamAnalysisPagedRequest.Keyword))
+            .ToExpression();
+
+            return expression;
+        }
+    }
+}

+ 148 - 0
src/Hotline.Application/Exam/Service/ExamManages/OfflineExamAnalysisService.cs

@@ -0,0 +1,148 @@
+using DocumentFormat.OpenXml.Drawing;
+using Exam.Infrastructure.Data.Entity;
+using FluentValidation;
+using Hotline.Application.Exam.Constants.Messages;
+using Hotline.Application.Exam.Interface.ExamManages;
+using Hotline.Application.Exam.QueryExtensions.ExamManages;
+using Hotline.Exams.ExamManages;
+using Hotline.Exams.Questions;
+using Hotline.Repository.SqlSugar;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.Exam.Interface;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.Questions;
+using Hotline.Repository.SqlSugar.Exam.Service;
+using Hotline.Share.Dtos.ExamManages;
+using Hotline.Share.Dtos.TestPapers;
+using Hotline.Share.Enums.Exams;
+using Hotline.Share.Requests.Exam;
+using Hotline.Share.ViewResponses.Exam;
+using Hotline.Tools;
+using JiebaNet.Segmenter.Common;
+using MapsterMapper;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using XF.Domain.Authentications;
+using XF.Domain.Dependency;
+
+namespace Hotline.Application.Exam.Service.ExamManages
+{
+    public class OfflineExamAnalysisService : ApiService<ExamOfflineExamAnalysis, AddOfflineExamAnalysisDto, UpdateOfflineExamAnalysisDto, HotlineDbContext>, IOfflineExamAnalysisService, IScopeDependency
+    {
+        private readonly IOfflineExamAnalysisRepository _repository;
+        private readonly ISessionContext _sessionContext;
+        private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
+        private readonly IServiceProvider _serviceProvider;
+        private readonly IMapper _mapper;
+
+        public OfflineExamAnalysisService(IOfflineExamAnalysisRepository repository,
+             ISessionContext sessionContext,
+            IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider,
+            IMapper mapper) : base(repository, mapper, sessionContext)
+        {
+            this._repository = repository;
+            this._sessionContext = sessionContext;
+            this._dataPermissionFilterBuilder = dataPermissionFilterBuilder;
+            this._serviceProvider = serviceProvider;
+            this._mapper = mapper;
+        }
+
+        #region public method
+        public Task<OfflineExamAnalysisDto> GetAsync(EntityQueryRequest entityQueryRequest)
+        {
+            throw new NotImplementedException();
+        }
+
+        public Task<(int, List<OfflineExamAnalysisViewResponse>)> GetListAsync(OfflineExamAnalysisPagedRequest queryRequest)
+        {
+            throw new NotImplementedException();
+        }
+
+        public async Task<PageViewResponse<OfflineExamAnalysisViewResponse>> GetPagedListAsync(OfflineExamAnalysisPagedRequest queryRequest)
+        {
+            var expression = queryRequest.GetExpression();
+            var offlineExamAnalysisTable = _repository.Queryable().Where(expression);
+
+            var queryable = offlineExamAnalysisTable.Select(x => new OfflineExamAnalysisViewResponse
+            {
+                CutoffScore = x.CutoffScore,
+                ExamName = x.ExamName,
+                DepartmentName = x.DepartmentName,
+                Id = x.Id,
+                Score = x.Score,
+                TotalScore = x.TotalScore,
+                UserName = x.UserName
+            }).OrderByPropertyNameIF(!string.IsNullOrEmpty(queryRequest.SortField), queryRequest.SortField, (OrderByType)(queryRequest.SortRule ?? 0));
+
+            var total = await offlineExamAnalysisTable.CountAsync();
+            var items = queryRequest.IsPaged ? await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize) : await queryable.ToListAsync();
+
+            var result = new PageViewResponse<OfflineExamAnalysisViewResponse>
+            {
+                Items = items,
+                Pagination = new Pagination(queryRequest.PageIndex, queryRequest.PageSize, total)
+            };
+
+            return result;
+        }
+
+        public async Task ImportExcel(IFormFile file, CancellationToken cancellationToken)
+        {
+            var stream = file.OpenReadStream();
+            var contents = ExcelHelper.Read(stream, true);
+
+            var offlineExamAnalysisDtos = new List<AddOfflineExamAnalysisDto>();
+
+            contents.ForEach(async item =>
+            {
+                var value = (item as ExpandoObject).GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[0]);
+
+                if (value == null)
+                    return;
+
+                var offlineExamAnalysisDto = BuildOfflineExamAnalysis(item as ExpandoObject);
+
+                if (offlineExamAnalysisDto != null)
+                    offlineExamAnalysisDtos.Add(offlineExamAnalysisDto);
+            });
+
+            await base.AddAsync(offlineExamAnalysisDtos, cancellationToken);
+
+            stream.Close();
+        }
+        #endregion
+
+        #region private method
+        private OfflineExamAnalysisDto BuildOfflineExamAnalysis(ExpandoObject? item)
+        {
+            var totalScore = 0;
+            var cutoffScore = 0;
+            var score = 0;
+
+            var offlineExamAnalysisDto = new OfflineExamAnalysisDto
+            {
+                UserName = item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[0]) != null ? item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[0]).ToString() : string.Empty,
+                DepartmentName= item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[1]) != null ? item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[1]).ToString() : string.Empty,
+                ExamName = item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[2]) != null ? item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[2]).ToString() : string.Empty,
+                StartTime = DateTime.TryParse(item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[3])?.ToString(),out DateTime startTime) ? startTime : DateTime.MinValue,
+                EndTime = item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[4])!=null? (DateTime.TryParse(item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[4])?.ToString(),out DateTime dateTime) ? dateTime : null):null,
+                TotalScore = int.TryParse(item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[5])?.ToString(),out totalScore)?totalScore:0,
+                CutoffScore = int.TryParse(item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[6])?.ToString(),out cutoffScore)? cutoffScore:0,
+                Score = int.TryParse(item.GetValueOrDefault(OfflineExamSystemConstants.ColumnNames[7])?.ToString(), out score) ? score : 0,
+
+            };
+
+            return offlineExamAnalysisDto; 
+        } 
+        #endregion
+    }
+}

+ 41 - 14
src/Hotline.Application/OrderApp/OrderDelayApp/OrderDelayApplication.cs

@@ -181,24 +181,25 @@ public class OrderDelayApplication : IOrderDelayApplication, IScopeDependency
     /// <returns></returns>
     public async Task BatchReviewAsync(BatchOrderDelayReviewRequest request, CancellationToken cancellation)
     {
-        var delayIds = request.DelayWithStepIds.Select(d => d.DelayId).Distinct().ToList();
-        var delays = await _orderDelayRepository.Queryable()
-            .Where(d => delayIds.Contains(d.Id))
-            .ToListAsync(cancellation);
+        //var delayIds = request.DelayWithStepIds.Select(d => d.DelayId).Distinct().ToList();
+        //var delays = await _orderDelayRepository.Queryable()
+        //    .Where(d => delayIds.Contains(d.Id))
+        //    .ToListAsync(cancellation);
 
         var apptaskItems = new List<AddApptaskItemRequest>();
         var req = new OrderDelayReviewWithSessionRequest
         {
-            SessionContext = (FakeSessionContext)_sessionContext,
+            SessionContext = CreateFakeSessionContext(_sessionContext),//(FakeSessionContext)_sessionContext,
             IsPass = request.IsPass,
             NextWorkflow = request.NextWorkflow
         };
-        foreach (var delay in delays)
+        foreach (var delay in request.DelayWithStepIds)
         {
-            req.NextWorkflow.StepId = request.DelayWithStepIds.First(d => d.DelayId == delay.Id).StepId;
+            req.NextWorkflow.WorkflowId = delay.WorkflowId;
+            req.NextWorkflow.StepId = delay.StepId;//request.DelayWithStepIds.First(d => d.DelayId == delay.Id).StepId;
             apptaskItems.Add(new AddApptaskItemRequest
             {
-                BusinessId = delay.Id,
+                BusinessId = delay.DelayId,
                 TaskParams = req
             });
         }
@@ -212,13 +213,39 @@ public class OrderDelayApplication : IOrderDelayApplication, IScopeDependency
 
         if (!string.IsNullOrEmpty(taskId))
         {
-            foreach (var orderDelay in delays)
-            {
-                orderDelay.DelayState = EDelayState.BatchProcessing;
-            }
-            await _orderDelayRepository.Updateable(delays)
-                .UpdateColumns(d=>new {d.DelayState})
+            //foreach (var orderDelay in delays)
+            //{
+            //    orderDelay.DelayState = EDelayState.BatchProcessing;
+            //}
+            //await _orderDelayRepository.Updateable(delays)
+            //    .UpdateColumns(d => new { d.DelayState })
+            //    .ExecuteCommandAsync(cancellation);
+            var delayIds = request.DelayWithStepIds.Select(d => d.DelayId).ToList();
+            await _orderDelayRepository.Updateable()
+                .SetColumns(d => d.DelayState == EDelayState.BatchProcessing)
+                .Where(d => delayIds.Contains(d.Id))
                 .ExecuteCommandAsync(cancellation);
         }
     }
+
+    private FakeSessionContext CreateFakeSessionContext(ISessionContext sessionContext)
+    {
+        return new FakeSessionContext
+        {
+            UserId = sessionContext.UserId,
+            UserName = sessionContext.UserName,
+            Phone = sessionContext.Phone,
+            Roles = sessionContext.Roles,
+            OrgId = sessionContext.OrgId,
+            OrgName = sessionContext.OrgName,
+            OrgLevel = sessionContext.OrgLevel,
+            OrgAreaCode = sessionContext.OrgAreaCode,
+            OrgIsCenter = sessionContext.OrgIsCenter,
+            OrgAreaName = sessionContext.OrgAreaName,
+            AreaId = sessionContext.AreaId,
+            ClientId = sessionContext.ClientId,
+            StaffNo = sessionContext.StaffNo,
+            OpenId = sessionContext.OpenId
+        };
+    }
 }

+ 20 - 0
src/Hotline.Repository.SqlSugar/Exam/Interfaces/ExamManages/IOfflineExamAnalysisRepository.cs

@@ -0,0 +1,20 @@
+using Hotline.Exams.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages
+{
+    /// <summary>
+    /// 线下考试统计仓储接口
+    /// </summary>
+    [Description("线下考试统计仓储接口")]
+    public interface IOfflineExamAnalysisRepository : IRepository<ExamOfflineExamAnalysis>, IExamRepository<ExamOfflineExamAnalysis, HotlineDbContext>
+    {
+    }
+}

+ 22 - 0
src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamManages/OfflineExamAnalysisRepository.cs

@@ -0,0 +1,22 @@
+using Hotline.Exams.ExamManages;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Validators.ExamManages;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Exam.Repositories.ExamManages
+{
+    public class OfflineExamAnalysisRepository : ExamRepository<ExamOfflineExamAnalysis>, IOfflineExamAnalysisRepository, IScopeDependency
+    {
+        public OfflineExamAnalysisRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
+        {
+            Validator = new OfflineExamAnalysisValidator();
+        }
+    }
+}

+ 63 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/OfflineExamAnalysisValidator.cs

@@ -0,0 +1,63 @@
+using Exam.Infrastructure.Extensions;
+using Exam.Infrastructure.Validation.Validation;
+using FluentValidation;
+using Hotline.Exams.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Core.Constants;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Validate;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Repository.SqlSugar.Exam.Validators.ExamManages
+{
+    public class OfflineExamAnalysisValidator : BaseValidator<ExamOfflineExamAnalysis>
+    {
+        private readonly IExamManageRepository _examManageRepository;
+
+        public OfflineExamAnalysisValidator()
+        {
+            RuleSet(ValidatorTypeConstants.Create, () =>
+            {
+                BaseValidateRule();
+
+                ValidateRuleWithAdd();
+            });
+
+            RuleSet(ValidatorTypeConstants.Modify, () =>
+            {
+                BaseValidateRule();
+
+                ValidateRuleWithModify();
+            });
+        }
+
+        protected override void BaseValidateRule()
+        {
+            base.BaseValidateRule();
+            RuleFor(m => m.UserName).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.UserName))));
+            RuleFor(m => m.DepartmentName).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.DepartmentName))));
+            RuleFor(m => m.ExamName).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.ExamName))));
+            RuleFor(m => m.TotalScore).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.TotalScore))));
+            RuleFor(m => m.Score).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.Score))));
+            RuleFor(m => m.CutoffScore).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.CutoffScore))));
+            RuleFor(m => m.TotalScore).Must((c, v) => c.Score <= v).WithMessage(x => string.Format(ExamErrorMessage.Greater, x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.Score)),x.GetType().GetDescription(nameof(ExamOfflineExamAnalysis.TotalScore))));
+        }
+
+        protected override void ValidateRuleWithAdd()
+        {
+            base.ValidateRuleWithAdd();
+            RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamAnswer.CreationTime))));
+        }
+
+        protected override void ValidateRuleWithModify()
+        {
+            base.ValidateRuleWithModify();
+            RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamAnswer.LastModificationTime))));
+
+        }
+
+    }
+}

+ 2 - 0
src/Hotline.Share/Dtos/CallCenter/BiSeatCallsDto.cs

@@ -141,6 +141,8 @@ public class BiSeatCallsDto
 
 public class BiSeatRestDto
 {
+    public string DayTime { get; set; }
+
     public string UserId { get; set; }
     public string? StaffNo { get; set; }
 

+ 75 - 0
src/Hotline.Share/Dtos/ExamManages/OfflineExamAnalysisDto.cs

@@ -0,0 +1,75 @@
+using Exam.Infrastructure.Data.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.ExamManages
+{
+    /// <summary>
+    /// 线下考试统计实体
+    /// </summary>
+    [Description("线下考试统计实体")]
+    public class OfflineExamAnalysisDto : UpdateOfflineExamAnalysisDto
+    {
+        
+    }
+
+    public class AddOfflineExamAnalysisDto : IAddRequest
+    {
+        /// <summary>
+        /// 参考人员
+        /// </summary>
+        [Description("参考人员")]
+        public string UserName { get; set; }
+
+        /// <summary>
+        /// 部门名称
+        /// </summary>
+        [Description("部门名称")]
+        public string DepartmentName { get; set; }
+
+        /// <summary>
+        /// 考试标题
+        /// </summary>
+        [Description("考试标题")]
+        public string ExamName { get; set; }
+
+        /// <summary>
+        /// 考试总分
+        /// </summary>
+        [Description("考试总分")]
+        public int TotalScore { get; set; }
+
+        /// <summary>
+        /// 合格分数
+        /// </summary>
+        [Description("合格分数")]
+        public int CutoffScore { get; set; }
+
+        /// <summary>
+        /// 考试分数
+        /// </summary>
+        [Description("考试分数")]
+        public int Score { get; set; }
+
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        [Description("开始时间")]
+        public DateTime StartTime { get; set; }
+
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        [Description("结束时间")]
+        public DateTime? EndTime { get; set; }
+    }
+
+    public class UpdateOfflineExamAnalysisDto : AddOfflineExamAnalysisDto,IActionRequest
+    {
+        public string Id { get; set; }
+    }
+}

+ 1 - 0
src/Hotline.Share/Dtos/Order/OrderDelay/DelayWithStepId.cs

@@ -3,5 +3,6 @@
 public class DelayWithStepId
 {
     public string DelayId { get; set; }
+    public string WorkflowId { get; set; }
     public string StepId { get; set; }
 }

+ 6 - 1
src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs

@@ -861,7 +861,7 @@ namespace Hotline.Share.Dtos.TrCallCenter
         /// 用户名
         /// </summary>
         public string UserName { get; set; }
-        
+
         /// <summary>
         /// 开始时间
         /// </summary>
@@ -1228,6 +1228,11 @@ namespace Hotline.Share.Dtos.TrCallCenter
         /// </summary>
         public double Duration { get; private set; }
 
+        /// <summary>
+        /// 用时分钟
+        /// </summary>
+        public double DurationMinutes => Math.Round((double)Duration / 60, 2);
+
     }
 
     public class TelActionListXthx

+ 6 - 0
src/Hotline.Share/Requests/Exam/OfflineExamAnalysisPagedRequest.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Requests.Exam
+{
+    public record OfflineExamAnalysisPagedRequest : AnalysisReportRequest
+    {
+    }
+}

+ 10 - 0
src/Hotline.Share/ViewResponses/Exam/OfflineExamAnalysisPageViewResponse.cs

@@ -0,0 +1,10 @@
+using Exam.Infrastructure.Data.Entity;
+using Exam.Share.ViewResponses.Exam;
+
+namespace Hotline.Share.ViewResponses.Exam
+{
+    public class OfflineExamAnalysisPageViewResponse : PageViewResponse<OfflineExamAnalysisViewResponse>
+    {
+    }
+
+}

+ 52 - 0
src/Hotline.Share/ViewResponses/Exam/OfflineExamAnalysisViewResponse.cs

@@ -0,0 +1,52 @@
+using Exam.Infrastructure.Data.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.ViewResponses.Exam
+{
+    public class OfflineExamAnalysisViewResponse : IViewResponse
+    {
+        /// <summary>
+        /// 参考人员
+        /// </summary>
+        [Description("参考人员")]
+        public string UserName { get; set; }
+
+        /// <summary>
+        /// 部门名称
+        /// </summary>
+        [Description("部门名称")]
+        public string DepartmentName { get; set; }
+
+        /// <summary>
+        /// 考试标题
+        /// </summary>
+        [Description("考试标题")]
+        public string ExamName { get; set; }
+
+        /// <summary>
+        /// 考试总分
+        /// </summary>
+        [Description("考试总分")]
+        public int TotalScore { get; set; }
+
+        /// <summary>
+        /// 合格分数
+        /// </summary>
+        [Description("合格分数")]
+        public int CutoffScore { get; set; }
+
+        /// <summary>
+        /// 考试分数
+        /// </summary>
+        [Description("考试分数")]
+        public int Score { get; set; }
+
+
+        public string Id { get; set ; }
+    }
+}

+ 69 - 0
src/Hotline/Exams/ExamManages/ExamOfflineExamAnalysis.cs

@@ -0,0 +1,69 @@
+using Hotline.Exams.Base;
+using SqlSugar;
+using System.ComponentModel;
+
+namespace Hotline.Exams.ExamManages
+{
+    /// <summary>
+    /// 线下考试统计
+    /// </summary>
+    [Description("线下考试统计")]
+    public class ExamOfflineExamAnalysis: ExamBusinessEntity
+    {
+        /// <summary>
+        /// 参考人员
+        /// </summary>
+        [SugarColumn(ColumnDescription = "参考人员")]
+        [Description("参考人员")]
+        public string UserName { get; set; }
+
+        /// <summary>
+        /// 部门名称
+        /// </summary>
+        [SugarColumn(ColumnDescription = "部门名称")]
+        [Description("部门名称")]
+        public string DepartmentName { get; set; }
+
+        /// <summary>
+        /// 考试标题
+        /// </summary>
+        [SugarColumn(ColumnDescription = "考试标题")]
+        [Description("考试标题")]
+        public string ExamName { get; set; }
+
+        /// <summary>
+        /// 考试总分
+        /// </summary>
+        [SugarColumn(ColumnDescription = "考试总分")]
+        [Description("考试总分")]
+        public int TotalScore { get; set; }
+
+        /// <summary>
+        /// 合格分数
+        /// </summary>
+        [SugarColumn(ColumnDescription = "合格分数")]
+        [Description("合格分数")]
+        public int CutoffScore { get; set; }
+
+        /// <summary>
+        /// 考试分数
+        /// </summary>
+        [SugarColumn(ColumnDescription = "考试分数")]
+        [Description("考试分数")]
+        public int Score { get; set; }
+
+        /// <summary>
+        /// 考试开始时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "考试开始时间")]
+        [Description("考试开始时间")]
+        public DateTime StartTime { get; set; }
+
+        /// <summary>
+        /// 考试结束时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "考试结束时间")]
+        [Description("考试结束时间")]
+        public DateTime? EndTime { get; set; }
+    }
+}

+ 62 - 0
src/Hotline/Exams/ExamManages/OfflineExamAnalysisExcel.cs

@@ -0,0 +1,62 @@
+using MiniExcelLibs.Attributes;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Exams.ExamManages
+{
+    public class OfflineExamAnalysisExcel
+    {
+        /// <summary>
+        /// 参考人员
+        /// </summary>
+        [ExcelColumnName("参考人员")]
+        public string UserName { get; set; }
+
+        /// <summary>
+        /// 部门名称
+        /// </summary>
+        [ExcelColumnName("部门名称")]
+        public string DepartmentName { get; set; }
+
+        /// <summary>
+        /// 考试标题
+        /// </summary>
+        [ExcelColumnName("考试标题")]
+        public string ExamName { get; set; }
+
+        /// <summary>
+        /// 考试总分
+        /// </summary>
+        [ExcelColumnName("考试总分")]
+        public int TotalScore { get; set; }
+
+        /// <summary>
+        /// 合格分数
+        /// </summary>
+        [ExcelColumnName("合格分数")]
+        public int CutoffScore { get; set; }
+
+        /// <summary>
+        /// 考试分数
+        /// </summary>
+        [ExcelColumnName("考试分数")]
+        public int Score { get; set; }
+
+        /// <summary>
+        /// 考试开始时间
+        /// </summary>
+        [ExcelColumnName("考试开始时间")]
+        public DateTime StartTime { get; set; }
+
+        /// <summary>
+        /// 考试结束时间
+        /// </summary>
+        [ExcelColumnName("考试结束时间")]
+        public DateTime? EndTime { get; set; }
+    }
+}