Procházet zdrojové kódy

Merge branch 'feature_aivisit' of Fengwo/hotline into dev

dengshengshuang před 11 měsíci
rodič
revize
5200017f90

+ 2 - 2
src/Hotline.Ai.Jths/AiJthsStartupExtensions.cs

@@ -18,9 +18,9 @@ namespace Hotline.Ai.Jths
 			return services;
 		}
 
-		public static IServiceCollection AddAiVisitService(this IServiceCollection services,string baseUrl,string appkey,string serviceversion,string sceneuid,string ruleuid,string visitFromNameKey,string visitFromGenderKey,string visitCreationTimeKey,string visitOrderTitleKey)
+		public static IServiceCollection AddAiVisitService(this IServiceCollection services,string baseUrl,string appkey,string serviceversion,string sceneuid,string ruleuid,string visitFromNameKey,string visitFromGenderKey,string visitCreationTimeKey,string visitOrderTitleKey,string visitIsCallOrderKey)
 		{
-			services.AddSingleton<IAiVisitService, AiVisitService>(_ => new AiVisitService(baseUrl, appkey, serviceversion, sceneuid, ruleuid,visitFromNameKey,visitFromGenderKey,visitCreationTimeKey,visitOrderTitleKey));
+			services.AddSingleton<IAiVisitService, AiVisitService>(_ => new AiVisitService(baseUrl, appkey, serviceversion, sceneuid, ruleuid,visitFromNameKey,visitFromGenderKey,visitCreationTimeKey,visitOrderTitleKey,visitIsCallOrderKey));
 			return services;
 		}
 	}

+ 45 - 1
src/Hotline.Ai.Jths/AiVisitConfig.cs

@@ -9,18 +9,62 @@ namespace Hotline.Ai.Jths
         public string SceneUid { get; set; }
         public string RuleUid { get;set; }
 
+        /// <summary>
+        /// 来电名称
+        /// </summary>
         public string VisitFromNameKey { get; set; }
 
+
+        /// <summary>
+        /// 来电性别
+        /// </summary>
         public string VisitFromGenderKey { get; set; }
 
+        /// <summary>
+        /// 来电时间
+        /// </summary>
         public string VisitCreationTimeKey { get; set; }
 
+        /// <summary>
+        /// 工单标题
+        /// </summary>
         public string VisitOrderTitleKey { get; set; }
 
+        /// <summary>
+        /// 是否来电工单
+        /// </summary>
+        public string VisitIsCallOrder { get; set; }
+
+        /// <summary>
+        /// 是否联系
+        /// </summary>
+        public string QuestionIdZone { get; set; }
+
+
+        /// <summary>
+        /// 是否解决
+        /// </summary>
         public string QuestionIdOne { get; set; }
 
+        /// <summary>
+        /// 办件结果满意度
+        /// </summary>
         public string QuestionIdTwo { get; set;}
 
-        public string VisitContentId { get; set; }
+        /// <summary>
+        /// 坐席是否满意
+        /// </summary>
+        public string QuestionIdThree { get; set; }
+
+        /// <summary>
+        /// 办件结果不满意原因
+        /// </summary>
+        public string VisitContentIdOne { get; set; }
+
+        /// <summary>
+        /// 坐席不满意原因
+        /// </summary>
+        public string VisitContentIdTwo { get; set;}
+
     }
 }

+ 13 - 3
src/Hotline.Ai.Jths/AiVisitService.cs

@@ -27,8 +27,9 @@ namespace Hotline.Ai.Jths
         private readonly string _visitFromGenderKey;
         private readonly string _visitCreationTimeKey;
         private readonly string _visitOrderTitleKey;
+        private readonly string _visitIsCallOrderKey;
 
-        public AiVisitService(string baseUrl, string appkey, string serviceversion, string sceneuid, string ruleuid,string visitFromNameKey,string visitFromGenderKey,string visitCreationTimeKey,string visitOrderTitleKey)
+        public AiVisitService(string baseUrl, string appkey, string serviceversion, string sceneuid, string ruleuid,string visitFromNameKey,string visitFromGenderKey,string visitCreationTimeKey,string visitOrderTitleKey,string visitIsCallOrderKey)
         {
             _baseUrl = baseUrl;
             _appkey = appkey;
@@ -39,6 +40,7 @@ namespace Hotline.Ai.Jths
             _visitFromGenderKey = visitFromGenderKey;
             _visitCreationTimeKey = visitCreationTimeKey;
             _visitOrderTitleKey = visitOrderTitleKey;
+            _visitIsCallOrderKey = visitIsCallOrderKey;
             var options = new RestClientOptions(_baseUrl);
             _client = new RestClient(options);
         }
@@ -68,20 +70,29 @@ namespace Hotline.Ai.Jths
                 {
                     if (!string.IsNullOrEmpty(item.Order.FromName))
                     {
+                        //来电名称
                         //开发环境 :OC_SCENE_VAR_FIELD11
                         //生产环境:OC_SCENE_VAR_FIELD12
                         taskData.VariableList.Add(new Variable() { Code = _visitFromNameKey, Value = item.Order.FromName });
                     }
+                    //来电性别
                     //开发环境: OC_SCENE_VAR_FIELD14
                     //生产环境:OC_SCENE_VAR_FIELD14
                     taskData.VariableList.Add(new Variable() { Code = _visitFromGenderKey, Value = item.Order.FromGender == EGender.Female ? "女士" : "先生" });
                 }
+                //来电时间
                 //开发环境:OC_SCENE_VAR_FIELD17
                 //生产环境:OC_SCENE_VAR_FIELD19
                 taskData.VariableList.Add(new Variable() { Code = _visitCreationTimeKey, Value = item.Order.CreationTime.ToString("yyyy年MM月dd日hh点mm分") });
+                //工单标题
                 //开发环境:OC_SCENE_VAR_FIELD18
                 //生产环境:OC_SCENE_VAR_FIELD20
                 taskData.VariableList.Add(new Variable() { Code = _visitOrderTitleKey, Value = item.Order.Title });
+
+                //是否来电工单
+                //开发环境:
+                //生产环境:
+                taskData.VariableList.Add(new Variable() { Code = _visitIsCallOrderKey, Value = item.Order.SourceChannelCode == "RGDH" ? "income" : "outbound" });
                 taskDataList.Add(taskData);
             }
             requestData.TaskDataList = taskDataList;
@@ -101,7 +112,6 @@ namespace Hotline.Ai.Jths
                     else
                     {
                         aiOrderVisit.AiOrderVisitDetails[i].AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.LoseEfficacy;
-                        //处理回访状态TODO
                     }
                 }
             }
@@ -113,7 +123,7 @@ namespace Hotline.Ai.Jths
         {
             var dto = new AiVisitServiceQueryRequest() { BatchUid = batchId, TaskUid = taskId,PageNo=1, PageSize=100 };
             var response = await ExecuteAsync<AiVisitServiceQueryRequest, AiVisitServiceQueryResponse>(_baseUrl + "/edas/task/status/real", Method.Get, dto, cancellationToken);
-            if (response!=null && response.Result.Result.Count>0)
+            if (response!=null && response.Result!=null && response.Result.Result.Count>0)
             {
                 return new AiVisitQueryData() { Uid = response.Result.Result[0].Uid, Status = response.Result.Result[0].Status };
             }

+ 101 - 26
src/Hotline.Api/Controllers/AiController.cs

@@ -20,9 +20,11 @@ using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
 using Newtonsoft.Json;
+using SqlSugar;
 using System.Threading;
 using XF.Domain.Authentications;
 using XF.Domain.Constants;
+using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
 namespace Hotline.Api.Controllers
@@ -124,70 +126,123 @@ namespace Hotline.Api.Controllers
                     var aiOrderVisitDetail = aiOrderVisit.AiOrderVisitDetails.FirstOrDefault(x => x.TaskUid == dto.TaskUid);
                     if (aiOrderVisitDetail != null)
                     {
+                        var callRecord = dto.CallRecordList.OrderBy(x => x.CallStartTime).LastOrDefault();
                         // 回访结果(ReturnVisit)[1成功、0不涉及、-1失败]
-                        var callRecord = dto.CallRecordList.OrderByDescending(x => x.CallNo).FirstOrDefault(x => x.ReturnVisit == 1);
+                       
                         if (callRecord != null) //有结果的任务
                         {
                             aiOrderVisitDetail.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.Ended; //更新AI子表
                             aiOrderVisitDetail.AiVisitTime = DateTime.Now;
                             aiOrderVisit.VisitedCount++;
                             //处理结果
-                            var visitDetail = _orderVisitDetailRepository.Queryable().Where(x => x.VisitId == aiOrderVisitDetail.OrderVisit.Id);
+                            var visitDetail = _orderVisitDetailRepository.Queryable().Where(x => x.VisitId == aiOrderVisitDetail.OrderVisit.Id).ToList();
                             //先处理子表
-                            //先处理坐席(因没有坐席回访,所以默认满意)
-                            var seatDetail = visitDetail.First(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Seat);
-                            if (seatDetail != null)
-                            {
-                                seatDetail.VoiceEvaluate = Share.Enums.Order.EVoiceEvaluate.Satisfied;
-                                seatDetail.SeatEvaluate = Share.Enums.Order.ESeatEvaluate.Satisfied;
-                            }
-                            await _orderVisitDetailRepository.UpdateAsync(seatDetail, HttpContext.RequestAborted);
+
                             //处理部门
                             var orgDetail = visitDetail.Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Org).ToList();
                             //过滤结果
                             var orgProcessingResults = new Kv();
                             var orgHandledAttitude = new Kv();
+                            ESeatEvaluate? seatEvaluate = null;
                             var visitContent = "";
+                            var seatVisitContent = "";
+                            var volveConent = "";
+                            bool? isSolve =  null;
+                            bool? isContact = null;
+                            //通话录音
+                            var recordUrl = callRecord.RecordUrl;
                             foreach (var item in callRecord.QuestionnaireResult)
                             {
-                                //服务过程满意度
+                                ////服务过程满意度
+                                //if (item.QuestionId == _options.Value.QuestionIdOne)
+                                //{
+                                //    if (item.QuestionResult == "满意")
+                                //    {
+                                //        orgHandledAttitude = new Kv() { Key="4", Value="满意" };
+                                //    }
+                                //    else
+                                //    {
+                                //        orgHandledAttitude = new Kv() { Key = "2", Value = "不满意" };
+
+                                //    }
+                                //}
+                                //是否联系
+                                if (item.QuestionId == _options.Value.QuestionIdZone)
+                                {
+                                    if (item.QuestionResult == "有联系")
+                                    {
+                                        isContact = true;
+                                    }
+                                    else if(item.QuestionResult == "没有联系")
+                                    {
+                                        isContact = false;
+                                    }
+                                }
+                                //是否解决
                                 if (item.QuestionId == _options.Value.QuestionIdOne)
                                 {
-                                    if (item.QuestionResult == "满意")
+                                    if (item.QuestionResult == "得到解决")
                                     {
-                                        orgHandledAttitude = new Kv() { Key="4", Value="满意" };
+                                        isSolve = true;
                                     }
-                                    else
+                                    else if(item.QuestionResult == "未得到解决")
                                     {
-                                        orgHandledAttitude = new Kv() { Key = "2", Value = "不满意" };
-                                      
+                                        isSolve = false;
                                     }
                                 }
                                 //办件结果满意度
                                 if (item.QuestionId == _options.Value.QuestionIdTwo)
                                 {
-                                    if (item.QuestionResult == "满意")
+                                    if (item.QuestionResult == "办件结果满意")
                                     {
                                         orgProcessingResults = new Kv() { Key = "4", Value = "满意" };
                                     }
-                                    else
+                                    else if(item.QuestionResult == "办件结果不满意")
                                     {
                                         orgProcessingResults = new Kv() { Key = "2", Value = "不满意" };
-                                        visitContent = callRecord.SceneVariable[_options.Value.VisitContentId];
+                                        visitContent = callRecord.SceneVariable[_options.Value.VisitContentIdOne];
                                     }
                                 }
                                 else
                                 {
                                     aiOrderVisitDetail.OrderVisit.VisitState = Share.Enums.Order.EVisitState.WaitForVisit;
                                 }
+
+                                //坐席是否满意
+                                if (item.QuestionId == _options.Value.QuestionIdThree)
+                                {
+                                    if (item.QuestionResult == "满意接电坐席")
+                                    {
+                                        seatEvaluate = ESeatEvaluate.Satisfied;
+                                    }
+                                    else if(item.QuestionResult == "不满意接电坐席")
+                                    {
+                                        seatEvaluate = ESeatEvaluate.NoSatisfied;
+                                        seatVisitContent = callRecord.SceneVariable[_options.Value.VisitContentIdTwo];
+                                    }
+                                }
                             }
+
+                            //先处理坐席(因没有坐席回访,所以默认满意)
+                            var seatDetail = visitDetail.Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Seat).ToList();
+                            seatDetail.ForEach(x =>
+                            {
+                                x.VoiceEvaluate = Share.Enums.Order.EVoiceEvaluate.Satisfied;
+                                x.SeatEvaluate = seatEvaluate;
+                                x.VisitContent = seatVisitContent;
+                            });
+                           
+                            await _orderVisitDetailRepository.UpdateRangeAsync(seatDetail, HttpContext.RequestAborted);
+
                             //处理结果
                             orgDetail.ForEach(x =>
                             {
                                 x.OrgHandledAttitude = orgHandledAttitude;
                                 x.OrgProcessingResults = orgProcessingResults;
                                 x.VisitContent = visitContent;
-                                if (orgProcessingResults.Value == "不满意")
+                                x.Volved = isSolve;
+                                x.IsContact = isContact;
+                                if (orgProcessingResults.Value == "不满意" || (string.IsNullOrEmpty(orgProcessingResults.Key) && seatEvaluate!=null && isSolve!=null && isContact!=null))
                                 {
                                     //x.OrgNoSatisfiedReason = new List<Kv>() { new Kv() { Key = "7", Value = "未回复" } };
                                     //TODO 记录不满意原因到内容中供人工回访甄别选择不满意原因
@@ -212,6 +267,9 @@ namespace Hotline.Api.Controllers
                             {
                                 aiOrderVisitDetail.OrderVisit.NowEvaluate = orgProcessingResults;
                             }
+                            //处理是否回访完成TODO
+
+
                             await _orderVisitRepository.UpdateAsync(aiOrderVisitDetail.OrderVisit, HttpContext.RequestAborted);
 
                             //处理Order表
@@ -230,7 +288,7 @@ namespace Hotline.Api.Controllers
                                     VisitType = aiOrderVisitDetail.OrderVisit.VisitType,
                                     VisitName = aiOrderVisitDetail.OrderVisit.CreatorName,
                                     VisitTime = aiOrderVisitDetail.OrderVisit.VisitTime,
-                                    VisitRemark = string.IsNullOrEmpty(visitContent)?aiOrderVisitDetail.OrderVisit.NowEvaluate?.Value: visitContent,
+                                    VisitRemark = string.IsNullOrEmpty(visitContent) ? aiOrderVisitDetail.OrderVisit.NowEvaluate?.Value : visitContent,
                                     AreaCode = aiOrderVisitDetail.OrderVisit.Order.AreaCode!,
                                     SubjectResultSatifyCode = orgProcessingResults.Key,
                                     FirstSatisfactionCode = aiOrderVisitDetail.OrderVisit.Order.FirstVisitResultCode!,
@@ -261,6 +319,8 @@ namespace Hotline.Api.Controllers
                             aiOrderVisitDetail.IsSuccess = false;
                             await _orderVisitRepository.UpdateAsync(aiOrderVisitDetail.OrderVisit, HttpContext.RequestAborted);
                         }
+                        //var callRecord = dto.CallRecordList.OrderByDescending(x => x.CallNo).FirstOrDefault(x => x.ReturnVisit == 1);
+                       
                         
                         await _aiOrderVisitDetailRepository.UpdateAsync(aiOrderVisitDetail, HttpContext.RequestAborted);
                         if ((aiOrderVisit.VisitedFailCount+aiOrderVisit.VisitedCount)== aiOrderVisit.HasVisitCount)
@@ -414,6 +474,12 @@ namespace Hotline.Api.Controllers
         [HttpPost("aivisit/add-aivisit")]
         public async Task AddAiVisit([FromBody]AddAiVisitDto dto)
         {
+            //验证是否有重复电话
+            if(dto.AiOrderVisitDetails.Distinct().Count() != dto.AiOrderVisitDetails.Count)
+            {
+                throw UserFriendlyException.SameMessage("任务中存在重复外呼号码,请检查后重新提交");
+            }
+
             var model = _mapper.Map<AiOrderVisit>(dto);
 
             var detaillist = _mapper.Map<List<AiOrderVisitDetail>>(dto.AiOrderVisitDetails);
@@ -432,11 +498,7 @@ namespace Hotline.Api.Controllers
                 x.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.InProgress;
             });
             await _aiOrderVisitDetailRepository.AddRangeAsync(detaillist, HttpContext.RequestAborted);
-            //修改回访主表
-             await _orderVisitRepository.Updateable()
-                .SetColumns(x => x.IsCanAiVisit == false)
-                .SetColumns(x=> x.VisitState == EVisitState.Visiting)
-                .Where(x=> detaillist.Select(s=>s.OrderVisitId).Contains(x.Id)).ExecuteCommandAsync(HttpContext.RequestAborted);
+            
             //推送任务
             //准备原始数据
             var pushModel = await _aiOrderVisitRepository.Queryable()
@@ -445,6 +507,19 @@ namespace Hotline.Api.Controllers
                 .FirstAsync(x => x.Id == id);
             
             var newModel = await _aiVisitService.CreateAiOrderVisitTask(pushModel, HttpContext.RequestAborted);
+
+            if (!string.IsNullOrEmpty(newModel.BatchUid))
+            {
+                //修改回访主表
+                await _orderVisitRepository.Updateable()
+                   .SetColumns(x => x.IsCanAiVisit == false)
+                   .SetColumns(x => x.VisitState == EVisitState.Visiting)
+                   .Where(x => detaillist.Select(s => s.OrderVisitId).Contains(x.Id)).ExecuteCommandAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                newModel.TaskState = Share.Enums.Ai.EAiOrderVisitTaskState.Ended;
+            }
             await _aiOrderVisitRepository.UpdateAsync(newModel, HttpContext.RequestAborted);
             await _aiOrderVisitDetailRepository.UpdateRangeAsync(newModel.AiOrderVisitDetails, HttpContext.RequestAborted);
         }

+ 1 - 1
src/Hotline.Api/Controllers/OrderController.cs

@@ -679,7 +679,7 @@ public class OrderController : BaseController
             SeatEvaluate = seatEvaluate,
             RecordingFileUrl = recordingFileUrl,
             RecordingBaseAddress = recordingBaseAddress,
-            RecordingAbsolutePath = recordingAbsolutePath
+            RecordingAbsolutePath = recordingAbsolutePath,
         };
     }
 

+ 11 - 1
src/Hotline.Api/StartupExtensions.cs

@@ -112,7 +112,17 @@ internal static class StartupExtensions
         services.AddYbEnterpriseSdk(enterpriseConfig?.AddressUrl);
   
         var aiVisitConfig = configuration.GetSection("AiVisit").Get<AiVisitConfig>();
-        services.AddAiVisitService(aiVisitConfig.Url, aiVisitConfig.Appkey, aiVisitConfig.ServiceVersion, aiVisitConfig.SceneUid, aiVisitConfig.RuleUid,aiVisitConfig.VisitFromNameKey,aiVisitConfig.VisitFromGenderKey,aiVisitConfig.VisitCreationTimeKey,aiVisitConfig.VisitOrderTitleKey);
+        services.AddAiVisitService(
+            aiVisitConfig.Url, 
+            aiVisitConfig.Appkey, 
+            aiVisitConfig.ServiceVersion, 
+            aiVisitConfig.SceneUid, 
+            aiVisitConfig.RuleUid,
+            aiVisitConfig.VisitFromNameKey,
+            aiVisitConfig.VisitFromGenderKey,
+            aiVisitConfig.VisitCreationTimeKey,
+            aiVisitConfig.VisitOrderTitleKey,
+            aiVisitConfig.VisitIsCallOrder);
 
         //sqlsugar
         services.AddSqlSugar(configuration);

+ 15 - 10
src/Hotline.Api/config/appsettings.Development.json

@@ -205,18 +205,23 @@
   },
   //智能回访
   "AiVisit": {
-    "Url": "http://118.121.201.140:19061",
+    "Url": "http://118.122.73.80:19061",
     "Appkey": "MTAwMDAx",
     "ServiceVersion": "V1.0.0", //接口版本号
-    "SceneUid": "MTAwMDAxM4yRrAE5SsihkQkKuyMwM", //场景ID
-    "RuleUid": "MTAwMDAxSGdDJryoQUgoDeiKlsTEyc", //现有规则ID
-    "VisitFromNameKey": "OC_SCENE_VAR_FIELD11", //来电名称       //开发环境 :OC_SCENE_VAR_FIELD11   //生产环境:OC_SCENE_VAR_FIELD12
-    "VisitFromGenderKey": "OC_SCENE_VAR_FIELD14", //来电性别     //开发环境: OC_SCENE_VAR_FIELD14   //生产环境:OC_SCENE_VAR_FIELD14
-    "VisitCreationTimeKey": "OC_SCENE_VAR_FIELD17", //来电时间   //开发环境:OC_SCENE_VAR_FIELD17    //生产环境:OC_SCENE_VAR_FIELD19
-    "VisitOrderTitleKey": "OC_SCENE_VAR_FIELD18", //工单标题      //开发环境:OC_SCENE_VAR_FIELD18    //生产环境:OC_SCENE_VAR_FIELD20
-    "QuestionIdOne": "MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM", //服务过程满意度 //开发环境:MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM  //生产环境:MTAwMDAxvgT-2PoYRR8pxyL4p8AJsM
-    "QuestionIdTwo": "MTAwMDAxWQWym04VSRwn4dmWKnYEsQ", //办件结果满意度 //开发环境:MTAwMDAxWQWym04VSRwn4dmWKnYEsQ  //生产环境:MTAwMDAxhIyRJzpwTskpsiXPD-uwl0
-    "VisitContentId": "NotSat2" //不满意原因 // 开发环境:NotSat2   //生产环境:NotSat2
+    "SceneUid": "MTAwMDAxVW7cUNRwRegsLGqb0pvXCU", //场景ID
+    "RuleUid": "MTAwMDAxUbQsuOcmS5ApRyHGyWQr7g", //现有规则ID
+    "VisitFromNameKey": "OC_SCENE_VAR_FIELD14", //来电名称       //开发环境 :OC_SCENE_VAR_FIELD14  //生产环境:OC_SCENE_VAR_FIELD12
+    "VisitFromGenderKey": "OC_SCENE_VAR_FIELD13", //来电性别     //开发环境: OC_SCENE_VAR_FIELD13   //生产环境:OC_SCENE_VAR_FIELD14
+    "VisitCreationTimeKey": "OC_SCENE_VAR_FIELD15", //来电时间   //开发环境:OC_SCENE_VAR_FIELD15    //生产环境:OC_SCENE_VAR_FIELD19
+    "VisitOrderTitleKey": "OC_SCENE_VAR_FIELD16", //工单标题      //开发环境:OC_SCENE_VAR_FIELD16    //生产环境:OC_SCENE_VAR_FIELD20
+    "VisitIsCallOrder": "OC_SCENE_VAR_FIELD17", //是否来电工单 //开发环境:OC_SCENE_VAR_FIELD17          //生产环境:
+    //"QuestionIdOne": "MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM", //服务过程满意度 //开发环境:MTAwMDAxK1F9Qnu-QXYolr9JoOI8fM  //生产环境:MTAwMDAxvgT-2PoYRR8pxyL4p8AJsM
+    "QuestionIdZone": "MTAwMDAxvpXEOVcRQR0meGKouw6oXU", //是否联系  //开发环境:MTAwMDAxvpXEOVcRQR0meGKouw6oXU    //测试环境:
+    "QuestionIdOne": "MTAwMDAxP2AJqUCvTU4jsgzvRkADVo", //是否解决 , //开发环境:MTAwMDAxP2AJqUCvTU4jsgzvRkADVo   //生产环境:
+    "QuestionIdTwo": "MTAwMDAx_mLpLD0hSyosIwvgW-byjg", //办件结果满意度 //开发环境:MTAwMDAx_mLpLD0hSyosIwvgW-byjg  //生产环境:MTAwMDAxhIyRJzpwTskpsiXPD-uwl0
+    "QuestionIdThree": "MTAwMDAxos3PXU5TTzEnXMSU8GeApc", //坐席是否满意  //开发环境:  //生产环境:
+    "VisitContentIdOne": "reason1", //办件结果不满意原因 // 开发环境:NotSat2   //生产环境:NotSat2
+    "VisitContentIdTwo": "reason2", //坐席不满意原因  // 开发环境:    //生产环境:
   },
   //智能质检
   "AiQuality": {

+ 7 - 0
src/Hotline.Share/Dtos/Ai/AiDto.cs

@@ -42,6 +42,13 @@ namespace Hotline.Share.Dtos.Ai
         /// </summary>
         public int CallStatus { get; set; }
 
+        /// <summary>
+        /// 拨通时间
+        /// </summary>
+        public DateTime CallStartTime { get; set; }
+
+        public string? RecordUrl { get; set; }
+
         /// <summary>
         /// 回访结果 (1成功、2:不涉及、3:失败)
         /// </summary>

+ 14 - 1
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -119,6 +119,11 @@ namespace Hotline.Share.Dtos.Order
         /// </summary>
         public bool? Volved { get; set; }
 
+        /// <summary>
+        /// 未解决备注
+        /// </summary>
+        public string? VolveConent { get; set; }
+
         /// <summary>
         /// 回访内容
         /// </summary>
@@ -353,7 +358,10 @@ namespace Hotline.Share.Dtos.Order
 
         public Kv? NowEvaluate { get; set; }
 
-
+        /// <summary>
+        /// 智能回访录音地址
+        /// </summary>
+        public string? RecordUrl { get; set; }
     }
 
     public class OrderVisitDetailDto
@@ -442,6 +450,11 @@ namespace Hotline.Share.Dtos.Order
         /// 回访对象类型 10:话务员 20:部门
         /// </summary>
         public EVisitTarget VisitTarget { get; set; }
+
+        /// <summary>
+        /// 未解决备注
+        /// </summary>
+        public string? VolveConent { get; set; }
     }
 
     public class DistributionVisitRspDto

+ 5 - 0
src/Hotline/Orders/OrderVisit.cs

@@ -120,6 +120,11 @@ public class OrderVisit : CreationEntity
     [SugarColumn( DefaultValue = "0" )]
     public int AiVisitCount { get; set; }
 
+    /// <summary>
+    /// 智能回访录音地址
+    /// </summary>
+    public string? RecordUrl { get; set; }
+
 
     public void AiVisitTime()
     {

+ 14 - 16
src/Hotline/Orders/OrderVisitDetail.cs

@@ -34,22 +34,20 @@ namespace Hotline.Orders
         /// </summary>
         public ESeatEvaluate? SeatEvaluate { get; set; }
 
-        ///// <summary>
-        ///// 是否联系
-        ///// </summary>
-        //public bool? IsContact { get; set; }
-
-        ///// <summary>
-        ///// 处理结果
-        ///// </summary>
-        //public bool? Volved { get; set; }
-
-        ///// <summary>
-        ///// 未处理内容
-        ///// </summary>
-        //public string? VolveConent { get; set; }
-
-        //public string? RecordUrl { get; set; }
+        /// <summary>
+        /// 是否联系
+        /// </summary>
+        public bool? IsContact { get; set; }
+
+        /// <summary>
+        /// 处理结果
+        /// </summary>
+        public bool? Volved { get; set; }
+
+        /// <summary>
+        /// 未处理内容
+        /// </summary>
+        public string? VolveConent { get; set; }
 
 
         /// <summary>