瀏覽代碼

会话记录保存实现

Zhangbw 2 月之前
父節點
當前提交
d12568a8e7
共有 3 個文件被更改,包括 116 次插入54 次删除
  1. 5 5
      src/api/talk/session/index.ts
  2. 2 11
      src/api/talk/session/types.ts
  3. 109 38
      src/views/talk/session/index.vue

+ 5 - 5
src/api/talk/session/index.ts

@@ -3,7 +3,7 @@ import { SessionVO, SessionQuery, SessionForm } from './types';
 
 export function listSession(query: SessionQuery) {
   return request({
-    url: '/talk/session/list',
+    url: '/talk/admin/session/list',
     method: 'get',
     params: query
   });
@@ -11,14 +11,14 @@ export function listSession(query: SessionQuery) {
 
 export function getSession(id: string | number) {
   return request({
-    url: '/talk/session/' + id,
+    url: '/talk/admin/session/' + id,
     method: 'get'
   });
 }
 
 export function addSession(data: SessionForm) {
   return request({
-    url: '/talk/session',
+    url: '/talk/admin/session',
     method: 'post',
     data: data
   });
@@ -26,7 +26,7 @@ export function addSession(data: SessionForm) {
 
 export function updateSession(data: SessionForm) {
   return request({
-    url: '/talk/session',
+    url: '/talk/admin/session',
     method: 'put',
     data: data
   });
@@ -34,7 +34,7 @@ export function updateSession(data: SessionForm) {
 
 export function delSession(id: string | number | Array<string | number>) {
   return request({
-    url: '/talk/session/' + id,
+    url: '/talk/admin/session/' + id,
     method: 'delete'
   });
 }

+ 2 - 11
src/api/talk/session/types.ts

@@ -2,13 +2,9 @@ export interface SessionVO {
   id: string | number;
   sessionId: string;
   agentId: number;
+  userId?: number;
   customerPhone?: string;
   conversationJson?: string;
-  messageCount: number;
-  userMessageCount: number;
-  agentMessageCount: number;
-  duration?: number;
-  status: string;
   startTime?: string;
   endTime?: string;
   createTime?: string;
@@ -21,11 +17,6 @@ export interface SessionForm {
   agentId?: number;
   customerPhone?: string;
   conversationJson?: string;
-  messageCount?: number;
-  userMessageCount?: number;
-  agentMessageCount?: number;
-  duration?: number;
-  status?: string;
   startTime?: string;
   endTime?: string;
 }
@@ -34,7 +25,7 @@ export interface SessionQuery extends PageQuery {
   sessionId?: string;
   agentId?: number;
   customerPhone?: string;
-  status?: string;
+  userId?: number;
   startTime?: string;
   endTime?: string;
 }

+ 109 - 38
src/views/talk/session/index.vue

@@ -4,8 +4,8 @@
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="会话唯一标识" prop="sessionId">
-              <el-input v-model="queryParams.sessionId" placeholder="请输入会话唯一标识" clearable @keyup.enter="handleQuery" />
+            <el-form-item label="会话标识" prop="sessionId">
+              <el-input v-model="queryParams.sessionId" placeholder="请输入会话标识" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="客服ID" prop="agentId">
               <el-input v-model="queryParams.agentId" placeholder="请输入客服ID" clearable @keyup.enter="handleQuery" />
@@ -13,26 +13,24 @@
             <el-form-item label="客户电话" prop="customerPhone">
               <el-input v-model="queryParams.customerPhone" placeholder="请输入客户电话" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="会话状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="请选择会话状态" clearable>
-                <el-option label="进行中" value="0" />
-                <el-option label="已结束" value="1" />
-              </el-select>
+            <el-form-item label="创建人" prop="userId">
+              <el-input v-model="queryParams.userId" placeholder="请输入创建人ID" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="会话开始时间" prop="startTime">
+            <div style="width: 100%"></div>
+            <el-form-item label="开始时间" prop="startTime">
               <el-date-picker clearable
                 v-model="queryParams.startTime"
                 type="date"
                 value-format="YYYY-MM-DD"
-                placeholder="请选择会话开始时间"
+                placeholder="请选择开始时间"
               />
             </el-form-item>
-            <el-form-item label="会话结束时间" prop="endTime">
+            <el-form-item label="结束时间" prop="endTime">
               <el-date-picker clearable
                 v-model="queryParams.endTime"
                 type="date"
                 value-format="YYYY-MM-DD"
-                placeholder="请选择会话结束时间"
+                placeholder="请选择结束时间"
               />
             </el-form-item>
             <el-form-item>
@@ -59,27 +57,17 @@
 
       <el-table v-loading="loading" border :data="sessionList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="会话ID" align="center" prop="id" v-if="false" />
+        <el-table-column label="会话ID" align="center" prop="id" width="80" />
         <el-table-column label="会话标识" align="center" prop="sessionId" width="200" show-overflow-tooltip />
         <el-table-column label="客服ID" align="center" prop="agentId" />
         <el-table-column label="客户电话" align="center" prop="customerPhone" />
-        <el-table-column label="消息总数" align="center" prop="messageCount" />
-        <el-table-column label="用户消息数" align="center" prop="userMessageCount" />
-        <el-table-column label="客服消息数" align="center" prop="agentMessageCount" />
-        <el-table-column label="对话时长(秒)" align="center" prop="duration" />
-        <el-table-column label="会话状态" align="center" prop="status">
-          <template #default="scope">
-            <el-tag :type="scope.row.status === '0' ? 'warning' : 'success'">
-              {{ scope.row.status === '0' ? '进行中' : '已结束' }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="会话开始时间" align="center" prop="startTime" width="180">
+        <el-table-column label="创建人" align="center" prop="userId" />
+        <el-table-column label="开始时间" align="center" prop="startTime" width="180">
           <template #default="scope">
             <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}') }}</span>
           </template>
         </el-table-column>
-        <el-table-column label="会话结束时间" align="center" prop="endTime" width="180">
+        <el-table-column label="结束时间" align="center" prop="endTime" width="180">
           <template #default="scope">
             <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}:{i}') }}</span>
           </template>
@@ -105,21 +93,24 @@
         <el-descriptions-item label="会话标识">{{ sessionDetail.sessionId }}</el-descriptions-item>
         <el-descriptions-item label="客服ID">{{ sessionDetail.agentId }}</el-descriptions-item>
         <el-descriptions-item label="客户电话">{{ sessionDetail.customerPhone }}</el-descriptions-item>
-        <el-descriptions-item label="会话状态">
-          <el-tag :type="sessionDetail.status === '0' ? 'warning' : 'success'">
-            {{ sessionDetail.status === '0' ? '进行中' : '已结束' }}
-          </el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="消息总数">{{ sessionDetail.messageCount }}</el-descriptions-item>
-        <el-descriptions-item label="用户消息数">{{ sessionDetail.userMessageCount }}</el-descriptions-item>
-        <el-descriptions-item label="客服消息数">{{ sessionDetail.agentMessageCount }}</el-descriptions-item>
-        <el-descriptions-item label="对话时长">{{ sessionDetail.duration }}秒</el-descriptions-item>
+        <el-descriptions-item label="创建人">{{ sessionDetail.userId }}</el-descriptions-item>
         <el-descriptions-item label="开始时间">{{ parseTime(sessionDetail.startTime) }}</el-descriptions-item>
         <el-descriptions-item label="结束时间">{{ parseTime(sessionDetail.endTime) }}</el-descriptions-item>
       </el-descriptions>
       <el-divider content-position="left">对话内容</el-divider>
       <div class="conversation-content">
-        <pre>{{ sessionDetail.conversationJson }}</pre>
+        <div v-if="parsedConversation.length > 0" class="message-list">
+          <div v-for="(msg, index) in parsedConversation" :key="index" class="message-item">
+            <div class="message-header">
+              <span class="message-role" :class="msg.role === 'user' ? 'user-role' : 'assistant-role'">
+                {{ msg.role === 'user' ? 'User' : 'AI' }}
+              </span>
+              <span class="message-time">{{ formatTimestamp(msg.timestamp) }}</span>
+            </div>
+            <div class="message-content">{{ msg.content }}</div>
+          </div>
+        </div>
+        <div v-else class="empty-conversation">暂无对话内容</div>
       </div>
       <template #footer>
         <div class="dialog-footer">
@@ -159,7 +150,7 @@ const data = reactive<PageData<any, SessionQuery>>({
     sessionId: undefined,
     agentId: undefined,
     customerPhone: undefined,
-    status: undefined,
+    userId: undefined,
     startTime: undefined,
     endTime: undefined
   },
@@ -168,6 +159,33 @@ const data = reactive<PageData<any, SessionQuery>>({
 
 const { queryParams } = toRefs(data);
 
+/** 解析对话内容 */
+const parsedConversation = computed(() => {
+  if (!sessionDetail.value.conversationJson) {
+    return [];
+  }
+  try {
+    return JSON.parse(sessionDetail.value.conversationJson);
+  } catch (e) {
+    console.error('解析对话内容失败:', e);
+    return [];
+  }
+});
+
+/** 格式化时间戳 */
+const formatTimestamp = (timestamp: string) => {
+  if (!timestamp) return '';
+  const date = new Date(parseInt(timestamp));
+  return date.toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit',
+    second: '2-digit'
+  });
+};
+
 /** 查询会话列表 */
 const getList = async () => {
   loading.value = true;
@@ -232,9 +250,62 @@ onMounted(() => {
   border-radius: 4px;
 }
 
-.conversation-content pre {
+.message-list {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+}
+
+.message-item {
+  background: white;
+  padding: 12px;
+  border-radius: 8px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.message-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 8px;
+  padding-bottom: 6px;
+  border-bottom: 1px solid #e5e7eb;
+}
+
+.message-role {
+  font-weight: 600;
+  font-size: 14px;
+  padding: 2px 8px;
+  border-radius: 4px;
+}
+
+.user-role {
+  background-color: #dbeafe;
+  color: #1e40af;
+}
+
+.assistant-role {
+  background-color: #dcfce7;
+  color: #166534;
+}
+
+.message-time {
+  font-size: 12px;
+  color: #6b7280;
+}
+
+.message-content {
+  font-size: 14px;
+  line-height: 1.6;
+  color: #374151;
   white-space: pre-wrap;
   word-wrap: break-word;
-  margin: 0;
+}
+
+.empty-conversation {
+  text-align: center;
+  color: #9ca3af;
+  padding: 20px;
+  font-size: 14px;
 }
 </style>