From 68a82fa2ec3e315ac75d160865bac035e2cc696a Mon Sep 17 00:00:00 2001 From: tim Date: Sun, 7 Sep 2025 23:50:11 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E5=9B=9E=E5=A4=8Dui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/pages/message-box/[id].vue | 47 +++++++++++++++++++++++- frontend_nuxt/plugins/iconpark.client.ts | 2 + 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/frontend_nuxt/pages/message-box/[id].vue b/frontend_nuxt/pages/message-box/[id].vue index 4e07ac7da..206a89e99 100644 --- a/frontend_nuxt/pages/message-box/[id].vue +++ b/frontend_nuxt/pages/message-box/[id].vue @@ -36,7 +36,11 @@
-
{{ item.replyTo.sender.username }}
+
+ + +
{{ item.replyTo.sender.username }}:
+
@@ -63,11 +67,17 @@
+
+ +
有5条新消息
+
+
正在回复 {{ replyTo.sender.username }}: {{ stripMarkdownLength(replyTo.content, 50) }}
+
@@ -454,7 +464,6 @@ function goBack() { } .chat-container.float { - height: 100vh; } .chat-header { @@ -555,6 +564,21 @@ function goBack() { gap: 10px; } +.new-message-container { + display: flex; + + flex-direction: row; + align-items: center; + gap: 5px; + cursor: pointer; + border: 1px solid var(--normal-border-color); + border-radius: 20px; + padding: 3px 6px; + box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1); + width: fit-content; + margin: auto; +} + .user-name { font-size: 14px; font-weight: 600; @@ -608,6 +632,18 @@ function goBack() { margin-right: 10px; } +.reply-icon { + color: var(--primary-color); + margin-right: 5px; +} + +.reply-avatar { + width: 20px; + height: 20px; + border-radius: 50%; + margin-right: 5px; +} + .reply-preview { margin-top: 10px; padding: 10px; @@ -617,9 +653,16 @@ function goBack() { background-color: var(--normal-light-background-color); } +.reply-header { + display: flex; + flex-direction: row; + align-items: center; +} + .reply-author { font-weight: bold; margin-bottom: 2px; + opacity: 0.5; } .reply-btn { diff --git a/frontend_nuxt/plugins/iconpark.client.ts b/frontend_nuxt/plugins/iconpark.client.ts index 33efc8a73..ab87cc6bf 100644 --- a/frontend_nuxt/plugins/iconpark.client.ts +++ b/frontend_nuxt/plugins/iconpark.client.ts @@ -73,6 +73,7 @@ import { RobotOne, Server, Protection, + DoubleDown, } from '@icon-park/vue-next' export default defineNuxtPlugin((nuxtApp) => { @@ -149,4 +150,5 @@ export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.component('RobotOne', RobotOne) nuxtApp.vueApp.component('ServerIcon', Server) nuxtApp.vueApp.component('Protection', Protection) + nuxtApp.vueApp.component('DoubleDown', DoubleDown) }) From ad481cffca86d9973a655cd159e274d47e1902eb Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Sun, 7 Sep 2025 23:57:06 +0800 Subject: [PATCH 2/2] feat: add floating new message indicator --- frontend_nuxt/pages/message-box/[id].vue | 34 +++++++++++++++++------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/frontend_nuxt/pages/message-box/[id].vue b/frontend_nuxt/pages/message-box/[id].vue index 206a89e99..58e43962e 100644 --- a/frontend_nuxt/pages/message-box/[id].vue +++ b/frontend_nuxt/pages/message-box/[id].vue @@ -67,9 +67,13 @@
-
+
-
有5条新消息
+
有{{ newMessagesCount }}条新消息
@@ -130,6 +134,7 @@ const isChannel = ref(false) const isFloatMode = computed(() => route.query.float !== undefined) const floatRoute = useState('messageFloatRoute') const replyTo = ref(null) +const newMessagesCount = ref(0) const isUserNearBottom = ref(true) function updateNearBottom() { @@ -137,6 +142,9 @@ function updateNearBottom() { if (!el) return const threshold = 40 // px isUserNearBottom.value = el.scrollHeight - el.scrollTop - el.clientHeight <= threshold + if (isUserNearBottom.value) { + newMessagesCount.value = 0 + } } const hasMoreMessages = computed(() => currentPage.value < totalPages.value - 1) @@ -180,6 +188,11 @@ function scrollToBottomInstant() { el.scrollTop = el.scrollHeight } +function handleScrollToBottom() { + scrollToBottomSmooth() + newMessagesCount.value = 0 +} + async function fetchMessages(page = 0) { if (page === 0) { loading.value = true @@ -311,6 +324,7 @@ async function sendMessage(content, clearInput) { await nextTick() // 仅“发送消息成功后”才平滑滚动到底部 scrollToBottomSmooth() + newMessagesCount.value = 0 } catch (e) { toast.error(e.message) } finally { @@ -383,6 +397,8 @@ const subscribeToConversation = () => { if (isUserNearBottom.value) { scrollToBottomSmooth() + } else { + newMessagesCount.value += 1 } } catch (e) { console.error('Failed to parse websocket message', e) @@ -566,7 +582,6 @@ function goBack() { .new-message-container { display: flex; - flex-direction: row; align-items: center; gap: 5px; @@ -576,7 +591,12 @@ function goBack() { padding: 3px 6px; box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1); width: fit-content; - margin: auto; + position: absolute; + bottom: calc(100% + 20px); + left: 50%; + transform: translateX(-50%); + z-index: 10; + background-color: var(--background-color); } .user-name { @@ -609,11 +629,6 @@ function goBack() { border-bottom-left-radius: 4px; } -.message-input-area { - margin-left: 20px; - margin-right: 20px; -} - .loading-container { display: flex; justify-content: center; @@ -630,6 +645,7 @@ function goBack() { .message-input-area { margin-left: 10px; margin-right: 10px; + position: relative; } .reply-icon {