Browse Source

feat: 联调Chat Log和AI API Log部分接口

zhouyuhao 6 months ago
parent
commit
81c125b5d7

+ 15 - 0
src/api/module/AIRobot.ts

@@ -221,3 +221,18 @@ export const getAIApiLogAllTableData = (params: any, config: any) => {
     config
   )
 }
+
+/**
+ * 获取ai api log弹窗详情
+ */
+export const getAIApiLogDialog = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_chat_log',
+      operate: 'api_log',
+      ...params
+    },
+    config
+  )
+}

+ 27 - 22
src/views/AIApiLog/src/AIApiLog.vue

@@ -1,31 +1,27 @@
 <script lang="ts" setup>
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
 import TableView from './components/TableView'
+import dayjs from 'dayjs'
 
-const OperationSearch = ref()
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const containerHeight = useCalculatingHeight(document.documentElement, 290, [filterRef])
 const searchData = ref({
-  inputModel: '',
-  startDate: '',
-  endDate: '',
-  aiModel: '',
-  comparator: 'thanOrEqual',
-  responseDuration: 0
+  text_search: '',
+  request_date_start: '',
+  request_date_end: '',
+  ai_model: '',
+  response_duration_type: '',
+  response_duration_num: null
 })
 
 const aiModelList = [
   {
-    label: 'Deepseek-chat',
-    value: 'deepseekChat'
+    label: 'Deepseek',
+    value: 'Deepseek'
   },
   {
-    label: 'Deepseek-search',
-    value: 'deepseekSearch'
-  },
-  {
-    label: 'Claude 3.7 Sonnet',
-    value: 'claude'
+    label: 'Claude',
+    value: 'Claude'
   }
 ]
 
@@ -50,8 +46,13 @@ const Search = () => {
   tableRef.value.SearchOperationLog(searchData.value)
 }
 const DateChange = (date: any) => {
-  searchData.value.startDate = date[0]
-  searchData.value.endDate = date[1]
+  if (!date) {
+    searchData.value.request_date_start = ''
+    searchData.value.request_date_end = ''
+  } else {
+    searchData.value.request_date_start = dayjs(date[0]).format('DD/MM/YYYY')
+    searchData.value.request_date_end = dayjs(date[1]).format('DD/MM/YYYY')
+  }
   tableRef.value.SearchOperationLog(searchData.value)
 }
 </script>
@@ -63,7 +64,7 @@ const DateChange = (date: any) => {
         <div class="input-tips_filter">
           <el-input
             placeholder="Search Request ID、Question ID"
-            v-model="OperationSearch"
+            v-model="searchData.text_search"
             class="log_input"
           >
             <template #prefix>
@@ -80,7 +81,7 @@ const DateChange = (date: any) => {
           <CalendarDate @DateChange="DateChange"></CalendarDate>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.aiModel" placeholder="AI Model">
+          <el-select v-model="searchData.ai_model" placeholder="AI Model">
             <el-option
               v-for="item in aiModelList"
               :key="item.value"
@@ -91,7 +92,11 @@ const DateChange = (date: any) => {
         </div>
         <div class="comparator-tips_filter">
           <span>Response Duration</span>
-          <el-select v-model="searchData.comparator" style="width: 70px; margin: 0 6px">
+          <el-select
+            placeholder=""
+            v-model="searchData.response_duration_type"
+            style="width: 70px; margin: 0 6px"
+          >
             <el-option
               v-for="item in comparatorList"
               :key="item.value"
@@ -101,8 +106,8 @@ const DateChange = (date: any) => {
             </el-option>
           </el-select>
           <el-input-number
-            v-model="searchData.responseDuration"
-            placeholder="s"
+            v-model="searchData.response_duration_num"
+            placeholder=""
             :controls="false"
             :min="0"
             style="width: 60px"

+ 28 - 28
src/views/AIApiLog/src/components/LogDialog.vue

@@ -1,8 +1,20 @@
 <script setup lang="ts">
 const dialogVisible = ref(false)
 
-const openDialog = () => {
+const requestContent = ref()
+const responseContent = ref()
+const requestContentRef = ref<HTMLElement | null>(null)
+const responseHeight = ref(580)
+const openDialog = (request, response) => {
   dialogVisible.value = true
+  requestContent.value = request
+  responseContent.value = response
+  nextTick(() => {
+    if (requestContentRef.value) {
+      const height = requestContentRef.value.scrollHeight
+      responseHeight.value = 726 - height - 122
+    }
+  })
 }
 defineExpose({
   openDialog
@@ -10,37 +22,24 @@ defineExpose({
 </script>
 
 <template>
-  <el-dialog v-model="dialogVisible" class="log-dialog" title="AI API Log" width="1000" top="10vh">
+  <el-dialog
+    v-model="dialogVisible"
+    class="ai-api-log-dialog"
+    title="AI API Log"
+    width="1000"
+    top="10vh"
+  >
     <div class="request-section">
       <div class="title">Request Content</div>
-      <div class="content">
-        Hello, I would like to check the status of my package. The tracking number is ABC123456789.
+      <div class="content" ref="requestContentRef">
+        {{ requestContent }}
       </div>
     </div>
     <el-divider style="margin: 16px 0" />
     <div class="response-section">
-      <div class="title">Request Content</div>
-      <p class="content">
-        Hey there! For the package with tracking number ABC123456789, the latest update is: [insert
-        latest tracking status here, e.g., shipped, in transit, arrived at the delivery hub, out for
-        delivery, etc.]. You can see more details by clicking this link: [insert detailed tracking
-        link here].Hey there! For the package with tracking number ABC123456789, the latest update
-        is: [insert latest tracking status here, e.g., shipped, in transit, arrived at the delivery
-        hub, out for delivery, etc.]. You can see more details by clicking this link: [insert
-        detailed tracking link here].Hey there! For the package with tracking number ABC123456789,
-        the latest update is: [insert latest tracking status here, e.g., shipped, in transit,
-        arrived at the delivery hub, out for delivery, etc.]. You can see more details by clicking
-        this link: [insert detailed tracking link here].Hey there! For the package with tracking
-        number ABC123456789, the latest update is: [insert latest tracking status here, e.g.,
-        shipped, in transit, arrived at the delivery hub, out for delivery, etc.]. You can see more
-        details by clicking this link: [insert detailed tracking link here].Hey there! For the
-        package with tracking number ABC123456789, the latest update is: [insert latest tracking
-        status here, e.g., shipped, in transit, arrived at the delivery hub, out for delivery,
-        etc.]. You can see more details by clicking this link: [insert detailed tracking link
-        here].Hey there! For the package with tracking number ABC123456789, the latest update is:
-        [insert latest tracking status here, e.g., shipped, in transit, arrived at the delivery hub,
-        out for delivery, etc.]. You can see more details by clicking this link: [insert detailed
-        tracking link here].
+      <div class="title">Response Content</div>
+      <p class="content" :style="{ height: responseHeight + 'px' }">
+        {{ responseContent }}
       </p>
     </div>
   </el-dialog>
@@ -67,12 +66,13 @@ defineExpose({
   .content {
     padding: 8px 16px 20px 16px;
     border-radius: 6px;
+    overflow: auto;
     background-color: var(--color-share-link-bg);
   }
 }
 </style>
-<style>
-.log-dialog {
+<style lang="scss">
+.ai-api-log-dialog {
   height: 80%;
   .el-dialog__body {
     padding: 0;

+ 27 - 3
src/views/AIApiLog/src/components/TableView/src/TableView.vue

@@ -335,8 +335,21 @@ const handleCheckAllChange = ({ records }: any) => {
 }
 
 const logDialogRef = ref()
-const handleLogDetail = (row) => {
-  logDialogRef.value.openDialog(row)
+const logLoading = ref(false)
+const handleLinkClick = (row) => {
+  logLoading.value = true
+  $api
+    .getAIApiLogDialog({
+      request_id: row.request_id
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        logLoading.value = false
+        const data = res.data.Data
+        // 打开日志详情对话框
+        logDialogRef.value.openDialog(data.request_content, data.ai_response_content)
+      }
+    })
 }
 
 defineExpose({
@@ -353,7 +366,13 @@ defineExpose({
     element-loading-custom-class="element-loading"
     element-loading-background="rgb(43, 47, 54, 0.7)"
   >
-    <div class="table-tools">
+    <div
+      class="table-tools"
+      v-loading.fullscreen.lock="logLoading"
+      element-loading-text="Loading..."
+      element-loading-custom-class="element-loading"
+      element-loading-background="rgb(43, 47, 54, 0.7)"
+    >
       <div class="left-total-records">{{ selectedNumber }} Selected</div>
       <div class="right-tools-btn">
         <el-button class="el-button--main el-button--pain-theme" @click="handleDownload">
@@ -375,6 +394,11 @@ defineExpose({
       <template #empty v-if="!tableLoadingTableData && tableData.data.length === 0">
         <VEmpty></VEmpty>
       </template>
+      <template #link="{ row, column }">
+        <span style="color: var(--color-theme); cursor: pointer" @click="handleLinkClick(row)">
+          {{ row[column.field] }}
+        </span>
+      </template>
     </vxe-grid>
     <vxe-grid :height="10" ref="allTableRef" class="all-table" v-bind="allTable"> </vxe-grid>
     <div class="bottom-pagination">

+ 33 - 25
src/views/ChatLog/src/ChatLog.vue

@@ -1,21 +1,20 @@
 <script lang="ts" setup>
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
 import TableView from './components/TableView'
-import LogDialog from '@/views/AIApiLog/src/components/LogDialog.vue'
 import dayjs from 'dayjs'
 
 const filterRef: Ref<HTMLElement | null> = ref(null)
 const containerHeight = useCalculatingHeight(document.documentElement, 290, [filterRef])
 const searchData = ref({
   text_search: '',
-  question_time_start: '',
-  question_time_end: '',
+  question_date_start: '',
+  question_date_end: '',
   user_type: '',
-  questionType: '',
-  answerType: '',
+  question_type: '',
+  answer_type: '',
   answer_satisfication: '',
-  response_duration_type: 'thanOrEqual',
-  response_duration_num: 0
+  response_duration_type: '',
+  response_duration_num: null
 })
 
 const userTypeList = [
@@ -59,15 +58,15 @@ const AnswerTypeList = [
 const answerSatisfactionList = [
   {
     label: 'Null',
-    value: 'null'
+    value: 'Null'
   },
   {
     label: 'Good',
-    value: 'good'
+    value: 'Good'
   },
   {
     label: 'Not Good',
-    value: 'notGood'
+    value: 'Not Good'
   }
 ]
 
@@ -91,15 +90,15 @@ const Search = () => {
   tableRef.value.searchTableData(searchData.value)
 }
 const DateChange = (date: any) => {
-  searchData.value.question_time_start = dayjs(date[0]).format('YYYY-MM-DD')
-  searchData.value.question_time_end = dayjs(date[1]).format('YYYY-MM-DD')
+  if (!date) {
+    searchData.value.question_date_start = ''
+    searchData.value.question_date_end = ''
+  } else {
+    searchData.value.question_date_start = dayjs(date[0]).format('DD/MM/YYYY')
+    searchData.value.question_date_end = dayjs(date[1]).format('DD/MM/YYYY')
+  }
   tableRef.value.searchTableData(searchData.value)
 }
-
-const logDialogRef = ref()
-const openDialog = () => {
-  logDialogRef.value.openDialog()
-}
 </script>
 <template>
   <div class="dashboard">
@@ -110,6 +109,7 @@ const openDialog = () => {
           <el-input
             placeholder="Search Question ID、User"
             v-model="searchData.text_search"
+            clearable
             class="log_input"
           >
             <template #prefix>
@@ -126,7 +126,7 @@ const openDialog = () => {
           <CalendarDate @DateChange="DateChange"></CalendarDate>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.user_type" placeholder="User Type">
+          <el-select v-model="searchData.user_type" clearable placeholder="User Type">
             <el-option
               v-for="item in userTypeList"
               :key="item.value"
@@ -136,7 +136,7 @@ const openDialog = () => {
           </el-select>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.questionType" placeholder="Question Type">
+          <el-select clearable v-model="searchData.question_type" placeholder="Question Type">
             <el-option
               v-for="item in questionTypeList"
               :key="item.value"
@@ -147,7 +147,7 @@ const openDialog = () => {
           </el-select>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.answerType" placeholder="Answer Type">
+          <el-select clearable v-model="searchData.answer_type" placeholder="Answer Type">
             <el-option
               v-for="item in AnswerTypeList"
               :key="item.value"
@@ -158,7 +158,11 @@ const openDialog = () => {
           </el-select>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.answer_satisfication" placeholder="Answer Satisfaction">
+          <el-select
+            clearable
+            v-model="searchData.answer_satisfication"
+            placeholder="Answer Satisfaction"
+          >
             <el-option
               v-for="item in answerSatisfactionList"
               :key="item.value"
@@ -170,7 +174,12 @@ const openDialog = () => {
         </div>
         <div class="response_duration_type-tips_filter">
           <span>Response Duration</span>
-          <el-select v-model="searchData.response_duration_type" style="width: 70px; margin: 0 6px">
+          <el-select
+            clearable
+            v-model="searchData.response_duration_type"
+            style="width: 70px; margin: 0 6px"
+            placeholder=""
+          >
             <el-option
               v-for="item in response_duration_typeList"
               :key="item.value"
@@ -181,17 +190,16 @@ const openDialog = () => {
           </el-select>
           <el-input-number
             v-model="searchData.response_duration_num"
-            placeholder="s"
+            placeholder=""
             :controls="false"
             :min="0"
-            style="width: 60px"
+            style="width: 60px; height: 34px"
           ></el-input-number>
         </div>
         <el-button class="el-button--dark" @click="Search">Search</el-button>
       </div>
     </div>
     <TableView :height="containerHeight" :searchData="searchData" ref="tableRef"></TableView>
-    <LogDialog ref="logDialogRef" />
   </div>
 </template>
 

+ 26 - 4
src/views/ChatLog/src/components/TableView/src/TableView.vue

@@ -6,6 +6,7 @@ import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import dayjs from 'dayjs'
 import { formatTimezone, formatNumber } from '@/utils/tools'
+import LogDialog from '@/views/AIApiLog/src/components/LogDialog.vue'
 
 const props = defineProps({
   height: {
@@ -126,7 +127,7 @@ const getTableData = async (isPageChange?: boolean) => {
 const searchTableData = (val: any) => {
   tableLoadingTableData.value = true
   $api
-    .getChatLogAllTableData({
+    .getChatLogTableData({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       rc: -1,
@@ -335,9 +336,22 @@ const handleCheckAllChange = ({ records }: any) => {
   selectedTableData.value = records
 }
 
+const logDialogRef = ref()
+const logLoading = ref(false)
 const handleLogDetail = (row: any) => {
-  // 打开日志详情对话框
-  downloadDialogRef.value.openDialog(row)
+  logLoading.value = true
+  $api
+    .getAIApiLogDialog({
+      request_id: row.request_id
+    })
+    .then((res: any) => {
+      if (res.code === 200) {
+        logLoading.value = false
+        const data = res.data.Data
+        // 打开日志详情对话框
+        logDialogRef.value.openDialog(data.request_content, data.ai_response_content)
+      }
+    })
 }
 defineExpose({
   searchTableData
@@ -353,7 +367,13 @@ defineExpose({
     element-loading-custom-class="element-loading"
     element-loading-background="rgb(43, 47, 54, 0.7)"
   >
-    <div class="table-tools">
+    <div
+      class="table-tools"
+      v-loading.fullscreen.lock="logLoading"
+      element-loading-text="Loading..."
+      element-loading-custom-class="element-loading"
+      element-loading-background="rgb(43, 47, 54, 0.7)"
+    >
       <div class="left-total-records">{{ selectedNumber }} Selected</div>
       <div class="right-tools-btn">
         <el-button class="el-button--main el-button--pain-theme" @click="handleDownload">
@@ -380,6 +400,7 @@ defineExpose({
         <el-button
           style="height: 24px; padding: 8px 4px; padding-left: 5px; font-size: 12px"
           @click="handleLogDetail(row)"
+          v-if="row['Question Type'] !== 'Predefined Question'"
         >
           <span
             style="margin-right: 2px; font-size: 15px"
@@ -411,6 +432,7 @@ defineExpose({
       ref="downloadDialogRef"
       :isHideSelectColumn="true"
     />
+    <LogDialog ref="logDialogRef" />
   </div>
 </template>