diff --git a/pages/Chat/Chat.css b/pages/Chat/Chat.css
index ea8f4e7..ee07b11 100644
--- a/pages/Chat/Chat.css
+++ b/pages/Chat/Chat.css
@@ -507,6 +507,10 @@
font-size: 48rpx;
}
+.chat-btn-group .head-btn:nth-child(4) {
+ /* 刷新按钮 */
+}
+
.log-out {
/* background: #ffd4d4; */
}
diff --git a/pages/Chat/Chat.vue b/pages/Chat/Chat.vue
index 0206869..8d0b219 100644
--- a/pages/Chat/Chat.vue
+++ b/pages/Chat/Chat.vue
@@ -99,10 +99,13 @@
-
-
-
-
+
+
+
+
+
+
+
@@ -839,6 +842,71 @@ import { openFile as openFileNative, downloadAndOpen } from '@/utils/fileOpener.
})
}
+ // 刷新当前会话消息
+ const handleRefresh = async () => {
+ // 1. 重置输入框状态
+ isThinking.value = false
+ isSelfSent.value = false
+ socketStore.isThinking = false
+ textMessage.value = ''
+ uploadedFiles.value = []
+ previewFileArray.value = []
+ // 移除流式消息占位
+ if (streamingMessageId.value) {
+ allmessages.value = allmessages.value.filter(m => m._id !== streamingMessageId.value)
+ streamingMessageId.value = null
+ }
+
+ const titleMap = { 0: 'AI消息', 1: '好友消息', 2: '群聊消息' }
+ const title = titleMap[ChatType.value] || '消息'
+ uni.showLoading({ title: `刷新${title}中...`, mask: true })
+
+ try {
+ // 2. 检查当前 token 是否还有效
+ const token = getToken()
+ if (!token) {
+ uni.hideLoading()
+ uni.showToast({ title: '登录已失效,请重新登录', icon: 'none', duration: 1500 })
+ setTimeout(() => uni.reLaunch({ url: '/pages/Login/Login' }), 1500)
+ return
+ }
+ await getUserInfo(token)
+
+ // 3. 确保 AI 对话模式下 socket 连接正常(PC 离线由 watcher 实时监控)
+ if (ChatType.value === 0 && !socketStore.isConnected) {
+ await handleConnect()
+ }
+
+ // 4. 刷新消息
+ switch (ChatType.value) {
+ case 0:
+ await takeConversationMessages()
+ break
+ case 1:
+ await takeFriendMessages()
+ break
+ case 2:
+ await takeGroupMessages()
+ break
+ default:
+ await takeConversationMessages()
+ break
+ }
+ uni.hideLoading()
+ uni.showToast({ title: '已刷新', icon: 'success', duration: 1200 })
+ } catch (e) {
+ uni.hideLoading()
+ // 区分 token 失效和其他错误
+ const errMsg = typeof e === 'string' ? e : (e?.message || '')
+ if (errMsg.includes('token') || errMsg.includes('Token') || errMsg.includes('登录') || errMsg.includes('过期')) {
+ uni.showToast({ title: '登录已失效,请重新登录', icon: 'none', duration: 1500 })
+ setTimeout(() => uni.reLaunch({ url: '/pages/Login/Login' }), 1500)
+ } else {
+ uni.showToast({ title: '刷新失败', icon: 'error', duration: 1500 })
+ }
+ }
+ }
+
const previewFileArray = ref([])
const uploadPhoto = () => {
console.log('点击了拍照上传');
@@ -1368,7 +1436,10 @@ import { openFile as openFileNative, downloadAndOpen } from '@/utils/fileOpener.
if (!oldVal && newVal) {
console.log('AI开始回复(跨设备同步),锁定输入框');
isThinking.value = true
- // 非本设备发起时,也需要添加流式气泡
+ // 跨设备场景:先加载最新消息(含 PC 发的用户消息),再追加流式气泡
+ if (!isSelfSent.value) {
+ await takeConversationMessages()
+ }
if (!streamingMessageId.value) {
streamingMessageId.value = 'streaming-' + Date.now()
allmessages.value = [...allmessages.value, {
@@ -1416,6 +1487,25 @@ import { openFile as openFileNative, downloadAndOpen } from '@/utils/fileOpener.
}
})
+ // 监听 pc_offline,PC 端下线时立即强制跳转登录页
+ watch(() => socketStore.pcOffline, (offline) => {
+ if (offline) {
+ isThinking.value = false
+ socketStore.isThinking = false
+ socketStore.pcOffline = false
+ uni.showToast({
+ title: 'PC端不在线,请先登录',
+ icon: 'none',
+ duration: 1500
+ })
+ setTimeout(() => {
+ uni.reLaunch({
+ url: '/pages/Login/Login'
+ })
+ }, 1500)
+ }
+ })
+
// 监听流式消息内容,实时更新 AI 回复(流式输出核心)
watch(() => socketStore.messageString, (newContent) => {
if (!streamingMessageId.value || !socketStore.isThinking) return
diff --git a/stores/socket.js b/stores/socket.js
index d51bf4a..941bfe0 100644
--- a/stores/socket.js
+++ b/stores/socket.js
@@ -30,6 +30,7 @@ export const useSocketStore = defineStore('socket', () => {
const maxLogCount = ref(20)
const authFailReason = ref('')
+ const pcOffline = ref(false)
// ==================== 计算属性 ====================
const isConnected = computed(() => connectionStatus.value === 'connected')
@@ -66,6 +67,7 @@ export const useSocketStore = defineStore('socket', () => {
...config.value,
...options
}
+ pcOffline.value = false // 每次连接时重置 PC 离线标记
addLog('info',
`准备连接WebSocket。Token:${config.value.token || '未设置'}。ConversationId: ${config.value.conversationId || '未设置'}`
)
@@ -182,6 +184,7 @@ export const useSocketStore = defineStore('socket', () => {
break
case 'pc_offline':
+ pcOffline.value = true
addLog('warn', 'PC 端已离线')
break
@@ -287,6 +290,7 @@ export const useSocketStore = defineStore('socket', () => {
logs,
config,
authFailReason,
+ pcOffline,
// 计算属性
isConnected,