Browse Source

refactor: 质检查询通话记录

xf 9 tháng trước cách đây
mục cha
commit
b8a2610c52

+ 23 - 11
src/Hotline.Ai.Jths/AiQualityService.cs

@@ -7,6 +7,7 @@ using Hotline.Orders;
 using Newtonsoft.Json;
 using System.Text;
 using System.Security.Cryptography;
+using Org.BouncyCastle.Tls;
 
 namespace Hotline.Ai.Jths
 {
@@ -21,27 +22,38 @@ namespace Hotline.Ai.Jths
             _baseUrl = baseUrl;
         }
 
-        public async Task CreateAiOrderQualityTask(Hotline.Quality.Quality model, TrCallRecord? call, Order order, string viteRecordPrefix, CancellationToken cancellationToken)
+        public async Task CreateAiOrderQualityTask(
+            Hotline.Quality.Quality model,
+             string audioFile,
+             string fromNo,
+             DateTime? callStartTime,
+            Order order,
+             string viteRecordPrefix,
+             CancellationToken cancellationToken)
         {
-            if (string.IsNullOrEmpty(call?.RecordingFileName)) return;
-            var fileName = call.RecordingFileName.Split(".");
-            var length = fileName.Count() - 1;
-            var recordForm = fileName.Any() && fileName.Length > 1 ? fileName[length] : string.Empty;
-			List<AiQualityDto> datalist = new List<AiQualityDto>();
+            if (string.IsNullOrEmpty(audioFile)) return;
+            //var fileName = call.RecordingFileName.Split(".");
+            //var length = fileName.Count() - 1;
+            //var recordForm = fileName.Any() && fileName.Length > 1 ? fileName[length] : string.Empty;
+            var fileExtension = Path.GetExtension(audioFile);
+            if (!string.IsNullOrEmpty(fileExtension) && fileExtension.StartsWith('.'))
+                fileExtension = fileExtension.Substring(1);
+
+            List<AiQualityDto> datalist = new List<AiQualityDto>();
             AiQualityDto aiQuality = new AiQualityDto
             {
                 RecordID = model.Id,
-                RecordPath = viteRecordPrefix + call.RecordingAbsolutePath,
+                RecordPath = viteRecordPrefix + audioFile,
                 AgentID = "1001",
-                CallNumber = call.CPN,
-                CallTime = call.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss"),
-                RecordForm = recordForm,
+                CallNumber = fromNo,
+                CallTime = callStartTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? string.Empty,
+                RecordForm = fileExtension,//recordForm,
                 ywlx = model.Source.ToString(),
             };
             datalist.Add(aiQuality);
             var data = JsonConvert.SerializeObject(datalist);
             var baseUrl = new Uri(_baseUrl);
-			await ExecuteAsync(baseUrl.ToString() + "routeinfo/api", Method.Post, data, cancellationToken);
+            await ExecuteAsync(baseUrl.ToString() + "routeinfo/api", Method.Post, data, cancellationToken);
         }
 
         public async Task<ApiResponse<TResponse>> ExecuteAsync<TRequest, TResponse>(string path, Method httpMethod,

+ 8 - 2
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -500,8 +500,14 @@ namespace Hotline.Api.Controllers
                         if (quality !=null)
                         {
 							var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
-							await _aiQualityService.CreateAiOrderQualityTask(quality, model, order, setting?.SettingValue[0], HttpContext.RequestAborted);
-						}
+							//await _aiQualityService.CreateAiOrderQualityTask(quality, model, order, setting?.SettingValue[0], HttpContext.RequestAborted);
+                            await _aiQualityService.CreateAiOrderQualityTask(
+                                quality,
+                                model.RecordingAbsolutePath,
+                                model.CPN,
+                                model.CreatedTime,
+                                order, setting?.SettingValue[0], HttpContext.RequestAborted);
+                        }
                     }
                 }
                 catch{}

+ 728 - 700
src/Hotline.Api/Controllers/QualityController.cs

@@ -29,713 +29,741 @@ using Hotline.Application.CallCenter;
 using Hotline.CallCenter.Configs;
 using Microsoft.Extensions.Options;
 using XF.Domain.Constants;
+using Hotline.Repository.SqlSugar.CallCenter;
 
 namespace Hotline.Api.Controllers
 {
-	public class QualityController : BaseController
-	{
-		private readonly ISessionContext _sessionContext;
-		private readonly IMapper _mapper;
-		private readonly IQualityRepository _qualitey;
-		private readonly IRepository<QualityDetail> _qualiteyDetail;
-		private readonly IRepository<QualityItem> _qualiteyItem;
-		private readonly IRepository<QualityTemplate> _qualityTemplate;
-		private readonly IRepository<QualityTemplateDetail> _qualiteyTemplateDetail;
-		private readonly IRepository<QualityProhibited> _qualiteyProhibited;
-		private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
-		private readonly IRepository<TrCallRecord> _trCallRecordRepository;
-		private readonly IQualityApplication _qualityApplication;
-		private readonly IOrderRepository _orderRepository;
-		private readonly IAiQualityService _aiQualityService;
-		private readonly ILogger<QualityController> _logger;
-		private readonly ISystemSettingCacheManager _systemSettingCacheManager;
-		private readonly ICallApplication _callApplication;
-		private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
-
-		public QualityController(
-			ISessionContext sessionContext,
-			IMapper mapper,
-			IQualityRepository qualitey,
-			IRepository<Quality.QualityDetail> qualiteyDetail,
-			IRepository<QualityItem> qualiteyItem,
-			IRepository<QualityTemplate> qualityTemplate,
-			IRepository<QualityTemplateDetail> qualiteyTemplateDetail,
-			IRepository<QualityProhibited> qualiteyProhibited,
-			ISystemDicDataCacheManager systemDicDataCacheManager,
-			 IRepository<TrCallRecord> trCallRecordRepository,
-			IQualityApplication qualityApplication,
-			IOrderRepository orderRepository,
-			IAiQualityService aiQualityService,
-			ILogger<QualityController> logger,
-			ISystemSettingCacheManager systemSettingCacheManager,
-			ICallApplication callApplication,
-			IOptionsSnapshot<CallCenterConfiguration> callcenterOptions)
-		{
-			_sessionContext = sessionContext;
-			_mapper = mapper;
-			_qualitey = qualitey;
-			_qualiteyDetail = qualiteyDetail;
-			_qualiteyItem = qualiteyItem;
-			_qualityTemplate = qualityTemplate;
-			_qualiteyTemplateDetail = qualiteyTemplateDetail;
-			_qualiteyProhibited = qualiteyProhibited;
-			_systemDicDataCacheManager = systemDicDataCacheManager;
-			_trCallRecordRepository = trCallRecordRepository;
-			_qualityApplication = qualityApplication;
-			_orderRepository = orderRepository;
-			_aiQualityService = aiQualityService;
-			_logger = logger;
-			_systemSettingCacheManager = systemSettingCacheManager;
-			_callApplication = callApplication;
-			_callcenterOptions = callcenterOptions;
-		}
-		#region 质检管理
-		/// <summary>
-		/// 删除质检
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpDelete]
-		public async Task Delete([FromBody] DeleteQualityDto dto)
-		{
-			foreach (var Id in dto.Ids)
-			{
-				await _qualitey.RemoveAsync(x => x.Id == Id);
-				List<QualityDetail> details = await _qualiteyDetail.Queryable().Where(x => x.QualityId == Id).ToListAsync();
-				await _qualiteyDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
-			}
-		}
-
-		/// <summary>
-		/// 更新质检
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.UpdateQuality)]
-		[HttpPut]
-		public async Task Update([FromBody] UpdateQualityDto dto)
-		{
-			await _qualityApplication.UpdateQualityAsync(dto, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 获取质检列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("list")]
-		public async Task<PagedDto<QualityDto>> List([FromQuery] QualityListDto dto)
-		{
-			var (total, items) = await _qualitey.Queryable()
-				.Includes(x => x.Order)
-				.Includes(x => x.Visit)
-				.Includes(x => x.Visit,e=>e.Employee)
-				.Includes(x => x.QualityDetails)
-				.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!))
-				.WhereIF(dto.State.HasValue, x => x.State == dto.State)
-				.WhereIF(dto.Source.HasValue, x=> x.Source == dto.Source)
-				.WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Accepted, x=> !string.IsNullOrEmpty(x.Order.CallId))
-				.WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Visit, x => !string.IsNullOrEmpty(x.Visit.CallId))
-				.WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
-				.WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
-				.WhereIF(dto.MaxGrade.HasValue,x=>x.Grade <= dto.MaxGrade)
-				.WhereIF(dto.MinGrade.HasValue,x => x.Grade >= dto.MinGrade)
-				.OrderByDescending(x => x.CreationTime)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<QualityDto>(total, _mapper.Map<IReadOnlyList<QualityDto>>(items));
-		}
-
-		/// <summary>
-		/// 获取质检实体
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[HttpGet("{id}")]
-		public async Task<QualityDto> Entity(string id)
-		{
-			var quality =	await _qualitey.Queryable()
-				.Includes(x => x.Order)
-				.Includes(x => x.Visit)
-				.Includes(x => x.Visit, e => e.Employee)
-				.Includes(x => x.QualityDetails)
-				.FirstAsync(x => x.Id == id);
-			var qualityDto = _mapper.Map<QualityDto>(quality);
-			// if (qualityDto.Order != null) {
-   //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
-   //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
-   //              if (call != null)
-   //              {
-			// 		qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
-			// 		qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
-   //              }
-			// }
-			// if (qualityDto.Visit != null)
-			// {
-   //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
-   //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
-   //              if (call != null)
-   //              {
-   //                  qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
-   //                  qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
-   //              }
-   //          }
-			
-			if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
-			{
-				if (qualityDto.Order != null) {
-					//var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
-					//var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
-					var call = await _callApplication.GetTianrunCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted); 
-					if (call != null)
-					{
-						qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
-						qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
-					}
-				}
-				if (qualityDto.Visit != null)
-				{
-					//var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
-					// var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
-					var call = await _callApplication.GetTianrunCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
-					if (call != null)
-					{
-						qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
-						qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
-					}
-				}
-			}
-			else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
-			{
-				if (!string.IsNullOrEmpty(qualityDto?.Order?.CallId))
-				{
-					var call = await _callApplication.GetCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted); 
-					if (call != null)
-					{
-						qualityDto.Order.RecordingBaseAddress = call.AudioFile;
-						qualityDto.Order.RecordingAbsolutePath = call.AudioFile;
-					}
-				}
-				if (!string.IsNullOrEmpty(qualityDto.Visit.CallId))
-				{
-					var call = await _callApplication.GetCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
-					if (call != null)
-					{
-						qualityDto.Visit.RecordingBaseAddress = call.AudioFile;
-						qualityDto.Visit.RecordingAbsolutePath = call.AudioFile;
-					}
-				}
-			}
-			
-			return qualityDto;
-		}
-		#endregion
-
-		#region 质检项管理 
-		/// <summary>
-		/// 新增项目
-		/// </summary>
-		/// <param name="dtos"></param>
-		/// <returns></returns>
-		[Permission(EPermission.AddQualityItem)]
-		[HttpPost("item")]
-		public async Task Add([FromBody] QualityItemAddDto dto)
-		{
-			var count = await _qualiteyItem.CountAsync(x => x.Name == dto.Name);
-			if (count > 0)
-				throw UserFriendlyException.SameMessage("质检项目名称已存在");
-			var model = _mapper.Map<QualityItem>(dto);
-			await _qualiteyItem.AddAsync(model, HttpContext.RequestAborted);
-		}
-
-		///// <summary>
-		///// 删除项目
-		///// </summary>
-		///// <param name="dto"></param>
-		///// <returns></returns>
-		//[Permission(EPermission.DeleteQualityItem)]
-		//[HttpDelete("item")]
-		//public async Task Delete([FromBody] QualityItemDeleteDto dto)
-		//{
-		//	await _qualiteyItem.RemoveAsync(x => x.Id == dto.Id);
-		//}
-
-		/// <summary>
-		/// 删除项目
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.DeleteQualityItem)]
-		[HttpDelete("itemBatch")]
-		public async Task Delete([FromBody] QualityItemBatchDeleteDto dto)
-		{
-			List<QualityItem> items = await _qualiteyItem.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
+    public class QualityController : BaseController
+    {
+        private readonly ISessionContext _sessionContext;
+        private readonly IMapper _mapper;
+        private readonly IQualityRepository _qualitey;
+        private readonly IRepository<QualityDetail> _qualiteyDetail;
+        private readonly IRepository<QualityItem> _qualiteyItem;
+        private readonly IRepository<QualityTemplate> _qualityTemplate;
+        private readonly IRepository<QualityTemplateDetail> _qualiteyTemplateDetail;
+        private readonly IRepository<QualityProhibited> _qualiteyProhibited;
+        private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+        //private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+        private readonly IQualityApplication _qualityApplication;
+        private readonly IOrderRepository _orderRepository;
+        private readonly IAiQualityService _aiQualityService;
+        private readonly ILogger<QualityController> _logger;
+        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+        private readonly ICallApplication _callApplication;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
+
+        public QualityController(
+            ISessionContext sessionContext,
+            IMapper mapper,
+            IQualityRepository qualitey,
+            IRepository<Quality.QualityDetail> qualiteyDetail,
+            IRepository<QualityItem> qualiteyItem,
+            IRepository<QualityTemplate> qualityTemplate,
+            IRepository<QualityTemplateDetail> qualiteyTemplateDetail,
+            IRepository<QualityProhibited> qualiteyProhibited,
+            ISystemDicDataCacheManager systemDicDataCacheManager,
+            //IRepository<TrCallRecord> trCallRecordRepository,
+            IQualityApplication qualityApplication,
+            IOrderRepository orderRepository,
+            IAiQualityService aiQualityService,
+            ILogger<QualityController> logger,
+            ISystemSettingCacheManager systemSettingCacheManager,
+            ICallApplication callApplication,
+            IOptionsSnapshot<CallCenterConfiguration> callcenterOptions)
+        {
+            _sessionContext = sessionContext;
+            _mapper = mapper;
+            _qualitey = qualitey;
+            _qualiteyDetail = qualiteyDetail;
+            _qualiteyItem = qualiteyItem;
+            _qualityTemplate = qualityTemplate;
+            _qualiteyTemplateDetail = qualiteyTemplateDetail;
+            _qualiteyProhibited = qualiteyProhibited;
+            _systemDicDataCacheManager = systemDicDataCacheManager;
+            //_trCallRecordRepository = trCallRecordRepository;
+            _qualityApplication = qualityApplication;
+            _orderRepository = orderRepository;
+            _aiQualityService = aiQualityService;
+            _logger = logger;
+            _systemSettingCacheManager = systemSettingCacheManager;
+            _callApplication = callApplication;
+            _callcenterOptions = callcenterOptions;
+        }
+        #region 质检管理
+        /// <summary>
+        /// 删除质检
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpDelete]
+        public async Task Delete([FromBody] DeleteQualityDto dto)
+        {
+            foreach (var Id in dto.Ids)
+            {
+                await _qualitey.RemoveAsync(x => x.Id == Id);
+                List<QualityDetail> details = await _qualiteyDetail.Queryable().Where(x => x.QualityId == Id).ToListAsync();
+                await _qualiteyDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
+            }
+        }
+
+        /// <summary>
+        /// 更新质检
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.UpdateQuality)]
+        [HttpPut]
+        public async Task Update([FromBody] UpdateQualityDto dto)
+        {
+            await _qualityApplication.UpdateQualityAsync(dto, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 获取质检列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("list")]
+        public async Task<PagedDto<QualityDto>> List([FromQuery] QualityListDto dto)
+        {
+            var (total, items) = await _qualitey.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.Visit)
+                .Includes(x => x.Visit, e => e.Employee)
+                .Includes(x => x.QualityDetails)
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!))
+                .WhereIF(dto.State.HasValue, x => x.State == dto.State)
+                .WhereIF(dto.Source.HasValue, x => x.Source == dto.Source)
+                .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Accepted, x => !string.IsNullOrEmpty(x.Order.CallId))
+                .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Visit, x => !string.IsNullOrEmpty(x.Visit.CallId))
+                .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
+                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
+                .WhereIF(dto.MaxGrade.HasValue, x => x.Grade <= dto.MaxGrade)
+                .WhereIF(dto.MinGrade.HasValue, x => x.Grade >= dto.MinGrade)
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<QualityDto>(total, _mapper.Map<IReadOnlyList<QualityDto>>(items));
+        }
+
+        /// <summary>
+        /// 获取质检实体
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("{id}")]
+        public async Task<QualityDto> Entity(string id)
+        {
+            var quality = await _qualitey.Queryable()
+                .Includes(x => x.Order)
+                .Includes(x => x.Visit)
+                .Includes(x => x.Visit, e => e.Employee)
+                .Includes(x => x.QualityDetails)
+                .FirstAsync(x => x.Id == id);
+            var qualityDto = _mapper.Map<QualityDto>(quality);
+            // if (qualityDto.Order != null) {
+            //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
+            //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
+            //              if (call != null)
+            //              {
+            // 		qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
+            // 		qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
+            //              }
+            // }
+            // if (qualityDto.Visit != null)
+            // {
+            //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
+            //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
+            //              if (call != null)
+            //              {
+            //                  qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
+            //                  qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
+            //              }
+            //          }
+
+            if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
+            {
+                if (qualityDto.Order != null)
+                {
+                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
+                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
+                    var call = await _callApplication.GetTianrunCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
+                    if (call != null)
+                    {
+                        qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
+                        qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
+                    }
+                }
+                if (qualityDto.Visit != null)
+                {
+                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
+                    // var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
+                    var call = await _callApplication.GetTianrunCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
+                    if (call != null)
+                    {
+                        qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
+                        qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
+                    }
+                }
+            }
+            else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
+            {
+                if (!string.IsNullOrEmpty(qualityDto?.Order?.CallId))
+                {
+                    var call = await _callApplication.GetCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
+                    if (call != null)
+                    {
+                        qualityDto.Order.RecordingBaseAddress = call.AudioFile;
+                        qualityDto.Order.RecordingAbsolutePath = call.AudioFile;
+                    }
+                }
+                if (!string.IsNullOrEmpty(qualityDto.Visit.CallId))
+                {
+                    var call = await _callApplication.GetCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
+                    if (call != null)
+                    {
+                        qualityDto.Visit.RecordingBaseAddress = call.AudioFile;
+                        qualityDto.Visit.RecordingAbsolutePath = call.AudioFile;
+                    }
+                }
+            }
+
+            return qualityDto;
+        }
+        #endregion
+
+        #region 质检项管理 
+        /// <summary>
+        /// 新增项目
+        /// </summary>
+        /// <param name="dtos"></param>
+        /// <returns></returns>
+        [Permission(EPermission.AddQualityItem)]
+        [HttpPost("item")]
+        public async Task Add([FromBody] QualityItemAddDto dto)
+        {
+            var count = await _qualiteyItem.CountAsync(x => x.Name == dto.Name);
+            if (count > 0)
+                throw UserFriendlyException.SameMessage("质检项目名称已存在");
+            var model = _mapper.Map<QualityItem>(dto);
+            await _qualiteyItem.AddAsync(model, HttpContext.RequestAborted);
+        }
+
+        ///// <summary>
+        ///// 删除项目
+        ///// </summary>
+        ///// <param name="dto"></param>
+        ///// <returns></returns>
+        //[Permission(EPermission.DeleteQualityItem)]
+        //[HttpDelete("item")]
+        //public async Task Delete([FromBody] QualityItemDeleteDto dto)
+        //{
+        //	await _qualiteyItem.RemoveAsync(x => x.Id == dto.Id);
+        //}
+
+        /// <summary>
+        /// 删除项目
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.DeleteQualityItem)]
+        [HttpDelete("itemBatch")]
+        public async Task Delete([FromBody] QualityItemBatchDeleteDto dto)
+        {
+            List<QualityItem> items = await _qualiteyItem.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
             foreach (var item in items)
             {
-	            var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name).AnyAsync();
-				//质检中已存在不可以删
-				if (detail) items.Remove(item);
-			}
-			if (items.Any())
-			{
-				await _qualiteyItem.RemoveRangeAsync(items, true, HttpContext.RequestAborted);
-				var tempItems = await _qualiteyTemplateDetail.Queryable().In(x => x.ItemId, items.Select(x => x.Id)).ToListAsync(HttpContext.RequestAborted);
-				if (tempItems.Any()) await _qualiteyTemplateDetail.RemoveRangeAsync(tempItems, HttpContext.RequestAborted);			
-			}
-		}
-
-		/// <summary>
-		/// 更新项目
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.UpdateQualityItem)]
-		[HttpPut("item")]
-		public async Task Update([FromBody] QualityItemUpdateDto dto)
-		{
-			var item = await _qualiteyItem.GetAsync(dto.Id, HttpContext.RequestAborted);
-			if (item is null)
-				throw UserFriendlyException.SameMessage("无效质检项目");
-			if (item.IsEnable != dto.IsEnable || item.Name != dto.Name) {
-				var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name && !x.IsDeleted).AnyAsync();
-				if(detail) throw UserFriendlyException.SameMessage("质检项目在中心质检中已使用,不能修改状态和名称!");
-			}
-			_mapper.Map(dto, item);
-			item.LastModificationName = _sessionContext.UserName;
-			await _qualiteyItem.UpdateAsync(item, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 获取项目列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.QualityItemList)]
-		[HttpGet("item/list")]
-		public async Task<PagedDto<QualityItemDto>> List([FromQuery] QualityItemListDto dto)
-		{
-			var (total, items) = await _qualiteyItem.Queryable()
-				.WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
-				.WhereIF(!string.IsNullOrEmpty(dto.GroupingName), d => d.GroupingName.Contains(dto.GroupingName!))
-				.WhereIF(dto.IsEnable.HasValue,d=>d.IsEnable == dto.IsEnable)
-				.OrderByDescending(x => x.CreationTime)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<QualityItemDto>(total, _mapper.Map<IReadOnlyList<QualityItemDto>>(items));
-		}
-
-		/// <summary>
-		/// 获取项目实体
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[HttpGet("item/{id}")]
-		public async Task<QualityItem> ItemEntity(string id)
-		{
-			return await _qualiteyItem.Queryable()
-				.FirstAsync(x => x.Id == id);
-		}
-
-		#endregion
-
-		#region 质检模版管理
-		/// <summary>
-		/// 新增模版
-		/// </summary>
-		/// <param name="dtos"></param>
-		/// <returns></returns>
-		[Permission(EPermission.AddQualityTemplate)]
-		[HttpPost("template")]
-		public async Task Add([FromBody] TemplateAddDto dto)
-		{
-			var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.IsEnable == 1);
-			if (groupingCount > 0 && dto.IsEnable == 1)
-				throw UserFriendlyException.SameMessage("当前已存在");
-			var names = dto.TemplateDetails.Select(x => x.ItemId).ToList();
-			var nameCount= names.GroupBy(x => x).Count(c => c.Count() > 1);
-			if (nameCount > 0)
-				throw UserFriendlyException.SameMessage("质检模版存在重复质检项");
-			var model = _mapper.Map<QualityTemplate>(dto);
-			var id = await _qualityTemplate.AddAsync(model, HttpContext.RequestAborted);
-			if (!string.IsNullOrEmpty(id))
-			{
-				foreach (var item in dto.TemplateDetails)
-				{
-					item.TemplateId = id;
-				}
-				List<QualityTemplateDetail> details = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
-				await _qualiteyTemplateDetail.AddRangeAsync(details, HttpContext.RequestAborted);
-			}
-		}
-
-		/// <summary>
-		/// 删除模版
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.DeleteQualityTemplate)]
-		[HttpDelete("template")]
-		public async Task Delete([FromBody] TemplateDeleteDto dto)
-		{
-			await _qualityTemplate.RemoveAsync(x => x.Id == dto.Id);
-			List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
-			await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 删除模版
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.DeleteQualityTemplate)]
-		[HttpDelete("templateBatch")]
-		public async Task Delete([FromBody] TemplateBatchDeleteDto dto)
-		{
-			List<QualityTemplate> templates = await _qualityTemplate.Queryable().In(x=>x.Id,dto.Ids).ToListAsync();
-			List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().In(x => x.TemplateId,dto.Ids).ToListAsync();
-			await _qualityTemplate.RemoveRangeAsync(templates, HttpContext.RequestAborted);
-			await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 更新模版
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.UpdateQualityTemplate)]
-		[HttpPut("template")]
-		public async Task Update([FromBody] TemplateUpdateDto dto)
-		{
-			var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
-			if (template is null)
-				throw UserFriendlyException.SameMessage("无效质检模版");
-			var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
-			if (groupingCount > 0)
-				throw UserFriendlyException.SameMessage("当前质检分类已存在");
-			_mapper.Map(dto, template);
-			template.LastModificationName = _sessionContext.UserName;
-			await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
-			if (dto.TemplateDetails.Any())
-			{
-				List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
-				await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
-				foreach (var item in dto.TemplateDetails)
-				{
-					item.TemplateId = dto.Id;
-				}
-				List<QualityTemplateDetail> newDetails = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
-				await _qualiteyTemplateDetail.AddRangeAsync(newDetails, HttpContext.RequestAborted);
-			}
-		}
-
-		/// <summary>
-		/// 获取模版列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.QualityTemplateList)]
-		[HttpGet("template/list")]
-		public async Task<PagedDto<QualityTemplateDto>> List([FromQuery] TemplateListDto dto)
-		{
-			var (total, items) = await _qualityTemplate.Queryable()
-				.Includes(x => x.templateDetails)
-				.Includes(x=>x.templateDetails,y=>y.QualityItem)
-				.WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
-				.WhereIF(dto.Grouping.HasValue, d => d.Grouping == dto.Grouping)
-				.WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)
-				.OrderByDescending(x => x.CreationTime)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<QualityTemplateDto>(total, _mapper.Map<IReadOnlyList<QualityTemplateDto>>(items));
-		}
-
-		/// <summary>
-		/// 获取模版实体
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[HttpGet("template/{id}")]
-		public async Task<QualityTemplateDto> TemplateEntity(string id)
-		{
-			var template = await _qualityTemplate.Queryable()
-				.Includes(x => x.templateDetails)
-				.Includes(x => x.templateDetails, y => y.QualityItem)
-				.FirstAsync(x => x.Id == id);
-			return _mapper.Map<QualityTemplateDto>(template);
-		}
-		/// <summary>
-		/// 启禁用
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.EnableQualityTemplate)]
-		[HttpPut("template/enable")]
-		public async Task Enable([FromBody] TemplateUpdateDto dto)
-		{
-			var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
-			var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
-			if (groupingCount > 0)
-				throw UserFriendlyException.SameMessage("当前质检分类已存在");
-			if (template is null)
-				throw UserFriendlyException.SameMessage("无效质检模版");
-			_mapper.Map(dto, template);
-			await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
-		}
-		#endregion
-
-		#region 质检词库管理
-
-		/// <summary>
-		/// 新增违禁词
-		/// </summary>
-		/// <param name="dtos"></param>
-		/// <returns></returns>
-		[Permission(EPermission.AddQualityProhibited)]
-		[HttpPost("prohibited")]
-		public async Task Add([FromBody] ProhibitedAddDto dto)
-		{
-			var model = _mapper.Map<QualityProhibited>(dto);
-			 await _qualiteyProhibited.AddAsync(model, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 删除违禁词
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.DeleteQualityProhibited)]
-		[HttpDelete("prohibited")]
-		public async Task Delete([FromBody] ProhibitedDeleteDto dto)
-		{
-			await _qualiteyProhibited.RemoveAsync(x => x.Id == dto.Id);
-		}
-
-		/// <summary>
-		/// 删除违禁词
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.DeleteQualityProhibited)]
-		[HttpDelete("prohibitedBatch")]
-		public async Task Delete([FromBody] ProhibitedBatchDeleteDto dto)
-		{
-            List<QualityProhibited> prohibiteds = await _qualiteyProhibited.Queryable().In(x=>x.Id,dto.Ids).ToListAsync();
-			await _qualiteyProhibited.RemoveRangeAsync(prohibiteds, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 更新违禁词
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.UpdateQualityProhibited)]
-		[HttpPut("prohibited")]
-		public async Task Update([FromBody] ProhibitedUpdateDto dto)
-		{
-			var prohibited = await _qualiteyProhibited.GetAsync(dto.Id, HttpContext.RequestAborted);
-			if (prohibited is null)
-				throw UserFriendlyException.SameMessage("无效质检模版");
-			_mapper.Map(dto, prohibited);
-			prohibited.LastModificationName = _sessionContext.UserName;
-			await _qualiteyProhibited.UpdateAsync(prohibited, HttpContext.RequestAborted);
-		}
-
-		/// <summary>
-		/// 获取违禁词列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[Permission(EPermission.QualityProhibitedList)]
-		[HttpGet("prohibited/list")]
-		public async Task<PagedDto<QualityProhibitedDto>> List([FromQuery] ProhibitedListDto dto)
-		{
-			var (total, items) = await _qualiteyProhibited.Queryable()
-				.WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
-				.WhereIF(!string.IsNullOrEmpty(dto.Classify), d => d.Classify.Contains(dto.Classify!))
-				.WhereIF(!string.IsNullOrEmpty(dto.Type), d => d.Type.Contains(dto.Type!))
-				.OrderByDescending(x => x.CreationTime)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<QualityProhibitedDto>(total, _mapper.Map<IReadOnlyList<QualityProhibitedDto>>(items));
-		}
-
-		/// <summary>
-		/// 获取违禁词实体
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[HttpGet("prohibited/{id}")]
-		public async Task<QualityProhibited> ProhibitedEntity(string id)
-		{
-			return await _qualiteyProhibited.Queryable()
-				.FirstAsync(x => x.Id == id);
-		}
-		#endregion
-
-		/// <summary>
-		/// 获取质检基本信息
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("base")]
-		public async Task<object> Base()
-		{
-			var rsp = new
-			{
-				QualityState = EnumExts.GetDescriptions<EQualityState>(),
-				QualitySource = EnumExts.GetDescriptions<EQualitySource>()
-			};
-			return rsp;
-		}
-
-		/// <summary>
-		/// 获取质检项目基本信息
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("item_base")]
-		public async Task<object> ItemBase()
-		{
-			var rsp = new
-			{
-				QualityItemGrouping = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.QualityItemGrouping)
-			};
-			return rsp;
-		}
-
-		/// <summary>
-		/// 获取质检模版基本信息
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("template_base")]
-		public async Task<object> TemplateBase()
-		{
-			var rsp = new
-			{
-				TemplateGrouping = EnumExts.GetDescriptions<ETemplateGrouping>()
-			};
-			return rsp;
-		}
-
-		/// <summary>
-		/// 获取质检违禁词基本信息
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("prohibited_base")]
-		public async Task<object> ProhibitedBase()
-		{
-			var rsp = new
-			{
-				ProhibitedClassify = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedClassify),
-				ProhibitedType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedType),
-			};
-			return rsp;
-		}
-
-		/// <summary>
-		/// 智能质检结果返回接收
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[AllowAnonymous]
-		[HttpPost("AiResult")]
-		[LogFilter("智能质检结果返回接收")]
-		public async Task AiResult([FromBody] List<AiQualityResultDto> dto) 
-		{
-			//Request.EnableBuffering();
-			//var sr = new StreamReader(Request.Body);
-			//var data = await sr.ReadToEndAsync(HttpContext.RequestAborted);
-			//_logger.LogInformation(data);
-			foreach (var item in dto)
-			{
-				var quality = await _qualitey.GetAsync(item.record_id);
-				if (quality is { State: EQualityState.Apply } && item.score_items != null && item.score_items.Any())
-				{
-					List<QualityDetail> details = new List<QualityDetail>();
-					foreach (var item2 in item.score_items)
-					{
-						if (item2.score > 0)
-						{
-							var detailsSentence = new List<QualityDetail>();
-							QualityDetail detail = new QualityDetail
-							{
-								QualityId = quality.Id,
-								Second = 0,
-								EndSecond = 0,
-								Name = item2.name,
-								Content = item2.description,
-								Intelligent = true,
-								Grade = item2.score,
-								Check = true,
-							};
-							if (item2?.qualityModels?.Count > 0)
-							{
-								foreach (var models  in item2.qualityModels)
-								{
-									if (models?.sentenceResults?.Count > 0)
-									{
-										for (int i = 0; i < models.sentenceResults.Count; i++)
-										{
-											var newDetail = new QualityDetail();
-											_mapper.Map(detail,newDetail);
-											var sentenceList = item.trans_data.sentence_list.First(x => x.index == models.sentenceResults[i].index);
-											newDetail.Second = sentenceList.start;
-											newDetail.EndSecond = sentenceList.end == null? 0: sentenceList.end;
-											newDetail.Content = sentenceList.text;
-											detailsSentence.Add(newDetail);
-										}
-									}
-								}
-							}
-							if (item2?.audioAttributes?.Count > 0)
-							{
-								foreach (var audio in item2.audioAttributes)
-								{
-									if (audio?.sentenceResults?.Count > 0)
-									{
+                var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name).AnyAsync();
+                //质检中已存在不可以删
+                if (detail) items.Remove(item);
+            }
+            if (items.Any())
+            {
+                await _qualiteyItem.RemoveRangeAsync(items, true, HttpContext.RequestAborted);
+                var tempItems = await _qualiteyTemplateDetail.Queryable().In(x => x.ItemId, items.Select(x => x.Id)).ToListAsync(HttpContext.RequestAborted);
+                if (tempItems.Any()) await _qualiteyTemplateDetail.RemoveRangeAsync(tempItems, HttpContext.RequestAborted);
+            }
+        }
+
+        /// <summary>
+        /// 更新项目
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.UpdateQualityItem)]
+        [HttpPut("item")]
+        public async Task Update([FromBody] QualityItemUpdateDto dto)
+        {
+            var item = await _qualiteyItem.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (item is null)
+                throw UserFriendlyException.SameMessage("无效质检项目");
+            if (item.IsEnable != dto.IsEnable || item.Name != dto.Name)
+            {
+                var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name && !x.IsDeleted).AnyAsync();
+                if (detail) throw UserFriendlyException.SameMessage("质检项目在中心质检中已使用,不能修改状态和名称!");
+            }
+            _mapper.Map(dto, item);
+            item.LastModificationName = _sessionContext.UserName;
+            await _qualiteyItem.UpdateAsync(item, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 获取项目列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.QualityItemList)]
+        [HttpGet("item/list")]
+        public async Task<PagedDto<QualityItemDto>> List([FromQuery] QualityItemListDto dto)
+        {
+            var (total, items) = await _qualiteyItem.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
+                .WhereIF(!string.IsNullOrEmpty(dto.GroupingName), d => d.GroupingName.Contains(dto.GroupingName!))
+                .WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<QualityItemDto>(total, _mapper.Map<IReadOnlyList<QualityItemDto>>(items));
+        }
+
+        /// <summary>
+        /// 获取项目实体
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("item/{id}")]
+        public async Task<QualityItem> ItemEntity(string id)
+        {
+            return await _qualiteyItem.Queryable()
+                .FirstAsync(x => x.Id == id);
+        }
+
+        #endregion
+
+        #region 质检模版管理
+        /// <summary>
+        /// 新增模版
+        /// </summary>
+        /// <param name="dtos"></param>
+        /// <returns></returns>
+        [Permission(EPermission.AddQualityTemplate)]
+        [HttpPost("template")]
+        public async Task Add([FromBody] TemplateAddDto dto)
+        {
+            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.IsEnable == 1);
+            if (groupingCount > 0 && dto.IsEnable == 1)
+                throw UserFriendlyException.SameMessage("当前已存在");
+            var names = dto.TemplateDetails.Select(x => x.ItemId).ToList();
+            var nameCount = names.GroupBy(x => x).Count(c => c.Count() > 1);
+            if (nameCount > 0)
+                throw UserFriendlyException.SameMessage("质检模版存在重复质检项");
+            var model = _mapper.Map<QualityTemplate>(dto);
+            var id = await _qualityTemplate.AddAsync(model, HttpContext.RequestAborted);
+            if (!string.IsNullOrEmpty(id))
+            {
+                foreach (var item in dto.TemplateDetails)
+                {
+                    item.TemplateId = id;
+                }
+                List<QualityTemplateDetail> details = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
+                await _qualiteyTemplateDetail.AddRangeAsync(details, HttpContext.RequestAborted);
+            }
+        }
+
+        /// <summary>
+        /// 删除模版
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.DeleteQualityTemplate)]
+        [HttpDelete("template")]
+        public async Task Delete([FromBody] TemplateDeleteDto dto)
+        {
+            await _qualityTemplate.RemoveAsync(x => x.Id == dto.Id);
+            List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
+            await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 删除模版
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.DeleteQualityTemplate)]
+        [HttpDelete("templateBatch")]
+        public async Task Delete([FromBody] TemplateBatchDeleteDto dto)
+        {
+            List<QualityTemplate> templates = await _qualityTemplate.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
+            List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().In(x => x.TemplateId, dto.Ids).ToListAsync();
+            await _qualityTemplate.RemoveRangeAsync(templates, HttpContext.RequestAborted);
+            await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 更新模版
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.UpdateQualityTemplate)]
+        [HttpPut("template")]
+        public async Task Update([FromBody] TemplateUpdateDto dto)
+        {
+            var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (template is null)
+                throw UserFriendlyException.SameMessage("无效质检模版");
+            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
+            if (groupingCount > 0)
+                throw UserFriendlyException.SameMessage("当前质检分类已存在");
+            _mapper.Map(dto, template);
+            template.LastModificationName = _sessionContext.UserName;
+            await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
+            if (dto.TemplateDetails.Any())
+            {
+                List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
+                await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
+                foreach (var item in dto.TemplateDetails)
+                {
+                    item.TemplateId = dto.Id;
+                }
+                List<QualityTemplateDetail> newDetails = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
+                await _qualiteyTemplateDetail.AddRangeAsync(newDetails, HttpContext.RequestAborted);
+            }
+        }
+
+        /// <summary>
+        /// 获取模版列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.QualityTemplateList)]
+        [HttpGet("template/list")]
+        public async Task<PagedDto<QualityTemplateDto>> List([FromQuery] TemplateListDto dto)
+        {
+            var (total, items) = await _qualityTemplate.Queryable()
+                .Includes(x => x.templateDetails)
+                .Includes(x => x.templateDetails, y => y.QualityItem)
+                .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
+                .WhereIF(dto.Grouping.HasValue, d => d.Grouping == dto.Grouping)
+                .WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<QualityTemplateDto>(total, _mapper.Map<IReadOnlyList<QualityTemplateDto>>(items));
+        }
+
+        /// <summary>
+        /// 获取模版实体
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("template/{id}")]
+        public async Task<QualityTemplateDto> TemplateEntity(string id)
+        {
+            var template = await _qualityTemplate.Queryable()
+                .Includes(x => x.templateDetails)
+                .Includes(x => x.templateDetails, y => y.QualityItem)
+                .FirstAsync(x => x.Id == id);
+            return _mapper.Map<QualityTemplateDto>(template);
+        }
+        /// <summary>
+        /// 启禁用
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.EnableQualityTemplate)]
+        [HttpPut("template/enable")]
+        public async Task Enable([FromBody] TemplateUpdateDto dto)
+        {
+            var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
+            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
+            if (groupingCount > 0)
+                throw UserFriendlyException.SameMessage("当前质检分类已存在");
+            if (template is null)
+                throw UserFriendlyException.SameMessage("无效质检模版");
+            _mapper.Map(dto, template);
+            await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
+        }
+        #endregion
+
+        #region 质检词库管理
+
+        /// <summary>
+        /// 新增违禁词
+        /// </summary>
+        /// <param name="dtos"></param>
+        /// <returns></returns>
+        [Permission(EPermission.AddQualityProhibited)]
+        [HttpPost("prohibited")]
+        public async Task Add([FromBody] ProhibitedAddDto dto)
+        {
+            var model = _mapper.Map<QualityProhibited>(dto);
+            await _qualiteyProhibited.AddAsync(model, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 删除违禁词
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.DeleteQualityProhibited)]
+        [HttpDelete("prohibited")]
+        public async Task Delete([FromBody] ProhibitedDeleteDto dto)
+        {
+            await _qualiteyProhibited.RemoveAsync(x => x.Id == dto.Id);
+        }
+
+        /// <summary>
+        /// 删除违禁词
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.DeleteQualityProhibited)]
+        [HttpDelete("prohibitedBatch")]
+        public async Task Delete([FromBody] ProhibitedBatchDeleteDto dto)
+        {
+            List<QualityProhibited> prohibiteds = await _qualiteyProhibited.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
+            await _qualiteyProhibited.RemoveRangeAsync(prohibiteds, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 更新违禁词
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.UpdateQualityProhibited)]
+        [HttpPut("prohibited")]
+        public async Task Update([FromBody] ProhibitedUpdateDto dto)
+        {
+            var prohibited = await _qualiteyProhibited.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (prohibited is null)
+                throw UserFriendlyException.SameMessage("无效质检模版");
+            _mapper.Map(dto, prohibited);
+            prohibited.LastModificationName = _sessionContext.UserName;
+            await _qualiteyProhibited.UpdateAsync(prohibited, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 获取违禁词列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [Permission(EPermission.QualityProhibitedList)]
+        [HttpGet("prohibited/list")]
+        public async Task<PagedDto<QualityProhibitedDto>> List([FromQuery] ProhibitedListDto dto)
+        {
+            var (total, items) = await _qualiteyProhibited.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
+                .WhereIF(!string.IsNullOrEmpty(dto.Classify), d => d.Classify.Contains(dto.Classify!))
+                .WhereIF(!string.IsNullOrEmpty(dto.Type), d => d.Type.Contains(dto.Type!))
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<QualityProhibitedDto>(total, _mapper.Map<IReadOnlyList<QualityProhibitedDto>>(items));
+        }
+
+        /// <summary>
+        /// 获取违禁词实体
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("prohibited/{id}")]
+        public async Task<QualityProhibited> ProhibitedEntity(string id)
+        {
+            return await _qualiteyProhibited.Queryable()
+                .FirstAsync(x => x.Id == id);
+        }
+        #endregion
+
+        /// <summary>
+        /// 获取质检基本信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("base")]
+        public async Task<object> Base()
+        {
+            var rsp = new
+            {
+                QualityState = EnumExts.GetDescriptions<EQualityState>(),
+                QualitySource = EnumExts.GetDescriptions<EQualitySource>()
+            };
+            return rsp;
+        }
+
+        /// <summary>
+        /// 获取质检项目基本信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("item_base")]
+        public async Task<object> ItemBase()
+        {
+            var rsp = new
+            {
+                QualityItemGrouping = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.QualityItemGrouping)
+            };
+            return rsp;
+        }
+
+        /// <summary>
+        /// 获取质检模版基本信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("template_base")]
+        public async Task<object> TemplateBase()
+        {
+            var rsp = new
+            {
+                TemplateGrouping = EnumExts.GetDescriptions<ETemplateGrouping>()
+            };
+            return rsp;
+        }
+
+        /// <summary>
+        /// 获取质检违禁词基本信息
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("prohibited_base")]
+        public async Task<object> ProhibitedBase()
+        {
+            var rsp = new
+            {
+                ProhibitedClassify = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedClassify),
+                ProhibitedType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedType),
+            };
+            return rsp;
+        }
+
+        /// <summary>
+        /// 智能质检结果返回接收
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("AiResult")]
+        [LogFilter("智能质检结果返回接收")]
+        public async Task AiResult([FromBody] List<AiQualityResultDto> dto)
+        {
+            //Request.EnableBuffering();
+            //var sr = new StreamReader(Request.Body);
+            //var data = await sr.ReadToEndAsync(HttpContext.RequestAborted);
+            //_logger.LogInformation(data);
+            foreach (var item in dto)
+            {
+                var quality = await _qualitey.GetAsync(item.record_id);
+                if (quality is { State: EQualityState.Apply } && item.score_items != null && item.score_items.Any())
+                {
+                    List<QualityDetail> details = new List<QualityDetail>();
+                    foreach (var item2 in item.score_items)
+                    {
+                        if (item2.score > 0)
+                        {
+                            var detailsSentence = new List<QualityDetail>();
+                            QualityDetail detail = new QualityDetail
+                            {
+                                QualityId = quality.Id,
+                                Second = 0,
+                                EndSecond = 0,
+                                Name = item2.name,
+                                Content = item2.description,
+                                Intelligent = true,
+                                Grade = item2.score,
+                                Check = true,
+                            };
+                            if (item2?.qualityModels?.Count > 0)
+                            {
+                                foreach (var models in item2.qualityModels)
+                                {
+                                    if (models?.sentenceResults?.Count > 0)
+                                    {
+                                        for (int i = 0; i < models.sentenceResults.Count; i++)
+                                        {
+                                            var newDetail = new QualityDetail();
+                                            _mapper.Map(detail, newDetail);
+                                            var sentenceList = item.trans_data.sentence_list.First(x => x.index == models.sentenceResults[i].index);
+                                            newDetail.Second = sentenceList.start;
+                                            newDetail.EndSecond = sentenceList.end == null ? 0 : sentenceList.end;
+                                            newDetail.Content = sentenceList.text;
+                                            detailsSentence.Add(newDetail);
+                                        }
+                                    }
+                                }
+                            }
+                            if (item2?.audioAttributes?.Count > 0)
+                            {
+                                foreach (var audio in item2.audioAttributes)
+                                {
+                                    if (audio?.sentenceResults?.Count > 0)
+                                    {
                                         for (int i = 0; i < audio.sentenceResults.Count; i++)
                                         {
-											var newDetail = new QualityDetail() ;
-											_mapper.Map(detail,newDetail);
-											var sentenceList = item.trans_data.sentence_list.First(x => x.index == audio.sentenceResults[i].index);
-											newDetail.Second = sentenceList.start;
-											newDetail.EndSecond = sentenceList.end == null ? 0 : sentenceList.end;
-											newDetail.Content = sentenceList.text;
-											detailsSentence.Add(newDetail);
-										}
-									}
-									
-								}
-							}
-							if (detailsSentence.Count == 0)
-							{
-								details.Add(detail);
-							}
-							else {
-								details.AddRange(detailsSentence);
-							}
-						}
-					}
-					await _qualiteyDetail.AddRangeAsync(details);
-				}
-			}
-		}
-
-		/// <summary>
-		/// 重推质检 
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[AllowAnonymous]
-		[HttpPost("AiResultTest/{id}")]
-		public async Task TaskAsync(string id)
-		{
-			var quality = await _qualitey.GetAsync(id, HttpContext.RequestAborted);
-			var order = await _orderRepository.GetAsync(quality.OrderId, HttpContext.RequestAborted);
-			if (order != null && !string.IsNullOrEmpty(order.CallId))
-			{
-				quality.AiQuality = true;
+                                            var newDetail = new QualityDetail();
+                                            _mapper.Map(detail, newDetail);
+                                            var sentenceList = item.trans_data.sentence_list.First(x => x.index == audio.sentenceResults[i].index);
+                                            newDetail.Second = sentenceList.start;
+                                            newDetail.EndSecond = sentenceList.end == null ? 0 : sentenceList.end;
+                                            newDetail.Content = sentenceList.text;
+                                            detailsSentence.Add(newDetail);
+                                        }
+                                    }
+
+                                }
+                            }
+                            if (detailsSentence.Count == 0)
+                            {
+                                details.Add(detail);
+                            }
+                            else
+                            {
+                                details.AddRange(detailsSentence);
+                            }
+                        }
+                    }
+                    await _qualiteyDetail.AddRangeAsync(details);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 重推质检 
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [AllowAnonymous]
+        [HttpPost("AiResultTest/{id}")]
+        public async Task TaskAsync(string id)
+        {
+            var quality = await _qualitey.GetAsync(id, HttpContext.RequestAborted);
+            var order = await _orderRepository.GetAsync(quality.OrderId, HttpContext.RequestAborted);
+            if (order != null && !string.IsNullOrEmpty(order.CallId))
+            {
+                quality.AiQuality = true;
                 //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId, HttpContext.RequestAborted); //由CallAccept改为OtherAccept
-                var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId, HttpContext.RequestAborted);
-                var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
-				await _aiQualityService.CreateAiOrderQualityTask(quality, call, order, setting?.SettingValue[0], HttpContext.RequestAborted);
-				await _qualitey.UpdateAsync(quality, HttpContext.RequestAborted);
-			}
-		}
+                //var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId, HttpContext.RequestAborted);
+
+                var audioFile = string.Empty;
+                var fromNo = string.Empty;
+                DateTime? callStartTime = null;
+                if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
+                {
+                    var call = await _callApplication.GetTianrunCallAsync(order.CallId, HttpContext.RequestAborted);
+                    audioFile = call.RecordingAbsolutePath;
+                    fromNo = call.CPN;
+                    callStartTime = call.CreatedTime;
+                }
+                else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
+                {
+                    var call = await _callApplication.GetCallAsync(order.CallId, HttpContext.RequestAborted);
+                    audioFile = call.AudioFile;
+                    fromNo = call.FromNo;
+                    callStartTime = call.BeginIvrTime;
+                }
 
-	}
+                var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
+                await _aiQualityService.CreateAiOrderQualityTask(
+                    quality,
+                    audioFile,
+                    fromNo,
+                    callStartTime,
+                    order, setting?.SettingValue[0], HttpContext.RequestAborted);
+                await _qualitey.UpdateAsync(quality, HttpContext.RequestAborted);
+            }
+        }
+
+    }
 }

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

@@ -348,7 +348,7 @@ public abstract class DefaultCallApplication : ICallApplication
     /// 查询通话记录
     /// </summary>
     public Task<List<TrCallRecord>> QueryTianrunCallsAsync(
-        string? phone, 
+        string? phone = null, 
         ECallDirection? direction = null,
         DateTime? callStartTimeStart = null,
         DateTime? callStartTimeEnd = null,

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

@@ -129,7 +129,8 @@ namespace Hotline.Application.CallCenter
                 .WhereIF(direction != null, d => d.CallDirection == direction)
                 .WhereIF(callStartTimeStart != null, d => d.BeginIvrTime >= callStartTimeStart)
                 .WhereIF(callStartTimeEnd != null, d => d.BeginIvrTime <= callStartTimeEnd)
-                .OrderBy(x => x.CreatedTime).ToListAsync(cancellationToken);
+                .OrderBy(x => x.CreatedTime)
+                .ToListAsync(cancellationToken);
         }
     }
 }

+ 45 - 11
src/Hotline.Application/Quality/QualityApplication.cs

@@ -1,12 +1,16 @@
 using Hotline.Ai.Quality;
+using Hotline.Application.CallCenter;
 using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Calls;
+using Hotline.CallCenter.Configs;
 using Hotline.Orders;
 using Hotline.Quality;
 using Hotline.Settings;
 using Hotline.Share.Dtos.Quality;
 using Hotline.Share.Enums.Quality;
 using MapsterMapper;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Constants;
 using XF.Domain.Dependency;
@@ -23,32 +27,37 @@ namespace Hotline.Application.Quality
         private readonly IQualityRepository _qualityRepository;
         private readonly IAiQualityService _aiQualityService;
         private readonly IOrderRepository _orderRepository;
-        private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+        //private readonly IRepository<TrCallRecord> _trCallRecordRepository;
         private readonly IRepository<QualityTemplate> _qualityTemplate;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+        private readonly ICallApplication _callApplication;
+        private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
 
-		public QualityApplication(
+        public QualityApplication(
             ISessionContext sessionContext,
             IMapper mapper,
             IRepository<QualityDetail> qualiteyDetail,
             IQualityRepository qualityRepository,
             IAiQualityService aiQualityService,
-            IRepository<TrCallRecord> trCallRecordRepository,
+            //IRepository<TrCallRecord> trCallRecordRepository,
             IRepository<QualityTemplate> qualityTemplate,
 			IOrderRepository orderRepository,
-            ISystemSettingCacheManager systemSettingCacheManager
-		)
+            ISystemSettingCacheManager systemSettingCacheManager,
+            ICallApplication callApplication,
+            IOptionsSnapshot<CallCenterConfiguration> callcenterOptions)
         {
             _sessionContext = sessionContext;
             _mapper = mapper;
             _qualiteyDetail = qualiteyDetail;
             _qualityRepository = qualityRepository;
             _aiQualityService = aiQualityService;
-            _trCallRecordRepository = trCallRecordRepository;
+            //_trCallRecordRepository = trCallRecordRepository;
             _qualityTemplate = qualityTemplate;
 			_orderRepository = orderRepository;
             _systemSettingCacheManager = systemSettingCacheManager;
-		}
+            _callApplication = callApplication;
+            _callcenterOptions = callcenterOptions;
+        }
 
         public async Task AddQualityAsync(EQualitySource Source, string OrderId, string VisitId, CancellationToken cancellationToken)
         {
@@ -108,10 +117,35 @@ namespace Hotline.Application.Quality
 			            quality.AiQuality = true;
 			            quality.Mode = "智能质检";
 			            //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId); //由CallAccept改成OtherAccept
-			            var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId);
-			            var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
-						await _aiQualityService.CreateAiOrderQualityTask(quality, call, order, setting?.SettingValue[0], cancellationToken);
-		            }
+			            //var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId);
+
+                        var audioFile = string.Empty;
+                        var fromNo = string.Empty;
+                        DateTime? callStartTime = null;
+                        if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.TianRun)
+                        {
+                            var call = await _callApplication.GetTianrunCallAsync(order.CallId, cancellationToken);
+                            audioFile = call.RecordingAbsolutePath;
+                            fromNo = call.CPN;
+                            callStartTime = call.CreatedTime;
+                        }
+                        else if (_callcenterOptions.Value.CallCenterType == AppDefaults.CallCenterType.XingTang)
+                        {
+                            var call = await _callApplication.GetCallAsync(order.CallId, cancellationToken);
+                            audioFile = call.AudioFile;
+                            fromNo = call.FromNo;
+                            callStartTime = call.BeginIvrTime;
+                        }
+
+                        var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
+						//await _aiQualityService.CreateAiOrderQualityTask(quality, call, order, setting?.SettingValue[0], cancellationToken);
+                        await _aiQualityService.CreateAiOrderQualityTask(
+                            quality,
+                            audioFile,
+                            fromNo,
+                            callStartTime,
+                            order, setting?.SettingValue[0], cancellationToken);
+                    }
 	            }
             }
 			await _qualityRepository.AddAsync(quality, cancellationToken);

+ 8 - 1
src/Hotline/Ai/Quality/IAiQualityService.cs

@@ -13,6 +13,13 @@ namespace Hotline.Ai.Quality
 {
     public interface IAiQualityService
 	{
-        Task CreateAiOrderQualityTask(Hotline.Quality.Quality model, TrCallRecord? call,Order order, string viteRecordPrefix, CancellationToken cancellationToken);
+        Task CreateAiOrderQualityTask(Hotline.Quality.Quality model, 
+            //TrCallRecord? call,
+            string audioFile,
+            string fromNo,
+            DateTime? callStartTime,
+            Order order, 
+            string viteRecordPrefix, 
+            CancellationToken cancellationToken);
 	}
 }

+ 132 - 132
src/Hotline/Quality/QualityDomainService.cs

@@ -1,140 +1,140 @@
-using Hotline.Ai.Quality;
-using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
-using Hotline.Orders;
-using Hotline.Settings;
-using Hotline.Share.Dtos.Quality;
-using Hotline.Share.Enums.Quality;
-using MapsterMapper;
-using XF.Domain.Authentications;
-using XF.Domain.Constants;
-using XF.Domain.Dependency;
-using XF.Domain.Exceptions;
-using XF.Domain.Repository;
+//using Hotline.Ai.Quality;
+//using Hotline.Caching.Interfaces;
+//using Hotline.CallCenter.Calls;
+//using Hotline.Orders;
+//using Hotline.Settings;
+//using Hotline.Share.Dtos.Quality;
+//using Hotline.Share.Enums.Quality;
+//using MapsterMapper;
+//using XF.Domain.Authentications;
+//using XF.Domain.Constants;
+//using XF.Domain.Dependency;
+//using XF.Domain.Exceptions;
+//using XF.Domain.Repository;
 
-namespace Hotline.Quality
-{
-    public class QualityDomainService : IQualityDomainService, IScopeDependency
-    {
-        private readonly ISessionContext _sessionContext;
-        private readonly IMapper _mapper;
-        private readonly IRepository<QualityDetail> _qualiteyDetail;
-        private readonly IQualityRepository _qualityRepository;
-        private readonly IAiQualityService _aiQualityService;
-        private readonly IOrderRepository _orderRepository;
-        private readonly IRepository<TrCallRecord> _trCallRecordRepository;
-        private readonly IRepository<QualityTemplate> _qualityTemplate;
-        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+//namespace Hotline.Quality
+//{
+//    public class QualityDomainService : IQualityDomainService, IScopeDependency
+//    {
+//        private readonly ISessionContext _sessionContext;
+//        private readonly IMapper _mapper;
+//        private readonly IRepository<QualityDetail> _qualiteyDetail;
+//        private readonly IQualityRepository _qualityRepository;
+//        private readonly IAiQualityService _aiQualityService;
+//        private readonly IOrderRepository _orderRepository;
+//        private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+//        private readonly IRepository<QualityTemplate> _qualityTemplate;
+//        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
 
-		public QualityDomainService(
-            ISessionContext sessionContext,
-            IMapper mapper,
-            IRepository<QualityDetail> qualiteyDetail,
-            IQualityRepository qualityRepository,
-            IAiQualityService aiQualityService,
-            IRepository<TrCallRecord> trCallRecordRepository,
-            IRepository<QualityTemplate> qualityTemplate,
-            IOrderRepository orderRepository,
-            ISystemSettingCacheManager systemSettingCacheManager
-			)
-        {
-            _sessionContext = sessionContext;
-            _mapper = mapper;
-            _qualiteyDetail = qualiteyDetail;
-            _qualityRepository = qualityRepository;
-            _aiQualityService = aiQualityService;
-            _trCallRecordRepository = trCallRecordRepository;
-            _qualityTemplate = qualityTemplate;
-            _orderRepository = orderRepository;
-            _systemSettingCacheManager = systemSettingCacheManager;
+//		public QualityDomainService(
+//            ISessionContext sessionContext,
+//            IMapper mapper,
+//            IRepository<QualityDetail> qualiteyDetail,
+//            IQualityRepository qualityRepository,
+//            IAiQualityService aiQualityService,
+//            IRepository<TrCallRecord> trCallRecordRepository,
+//            IRepository<QualityTemplate> qualityTemplate,
+//            IOrderRepository orderRepository,
+//            ISystemSettingCacheManager systemSettingCacheManager
+//			)
+//        {
+//            _sessionContext = sessionContext;
+//            _mapper = mapper;
+//            _qualiteyDetail = qualiteyDetail;
+//            _qualityRepository = qualityRepository;
+//            _aiQualityService = aiQualityService;
+//            _trCallRecordRepository = trCallRecordRepository;
+//            _qualityTemplate = qualityTemplate;
+//            _orderRepository = orderRepository;
+//            _systemSettingCacheManager = systemSettingCacheManager;
 
-		}
+//		}
 
-        public async Task AddQualityAsync(EQualitySource Source, string OrderId, string VisitId, CancellationToken cancellationToken)
-        {
-            QualityAddDto quality = new QualityAddDto
-            {
-                Source = Source,
-                OrderId = OrderId,
-                VisitId = VisitId
-            };
-            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
-            if (count <= 0)
-                await AddQualityAsync(quality, cancellationToken);
-        }
+//        public async Task AddQualityAsync(EQualitySource Source, string OrderId, string VisitId, CancellationToken cancellationToken)
+//        {
+//            QualityAddDto quality = new QualityAddDto
+//            {
+//                Source = Source,
+//                OrderId = OrderId,
+//                VisitId = VisitId
+//            };
+//            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
+//            if (count <= 0)
+//                await AddQualityAsync(quality, cancellationToken);
+//        }
 
-        public async Task AddQualityAsync(EQualitySource Source, string OrderId, CancellationToken cancellationToken)
-        {
-            QualityAddDto quality = new QualityAddDto
-            {
-                Source = Source,
-                OrderId = OrderId
-            };
-            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
-            if (count <= 0)
-                await AddQualityAsync(quality, cancellationToken);
-        }
+//        public async Task AddQualityAsync(EQualitySource Source, string OrderId, CancellationToken cancellationToken)
+//        {
+//            QualityAddDto quality = new QualityAddDto
+//            {
+//                Source = Source,
+//                OrderId = OrderId
+//            };
+//            var count = await _qualityRepository.CountAsync(x => x.OrderId == OrderId && x.Source == Source, cancellationToken);
+//            if (count <= 0)
+//                await AddQualityAsync(quality, cancellationToken);
+//        }
 
-        public async Task AddQualityAsync(QualityAddDto model, CancellationToken cancellationToken)
-        {
-            var quality = _mapper.Map<Hotline.Quality.Quality>(model);
-            quality.InitId();
+//        public async Task AddQualityAsync(QualityAddDto model, CancellationToken cancellationToken)
+//        {
+//            var quality = _mapper.Map<Hotline.Quality.Quality>(model);
+//            quality.InitId();
 
-            if (model.QualityDetails.Any())
-            {
-                foreach (var item in model.QualityDetails)
-                {
-                    item.QualityId = quality.Id;
-                }
-                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
-                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
-            }
-            //受理智能质检
-            if (model.Source == EQualitySource.Accepted)
-            {
-                var teAny = await _qualityTemplate.Queryable()
-                    .LeftJoin<QualityTemplateDetail>((x, d) => x.Id == d.TemplateId)
-                    .LeftJoin<QualityItem>((x, d, i) => d.ItemId == i.Id)
-                    .Where((x, d, i) => i.IsIntelligent == 1).AnyAsync();
-                if (teAny)
-                {
-                    var order = await _orderRepository.GetAsync(model.OrderId);
-                    if (order != null && !string.IsNullOrEmpty(order.CallId))
-                    {
-                        quality.AiQuality = true;
-                        quality.Mode = "智能质检";
-                        //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId); //由CallAccept改成OtherAccept
-                        var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId);
-                        var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
-						await _aiQualityService.CreateAiOrderQualityTask(quality, call, order, setting?.SettingValue[0],cancellationToken);
-                    }
-                }
-            }
-            await _qualityRepository.AddAsync(quality, cancellationToken);
-        }
+//            if (model.QualityDetails.Any())
+//            {
+//                foreach (var item in model.QualityDetails)
+//                {
+//                    item.QualityId = quality.Id;
+//                }
+//                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
+//                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
+//            }
+//            //受理智能质检
+//            if (model.Source == EQualitySource.Accepted)
+//            {
+//                var teAny = await _qualityTemplate.Queryable()
+//                    .LeftJoin<QualityTemplateDetail>((x, d) => x.Id == d.TemplateId)
+//                    .LeftJoin<QualityItem>((x, d, i) => d.ItemId == i.Id)
+//                    .Where((x, d, i) => i.IsIntelligent == 1).AnyAsync();
+//                if (teAny)
+//                {
+//                    var order = await _orderRepository.GetAsync(model.OrderId);
+//                    if (order != null && !string.IsNullOrEmpty(order.CallId))
+//                    {
+//                        quality.AiQuality = true;
+//                        quality.Mode = "智能质检";
+//                        //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId); //由CallAccept改成OtherAccept
+//                        var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId);
+//                        var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
+//						await _aiQualityService.CreateAiOrderQualityTask(quality, call, order, setting?.SettingValue[0],cancellationToken);
+//                    }
+//                }
+//            }
+//            await _qualityRepository.AddAsync(quality, cancellationToken);
+//        }
 
-        public async Task UpdateQualityAsync(UpdateQualityDto model, CancellationToken cancellationToken)
-        {
-            //验证工单是否可以申请
-            var quality = await _qualityRepository.GetAsync(model.Id, cancellationToken);
-            if (quality is null)
-                throw UserFriendlyException.SameMessage("无效质检");
-            _mapper.Map(model, quality);
-            quality.State = EQualityState.End;
-            quality.UserName = _sessionContext.UserName;
-            quality.QualityTime = DateTime.Now;
-            await _qualityRepository.UpdateAsync(quality, cancellationToken);
-            List<QualityDetail> deleteDetails = await _qualiteyDetail.Queryable().Where(x => x.QualityId == model.Id).ToListAsync(cancellationToken);
-            await _qualiteyDetail.RemoveRangeAsync(deleteDetails, cancellationToken);
-            if (model.QualityDetails.Any())
-            {
-                foreach (var item in model.QualityDetails)
-                {
-                    item.QualityId = model.Id;
-                }
-                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
-                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
-            }
-        }
-    }
-}
+//        public async Task UpdateQualityAsync(UpdateQualityDto model, CancellationToken cancellationToken)
+//        {
+//            //验证工单是否可以申请
+//            var quality = await _qualityRepository.GetAsync(model.Id, cancellationToken);
+//            if (quality is null)
+//                throw UserFriendlyException.SameMessage("无效质检");
+//            _mapper.Map(model, quality);
+//            quality.State = EQualityState.End;
+//            quality.UserName = _sessionContext.UserName;
+//            quality.QualityTime = DateTime.Now;
+//            await _qualityRepository.UpdateAsync(quality, cancellationToken);
+//            List<QualityDetail> deleteDetails = await _qualiteyDetail.Queryable().Where(x => x.QualityId == model.Id).ToListAsync(cancellationToken);
+//            await _qualiteyDetail.RemoveRangeAsync(deleteDetails, cancellationToken);
+//            if (model.QualityDetails.Any())
+//            {
+//                foreach (var item in model.QualityDetails)
+//                {
+//                    item.QualityId = model.Id;
+//                }
+//                List<QualityDetail> details = _mapper.Map<List<QualityDetail>>(model.QualityDetails);
+//                await _qualiteyDetail.AddRangeAsync(details, cancellationToken);
+//            }
+//        }
+//    }
+//}