Ver Fonte

feat: 联调Chat Log和AI Api Log页面接口

zhouyuhao há 6 meses atrás
pai
commit
3b0e41df63

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

@@ -133,3 +133,91 @@ export const AIRobotInit = (params: any, config: any) => {
     config
   )
 }
+
+/**
+ * 获取chat log 表格列
+ */
+export const getChatLogTableColumn = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_chat_log',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 根据筛选项获取chat log 表格数据
+ */
+export const getChatLogTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_chat_log',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取chat log 表格全部数据
+ */
+export const getChatLogAllTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_chat_log',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取ai api log 表格列
+ */
+export const getAIApiLogTableColumn = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_api_log',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 根据筛选项获取ai api log表格数据
+ */
+export const getAIApiLogTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_api_log',
+      operate: 'search',
+      ...params
+    },
+    config
+  )
+}
+
+/**
+ * 获取ai api log表格全部数据
+ */
+export const getAIApiLogAllTableData = (params: any, config: any) => {
+  return HttpAxios.post(
+    `${baseUrl}`,
+    {
+      action: 'robot_api_log',
+      operate: 'excel',
+      ...params
+    },
+    config
+  )
+}

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

@@ -2,7 +2,7 @@
 import { ref, nextTick, onMounted } from 'vue'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
 import DownloadDialog from './components/DownloadDialog.vue'
-// import { autoWidth } from '@/utils/table'
+import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import dayjs from 'dayjs'
 import { formatTimezone, formatNumber } from '@/utils/tools'
@@ -60,18 +60,17 @@ const handleColumns = (columns: any, status?: string) => {
 // 获取表格列
 const getTableColumns = async () => {
   tableLoadingColumn.value = true
-  await $api.getOperationTableColumns().then((res: any) => {
+  await $api.getAIApiLogTableColumn().then((res: any) => {
     if (res.code === 200) {
       tableData.value.columns = [
         { type: 'checkbox', width: 50, fixed: 'left' },
-        ...handleColumns(res.data.OperationTableColumns),
-        { title: 'Action', width: 106, fixed: 'right', slots: { default: 'action' } }
+        ...handleColumns(res.data.OperationTableColumns)
       ]
       tableOriginColumnsField.value = res.data.OperationTableColumns
     }
   })
   nextTick(() => {
-    // tableRef.value && autoWidth(tableData.value, tableRef.value)
+    tableRef.value && autoWidth(tableData.value, tableRef.value)
     tableLoadingColumn.value = false
     selectedNumber.value = 0
     selectedTableData.value = []
@@ -91,7 +90,7 @@ const assignTableData = (data: any) => {
     allTable.value.data = data.searchData || []
     // 为了让导出的表格列宽度自适应
     nextTick(() => {
-      // allTableRef.value && autoWidth(allTable.value, allTableRef.value)
+      allTableRef.value && autoWidth(allTable.value, allTableRef.value)
     })
   }, 1000)
 }
@@ -102,7 +101,7 @@ const getTableData = async (isPageChange?: boolean) => {
   const rc = isPageChange ? pageInfo.value.total : -1
   tableLoadingTableData.value = true
   await $api
-    .SearchOperationLog({
+    .getAIApiLogTableData({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       rc,
@@ -117,7 +116,7 @@ const getTableData = async (isPageChange?: boolean) => {
       selectedNumber.value = 0
       selectedTableData.value = []
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
       })
     })
@@ -126,7 +125,7 @@ const SearchOperationLog = (val: any) => {
   searchdata = val
   tableLoadingTableData.value = true
   $api
-    .SearchOperationLog({
+    .getAIApiLogTableData({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       rc: -1,
@@ -141,7 +140,7 @@ const SearchOperationLog = (val: any) => {
       selectedNumber.value = 0
       selectedTableData.value = []
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
       })
     })
@@ -149,7 +148,7 @@ const SearchOperationLog = (val: any) => {
 onMounted(() => {
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
     nextTick(() => {
-      // tableRef.value && autoWidth(tableData.value, tableRef.value)
+      tableRef.value && autoWidth(tableData.value, tableRef.value)
     })
   })
 })
@@ -276,7 +275,7 @@ const getExportTableData = (status: number) => {
     column = buildColumnString(allTable.value.columns)
   }
   $api
-    .OperationLogDownload({
+    .getAIApiLogAllTableData({
       selected_fields: column,
       tmp_search: tempSearch.value
     })
@@ -299,7 +298,7 @@ const exportTable = (status: number) => {
   const exportConfig: any = {
     type: 'xlsx',
     message: false,
-    filename: `Chat Log_${dayjs().format('YYYYMMDDHH[h]mm[m]ss[s]')}`
+    filename: `AI API Log_${dayjs().format('YYYYMMDDHH[h]mm[m]ss[s]')}`
   }
   if (status === 1) {
     exportConfig.columnFilterMethod = ({ column }: any) => {
@@ -376,19 +375,6 @@ defineExpose({
       <template #empty v-if="!tableLoadingTableData && tableData.data.length === 0">
         <VEmpty></VEmpty>
       </template>
-      <!-- action操作栏的插槽 -->
-      <template #action="{ row }">
-        <el-button
-          style="height: 24px; padding: 8px 4px; padding-left: 5px; font-size: 12px"
-          @click="handleLogDetail(row)"
-        >
-          <span
-            style="margin-right: 2px; font-size: 15px"
-            class="font_family icon-icon_ai_api_log_b"
-          ></span
-          >AI API Log
-        </el-button>
-      </template>
     </vxe-grid>
     <vxe-grid :height="10" ref="allTableRef" class="all-table" v-bind="allTable"> </vxe-grid>
     <div class="bottom-pagination">
@@ -407,7 +393,11 @@ defineExpose({
         />
       </div>
     </div>
-    <DownloadDialog @export="getExportTableData" ref="downloadDialogRef" />
+    <DownloadDialog
+      @export="getExportTableData"
+      :isHideSelectColumn="true"
+      ref="downloadDialogRef"
+    />
     <LogDialog ref="logDialogRef" />
   </div>
 </template>

+ 7 - 1
src/views/AIApiLog/src/components/TableView/src/components/DownloadDialog.vue

@@ -1,4 +1,10 @@
 <script setup lang="ts">
+const props = withDefaults(
+  defineProps<{
+    isHideSelectColumn: boolean
+  }>(),
+  { isHideSelectColumn: false }
+)
 const dialogVisible = ref(false)
 
 const openDialog = (selectedColumns: string[], slectedDataNumber: number) => {
@@ -41,7 +47,7 @@ defineExpose({
             }}</span>
           </div>
         </div>
-        <div class="download-filter">
+        <div class="download-filter" v-if="!props.isHideSelectColumn">
           <el-radio-group v-model="downloadFilter">
             <el-radio :value="1"
               >Download with selected columns

+ 29 - 29
src/views/ChatLog/src/ChatLog.vue

@@ -2,20 +2,20 @@
 import { useCalculatingHeight } from '@/hooks/calculatingHeight'
 import TableView from './components/TableView'
 import LogDialog from '@/views/AIApiLog/src/components/LogDialog.vue'
+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: '',
-  userType: '',
+  text_search: '',
+  question_time_start: '',
+  question_time_end: '',
+  user_type: '',
   questionType: '',
   answerType: '',
-  answerSatisfaction: '',
-  comparator: 'thanOrEqual',
-  responseDuration: 0
+  answer_satisfication: '',
+  response_duration_type: 'thanOrEqual',
+  response_duration_num: 0
 })
 
 const userTypeList = [
@@ -31,29 +31,29 @@ const userTypeList = [
 const questionTypeList = [
   {
     label: 'Predefined Question',
-    value: 'predefinedQuestion'
+    value: 'Predefined Question'
   },
   {
-    label: 'free text',
-    value: 'freeText'
+    label: 'Free Text',
+    value: 'Free Text'
   }
 ]
 const AnswerTypeList = [
   {
     label: 'Suspend',
-    value: 'suspend'
+    value: 'Suspend'
   },
   {
     label: 'Timeout',
-    value: 'timeout'
+    value: 'Timeout'
   },
   {
     label: 'Predefined Template',
-    value: 'predefinedTemplate'
+    value: 'Predefined Template'
   },
   {
     label: 'AI Answer',
-    value: 'AIAnswer'
+    value: 'AI Answer'
   }
 ]
 const answerSatisfactionList = [
@@ -71,7 +71,7 @@ const answerSatisfactionList = [
   }
 ]
 
-const comparatorList = [
+const response_duration_typeList = [
   {
     label: '>=',
     value: 'thanOrEqual'
@@ -88,12 +88,12 @@ const comparatorList = [
 const tableRef = ref()
 
 const Search = () => {
-  tableRef.value.SearchOperationLog(searchData.value)
+  tableRef.value.searchTableData(searchData.value)
 }
 const DateChange = (date: any) => {
-  searchData.value.startDate = date[0]
-  searchData.value.endDate = date[1]
-  tableRef.value.SearchOperationLog(searchData.value)
+  searchData.value.question_time_start = dayjs(date[0]).format('YYYY-MM-DD')
+  searchData.value.question_time_end = dayjs(date[1]).format('YYYY-MM-DD')
+  tableRef.value.searchTableData(searchData.value)
 }
 
 const logDialogRef = ref()
@@ -109,7 +109,7 @@ const openDialog = () => {
         <div class="input-tips_filter">
           <el-input
             placeholder="Search Question ID、User"
-            v-model="OperationSearch"
+            v-model="searchData.text_search"
             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.userType" placeholder="User Type">
+          <el-select v-model="searchData.user_type" placeholder="User Type">
             <el-option
               v-for="item in userTypeList"
               :key="item.value"
@@ -158,7 +158,7 @@ const openDialog = () => {
           </el-select>
         </div>
         <div class="tips_filter">
-          <el-select v-model="searchData.answerSatisfaction" placeholder="Answer Satisfaction">
+          <el-select v-model="searchData.answer_satisfication" placeholder="Answer Satisfaction">
             <el-option
               v-for="item in answerSatisfactionList"
               :key="item.value"
@@ -168,11 +168,11 @@ const openDialog = () => {
             </el-option>
           </el-select>
         </div>
-        <div class="comparator-tips_filter">
+        <div class="response_duration_type-tips_filter">
           <span>Response Duration</span>
-          <el-select v-model="searchData.comparator" style="width: 70px; margin: 0 6px">
+          <el-select v-model="searchData.response_duration_type" style="width: 70px; margin: 0 6px">
             <el-option
-              v-for="item in comparatorList"
+              v-for="item in response_duration_typeList"
               :key="item.value"
               :label="item.label"
               :value="item.value"
@@ -180,7 +180,7 @@ const openDialog = () => {
             </el-option>
           </el-select>
           <el-input-number
-            v-model="searchData.responseDuration"
+            v-model="searchData.response_duration_num"
             placeholder="s"
             :controls="false"
             :min="0"
@@ -190,7 +190,7 @@ const openDialog = () => {
         <el-button class="el-button--dark" @click="Search">Search</el-button>
       </div>
     </div>
-    <TableView :height="containerHeight" ref="tableRef"></TableView>
+    <TableView :height="containerHeight" :searchData="searchData" ref="tableRef"></TableView>
     <LogDialog ref="logDialogRef" />
   </div>
 </template>
@@ -249,7 +249,7 @@ const openDialog = () => {
   height: 32px;
   margin-right: 8px;
 }
-.comparator-tips_filter {
+.response_duration_type-tips_filter {
   flex: 1;
   display: flex;
   align-items: center;

+ 41 - 16
src/views/ChatLog/src/components/TableView/src/TableView.vue

@@ -2,7 +2,7 @@
 import { ref, nextTick, onMounted } from 'vue'
 import { type VxeGridInstance, type VxeGridProps } from 'vxe-table'
 import DownloadDialog from './components/DownloadDialog.vue'
-// import { autoWidth } from '@/utils/table'
+import { autoWidth } from '@/utils/table'
 import { useRowClickStyle } from '@/hooks/rowClickStyle'
 import dayjs from 'dayjs'
 import { formatTimezone, formatNumber } from '@/utils/tools'
@@ -11,6 +11,10 @@ const props = defineProps({
   height: {
     type: Number,
     default: 440
+  },
+  searchdata: {
+    type: Object,
+    default: () => ({})
   }
 })
 
@@ -58,11 +62,12 @@ const handleColumns = (columns: any, status?: string) => {
 // 获取表格列
 const getTableColumns = async () => {
   tableLoadingColumn.value = true
-  await $api.getOperationTableColumns().then((res: any) => {
+  await $api.getChatLogTableColumn().then((res: any) => {
     if (res.code === 200) {
       tableData.value.columns = [
         { type: 'checkbox', width: 50, fixed: 'left' },
-        ...handleColumns(res.data.OperationTableColumns)
+        ...handleColumns(res.data.OperationTableColumns),
+        { title: 'Action', width: 106, fixed: 'right', slots: { default: 'action' } }
       ]
       tableOriginColumnsField.value = res.data.OperationTableColumns
     }
@@ -88,22 +93,21 @@ const assignTableData = (data: any) => {
     allTable.value.data = data.searchData || []
     // 为了让导出的表格列宽度自适应
     nextTick(() => {
-      // allTableRef.value && autoWidth(allTable.value, allTableRef.value)
+      allTableRef.value && autoWidth(allTable.value, allTableRef.value)
     })
   }, 1000)
 }
 
-let searchdata: any = {}
 // 获取表格数据
 const getTableData = async (isPageChange?: boolean) => {
   const rc = isPageChange ? pageInfo.value.total : -1
   tableLoadingTableData.value = true
   await $api
-    .SearchOperationLog({
+    .getChatLogTableData({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       rc,
-      ...searchdata
+      ...props.searchdata
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -114,16 +118,15 @@ const getTableData = async (isPageChange?: boolean) => {
       selectedNumber.value = 0
       selectedTableData.value = []
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
       })
     })
 }
-const SearchOperationLog = (val: any) => {
-  searchdata = val
+const searchTableData = (val: any) => {
   tableLoadingTableData.value = true
   $api
-    .SearchOperationLog({
+    .getChatLogAllTableData({
       cp: pageInfo.value.pageNo,
       ps: pageInfo.value.pageSize,
       rc: -1,
@@ -138,7 +141,7 @@ const SearchOperationLog = (val: any) => {
       selectedNumber.value = 0
       selectedTableData.value = []
       nextTick(() => {
-        // tableRef.value && autoWidth(tableData.value, tableRef.value)
+        tableRef.value && autoWidth(tableData.value, tableRef.value)
         tableLoadingTableData.value = false
       })
     })
@@ -146,7 +149,7 @@ const SearchOperationLog = (val: any) => {
 onMounted(() => {
   Promise.all([getTableColumns(), getTableData(false)]).finally(() => {
     nextTick(() => {
-      // tableRef.value && autoWidth(tableData.value, tableRef.value)
+      tableRef.value && autoWidth(tableData.value, tableRef.value)
     })
   })
 })
@@ -274,7 +277,7 @@ const getExportTableData = (status: number) => {
   }
   $api
     .OperationLogDownload({
-      selected_fields: column,
+      // selected_fields: column,
       tmp_search: tempSearch.value
     })
     .then((res: any) => {
@@ -331,8 +334,13 @@ const handleCheckAllChange = ({ records }: any) => {
   selectedNumber.value = records.length
   selectedTableData.value = records
 }
+
+const handleLogDetail = (row: any) => {
+  // 打开日志详情对话框
+  downloadDialogRef.value.openDialog(row)
+}
 defineExpose({
-  SearchOperationLog
+  searchTableData
 })
 </script>
 
@@ -367,6 +375,19 @@ defineExpose({
       <template #empty v-if="!tableLoadingTableData && tableData.data.length === 0">
         <VEmpty> </VEmpty>
       </template>
+      <!-- action操作栏的插槽 -->
+      <template #action="{ row }">
+        <el-button
+          style="height: 24px; padding: 8px 4px; padding-left: 5px; font-size: 12px"
+          @click="handleLogDetail(row)"
+        >
+          <span
+            style="margin-right: 2px; font-size: 15px"
+            class="font_family icon-icon_ai_api_log_b"
+          ></span
+          >AI API Log
+        </el-button>
+      </template>
     </vxe-grid>
     <vxe-grid :height="10" ref="allTableRef" class="all-table" v-bind="allTable"> </vxe-grid>
     <div class="bottom-pagination">
@@ -385,7 +406,11 @@ defineExpose({
         />
       </div>
     </div>
-    <DownloadDialog @export="getExportTableData" ref="downloadDialogRef" />
+    <DownloadDialog
+      @export="getExportTableData"
+      ref="downloadDialogRef"
+      :isHideSelectColumn="true"
+    />
   </div>
 </template>
 

+ 7 - 1
src/views/ChatLog/src/components/TableView/src/components/DownloadDialog.vue

@@ -1,4 +1,10 @@
 <script setup lang="ts">
+const props = withDefaults(
+  defineProps<{
+    isHideSelectColumn: boolean
+  }>(),
+  { isHideSelectColumn: false }
+)
 const dialogVisible = ref(false)
 
 const openDialog = (selectedColumns: string[], slectedDataNumber: number) => {
@@ -41,7 +47,7 @@ defineExpose({
             }}</span>
           </div>
         </div>
-        <div class="download-filter">
+        <div class="download-filter" v-if="!props.isHideSelectColumn">
           <el-radio-group v-model="downloadFilter">
             <el-radio :value="1"
               >Download with selected columns

+ 3 - 0
src/views/Layout/src/LayoutView.vue

@@ -55,6 +55,9 @@ const getPrompt = () => {
     }
   })
 }
+onMounted(() => {
+  getPrompt()
+})
 </script>
 <template>
   <el-container class="layout-container">

+ 63 - 6
src/views/Layout/src/components/Menu/MenuView.vue

@@ -10,7 +10,64 @@ const userStore = useUserStore()
 
 const isCollapse = defineModel<boolean>()
 
-const menuList = ref()
+const menuList = ref([
+  {
+    index: '1',
+    label: 'Dashboard',
+    icon: 'icon_data_fill_b',
+    path: '/dashboard'
+  },
+  {
+    index: '2',
+    label: 'Booking',
+    icon: 'icon_booking__fill_b',
+    path: '/booking'
+  },
+  {
+    index: '3',
+    label: 'Tracking',
+    icon: 'icon_tracking__fill_b',
+    path: '/tracking'
+  },
+  {
+    index: '4',
+    label: 'System Management',
+    icon: 'icon_system__management_fill_b',
+    type: 'list',
+    children: [
+      {
+        index: '4-1',
+        label: 'System Message',
+        path: '/system-message'
+      },
+      {
+        index: '4-2',
+        label: 'System Settings',
+        path: '/SystemSettings'
+      },
+      {
+        index: '4-3',
+        label: 'Operation Log',
+        path: '/Operationlog'
+      },
+      {
+        index: '4-4',
+        label: 'Chat Log',
+        path: '/chat-log'
+      },
+      {
+        index: '4-5',
+        label: 'AI API  Log',
+        path: '/ai-api-log'
+      },
+      {
+        index: '4-6',
+        label: 'Prompt Configuration',
+        path: '/PromptConfiguration'
+      }
+    ]
+  }
+])
 watch(
   () => userStore.userInfo?.uname,
   () => {
@@ -18,11 +75,11 @@ watch(
   }
 )
 const getMenuList = () => {
-  $api.getMenuList().then((res) => {
-    if (res.code === 200) {
-      menuList.value = res.data
-    }
-  })
+  // $api.getMenuList().then((res) => {
+  //   if (res.code === 200) {
+  //     menuList.value = res.data
+  //   }
+  // })
 }
 getMenuList()
 //监听窗口大小