123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- using Hotline.Application.CallCenter;
- using Hotline.Share.Tools;
- using Hotline.Caching.Interfaces;
- using Hotline.CallCenter.BlackLists;
- using Hotline.CallCenter.Calls;
- using Hotline.CallCenter.Configs;
- using Hotline.CallCenter.Tels;
- using Hotline.EventBus;
- using Hotline.Quality.Notifications;
- using Hotline.Settings;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.CallCenter;
- using Hotline.Share.Dtos.Quality;
- using Hotline.Share.Dtos.TrCallCenter;
- using Hotline.Share.Enums.CallCenter;
- using Hotline.Repository.SqlSugar.Extensions;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Options;
- using System.Threading;
- using XF.Domain.Exceptions;
- using XF.Utility.EnumExtensions;
- using XF.Domain.Repository;
- using MapsterMapper;
- using SqlSugar;
- using Hotline.Api.Filter;
- using Microsoft.AspNetCore.Authorization;
- using Hotline.Share.Dtos.Order;
- using Hotline.Tools;
- using XF.Domain.Authentications;
- namespace Hotline.Api.Controllers
- {
- public class CallController : BaseController
- {
- private readonly ICallApplication _callApplication;
- private readonly Publisher _publisher;
- private readonly IMapper _mapper;
- private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
- private readonly ISystemSettingCacheManager _systemSettingCacheManager;
- private readonly IRepository<TelOperationXthx> _telOperationXthxRepository;
- public CallController(
- ICallApplication callApplication,
- Publisher publisher,
- IMapper mapper,
- IOptionsSnapshot<CallCenterConfiguration> callcenterOptions,
- ISystemSettingCacheManager systemSettingCacheManager,
- IRepository<TelOperationXthx> telOperationXthxRepository)
- {
- _callApplication = callApplication;
- _publisher = publisher;
- _mapper = mapper;
- _callcenterOptions = callcenterOptions;
- _systemSettingCacheManager = systemSettingCacheManager;
- _telOperationXthxRepository = telOperationXthxRepository;
- }
- /// <summary>
- /// 查询分机组和分机
- /// </summary>
- [HttpGet("querygrouptel")]
- public Task<IReadOnlyList<TelGroupDto>> QueryGroupTel()
- => _callApplication.QueryGroupTel(HttpContext.RequestAborted);
- /// <summary>
- /// 查询分机
- /// </summary>
- [HttpGet("tels")]
- public async Task<IList<TelDto>> QueryTels()
- => (await _callApplication.QueryTelsAsync(new QueryTelsInDto(null) { PageSize = 99999 }, HttpContext.RequestAborted)).Item2;
- /// <summary>
- /// 查询分机
- /// </summary>
- [HttpGet("tels-paged")]
- public async Task<PagedDto<TelDto>> QueryTelsAsync([FromQuery] QueryTelsInDto dto)
- => (await _callApplication.QueryTelsAsync(dto, HttpContext.RequestAborted)).ToPaged();
- /// <summary>
- /// 查询分机组
- /// </summary>
- [HttpGet("groups")]
- public Task<IReadOnlyList<TelGroupDto>> QueryTelGroups()
- => _callApplication.QueryTelGroupsAsync(HttpContext.RequestAborted);
- #region 黑名单
- //Task<string> AddBlackListAsync(AddBlacklistDto dto, CancellationToken cancellationToken);
- //Task RemoveBlackListAsync(string id, CancellationToken cancellationToken);
- //Task<List<Blacklist>> QueryBlackListsAsync(CancellationToken cancellationToken);
- #endregion
- /// <summary>
- /// 签入
- /// </summary>
- [HttpPost("signin")]
- [LogFilterAlpha("分机签入")]
- public Task<TrOnDutyResponseDto> SignIn([FromBody] SignInDto dto)
- => _callApplication.SignInAsync(dto, HttpContext.RequestAborted);
- /// <summary>
- /// 签出
- /// </summary>
- [HttpPost("signout")]
- [LogFilterAlpha("分机签出")]
- public Task SignOut()
- => _callApplication.SingOutAsync(HttpContext.RequestAborted);
- /// <summary>
- /// 签出
- /// </summary>
- [HttpPost("signout/{telNo}")]
- [LogFilterAlpha("分机签出")]
- public Task SignOut(string telNo)
- => _callApplication.SingOutAsync(telNo, HttpContext.RequestAborted);
- /// <summary>
- /// 查询当前用户的分机状态
- /// </summary>
- /// <returns></returns>
- [HttpGet("tel-state")]
- public Task<TrOnDutyResponseDto> GetTelState()
- => _callApplication.GetTelStateAsync(HttpContext.RequestAborted);
- /// <summary>
- /// 查询通话记录(固定数据量)
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("calls-fixed")]
- public async Task<List<CallNativeDto>> QueryCallsFixed([FromQuery] QueryCallsFixedDto dto)
- => await _callApplication.QueryCallsFixedAsync(dto, HttpContext.RequestAborted).ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
- /// <summary>
- /// 查询通话记录(固定数据量)
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("calls-fixed/count")]
- public async Task<int> QueryCallsFixedCount([FromQuery] QueryCallsFixedDto dto)
- => await _callApplication.QueryCallsFixedAsync(dto, HttpContext.RequestAborted).CountAsync(HttpContext.RequestAborted);
- /// <summary>
- /// 导出通话记录
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("calls-fixed/export")]
- [LogFilterAlpha("导出日志")]
- public async Task<FileStreamResult> ExportOrders([FromBody] ExportExcelDto<QueryCallsFixedDto> dto)
- {
- var query = _callApplication.QueryCallsFixedAsync(dto.QueryDto, HttpContext.RequestAborted);
- List<CallNativeDto> callls;
- if (dto.IsExportAll)
- {
- callls = await query.ToListAsync(HttpContext.RequestAborted);
- }
- else
- {
- var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
- callls = items;
- }
- dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<CallNativeDto>(dto.ColumnInfos);
- var dtos = callls
- .Select(stu => _mapper.Map(stu, typeof(CallNativeDto), dynamicClass))
- .Cast<object>()
- .ToList();
- var stream = ExcelHelper.CreateStream(dtos);
- return ExcelStreamResult(stream, "通话记录");
- }
- /// <summary>
- /// 查询通话记录
- /// </summary>
- /// <param name="callId"></param>
- /// <returns></returns>
- [HttpGet("{callId}")]
- public Task<List<CallNative>> GetCall(string callId)
- {
- //为兼容天润通话记录返回集合
- if (string.IsNullOrEmpty(callId)) return default;
- return _callApplication.GetCallListAsync(callId, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 通话记录基础数据
- /// </summary>
- /// <returns></returns>
- [HttpGet("base-data")]
- public object BaseData()
- {
- return new
- {
- Direction = EnumExts.GetDescriptions<ECallDirection>(),
- EndBy = EnumExts.GetDescriptions<EEndBy>(),
- };
- }
- /// <summary>
- /// 查询坐席操作记录(固定数据量)
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("tel-operations-fixed")]
- public async Task<IReadOnlyList<TelOperation>> QueryTelOperationsAsync([FromQuery] QueryTelOperationsFixedDto dto) =>
- await _callApplication.QueryTelOperationsAsync(dto).ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);
- /// <summary>
- /// 查询坐席操作记录(固定数据量)
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("tel-operations-fixed/count")]
- public async Task<int> QueryTelOperationsCountAsync([FromQuery] QueryTelOperationsFixedDto dto) =>
- await _callApplication.QueryTelOperationsAsync(dto).CountAsync(HttpContext.RequestAborted);
- /// <summary>
- /// 查询坐席操作记录基础数据
- /// </summary>
- [HttpGet("base-data-tel-operation")]
- public object BaseDataTelOperation()
- {
- return new
- {
- Operations = _callApplication.GetTelOperationOptions()
- };
- }
- /// <summary>
- /// 通话转写
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("calls/transliteration")]
- public async Task CallTransliteration([FromBody] CallTransliteration dto)
- {
- foreach (var id in dto.Ids)
- {
- var call = await _callApplication.GetTianrunCallAsync(id, HttpContext.RequestAborted);
- if (call is null)
- throw UserFriendlyException.SameMessage("通话信息错误");
- if (call.TransliterationState == ECallTransliterationState.Underway)
- throw UserFriendlyException.SameMessage("正在转写中,请勿重复点击,请稍作等待");
- if (call.TransliterationState == ECallTransliterationState.Succeed)
- throw UserFriendlyException.SameMessage("转写成功,不能重新转写");
- call.InitTransliterationId();
- await _callApplication.EditTransliterationStateAsync(call.Id, ECallTransliterationState.Underway, call.TransliterationId, HttpContext.RequestAborted);
- var audioFile = call.RecordingAbsolutePath;
- var fromNo = call.CPN;
- var callStartTime = call.CreatedTime;
- var Id = call.TransliterationId;
- var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
- var handler = new AiQualityHandler()
- {
- Id = Id,
- Source = "AiAnswered",
- AudioFile = audioFile,
- FromNo = fromNo,
- CallStartTime = callStartTime,
- ViteRecordPrefix = setting?.SettingValue[0],
- };
- await _publisher.PublishAsync(new AiOrderQualityNotify(handler), PublishStrategy.ParallelNoWait, HttpContext.RequestAborted);
- }
- }
- #region 坐席动作类型统计
- /// <summary>
- /// 坐席动作类型统计
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpGet("telaction/list")]
- public async Task<PagedDto<TelActionListXthx>> TelActionList([FromQuery] TelActionXthxDto dto)
- {
- var (total, items) = await _telOperationXthxRepository.Queryable()
- .WhereIF(string.IsNullOrEmpty(dto.TelNo) == false, x => x.TelNo.Contains(dto.TelNo))
- .WhereIF(dto.OperationStatus != null, x => x.OperationStatus == dto.OperationStatus)
- .WhereIF(string.IsNullOrEmpty(dto.UserName) == false, x => x.UserName.Contains(dto.UserName))
- .WhereIF(dto.StartTime.HasValue, x => x.StartTime >= dto.StartTime)
- .WhereIF(dto.EndTime.HasValue, x => x.StartTime <= dto.EndTime)
- .OrderByDescending(x => x.StartTime)
- .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
- return new PagedDto<TelActionListXthx>(total, _mapper.Map<IReadOnlyList<TelActionListXthx>>(items));
- }
- #endregion
- }
- }
|