mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-04-21 03:17:28 +08:00
feat:Websocket服务拆到单独服务,主后台保持单工通信
This commit is contained in:
@@ -100,10 +100,9 @@ import BasePlaceholder from '~/components/BasePlaceholder.vue'
|
||||
const config = useRuntimeConfig()
|
||||
const route = useRoute()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
const { connect, disconnect, subscribe, isConnected } = useWebSocket()
|
||||
const { connect, subscribe, unsubscribe, isConnected } = useWebSocket()
|
||||
const { fetchUnreadCount: refreshGlobalUnreadCount } = useUnreadCount()
|
||||
const { fetchChannelUnread: refreshChannelUnread } = useChannelsUnreadCount()
|
||||
let subscription = null
|
||||
|
||||
const messages = ref([])
|
||||
const participants = ref([])
|
||||
@@ -338,8 +337,12 @@ onMounted(async () => {
|
||||
// 初次进入频道时,平滑滚动到底部
|
||||
scrollToBottomSmooth()
|
||||
const token = getToken()
|
||||
if (token && !isConnected.value) {
|
||||
connect(token)
|
||||
if (token) {
|
||||
if (isConnected.value) {
|
||||
subscribeToConversation()
|
||||
} else {
|
||||
connect(token)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast.error('请先登录')
|
||||
@@ -347,26 +350,39 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
const subscribeToConversation = () => {
|
||||
if (!currentUser.value) return;
|
||||
const destination = `/topic/conversation/${conversationId}`
|
||||
|
||||
subscribe(destination, async (message) => {
|
||||
try {
|
||||
const parsedMessage = JSON.parse(message.body)
|
||||
|
||||
if (parsedMessage.sender && parsedMessage.sender.id === currentUser.value.id) {
|
||||
return
|
||||
}
|
||||
|
||||
messages.value.push({
|
||||
...parsedMessage,
|
||||
src: parsedMessage.sender.avatar,
|
||||
iconClick: () => openUser(parsedMessage.sender.id),
|
||||
})
|
||||
|
||||
await markConversationAsRead()
|
||||
await nextTick()
|
||||
|
||||
if (isUserNearBottom.value) {
|
||||
scrollToBottomSmooth()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse websocket message", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(isConnected, (newValue) => {
|
||||
if (newValue) {
|
||||
setTimeout(() => {
|
||||
subscription = subscribe(`/topic/conversation/${conversationId}`, async (message) => {
|
||||
// 避免重复显示当前用户发送的消息
|
||||
if (message.sender.id !== currentUser.value.id) {
|
||||
messages.value.push({
|
||||
...message,
|
||||
src: message.sender.avatar,
|
||||
iconClick: () => {
|
||||
openUser(message.sender.id)
|
||||
},
|
||||
})
|
||||
// 收到消息后只标记已读,不强制滚动(符合“非发送不拉底”)
|
||||
markConversationAsRead()
|
||||
await nextTick()
|
||||
updateNearBottom()
|
||||
}
|
||||
})
|
||||
}, 500)
|
||||
subscribeToConversation()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -378,7 +394,12 @@ onActivated(async () => {
|
||||
await nextTick()
|
||||
scrollToBottomSmooth()
|
||||
updateNearBottom()
|
||||
if (!isConnected.value) {
|
||||
|
||||
if (isConnected.value) {
|
||||
// 如果已连接,重新订阅
|
||||
subscribeToConversation()
|
||||
} else {
|
||||
// 如果未连接,则发起连接
|
||||
const token = getToken()
|
||||
if (token) connect(token)
|
||||
}
|
||||
@@ -386,22 +407,17 @@ onActivated(async () => {
|
||||
})
|
||||
|
||||
onDeactivated(() => {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe()
|
||||
subscription = null
|
||||
}
|
||||
disconnect()
|
||||
const destination = `/topic/conversation/${conversationId}`
|
||||
unsubscribe(destination)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe()
|
||||
subscription = null
|
||||
}
|
||||
const destination = `/topic/conversation/${conversationId}`
|
||||
unsubscribe(destination)
|
||||
|
||||
if (messagesListEl.value) {
|
||||
messagesListEl.value.removeEventListener('scroll', updateNearBottom)
|
||||
}
|
||||
disconnect()
|
||||
})
|
||||
|
||||
function minimize() {
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onUnmounted, watch, onActivated, computed } from 'vue'
|
||||
import { ref, onUnmounted, watch, onActivated, computed, onDeactivated } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getToken, fetchCurrentUser } from '~/utils/auth'
|
||||
import { toast } from '~/main'
|
||||
@@ -139,11 +139,10 @@ const error = ref(null)
|
||||
const route = useRoute()
|
||||
const currentUser = ref(null)
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
const { connect, disconnect, subscribe, isConnected } = useWebSocket()
|
||||
const { connect, subscribe, unsubscribe, isConnected } = useWebSocket()
|
||||
const { fetchUnreadCount: refreshGlobalUnreadCount } = useUnreadCount()
|
||||
const { fetchChannelUnread: refreshChannelUnread, setFromList: setChannelUnreadFromList } =
|
||||
useChannelsUnreadCount()
|
||||
let subscription = null
|
||||
|
||||
const activeTab = ref('channels')
|
||||
const tabs = [
|
||||
@@ -259,37 +258,45 @@ onActivated(async () => {
|
||||
refreshGlobalUnreadCount()
|
||||
refreshChannelUnread()
|
||||
const token = getToken()
|
||||
if (token && !isConnected.value) {
|
||||
connect(token)
|
||||
if (token) {
|
||||
if (isConnected.value) {
|
||||
// 如果已经连接,但可能因为组件销毁而取消了订阅,所以需要重新订阅
|
||||
subscribeToUserMessages()
|
||||
} else {
|
||||
// 如果未连接,则发起连接,连接成功后 watch 回调会处理订阅
|
||||
connect(token)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
watch(isConnected, (newValue) => {
|
||||
if (newValue && currentUser.value) {
|
||||
const destination = `/topic/user/${currentUser.value.id}/messages`
|
||||
|
||||
// 清理旧的订阅
|
||||
if (subscription) {
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
|
||||
subscription = subscribe(destination, (message) => {
|
||||
const subscribeToUserMessages = () => {
|
||||
if (!currentUser.value) return;
|
||||
const destination = `/topic/user/${currentUser.value.id}/messages`
|
||||
|
||||
subscribe(destination, (message) => {
|
||||
if (activeTab.value === 'messages') {
|
||||
fetchConversations()
|
||||
if (activeTab.value === 'channels') {
|
||||
fetchChannels()
|
||||
}
|
||||
})
|
||||
}
|
||||
fetchChannels()
|
||||
refreshGlobalUnreadCount()
|
||||
refreshChannelUnread()
|
||||
})
|
||||
}
|
||||
|
||||
watch(isConnected, (newValue) => {
|
||||
if (newValue) {
|
||||
subscribeToUserMessages()
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe()
|
||||
onDeactivated(() => {
|
||||
if (currentUser.value) {
|
||||
const destination = `/topic/user/${currentUser.value.id}/messages`
|
||||
unsubscribe(destination)
|
||||
}
|
||||
disconnect()
|
||||
})
|
||||
|
||||
function goToConversation(id) {
|
||||
|
||||
Reference in New Issue
Block a user