using CRM.Core.BLL.Util; using CRM.Core.Common.Layui; using CRM.Core.Model.Entity; using System; using System.Collections.Generic; using System.Linq; using System.Data; using System.Linq.Expressions; using CRM.Core.Model.Enum; using Newtonsoft.Json; using CRM.Core.Common; using System.Diagnostics; using System.ComponentModel; namespace CRM.Core.BLL.Csvr { public class Csvr_AiCallTask_BL : DbContextRepository { private CACHE_BL cache_BL = new CACHE_BL(); public List GetList(ref Laypage pager, AiRecordQueryDto dto) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var robotList = cache_BL.GetAiRobotList(); var robotName = robotList.FirstOrDefault()?.RobotName; var remark = robotList.FirstOrDefault()?.Remark; using (var db = new zxdContext()) { var orderQuery = from n in db.Csvr_Ai_CallTask_Orders group n by n.Taskid into model select new GroupTask { TaskId = model.Key.Value, LinkOrderId = model.Select(n => n.Orderid.Value).FirstOrDefault() }; if (dto.orderId.HasValue) { orderQuery = from n in db.Csvr_Ai_CallTask_Orders where n.Orderid == dto.orderId.Value group n by n.Taskid into model select new GroupTask { TaskId = model.Key.Value, LinkOrderId = model.Select(n => n.Orderid.Value).FirstOrDefault() }; } if (!string.IsNullOrEmpty(dto.channel)) { var channelQuery = from n in db.Csvr_Ai_CallTask_Orders join b in db.WX_SZZYORDER on n.Orderid equals b.ORDERID select new OrderTaskDto { Taskid = n.Taskid.Value, CHANNEL = b.CHANNEL, ORDERID = n.Orderid.Value }; var arr0 = dto.channel.Split('|'); if (arr0.Length > 1) { var predicates = new List>>(); foreach (var item in arr0) { var a = item.Split(','); var min = Convert.ToInt32(a[0]); var max = Convert.ToInt32(a[1]); predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max); } channelQuery = channelQuery.WhereOR(predicates.ToArray()); } else { var arr = dto.channel.Split(','); var min = Convert.ToInt32(arr[0]); var max = Convert.ToInt32(arr[1]); channelQuery = channelQuery.Where(m => m.CHANNEL >= min && m.CHANNEL <= max); } orderQuery = from a in channelQuery group a by a.Taskid into model select new GroupTask { TaskId = model.Key.Value, LinkOrderId = model.Select(n => n.ORDERID).FirstOrDefault() }; } var queryData = from o in orderQuery join b in db.Csvr_Ai_CallTask.AsQueryable() on o.TaskId equals b.Id into bs from b in bs.DefaultIfEmpty() join c in db.WX_SZZYORDER on o.LinkOrderId equals c.ORDERID into t1 from c in t1.DefaultIfEmpty() join d in db.RES_CUSTOMER on c.RESID equals d.RESID into t2 from d in t2.DefaultIfEmpty() select new AiCallTask_View { Robot = b.Robot, RobotName = robotName, Remark = remark, Id = b.Id, RESID = b.Resid, UMID= d.UMID, CallNo = d.LASTNUM3, CHANNEL = c.CHANNEL, CNAME = c.CNAME, AiStatus = b.ai_hgrecord_status, AiStatusName = b.ai_hgrecord_statusname, StartTime = b.StartTime, EndTime = b.EndTime, Audio = b.Audio, SvcTime = b.SvcTime, HasCall= b.hascall, HasCallName = b.hascall == null || b.hascall == 0?"否":"是", Ctime = b.Ctime, Rounds = b.Rounds == null ? 0:b.Rounds.Value }; if (!string.IsNullOrEmpty(dto.robot)&&dto.robot != "-3") { queryData = queryData.Where(n => n.Robot == dto.robot); } if(dto.robot == "-3") { var containRobot = robotList.Select(n => n.Robot).ToList(); queryData = queryData.Where(n => containRobot.Contains(n.Robot)); } if (!string.IsNullOrEmpty(dto.robotRemark)) { queryData = queryData.Where(n => n.Remark == dto.robotRemark); } if (!string.IsNullOrEmpty(dto.cname)) { queryData = queryData.Where(m => m.CNAME == dto.cname); } if (dto.xstime.HasValue) { queryData = queryData.Where(n => n.Ctime >= dto.xstime); } if (dto.xetime.HasValue) { dto.xetime = dto.xetime.Value.AddDays(1); queryData = queryData.Where(n => n.Ctime <= dto.xetime); } if (!string.IsNullOrWhiteSpace(dto.resId)) { queryData = queryData.Where(m => m.RESID == dto.resId); //where = where.And(m => m.RESID == dto.resId); } if (!string.IsNullOrWhiteSpace(dto.UMID)) { queryData = queryData.Where(m => m.UMID == dto.UMID); //where = where.And(m => m.RESID == dto.resId); } if (dto.aistatus > -3) { /*if(dto.aistatus == (int) EnumAiCallState.Ai外呼取消) { queryData = queryData.Where(m => m.AiStatus == dto.aistatus || m.AiStatus == (int)EnumAiCallState.人工回访成功); } else { queryData = queryData.Where(m => m.AiStatus == dto.aistatus); }*/ queryData = queryData.Where(m => m.AiStatus == dto.aistatus); } if (dto.type == -1) { List containState = new List() { (int) EnumAiCallState.AI外呼成功, (int) EnumAiCallState.AI外呼失败未答完, (int) EnumAiCallState.AI外呼未接通, (int) EnumAiCallState.AI外呼失败挂断, }; queryData = queryData.Where(n => containState.Contains(n.AiStatus.Value)); } else { queryData = queryData.Where(n => n.AiStatus.Value != (int)EnumAiCallState.人工回访成功); } if (!string.IsNullOrWhiteSpace(dto.RobotId)) { queryData = queryData.Where(n => n.Robot == dto.RobotId); } if (dto.hasCall > 0) { queryData = queryData.Where(n => n.HasCall == dto.hasCall); } queryData = queryData.OrderByDescending(n => n.Ctime); PagerUtil.SetPager(ref queryData, ref pager); var list = queryData.ToList(); stopwatch.Stop(); LogHelper.Info($"Ai日志用时 {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); var taskIds = list.Select(n => n.Id).ToList(); var orderTaskList = db.Csvr_Ai_CallTask_Orders.Where(n => taskIds.Contains(n.Taskid.Value)).ToList(); var orderidList = orderTaskList.Select(x => x.Orderid).ToList(); var orderList = db.WX_SZZYORDER.Where(n => orderidList.Contains(n.ORDERID)).ToList(); var companyList = cache_BL.GetCompanyVirtual(); foreach (var item in list) { var childOrder = orderTaskList.Where(n => n.Taskid.Value == item.Id).ToList(); item.ORDERID = string.Join(",", childOrder.Select(n => n.Orderid).ToList()); List channelList = new List(); var orderChannel = orderList.Where(n => childOrder.Select(x => x.Orderid).Contains(n.ORDERID)).Select(n=>n.CHANNEL).Distinct().ToList(); foreach(var channelitem in orderChannel) { channelList.Add(ConvertChannelName(companyList, channelitem)); } item.CHANNELNAME = string.Join(",",channelList); /*if (item.AiStatus == (int)EnumAiCallState.人工回访成功) { item.AiStatusName = EnumAiCallState.Ai外呼取消.ToString(); }*/ } stopwatch.Stop(); LogHelper.Info($"Ai列表日志用时 {stopwatch.ElapsedMilliseconds}ms"); return list; } } /// /// 转换事业部 /// /// /// /// private string ConvertChannelName(List channelList, int channel) { foreach (var item in channelList) { var channelStr = item.Channel.Split('|').ToList(); foreach (var str in channelStr) { var a = str.Split(','); var min = Convert.ToInt32(a[0]); var max = Convert.ToInt32(a[1]); if (channel >= min && channel <= max) { return item.CompanyName; } } } return ""; } public Csvr_Ai_CallTask GetModel(int? id) { using (var db = new zxdContext()) { var res = db.Csvr_Ai_CallTask.FirstOrDefault(n => n.Id == id); return res; } } public AiRecordDetailDto BuildAudioModel(int? id) { using (var db = new zxdContext()) { var record = db.Csvr_Ai_CallTask.FirstOrDefault(n => n.Id == id); if (record == null) { throw new Exception("找不到对应的数据"); } var robots = cache_BL.GetAiRobotList().FirstOrDefault(n => n.Robot == record.Robot); var data = new AiRecordDetailDto { robotName = robots?.RobotName, phoneNo = db.RES_CUSTOMER.FirstOrDefault(n => n.RESID == record.Resid)?.LASTNUM3, audio = record.Audio, sessionBeginTime = record.StartTime.Value.ToString("yyyy-MM-dd HH:mm:ss"), sessionEndTime = record.EndTime.Value.ToString("yyyy-MM-dd HH:mm:ss"), }; if (!string.IsNullOrWhiteSpace(record.Interact)) { data.logUserSessionDetailList = JsonConvert.DeserializeObject>(record.Interact); } return data; } } public List GetAudioByOrderId(decimal orderId) { var robotList = cache_BL.GetAiRobotList(); using (var db = new zxdContext()) { var robotName = robotList.FirstOrDefault()?.RobotName; var taskQuery = from n in db.Csvr_Ai_CallTask_Orders group n by n.Taskid into model let ids = model.Select(b => b.Orderid).ToList() select new { OrderId = ids, TaskId = model.Key }; var res = from b in db.Csvr_Ai_CallTask join a in taskQuery on b.Id equals a.TaskId where a.OrderId.ToList().Contains(orderId) select new AudioRecordView { Type = 2, RECORDID = b.Id, FILENAME = b.Audio, RESID = b.Resid, TIMELENGTH = b.SvcTime, SALESEID = b.Robot, TIMESTART = b.StartTime, TIMEEND = b.EndTime, ORDERID = orderId, CONTENT = b.Labels, Ctime = b.Ctime }; return res.ToList(); } } public List GetAiRecordSum(ref Laypage pager, AiRecordQueryDto dto) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var robotList = cache_BL.GetAiRobotList(); using (var db = new zxdContext()) { var robotName = robotList.FirstOrDefault()?.RobotName; var remark = robotList.FirstOrDefault()?.Remark; var sms = robotList.FirstOrDefault()?.SMS; var orderQuery = db.WX_SZZYORDER.AsQueryable(); List orderids = new List(); var hasOrderFilter = false; if (dto.orderId.HasValue) { orderQuery = orderQuery.Where(m => m.ORDERID == dto.orderId.Value); hasOrderFilter = true; } if (!string.IsNullOrEmpty(dto.cname)) { orderQuery = orderQuery.Where(m => m.CNAME == dto.cname); hasOrderFilter = true; } if (!string.IsNullOrEmpty(dto.channel)) { var arr0 = dto.channel.Split('|'); if (arr0.Length > 1) { var predicates = new List>>(); foreach (var item in arr0) { var a = item.Split(','); var min = Convert.ToInt32(a[0]); var max = Convert.ToInt32(a[1]); predicates.Add(m => m.CHANNEL >= min && m.CHANNEL <= max); } orderQuery = orderQuery.WhereOR(predicates.ToArray()); } else { var arr = dto.channel.Split(','); var min = Convert.ToInt32(arr[0]); var max = Convert.ToInt32(arr[1]); orderQuery = orderQuery.Where(m => m.CHANNEL >= min && m.CHANNEL <= max); } hasOrderFilter = true; } if (!string.IsNullOrWhiteSpace(dto.resId)) { orderQuery = orderQuery.Where(m => m.RESID == dto.resId); hasOrderFilter = true; } List aiExceptState = new List { (int)EnumAiCallState.Ai外呼取消, (int)EnumAiCallState.人工回访成功 }; //先筛选掉已经拨打的订单 /* var repeatOrder = db.Csvr_Ai_CallTask_Orders.GroupBy(n => n.Orderid).Where(n => n.Count() > 1).ToList(); List exceptTaskId = new List(); foreach(var item in repeatOrder) { var maxTaskId = item.Max(n=>n.Taskid); exceptTaskId.AddRange(item.Where(n => n.Taskid.Value != maxTaskId).Select(n => n.Taskid.Value).ToList()); }*/ if (hasOrderFilter) { orderids = orderQuery.Select(n => n.ORDERID).Distinct().ToList(); } var singleTaskQuery = db.Csvr_Ai_CallTask_Orders.GroupBy(n => n.Orderid).Select(n => n.Max(s => s.Taskid)); if (hasOrderFilter) { singleTaskQuery = db.Csvr_Ai_CallTask_Orders.Where(n => orderids.Contains(n.Orderid.Value)).GroupBy(n => n.Orderid).Select(n => n.Max(s => s.Taskid)); } var orderCountQuery = from n in db.Csvr_Ai_CallTask.AsQueryable() join b in singleTaskQuery on n.Id equals b group b by b into model select new { taskid = model.Key, count = model.Count() }; var taskQuery = from n in db.Csvr_Ai_CallTask.AsQueryable() join b in orderCountQuery on n.Id equals b.taskid select new { Robot = n.Robot, Status = n.Status, ai_hgrecord_status = n.ai_hgrecord_status, CallRet = n.CallRet, Labels = n.Labels, OrderCount = b.count, Ctime = n.Ctime }; if (dto.xstime.HasValue) { taskQuery = taskQuery.Where(n => n.Ctime >= dto.xstime); } if (dto.xetime.HasValue) { dto.xetime = dto.xetime.Value.AddDays(1); taskQuery = taskQuery.Where(n => n.Ctime <= dto.xetime); } var query = taskQuery.GroupBy(n => n.Robot).Select(model => new AiRecordSumView { Robot = model.Key, RobotName = robotName, Remark = remark, Sms = sms == "1" ? "是" : "否", UnConnectCount = model.Where(n => n.Status == 2 && n.CallRet != "0").Count(), WaitCount = model.Where(n => n.Status != 2 && !aiExceptState.Contains(n.ai_hgrecord_status)).Count(), DoneCount = model.Where(n => n.Status == 2).Count(), CallCount = model.Where(n => n.CallRet == "0").Count(), SuccessCount = model.Where(n => n.CallRet == "0" && n.Labels.Contains("正常访问")).Count(), WaitOrder = model.Where(n => n.Status != 2 && !aiExceptState.Contains(n.ai_hgrecord_status)).Sum(n => n.OrderCount), DoneOrder = model.Where(n => n.Status == 2).Sum(n => n.OrderCount), CallOrder = model.Where(n => n.CallRet == "0").Sum(n => n.OrderCount), SuccessOrder = model.Where(n => n.CallRet == "0" && n.Labels.Contains("正常访问")).Sum(n => n.OrderCount), FailConnectCount = model.Where(n => n.ai_hgrecord_status == (int)EnumAiCallState.AI外呼失败挂断).Count(), FailCount = model.Where(n => n.ai_hgrecord_status == (int)EnumAiCallState.AI外呼失败未答完).Count() } ); if (dto.robot == "-3") { var robotIds = robotList.Select(x => x.Robot).ToList(); //var robotFilter = orderQuery.Where(n => robotIds.Contains(n.Robot)).Select(s => s.Robot).ToList(); query = query.Where(n => robotIds.Contains(n.Robot)); } else { var robotFilter = robotList.Where(n => n.Robot ==dto.robot).Select(s => s.Robot).ToList(); query = query.Where(n => robotFilter.Contains(n.Robot)); } if (!string.IsNullOrWhiteSpace(dto.robotRemark)) { var remarkFilter = robotList.Where(n => n.Remark == dto.robotRemark).Select(n => n.Robot).ToList(); //var robotFilter = orderQuery.Where(n => remarkFilter.Contains(n.Robot)).Select(s => s.Robot).ToList(); query = query.Where(n => remarkFilter.Contains(n.Robot)); } PagerUtil.SetPager(ref query, ref pager); var list = query.ToList(); stopwatch.Stop(); LogHelper.Info($"Ai统计查询耗时{stopwatch.ElapsedMilliseconds}ms]"); foreach (var item in list) { item.CallPercent = (item.DoneCount == 0 ? 0 : Math.Round(Convert.ToDecimal(item.CallCount) / item.DoneCount, 2) * 100) + "%"; item.SuccessPercent = (item.CallCount == 0 ? 0 : Math.Round(Convert.ToDecimal(item.SuccessCount) / item.CallCount, 2) * 100) + "%"; item.SuccessOrderPercent = (item.DoneOrder == 0 ? 0 : Math.Round(Convert.ToDecimal(item.SuccessOrder) / item.DoneOrder, 2) * 100) + "%"; item.CallCompletePercent = (item.DoneCount == 0 ? 0 : Math.Round(Convert.ToDecimal(item.SuccessCount) / item.DoneCount, 2) * 100) + "%"; item.OrderCompletePercent = (item.CallOrder == 0 ? 0 : Math.Round(Convert.ToDecimal(item.SuccessOrder) / item.CallOrder, 2) * 100) + "%"; } return list; } } } public class AiCallTask_View { [DisplayName("任务Id")] public int Id { get; set; } public string sid { get; set; } [DisplayName("机器人Id")] public string Robot { get; set; } [DisplayName("AI话术")] public string RobotName { get; set; } [DisplayName("任务描述")] public string Remark { get; set; } [DisplayName("订单号")] public string ORDERID { get; set; } //public string Name { get; set; } /// /// 电话 /// [DisplayName("电话号码")] public string CallNo { get; set; } [DisplayName("事业部")] public int CHANNEL { get; set; } [DisplayName("事业部")] public string CHANNELNAME { get; set; } [DisplayName("客户编号")] public string RESID { get; set; } [DisplayName("客户新编号")] public string UMID { get; set; } [DisplayName("客户姓名")] public string CNAME { get; set; } public int? AiStatus { get; set; } [DisplayName("回访状态")] public string AiStatusName { get; set; } [DisplayName("外呼时长(秒)")] public int? SvcTime { get; set; } [DisplayName("外呼时间")] public DateTime? StartTime { get; set; } [DisplayName("挂机时间")] public DateTime? EndTime { get; set; } [DisplayName("录音")] public string Audio { get; set; } [DisplayName("是否重拨")] public int? HasCall { get; set; } [DisplayName("是否重拨")] public string HasCallName { get; set; } public DateTime? Ctime { get; set; } [DisplayName("轮次")] public int Rounds { get; set; } /*public string OrderIdList { get; set; }*/ /* public int? ReTryCount { get; set; }*/ } public class AiCallTaskExportView:AiCallTaskDetailExportView { [DisplayName("AI话术")] public string RobotName { get; set; } [DisplayName("任务描述")] public string Remark { get; set; } } public class AiCallTaskDetailExportView { /// /// 电话 /// [DisplayName("用户号码")] public string CallNo { get; set; } [DisplayName("事业部")] public string CHANNELNAME { get; set; } [DisplayName("客户Id")] public string RESID { get; set; } [DisplayName("客户姓名")] public string CNAME { get; set; } [DisplayName("订单号")] public string ORDERID { get; set; } //public string Name { get; set; } [DisplayName("AI外呼状态")] public string AiStatusName { get; set; } [DisplayName("录音编号")] public decimal Id { get; set; } [DisplayName("外呼时长")] public int? SvcTime { get; set; } [DisplayName("是否重拨")] public string HasCallName { get; set; } [DisplayName("对话轮次")] public int Rounds { get; set; } [DisplayName("外呼时间")] public DateTime? StartTime { get; set; } [DisplayName("挂机时间")] public DateTime? EndTime { get; set; } [DisplayName("录音")] public string Audio { get; set; } } public class AiRecordQueryDto { /// /// 事业部 /// public string channel { get; set; } /// /// 客户id /// public string resId { get; set; } public string UMID { get; set; } /// /// 订单号 /// public decimal? orderId { get; set; } public string cname { get; set; } public int aistatus { get; set; } = -3; /// /// 默认全部 /// public int type { get; set; } = -3; public string RobotId { get; set; } = ""; public int hasCall { get; set; } = -3; public DateTime? xstime { get; set; } public DateTime? xetime { get; set; } public string robot { get; set; } = "-3"; public string robotRemark { get; set; } } public class AiRecordSumView { public string Robot { get; set; } public string RobotName { get; set; } public string Remark { get; set; } public int WaitCount { get; set; } public int DoneCount { get; set; } public int UnConnectCount { get; set; } public int FailCount { get; set; } public int FailConnectCount { get; set; } public string CallPercent { get; set; } public string SuccessPercent { get; set; } public int SuccessCount { get; set; } public int CallCount { get; set; } public string Sms { get; set; } public int WaitOrder { get; set; } public int DoneOrder { get; set; } public int CallOrder { get; set; } public int SuccessOrder { get; set; } public string SuccessOrderPercent { get; set; } /// /// 外呼完成率(外呼成功人次/已外呼人次) /// public string CallCompletePercent { get; set; } /// /// 订单成功率(已成功订单数/已接通订单数) /// public string OrderCompletePercent { get; set; } } /// /// 录音列表 /// public class AiRecordDetailDto { public string robotId { get; set; } public string robotName { get; set; } public string phoneNo { get; set; } public string audio { get; set; } public string sessionBeginTime { get; set; } public string sessionEndTime { get; set; } public List logUserSessionDetailList { get; set; } } public class MsgContent { public DateTime Time { get; set; } public string Type { get; set; } public string Content { get; set; } public string Nodeid { get; set; } public string Nodename { get; set; } public string Ugc { get; set; } } public class AudioRecordView { /// /// 默认为普通录音 /// public int Type { get; set; } = 1; public decimal? RECORDID { get; set; } public string sid { get; set; } public string FILENAME { get; set; } public string RESID { get; set; } public decimal? TIMELENGTH { get; set; } public string SALESEID { get; set; } public DateTime? TIMESTART { get; set; } public DateTime? TIMEEND { get; set; } public decimal? ORDERID { get; set; } public string CONTENT { get; set; } public DateTime? Ctime { get; set; } public string COMPANYCODE { get; set; } } public class OrderTaskDto { public string Robot { get; set; } public decimal ORDERID { get; set; } public string CNAME { get; set; } public int CHANNEL { get; set; } public string RESID { get; set; } public int? Taskid { get; set; } } public class GroupTask { public decimal TaskId { get; set; } public decimal LinkOrderId { get; set; } } }