feat: 消息会话的调整和增加时间戳
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
<ChatRoleMe v-if="msg.messageRole === MessageRole.ME" :msg="msg">
|
||||
<template #header>
|
||||
<!-- 名字和时间 -->
|
||||
<ChatNameTime :showReverse="true" />
|
||||
<ChatNameTime :showReverse="true" :msg="msg" />
|
||||
</template>
|
||||
</ChatRoleMe>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<ChatRoleAI v-if="msg.messageRole === MessageRole.AI" :msg="msg">
|
||||
<template #header>
|
||||
<!-- 名字和时间 -->
|
||||
<ChatNameTime :showReverse="false" />
|
||||
<ChatNameTime :showReverse="false" :msg="msg" />
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
@@ -316,6 +316,7 @@ const loadConversationMessages = async (convId: string) => {
|
||||
messageId: msg.messageId,
|
||||
messageRole: msg.messageSenderRole === 'user' ? MessageRole.ME : MessageRole.AI,
|
||||
messageContent: msg.messageContent,
|
||||
timestamp: msg.timestamp,
|
||||
finished: true, // 历史消息已完成
|
||||
}));
|
||||
console.log("加载历史消息:", chatMsgList.value);
|
||||
@@ -348,7 +349,8 @@ const initWebSocket = async () => {
|
||||
|
||||
// 使用配置的WebSocket服务器地址
|
||||
const token = getAccessToken();
|
||||
const wsUrl = `wss://onefeel.brother7.cn/ingress/agent/ws/chat?access_token=${token}`;
|
||||
// const wsUrl = `wss://onefeel.brother7.cn/ingress/agent/ws/chat?access_token=${token}`;
|
||||
const wsUrl = `wss://onefeel.brother7.cn/ingress/nianxx/ws?token=${token}`;
|
||||
// 初始化WebSocket管理器
|
||||
webSocketManager = new WebSocketManager({
|
||||
wsUrl: wsUrl,
|
||||
@@ -408,6 +410,17 @@ const initWebSocket = async () => {
|
||||
// 处理WebSocket消息
|
||||
const handleWebSocketMessage = (data: any) => {
|
||||
console.log("收到WebSocket消息:", data);
|
||||
|
||||
if (data.type === 'notification' && data.event === 'connected') {
|
||||
console.log("WebSocket连接已建立,服务器消息:", data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type === 'heartbeat') {
|
||||
console.log("收到心跳消息:", data);
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证关键字段(若服务端传回 conversationId/agentId,则校验是否属于当前会话)
|
||||
if (data.conversationId && data.conversationId !== conversationId.value) {
|
||||
console.warn("收到不属于当前会话的消息,忽略", data.conversationId);
|
||||
@@ -428,7 +441,7 @@ const handleWebSocketMessage = (data: any) => {
|
||||
}
|
||||
|
||||
// 优先使用 messageId 进行匹配
|
||||
const msgId = data.messageId || data.id || data.msgId;
|
||||
const msgId = data.messageId || data.reply_message_id || data.id || data.msgId;
|
||||
let aiMsgIndex = -1;
|
||||
if (msgId && pendingMap.has(msgId)) {
|
||||
aiMsgIndex = pendingMap.get(msgId);
|
||||
@@ -462,8 +475,14 @@ const handleWebSocketMessage = (data: any) => {
|
||||
nextTick(() => scrollToBottom());
|
||||
}
|
||||
|
||||
/// 对于通知类消息,如果没有明确的完成状态,默认视为已完成,触发后续处理逻辑(例如心跳、连接建立等事件)
|
||||
if (data.type === 'notification') {
|
||||
data.finish = data.finish || true; // 确保 finish 字段存在
|
||||
}
|
||||
|
||||
// 处理完成状态
|
||||
if (data.finish) {
|
||||
chatMsgList.value[aiMsgIndex].timestamp = Date.now();
|
||||
chatMsgList.value[aiMsgIndex].finished = data.finish;
|
||||
const msg = chatMsgList.value[aiMsgIndex].messageContent;
|
||||
if (!msg || chatMsgList.value[aiMsgIndex].isLoading) {
|
||||
@@ -554,6 +573,7 @@ const sendMessage = async (message: string, isInstruct: boolean = false) => {
|
||||
messageId: IdUtils.generateMessageId(),
|
||||
messageRole: MessageRole.ME,
|
||||
messageContent: message,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
chatMsgList.value.push(newMsg);
|
||||
inputMessage.value = "";
|
||||
|
||||
@@ -1,17 +1,65 @@
|
||||
<template>
|
||||
<div class="flex items-start gap-2 pt-0.5 mb-2" :class="showReverse ? 'flex-row-reverse' : 'flex-row'">
|
||||
<span class="text-xs text-[#4E5969]"> ZHINIAN</span>
|
||||
<span class="text-xs text-[#86909C]"> 20:30</span>
|
||||
<div class="flex items-start gap-2 pt-0.5 mb-2" :class="props.showReverse ? 'flex-row-reverse' : 'flex-row'">
|
||||
<span class="text-xs text-[#4E5969]">{{ props.msg?.messageRole === MessageRole.AI ? 'NIANXX' : '我' }}</span>
|
||||
<span class="text-xs text-[#86909C]">{{ formattedTime }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { ChatMessage, MessageRole } from '../model/ChatModel'
|
||||
|
||||
interface Props {
|
||||
showReverse: boolean
|
||||
msg?: ChatMessage
|
||||
showReverse?: boolean
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showReverse: false
|
||||
})
|
||||
|
||||
const formattedTime = computed(() => {
|
||||
const tsRaw = props.msg?.timestamp
|
||||
if (tsRaw == null) return ''
|
||||
let ts = Number(tsRaw)
|
||||
if (isNaN(ts)) return ''
|
||||
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
|
||||
// Heuristic:
|
||||
// - If ts < 1e9, treat as a duration in seconds and convert to dd-hh-mm (legacy)
|
||||
// - If ts looks like an epoch (seconds or ms) format to YYYY年MM月DD日 HH:mm:ss
|
||||
if (ts < 1e9) {
|
||||
const totalSeconds = Math.floor(ts)
|
||||
const days = Math.floor(totalSeconds / 86400)
|
||||
const hours = Math.floor((totalSeconds % 86400) / 3600)
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60)
|
||||
return `${String(days).padStart(2, '0')}-${pad(hours)}-${pad(minutes)}`
|
||||
}
|
||||
|
||||
// epoch handling: convert seconds -> ms when appropriate
|
||||
if (ts < 1e12) ts = ts * 1000
|
||||
const d = new Date(ts)
|
||||
if (isNaN(d.getTime())) return ''
|
||||
const Y = d.getFullYear()
|
||||
const M = pad(d.getMonth() + 1)
|
||||
const D = pad(d.getDate())
|
||||
const h = pad(d.getHours())
|
||||
const m = pad(d.getMinutes())
|
||||
const s = pad(d.getSeconds())
|
||||
|
||||
// If the timestamp is the same calendar day as today, show only time HH:mm:ss
|
||||
const now = new Date()
|
||||
const sameDay = now.getFullYear() === d.getFullYear()
|
||||
&& now.getMonth() === d.getMonth()
|
||||
&& now.getDate() === d.getDate()
|
||||
|
||||
if (sameDay) {
|
||||
return `${h}:${m}:${s}`
|
||||
}
|
||||
|
||||
// otherwise show YYYY-MM-DD HH:mm:ss
|
||||
return `${Y}-${M}-${D} ${h}:${m}:${s}`
|
||||
})
|
||||
|
||||
</script>
|
||||
@@ -24,6 +24,8 @@ export class ChatMessage {
|
||||
toolCall?: any;
|
||||
// 问题信息
|
||||
question?: string;
|
||||
// 时间戳
|
||||
timestamp?: number;
|
||||
|
||||
constructor(
|
||||
messageId: string,
|
||||
@@ -32,7 +34,8 @@ export class ChatMessage {
|
||||
isLoading: boolean = false,
|
||||
finished: boolean = false,
|
||||
toolCall?: any,
|
||||
question?: any
|
||||
question?: any,
|
||||
timestamp?: number
|
||||
) {
|
||||
this.messageId = messageId;
|
||||
this.messageRole = messageRole;
|
||||
@@ -41,5 +44,6 @@ export class ChatMessage {
|
||||
this.finished = finished;
|
||||
this.toolCall = toolCall;
|
||||
this.question = question;
|
||||
this.timestamp = timestamp || Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user