ShuanghongS преди 6 месеца
родител
ревизия
050ed5fd4c
променени са 4 файла, в които са добавени 401 реда и са изтрити 28 реда
  1. 6 0
      main_new_version.php
  2. 7 1
      service/column.class.php
  3. 233 20
      service/robot.class.php
  4. 155 7
      utils/common.class.php

+ 6 - 0
main_new_version.php

@@ -785,6 +785,12 @@ switch ($action) {
     case 'robot_chat':
         robot::getInstance()->ai_chat();
         break;          
+    case 'robot_chat_log':
+        robot::getInstance()->robot_chat_log();
+        break;
+    case 'robot_api_log':
+        robot::getInstance()->robot_api_log();
+        break;        
     case 'system_setting':
         tools::getInstance()->user_system_setting();
         break;

+ 7 - 1
service/column.class.php

@@ -296,7 +296,13 @@ class column {
             return array("operation_time" =>array("formatter" =>"dateTime"));
         }
         if ($type == "Robot_Chat_Search"){
-            return array("question_date" =>array("formatter" =>"dateTime"));
+            return array("request_time" =>array("formatter" =>"dateTime"),
+                         "response_time" =>array("formatter" =>"dateTime"));
+        }
+        if ($type == "Robot_API_Search"){
+            return array("request_time" =>array("formatter" =>"dateTime"),
+                         "response_time" =>array("formatter" =>"dateTime"),
+                        "request_id" =>array("type" =>"link"));
         }
     }
 

+ 233 - 20
service/robot.class.php

@@ -27,6 +27,7 @@ class robot{
         }
         return self::$_robot;
     }
+
     public function robot_chat_log() {
         $operate = utils::_get('operate');
         $operate = strtolower($operate);
@@ -40,7 +41,91 @@ class robot{
         }
 
         if ($operate == "search") {
-            //$this->_operation_search();
+            $cp = common::check_input($_POST ['cp']); //current_page
+            $ps = common::check_input($_POST ['ps']); //ps
+            if (empty($ps))
+                $ps = 10;
+
+            $sqlWhere = ' where 1=1';
+            $text_search = common::check_input($_POST ['text_search']); 
+            $user_type = common::check_input($_POST ['user_type']);
+            $question_type = common::check_input($_POST ['question_type']); 
+            $answer_type = common::check_input($_POST ['answer_type']); 
+            $answer_satisfication = common::check_input($_POST ['answer_satisfication']);
+            $response_duration_type = common::check_input($_POST ['response_duration_type']);  
+            $response_duration_num = common::check_input($_POST ['response_duration_num']); 
+            
+            if (!empty($text_search)){
+                $sqlWhere .= " and (question_id ilike '%" . $text_search . "%' or user_name ilike '%" . $text_search . "%')";
+            }
+            if (isset($_POST['question_date_start']) && !empty($_POST['question_date_start'])){
+                $sqlWhere .= " and question_date >= '" . common::usDate2sqlDate($_POST['question_date_start']) . " 00:00:00'";
+            }
+            if (isset($_POST['question_date_end']) && !empty($_POST['question_date_end'])){
+                $sqlWhere .= " and question_date <= '" . common::usDate2sqlDate($_POST['question_date_end']) . " 23:59:59'";
+            }
+
+            if (!empty($user_type)){
+                $sqlWhere .= " and user_type = '".strtolower($user_type)."'";
+            }
+            if (!empty($question_type)){
+                //$question_type = $question_type == 'Free Text' ? "Free Question" : $question_type;
+                $sqlWhere .= " and question_type = '$question_type'";
+            }
+            if (!empty($answer_type)){
+                $sqlWhere .= " and answer_type = '$answer_type'";
+            }
+            if (!empty($answer_satisfication)){
+                $answer_satisfication = $answer_satisfication == 'Null' ? '' : $answer_satisfication;
+                $sqlWhere .= " and COALESCE(answer_satisfication,'') = '$answer_satisfication'";
+            }
+            if (!empty($response_duration_type) && !empty($response_duration_num)){
+               if($response_duration_type == "thanOrEqual"){
+                    $sqlWhere .= " and response_duration >= '$response_duration_num'";
+               } elseif ($response_duration_type == "equal"){
+                    $sqlWhere .= " and response_duration = '$response_duration_num'";
+               } else {
+                    $sqlWhere .= " and response_duration <= '$response_duration_num'";
+               }
+            }
+           
+            $rc = $_POST ['rc'];
+            if ($rc == - 1) {
+                $sql = "SELECT count(1) from public.kln_robot_chat_log" . $sqlWhere;
+                error_log($sql);
+                $rc = common::excuteOneSql($sql);
+            }
+            $tp = ceil($rc / $ps);
+            $order_by = " id desc";
+        
+            if ($rc > 0) {
+                $sql = "SELECT ".column::getInstance()->getSearchSqlForDisplay('Robot_Chat_Search').", 
+                    to_char(response_time, 'YYYY/MM/DD HH24:MI:SS') as _response_time,
+                    to_char(request_time, 'YYYY/MM/DD HH24:MI:SS') as _request_time,
+                    request_id 
+                from public.kln_robot_chat_log " . $sqlWhere . 
+                            " order by $order_by limit " . $ps . " offset " . ($cp - 1) * $ps;
+                $rs = common::excuteListSql($sql);
+                foreach($rs as $key => $val){
+                    $rs[$key]["response_time"] = $val["_response_time"];
+                    $rs[$key]["request_time"] = $val["_request_time"];
+                }
+                $arrTmp = array('searchData' => $rs, 
+                'tmp_search' => common::deCode($sql, 'E'),
+                'rc' => intval($rc),
+                'ps' => intval($ps),
+                'cp' => intval($cp),
+                'tp' => intval($tp));
+            } else {
+            $arrTmp = array('searchData' => array(), 
+                'tmp_search' => common::deCode($sql, 'E'),
+                'rc' => intval($rc),
+                'ps' => intval($ps),
+                'cp' => intval($cp),
+                'tp' => intval($tp));
+            }
+            common::echo_json_encode(200,$arrTmp);
+            exit();
         }
 
         if ($operate == "excel") {
@@ -50,11 +135,131 @@ class robot{
                 $rss = common::excuteListSql($sql);
             }
             foreach($rss as $key =>$val){
-                $rss[$key]['Operation Time'] = $rss[$key]['_operation_time'];
+                $rs[$key]["response_time"] = $val["_response_time"];
+                $rs[$key]["request_time"] = $val["_request_time"];
             }
             common::echo_json_encode(200,array("msg"=>"success","Data" => $rss));
             exit;
         }
+
+        if ($operate == "api_log") {
+            $request_id = common::check_input($_POST['request_id']);
+            $sql = "select question_content,ai_response_content from public.kln_robot_chat_log where request_id = '$request_id'";
+            $data = common::excuteObjectSql($sql);
+            $question_content = $data['question_content'];
+            $ai_response_content = json_decode($data['ai_response_content']);
+            common::echo_json_encode(200,array("msg"=>"success","Data" => array("request_content" =>$question_content, "ai_response_content"=>$ai_response_content)));
+            //common::echo_json_encode(200,array("msg"=>"success","Data" => $data));
+            exit;
+        }
+        
+    }
+
+    public function robot_api_log() {
+        $operate = utils::_get('operate');
+        $operate = strtolower($operate);
+
+        if (empty($operate)) {
+            $column = column::getInstance()->getDisplayColumn('Robot_API_Search');
+            $OperationTableColumns = column::getInstance()->tableColumns('Robot_API_Search',$column);
+            $data['OperationTableColumns'] = $OperationTableColumns;
+            common::echo_json_encode(200,$data);
+            exit();
+        }
+
+        if ($operate == "search") {
+            $cp = common::check_input($_POST ['cp']); //current_page
+            $ps = common::check_input($_POST ['ps']); //ps
+            if (empty($ps))
+                $ps = 10;
+
+            //只查询自由问题
+            $sqlWhere = " where 1=1 and question_type = 'Free Text' ";
+            $text_search = common::check_input($_POST ['text_search']); 
+            $ai_model = common::check_input($_POST ['ai_model']); 
+            $response_duration_type = common::check_input($_POST ['response_duration_type']);  
+            $response_duration_num = common::check_input($_POST ['response_duration_num']);
+            
+            
+            if (!empty($text_search)){
+                $sqlWhere .= " and (question_id ilike '%" . $text_search . "%' or request_id ilike '%" . $text_search . "%')";
+            }
+            if (!empty($ai_model)){
+                $sqlWhere .= " and lower(ai_model) = '".strtolower($ai_model)."'";
+            }
+            if (isset($_POST['request_date_start']) && !empty($_POST['request_date_start']))
+                $sqlWhere .= " and request_time >= '" . common::usDate2sqlDate($_POST['request_date_start']) . " 00:00:00'";
+            if (isset($_POST['request_date_end']) && !empty($_POST['request_date_end']))
+                $sqlWhere .= " and request_time <= '" . common::usDate2sqlDate($_POST['request_date_end']) . " 23:59:59'";
+
+            if (!empty($response_duration_type) && !empty($response_duration_num)){
+               if($response_duration_type == "thanOrEqual"){
+                    $sqlWhere .= " and response_duration >= '$response_duration_num'";
+               } elseif ($response_duration_type == "equal"){
+                    $sqlWhere .= " and response_duration = '$response_duration_num'";
+               } else {
+                    $sqlWhere .= " and response_duration <= '$response_duration_num'";
+               }
+            }
+
+            $rc = $_POST ['rc'];
+            if ($rc == - 1) {
+                $sql = "SELECT count(1) from public.kln_robot_chat_log" . $sqlWhere;
+                $rc = common::excuteOneSql($sql);
+            }
+            $tp = ceil($rc / $ps);
+            $order_by = " id desc";
+        
+            if ($rc > 0) {
+                $sql = "SELECT ".column::getInstance()->getSearchSqlForDisplay('Robot_API_Search').", 
+                    to_char(response_time, 'YYYY/MM/DD HH24:MI:SS') as _response_time,
+                    to_char(request_time, 'YYYY/MM/DD HH24:MI:SS') as _request_time 
+                from public.kln_robot_chat_log " . $sqlWhere . 
+                            " order by $order_by limit " . $ps . " offset " . ($cp - 1) * $ps;
+                $rs = common::excuteListSql($sql);
+                foreach($rs as $key => $val){
+                    $rs[$key]["response_time"] = $val["_response_time"];
+                    $rs[$key]["request_time"] = $val["_request_time"];
+                }
+                $arrTmp = array('searchData' => $rs, 
+                'tmp_search' => common::deCode($sql, 'E'),
+                'rc' => $rc,
+                'ps' => $ps,
+                'cp' => $cp,
+                'tp' => $tp);
+            } else {
+            $arrTmp = array('searchData' => array(), 
+                'tmp_search' => common::deCode($sql, 'E'),
+                'rc' => $rc,
+                'ps' => $ps,
+                'cp' => $cp,
+                'tp' => $tp);
+            }
+            common::echo_json_encode(200,$arrTmp);
+            exit();
+        }
+
+        if ($operate == "excel") {
+            $sql = common::deCode($_POST ['tmp_search'], 'D');
+            $sql = substr($sql, 0, strripos($sql, " limit"));
+            if(!empty($sql)){
+                $rss = common::excuteListSql($sql);
+            }
+            foreach($rss as $key =>$val){
+                $rs[$key]["response_time"] = $val["_response_time"];
+                $rs[$key]["request_time"] = $val["_request_time"];
+            }
+            common::echo_json_encode(200,array("msg"=>"success","Data" => $rss));
+            exit;
+        }
+
+        if ($operate == "api_log") {
+            $request_id = common::check_input($_POST['request_id']);
+            $sql = "select request_content,ai_response_content from public.kln_robot_chat_log where request_id = '$request_id'";
+            $data = common::excuteObjectSql($sql);
+            common::echo_json_encode(200,array("msg"=>"success","Data" => $data));
+            exit;
+        }
         
     }
 
@@ -247,9 +452,9 @@ class robot{
             $response_duration = $date2->getTimestamp() - $date1->getTimestamp();
 
             //回答问题类型,在没有超时的情况下,固定:AI回答
-            $answer_type = "AI回答";
+            $answer_type = "AI Answer";
             if ($response_duration > 120){
-                $answer_type = "回答超时";
+                $answer_type = "Timeout";
             }
             //获取自然序列
             $sequence = common::getChatAiSequence();
@@ -261,7 +466,7 @@ class robot{
             $user_name = common::check_input(_getLoginName());
             $user_type = _isApexLogin() ? "employee" : "customer";
             //这里的测试,固定写自由文本
-            $question_type = 'free text';
+            $question_type = 'Free Text';
             $question_id = common::check_input($question_id);
             $question_content = common::check_input($message);
             $answer_type = common::check_input($answer_type);
@@ -374,7 +579,6 @@ class robot{
             common::echo_json_encode(200,$data);
             exit();
         }
-
         /**
          * ai 自由聊天
         */
@@ -384,13 +588,14 @@ class robot{
             //系统提示词
             $systemPrompt = common::check_input($_POST["prompt"]);
             $question_type = common::check_input($_POST['question_type']);
+            $question_type = $question_type == 'Free Question' ? "Free Text" : $question_type;
             $question_content = common::check_input($_POST['question_content']);
 
             //固定问题的原始问题
             $fixed_faq = common::check_input($_POST['fixed_faq']);
             //claude  deepseek  根據賬號信息判断
             $model = common::getUserCountry();
-            $answer_type  = $question_type == "Free Question" ? "AI回答" : "预定义模板回答";
+            $model = "deepseek"; 
 
             //获取自然序列
             $sequence = common::getChatAiSequence();
@@ -404,9 +609,9 @@ class robot{
             
             //首先生成基本记录数据 以便以后根据情况更新状态
             $sql = "INSERT INTO public.kln_robot_chat_log(serial_no, question_id, user_name, user_type, question_type, question_content, 
-                    answer_type, question_date, question_time, request_id, request_time)
+                    question_date, question_time, request_id, request_time,ai_model)
             VALUES ('$serial_no','$question_id', '$user_name', '$user_type', '$question_type', '$question_content', 
-                    '$answer_type',now(),to_char(CURRENT_TIME::time, 'HH24:MI:SS'), '$request_id',now());";
+                    now(),to_char(CURRENT_TIME::time, 'HH24:MI:SS'), '$request_id',now(),'$model');";
             $rs = common::excuteUpdateSql($sql);
             if (!$rs) {
                 $data = array("type"=>"markdown","data" => "AI Chat Save Error");
@@ -436,7 +641,7 @@ class robot{
 
         if($operate == "ai_chat_stop"){
             $serial_no = common::check_input($_POST["serial_no"]);
-            $updateSql = "update public.kln_robot_chat_log  set answer_type = '回答被动停止' where serial_no = '$serial_no'";
+            $updateSql = "update public.kln_robot_chat_log  set answer_type = 'Suspend' where serial_no = '$serial_no'";
 
             $updateRs = common::excuteUpdateSql($updateSql);
             if (!$updateRs) {
@@ -450,7 +655,7 @@ class robot{
 
         if($operate == "ai_chat_answer_mark"){
             $serial_no = common::check_input($_POST["serial_no"]);
-            $answer_satisfication = common::check_input($_POST["answer_satisfication"]);
+            $answer_satisfication = common::check_input($_POST["feedback"]);
             $updateSql = "update public.kln_robot_chat_log  set answer_satisfication = '$answer_satisfication' where serial_no = '$serial_no'";
 
             $updateRs = common::excuteUpdateSql($updateSql);
@@ -463,6 +668,14 @@ class robot{
             exit(); 
         }
 
+        if($operate == "download"){
+            $faq = common::deCode($_GET['faq'], 'D');
+            $sql = common::getFaqSql($faq);
+            $column = common::getFaqColumnSql($faq);
+            
+        }
+
+
     }
 
     public function dealPromptFormatAndVue($configuration){
@@ -589,9 +802,9 @@ class robot{
             CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
         $response_duration =   $response_pram['response_duration'];
         //回答问题类型,在没有超时的情况下,固定:AI回答
-        $answer_type = "AI回答";
+        $answer_type = "AI Answer";
         if ($response_duration > 120){
-            $answer_type = "回答超时";
+            $answer_type = "Timeout";
         }
         $request_content = common::check_input(json_encode($response['data']));
         $ai_response_content = common::check_input(json_encode($response['full_response']));
@@ -628,8 +841,8 @@ class robot{
         }
 
         //update 更新
-        $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
-            answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
+        $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',answer = '".common::check_input($answer)."',
+            answer_type = case when COALESCE(answer_type,'') = 'Suspend' then 'Suspend' else '$answer_type' end,
             request_content='$request_content',
             input_token='$input_token',ai_response_content='$ai_response_content',
             output_token='$output_token',response_time=now(),response_duration='$response_duration'
@@ -662,16 +875,16 @@ class robot{
             CEIL(EXTRACT(EPOCH FROM (now() - question_date))) AS response_duration from public.kln_robot_chat_log where serial_no = '$serial_no'");
         $response_duration =   $response_pram['response_duration'];
         //回答问题类型,在没有超时的情况下,固定:AI回答
-        $answer_type = "AI回答";
+        $answer_type = "Predefined Template";
         if ($response_duration > 120){
-            $answer_type = "回答超时";
+            $answer_type = "Timeout";
         }
         
         $request_content = common::check_input($question_content);
         $ai_response_content = common::check_input($answer);
         //update 更新
-        $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',
-            answer_type = case when COALESCE(answer_type,'') = '回答被动停止' then '回答被动停止' else '$answer_type' end,
+        $updateSql = "update public.kln_robot_chat_log set answer_duration = '$response_duration',answer_template='$answer_template',answer = '".common::check_input($answer)."',
+            answer_type = case when COALESCE(answer_type,'') = 'Suspend' then 'Suspend' else '$answer_type' end,
             request_content='$request_content',
             input_token='$input_token',ai_response_content='$ai_response_content',
             output_token='$output_token',response_time=now(),response_duration='$response_duration'
@@ -684,7 +897,7 @@ class robot{
             exit();
         }
         return $answer;
-    }
+    } 
 }
 
 ?>

+ 155 - 7
utils/common.class.php

@@ -138,6 +138,7 @@ class common {
                     self::timeoutPrintInfor($httpAccept, $ajax, 'yes');
                 } else {
                     $_SESSION["LAST_OPERATE_TIME"] = time();
+
                     if (!_isAdmin() && $_GET["action"] != "linkcrm") {
                         if (!utils::checkExist($_SESSION['ONLINE_USER']['permission'], $action) 
                             && !(stripos($action, "main") === 0) 
@@ -145,7 +146,7 @@ class common {
                             && !(stripos($action, "feature_update") === 0)
                             && !(stripos($action, "ajax") === 0)
                             && !(stripos($action, "opreation_log") === 0)
-                            && !(stripos($action, "robot") === 0)
+                            && !(stripos($action, "robot") === 0)   // robot 开头的都匹配上了
                             && !(stripos($action, "system_setting") === 0)
                             && !(stripos($action, "monitoring_setting") === 0)
                             && !(stripos($action, "notifications_rules") === 0)) {
@@ -2654,7 +2655,14 @@ class common {
                 $data = $refer_data;
             }
             $reference = utils::replacementsFixedMultilineForFixed($data,$reference,$fixedChat['table_format_tr']);
-            //$data_download = "main_new_version.php?action=ocean_order&operate=download&temp=". common::deCode($fixedChat["fixed_faq"]);
+
+            $total = array("Download_Complete" =>"");
+            if ($count > 10){
+                $httpUrl = "main_new_version.php?action=ai_chat&operate=download&faq=". common::deCode($fixedChat["fixed_faq"]);
+                $download_complete = '- Due to page limitations, only the first 10 records are currently displayed. If you need the complete data, please click the <a href="'.$httpUrl.'" target="_blank">Download Complete</a> button.';
+                $total = array("Download_Complete" =>$download_complete);
+            }
+            $reference = utils::replacementsFixed($total,$reference,array("Download_Complete"));
         }
 
         if($fixedChat["fixed_faq"] == "List shipments with milestone updates in the last 7 days."){
@@ -2707,12 +2715,20 @@ class common {
             if(!empty($dateGroups)){
                 $timeline_view = "## Timeline View: \n";
             }
-            foreach($dateGroups as $key => $count){
-                $timeline_view.="- ".$count['update_date_format'].": ".$count['total_count']." shipments reached milestones \n";
+            foreach($dateGroups as $key => $tv_count){
+                $timeline_view.="- ".$tv_count['update_date_format'].": ".$tv_count['total_count']." shipments reached milestones \n";
             }
             $total = array("Timeline View" =>$timeline_view);
             $reference = utils::replacementsFixed($total,$reference,array("Timeline View"));
 
+            $total = array("Download_Complete" =>"");
+            if ($count > 10){
+                $httpUrl = "main_new_version.php?action=ai_chat&operate=download&faq=". common::deCode($fixedChat["fixed_faq"]);
+                $download_complete = '- Due to page limitations, only the first 10 records are currently displayed. If you need the complete data, please click the <a href="'.$httpUrl.'" target="_blank">Download Complete</a> button.';
+                $total = array("Download_Complete" =>$download_complete);
+            }
+            $reference = utils::replacementsFixed($total,$reference,array("Download_Complete"));
+
             error_log($reference);
         }
 
@@ -2862,11 +2878,19 @@ class common {
             if(!empty($dateGroups)){
                 $timeline_view = "## Timeline View: \n";
             }
-            foreach($dateGroups as $key => $count){
-                $timeline_view.="- ".$count['_eventdate'].": ".$count['total_count']." containers have been updated \n";
+            foreach($dateGroups as $key => $tv_count){
+                $timeline_view.="- ".$tv_count['_eventdate'].": ".$tv_count['total_count']." containers have been updated \n";
             }
             $total = array("Timeline View" =>$timeline_view);
             $reference = utils::replacementsFixed($total,$reference,array("Timeline View"));
+
+            $total = array("Download_Complete" =>"");
+            if ($count > 10){
+                $httpUrl = "main_new_version.php?action=ai_chat&operate=download&faq=". common::deCode($fixedChat["fixed_faq"]);
+                $download_complete = '- Due to page limitations, only the first 10 records are currently displayed. If you need the complete data, please click the <a href="'.$httpUrl.'" target="_blank">Download Complete</a> button.';
+                $total = array("Download_Complete" =>$download_complete);
+            }
+            $reference = utils::replacementsFixed($total,$reference,array("Download_Complete"));
         }
 
         if($fixedChat["fixed_faq"] == "Today's shipments summary."){
@@ -2922,6 +2946,14 @@ class common {
             $dateGroups = common::excuteListSql($sqlview);
             $total = array("dep" =>$dateGroups[0]['dep'],"arr" => $dateGroups[0]['arr'],"del" => $dateGroups[0]['del']);
             $reference = utils::replacementsFixed($total,$reference,[]);
+
+            $total = array("Download_Complete" =>"");
+            if ($count > 10){
+                $httpUrl = "main_new_version.php?action=ai_chat&operate=download&faq=". common::deCode($fixedChat["fixed_faq"]);
+                $download_complete = '- Due to page limitations, only the first 10 records are currently displayed. If you need the complete data, please click the <a href="'.$httpUrl.'" target="_blank">Download Complete</a> button.';
+                $total = array("Download_Complete" =>$download_complete);
+            }
+            $reference = utils::replacementsFixed($total,$reference,array("Download_Complete"));
         }
 
         if($fixedChat["fixed_faq"] == "Show me the current location of my shipment."){
@@ -2962,7 +2994,15 @@ class common {
                 $sql = utils::getDmoeSqlForAi($fixedChat["fixed_faq"]);
             }
 
-            $sqlDetail = $sql;
+            $sqlArr = explode(";", $sql);
+            $sqlCount = $sqlArr[0];
+            //拼接用户权限
+            $sqlWhere = '  ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
+            $sqlCount = str_replace('<{ExtendHand_KLN}>', $sqlWhere, $sqlCount);
+            error_log("countSql:".$sqlCount);
+            $count = common::excuteOneSql($sqlCount);
+            
+            $sqlDetail = $sqlArr[1];
             //拼接用户权限
             $sqlWhere = '  ' . common::searchExtendHand_KLN("ocean", $_SESSION["ONLINE_USER"]);
             $sqlDetail = str_replace('<{ExtendHand_KLN}>', $sqlWhere, $sqlDetail);
@@ -2986,6 +3026,14 @@ class common {
             }
             $data = $refer_data;
             $reference = utils::replacementsFixedMultilineForFixed($data,$fixedChat['answer_style'],$fixedChat['table_format_tr']);
+
+            $total = array("Download_Complete" =>"");
+            if ($count > 10){
+                $httpUrl = "main_new_version.php?action=ai_chat&operate=download&faq=". common::deCode($fixedChat["fixed_faq"]);
+                $download_complete = '- Due to page limitations, only the first 10 records are currently displayed. If you need the complete data, please click the <a href="'.$httpUrl.'" target="_blank">Download Complete</a> button.';
+                $total = array("Download_Complete" =>$download_complete);
+            }
+            $reference = utils::replacementsFixed($total,$reference,array("Download_Complete"));
         }
 
         if($fixedChat["fixed_faq"] == "Set up automatic notifications for shipment updates." 
@@ -3024,5 +3072,105 @@ class common {
         }
         return $hours;
     }
+
+    /**
+     * 获取固定问题的查询sql
+    */
+    public static function getFaqSql($faq){
+        $sqlObj = common::excuteObjectSql("select fixed_sql from public.kln_robot_chat_fixed where fixed_faq = '$faq'");
+        $fixed_sql = $sqlObj['fixed_sql'];
+
+        $sqlDetail = '';
+        $sqlArr = explode(";", $fixed_sql);
+        if(count($sqlArr) > 1){
+            $sqlDetail = $sqlArr[1];
+            $search = 'limit 10';
+            $sqlDetail = str_ireplace($search, '', $sqlDetail);
+        }
+        return $sqlDetail;
+    }
+
+    /**
+     * 获取固定问题列
+    */
+    public static function getFaqColumnSql($faq){
+         //返回格式相同的放到一起处理
+        if($faq == "Shipments arriving in the next 7 days."){
+            // | HBL/HAWB No. | Origin           | Destination      | Latest Milestone | ETA       | Cargo Type    | Actions          |
+            // |--------------|------------------|------------------|------------------|-----------|---------------|------------------|
+            // | {{h_bol}} | {{place_of_receipt_exp}} | {{place_of_delivery_exp}} | {{description}} | {{eta}} | {{cargo_type}} | {{action}} |
+            $columns = array();
+            $columns[] = array("display_name" => "HBL/HAWB No.","database_column_name"=>"h_bol");
+            $columns[] = array("display_name" => "Origin","database_column_name"=>"place_of_receipt_exp");
+            $columns[] = array("display_name" => "Destination","database_column_name"=>"place_of_delivery_exp");
+            $columns[] = array("display_name" => "Latest Milestone","database_column_name"=>"description");
+            $columns[] = array("display_name" => "ETA","database_column_name"=>"eta");
+            $columns[] = array("display_name" => "Cargo Type","database_column_name"=>"cargo_type");
+        }
+
+        if($faq == "List shipments with milestone updates in the last 7 days."){
+            // | HBL/HAWB No. | Latest Milestone           | Time                         | Location                  | Actions          |
+            // |--------------|----------------------------|------------------------------|---------------------------|------------------|
+            // | {{h_bol}} | {{description}} | {{update_date}} | {{locations}} | {{action}} |
+            $columns = array();
+            $columns[] = array("display_name" => "HBL/HAWB No.","database_column_name"=>"h_bol");
+            $columns[] = array("display_name" => "Latest Milestone","database_column_name"=>"description");
+            $columns[] = array("display_name" => "Time","database_column_name"=>"update_date");
+            $columns[] = array("display_name" => "Location","database_column_name"=>"locations");
+        }
+
+        if($faq == "What is the current status of my active shipments?"){
+            // | HBL/HAWB No. | Origin           | Destination      | Latest Milestone           | Time                         | Location                  | Cargo Type    | Actions          |
+            // |--------------|------------------|------------------|----------------------------|------------------------------|---------------------------|---------------|------------------|
+            // | {{h_bol}} | {{place_of_receipt_exp}} | {{place_of_delivery_exp}} | {{description}} | {{time}} | {{locations}} | {{cargo_type}} | {{action}} |
+            $columns = array();
+            $columns[] = array("display_name" => "HBL/HAWB No.","database_column_name"=>"h_bol");
+            $columns[] = array("display_name" => "Origin","database_column_name"=>"place_of_receipt_exp");
+            $columns[] = array("display_name" => "Destination","database_column_name"=>"place_of_delivery_exp");
+            $columns[] = array("display_name" => "Latest Milestone","database_column_name"=>"description");
+            $columns[] = array("display_name" => "Time","database_column_name"=>"time");
+            $columns[] = array("display_name" => "Location","database_column_name"=>"locations");
+            $columns[] = array("display_name" => "Cargo Type","database_column_name"=>"cargo_type");
+        }
+
+        if($faq == "List shipments with container status updates in the last 7 days."){
+            // | Container No. | Container Status           | Time                         | Location                  | Actions          |
+            // |---------------|----------------------------|------------------------------|---------------------------|------------------|
+            // | {{container_no}} | {{description}} | {{time}} | {{uncity}} | {{action}} | 
+            $columns = array();
+            $columns[] = array("display_name" => "Container No.","database_column_name"=>"container_no");
+            $columns[] = array("display_name" => "Container Status","database_column_name"=>"description");
+            $columns[] = array("display_name" => "Time","database_column_name"=>"time");
+            $columns[] = array("display_name" => "Location","database_column_name"=>"uncity");
+        }
+
+        if($faq == "Today's shipments summary."){
+            // | HBL/HAWB No. | Mode | Origin           | Destination      | Action Type | Action Time             | Action Location | Actions          |
+            // |--------------|------|------------------|------------------|-------------|-------------------------|-----------------|------------------|
+            // | {{h_bol}} | {{transport_mode}} | {{place_of_receipt_exp}} | {{place_of_delivery_exp}} | {{action_type}} | {{time}} | {{locations}} | {{action}} |
+            $columns = array();
+            $columns[] = array("display_name" => "HBL/HAWB No.","database_column_name"=>"h_bol");
+            $columns[] = array("display_name" => "Mode","database_column_name"=>"transport_mode");
+            $columns[] = array("display_name" => "Origin","database_column_name"=>"place_of_receipt_exp");
+            $columns[] = array("display_name" => "Destination","database_column_name"=>"place_of_delivery_exp");
+            $columns[] = array("display_name" => "Action Type","database_column_name"=>"action_type");
+            $columns[] = array("display_name" => "Action Time","database_column_name"=>"time");
+            $columns[] = array("display_name" => "Action Location","database_column_name"=>"locations");
+        }
+
+        if($faq == "Sort my active shipments by earliest arrival date."){
+            // | ETA    | HBOL/HAWB No. | Mode  | Origin           | Destination      | Days to Arrival | Actions          |
+            // |--------|---------------|-------|------------------|------------------|-----------------|------------------|
+            // | {{eta}} | {{h_bol}} | {{transport_mode}} | {{place_of_receipt_exp}} | {{place_of_delivery_exp}} | {{day_to_arr}} | {{action}} |
+            $columns = array();
+            $columns[] = array("display_name" => "ETA","database_column_name"=>"eta");
+            $columns[] = array("display_name" => "HBL/HAWB No.","database_column_name"=>"h_bol");
+            $columns[] = array("display_name" => "Mode","database_column_name"=>"transport_mode");
+            $columns[] = array("display_name" => "Origin","database_column_name"=>"place_of_receipt_exp");
+            $columns[] = array("display_name" => "Destination","database_column_name"=>"place_of_delivery_exp");
+            $columns[] = array("display_name" => "Days to Arrival","database_column_name"=>"day_to_arr");
+        }
+        return $columns;
+    }
 }
 ?>