From 597bc09c57a1d126c526420b761cae5fc5a47a41 Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:15:22 +0800 Subject: [PATCH 1/5] fix: offset vditor toolbar when pinned --- frontend/src/assets/global.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css index 1eaff1765..88432945e 100644 --- a/frontend/src/assets/global.css +++ b/frontend/src/assets/global.css @@ -65,7 +65,11 @@ body { *************************/ .vditor { min-height: 200px; -} +} +.vditor-toolbar--pin { + top: var(--header-height) !important; + z-index: 900 !important; +} /* .vditor { --textarea-background-color: transparent; border: none !important; From f5a3206f36fe947f7a8627c76ef806de97cb6894 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 6 Aug 2025 17:23:19 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20sticky=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/assets/global.css | 3 ++- frontend/src/views/AboutPageView.vue | 4 +--- frontend/src/views/HomePageView.vue | 2 +- frontend/src/views/MessagePageView.vue | 2 +- frontend/src/views/NewPostPageView.vue | 2 -- frontend/src/views/ProfileView.vue | 5 +---- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css index 88432945e..77be29063 100644 --- a/frontend/src/assets/global.css +++ b/frontend/src/assets/global.css @@ -66,10 +66,11 @@ body { .vditor { min-height: 200px; } + .vditor-toolbar--pin { top: var(--header-height) !important; - z-index: 900 !important; } + /* .vditor { --textarea-background-color: transparent; border: none !important; diff --git a/frontend/src/views/AboutPageView.vue b/frontend/src/views/AboutPageView.vue index f36ba3489..669218787 100644 --- a/frontend/src/views/AboutPageView.vue +++ b/frontend/src/views/AboutPageView.vue @@ -75,13 +75,11 @@ export default { max-width: var(--page-max-width); background-color: var(--background-color); margin: 0 auto; - height: 100%; - overflow-y: auto; } .about-tabs { position: sticky; - top: 1px; + top: calc(var(--header-height) + 1px); z-index: 200; background-color: var(--background-color-blur); display: flex; diff --git a/frontend/src/views/HomePageView.vue b/frontend/src/views/HomePageView.vue index bbae20c0b..bd5a3ab13 100644 --- a/frontend/src/views/HomePageView.vue +++ b/frontend/src/views/HomePageView.vue @@ -433,7 +433,7 @@ export default { .topic-container { position: sticky; - top: 1px; + top: calc(var(--header-height) + 1px); z-index: 10; background-color: var(--background-color-blur); display: flex; diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue index 03b79d59f..3eda7cf51 100644 --- a/frontend/src/views/MessagePageView.vue +++ b/frontend/src/views/MessagePageView.vue @@ -632,7 +632,7 @@ export default { .message-page-header { position: sticky; - top: 1px; + top: calc(var(--header-height) + 1px); z-index: 200; background-color: var(--background-color-blur); display: flex; diff --git a/frontend/src/views/NewPostPageView.vue b/frontend/src/views/NewPostPageView.vue index 1038df159..190c85409 100644 --- a/frontend/src/views/NewPostPageView.vue +++ b/frontend/src/views/NewPostPageView.vue @@ -261,10 +261,8 @@ export default { display: flex; justify-content: center; background-color: var(--background-color); - height: 100%; padding-right: 20px; padding-left: 20px; - overflow-y: auto; } .new-post-form { diff --git a/frontend/src/views/ProfileView.vue b/frontend/src/views/ProfileView.vue index 4470100dd..672e8d463 100644 --- a/frontend/src/views/ProfileView.vue +++ b/frontend/src/views/ProfileView.vue @@ -497,9 +497,6 @@ export default { .profile-page { background-color: var(--background-color); - height: 100%; - overflow-y: auto; - overflow-x: hidden; } .profile-page-header { @@ -639,7 +636,7 @@ export default { .profile-tabs { position: sticky; - top: 1px; + top: calc(var(--header-height) + 1px); z-index: 200; background-color: var(--background-color-blur); display: flex; From 597f682b755a2a55830fd5779069b779e9c343cb Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 6 Aug 2025 18:37:51 +0800 Subject: [PATCH 3/5] fix: message page layout fix --- frontend/src/views/MessagePageView.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue index 3eda7cf51..ca15bfb14 100644 --- a/frontend/src/views/MessagePageView.vue +++ b/frontend/src/views/MessagePageView.vue @@ -628,11 +628,12 @@ export default { .message-page { background-color: var(--background-color); + overflow-x: hidden; } .message-page-header { position: sticky; - top: calc(var(--header-height) + 1px); + top: 1px; z-index: 200; background-color: var(--background-color-blur); display: flex; @@ -769,9 +770,5 @@ export default { .has_read_button { display: none; } - - .message-page { - overflow-x: hidden; - } } From c838caf9e13bab9e80f3d1cb40ce8ea171d23332 Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:52:02 +0800 Subject: [PATCH 4/5] feat: update notification read UI instantly --- frontend/src/views/MessagePageView.vue | 40 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue index ca15bfb14..c04db1f43 100644 --- a/frontend/src/views/MessagePageView.vue +++ b/frontend/src/views/MessagePageView.vue @@ -299,7 +299,7 @@ import BaseTimeline from '../components/BaseTimeline.vue' import BasePlaceholder from '../components/BasePlaceholder.vue' import NotificationContainer from '../components/NotificationContainer.vue' import { getToken, authState } from '../utils/auth' -import { markNotificationsRead, fetchUnreadCount } from '../utils/notification' +import { markNotificationsRead, fetchUnreadCount, notificationState } from '../utils/notification' import { toast } from '../main' import { stripMarkdownLength } from '../utils/markdown' import TimeManager from '../utils/time' @@ -322,28 +322,42 @@ export default { const markRead = async id => { if (!id) return + const n = notifications.value.find(n => n.id === id) + if (!n || n.read) return + n.read = true + if (notificationState.unreadCount > 0) notificationState.unreadCount-- const ok = await markNotificationsRead([id]) - if (ok) { - const n = notifications.value.find(n => n.id === id) - if (n) n.read = true - await fetchUnreadCount() + if (!ok) { + n.read = false + notificationState.unreadCount++ + } else { + fetchUnreadCount() } } const markAllRead = async () => { // 除了 REGISTER_REQUEST 类型消息 - const idsToMark = notifications.value.filter(n => n.type !== 'REGISTER_REQUEST').map(n => n.id) + const idsToMark = notifications.value + .filter(n => n.type !== 'REGISTER_REQUEST' && !n.read) + .map(n => n.id) + if (idsToMark.length === 0) return + notifications.value.forEach(n => { + if (n.type !== 'REGISTER_REQUEST') n.read = true + }) + notificationState.unreadCount = notifications.value.filter(n => !n.read).length const ok = await markNotificationsRead(idsToMark) - if (ok) { + if (!ok) { notifications.value.forEach(n => { - if (n.type !== 'REGISTER_REQUEST') n.read = true + if (idsToMark.includes(n.id)) n.read = false }) await fetchUnreadCount() - if (authState.role === 'ADMIN') { - toast.success('已读所有消息(注册请求除外)') - } else { - toast.success('已读所有消息') - } + return + } + fetchUnreadCount() + if (authState.role === 'ADMIN') { + toast.success('已读所有消息(注册请求除外)') + } else { + toast.success('已读所有消息') } } From 5709b0d6fdaca0efde24a4b9939dd9951a494c6e Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:58:01 +0800 Subject: [PATCH 5/5] refactor: reuse shared reaction emoji map --- frontend/src/components/ReactionsGroup.vue | 33 +++------------------- frontend/src/utils/reactions.js | 25 ++++++++++++++++ frontend/src/views/MessagePageView.vue | 27 +----------------- 3 files changed, 30 insertions(+), 55 deletions(-) create mode 100644 frontend/src/utils/reactions.js diff --git a/frontend/src/components/ReactionsGroup.vue b/frontend/src/components/ReactionsGroup.vue index be996796d..2398c22be 100644 --- a/frontend/src/components/ReactionsGroup.vue +++ b/frontend/src/components/ReactionsGroup.vue @@ -4,7 +4,7 @@
@@ -24,7 +24,7 @@
- {{ iconMap[t] }}{{ counts[t] }} + {{ reactionEmojiMap[t] }}{{ counts[t] }}
@@ -34,6 +34,7 @@ import { ref, computed, watch, onMounted } from 'vue' import { API_BASE_URL, toast } from '../main' import { getToken, authState } from '../utils/auth' +import { reactionEmojiMap } from '../utils/reactions' let cachedTypes = null const fetchTypes = async () => { @@ -54,32 +55,6 @@ const fetchTypes = async () => { return cachedTypes } -const iconMap = { - LIKE: '❤️', - DISLIKE: '👎', - RECOMMEND: '👏', - ANGRY: '😡', - FLUSHED: '😳', - STAR_STRUCK: '🤩', - ROFL: '🤣', - HOLDING_BACK_TEARS: '🥹', - MIND_BLOWN: '🤯', - POOP: '💩', - CLOWN: '🤡', - SKULL: '☠️', - FIRE: '🔥', - EYES: '👀', - FROWN: '☹️', - HOT: '🥵', - EAGLE: '🦅', - SPIDER: '🕷️', - BAT: '🦇', - CHINA: '🇨🇳', - USA: '🇺🇸', - JAPAN: '🇯🇵', - KOREA: '🇰🇷' -} - export default { name: 'ReactionsGroup', props: { @@ -202,7 +177,7 @@ export default { } return { - iconMap, + reactionEmojiMap, counts, totalCount, likeCount, diff --git a/frontend/src/utils/reactions.js b/frontend/src/utils/reactions.js new file mode 100644 index 000000000..7fa967de7 --- /dev/null +++ b/frontend/src/utils/reactions.js @@ -0,0 +1,25 @@ +export const reactionEmojiMap = { + LIKE: '❤️', + DISLIKE: '👎', + RECOMMEND: '👏', + ANGRY: '😡', + FLUSHED: '😳', + STAR_STRUCK: '🤩', + ROFL: '🤣', + HOLDING_BACK_TEARS: '🥹', + MIND_BLOWN: '🤯', + POOP: '💩', + CLOWN: '🤡', + SKULL: '☠️', + FIRE: '🔥', + EYES: '👀', + FROWN: '☹️', + HOT: '🥵', + EAGLE: '🦅', + SPIDER: '🕷️', + BAT: '🦇', + CHINA: '🇨🇳', + USA: '🇺🇸', + JAPAN: '🇯🇵', + KOREA: '🇰🇷' +} diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue index ca15bfb14..4d4672a00 100644 --- a/frontend/src/views/MessagePageView.vue +++ b/frontend/src/views/MessagePageView.vue @@ -304,6 +304,7 @@ import { toast } from '../main' import { stripMarkdownLength } from '../utils/markdown' import TimeManager from '../utils/time' import { hatch } from 'ldrs' +import { reactionEmojiMap } from '../utils/reactions' hatch.register() export default { @@ -364,32 +365,6 @@ export default { MENTION: 'fas fa-at' } - const reactionEmojiMap = { - LIKE: '❤️', - DISLIKE: '👎', - RECOMMEND: '👏', - ANGRY: '😡', - FLUSHED: '😳', - STAR_STRUCK: '🤩', - ROFL: '🤣', - HOLDING_BACK_TEARS: '🥹', - MIND_BLOWN: '🤯', - POOP: '💩', - CLOWN: '🤡', - SKULL: '☠️', - FIRE: '🔥', - EYES: '👀', - FROWN: '☹️', - HOT: '🥵', - EAGLE: '🦅', - SPIDER: '🕷️', - BAT: '🦇', - CHINA: '🇨🇳', - USA: '🇺🇸', - JAPAN: '🇯🇵', - KOREA: '🇰🇷' - } - const fetchNotifications = async () => { try { const token = getToken()