diff --git a/frontend_nuxt/app.vue b/frontend_nuxt/app.vue index 9c1ff809a..895e82d3a 100644 --- a/frontend_nuxt/app.vue +++ b/frontend_nuxt/app.vue @@ -26,7 +26,7 @@ export default { components: { HeaderComponent, MenuComponent, GlobalPopups }, data() { return { - menuVisible: process.client ? window.innerWidth > 768 : false + menuVisible: true } }, computed: { @@ -45,7 +45,9 @@ export default { } }, async mounted() { - // placeholder for future global initializations + if (typeof window !== 'undefined') { + this.menuVisible = window.innerWidth > 768 + } }, methods: {} } diff --git a/frontend_nuxt/components/DropdownMenu.vue b/frontend_nuxt/components/DropdownMenu.vue index a59c4c2c5..cd5679342 100644 --- a/frontend_nuxt/components/DropdownMenu.vue +++ b/frontend_nuxt/components/DropdownMenu.vue @@ -69,6 +69,8 @@ export default { .dropdown-menu-container { position: absolute; + top: 100%; + right: 0; background-color: var(--menu-background-color); border: 1px solid var(--normal-border-color); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); diff --git a/frontend_nuxt/components/HeaderComponent.vue b/frontend_nuxt/components/HeaderComponent.vue index 7bce6c142..7abf4ff66 100644 --- a/frontend_nuxt/components/HeaderComponent.vue +++ b/frontend_nuxt/components/HeaderComponent.vue @@ -15,27 +15,29 @@ -
-
- + +
+
+ +
+ + +
- - - -
-
-
- +
+
+ +
+
登录
+
注册
-
登录
-
注册
-
+
@@ -49,6 +51,7 @@ import { fetchUnreadCount, notificationState } from '~/utils/notification' import DropdownMenu from '~/components/DropdownMenu.vue' import SearchDropdown from '~/components/SearchDropdown.vue' import { isMobile } from '~/utils/screen' +import { ClientOnly } from '#components' export default { name: 'HeaderComponent', @@ -62,27 +65,82 @@ export default { data() { return { avatar: '', - showSearch: false + showSearch: false, + searchDropdown: null } }, - computed: { - isLogin() { - return authState.loggedIn - }, - isMobile() { - return isMobile.value - }, - headerMenuItems() { - return [ - { text: '设置', onClick: this.goToSettings }, - { text: '个人主页', onClick: this.goToProfile }, - { text: '退出', onClick: this.goToLogout } - ] - }, - unreadCount() { - return notificationState.unreadCount + setup() { + const isLogin = computed(() => authState.loggedIn) + const isMobile = computed(() => isMobile.value) + const unreadCount = computed(() => notificationState.unreadCount) + const router = useRouter() + + const goToHome = () => { + router.push('/') + } + const search = () => { + showSearch.value = true + nextTick(() => { + searchDropdown.value.toggle() + }) + } + const closeSearch = () => { + nextTick(() => { + showSearch.value = false + }) + } + const goToLogin = () => { + router.push('/login') + } + const goToSettings = () => { + router.push('/settings') + } + const goToProfile = async () => { + if (!authState.loggedIn) { + router.push('/login') + return + } + let id = authState.username || authState.userId + if (!id) { + const user = await loadCurrentUser() + if (user) { + id = user.username || user.id + } + } + if (id) { + router.push(`/users/${id}`) + } + } + const goToSignup = () => { + router.push('/signup') + } + const goToLogout = () => { + clearToken() + this.$router.push('/login') + } + + const headerMenuItems = computed(() => [ + { text: '设置', onClick: goToSettings }, + { text: '个人主页', onClick: goToProfile }, + { text: '退出', onClick: goToLogout } + ]) + + return { + isLogin, + isMobile, + headerMenuItems, + unreadCount, + goToHome, + search, + closeSearch, + goToLogin, + goToSettings, + goToProfile, + goToSignup, + goToLogout } }, + async mounted() { const updateAvatar = async () => { if (authState.loggedIn) { @@ -113,57 +171,6 @@ export default { this.showSearch = false }) }, - - - methods: { - goToHome() { - this.$router.push('/').then(() => { - window.location.reload() - }) - }, - search() { - this.showSearch = true - nextTick(() => { - this.$refs.searchDropdown.toggle() - }) - }, - closeSearch() { - nextTick(() => { - this.showSearch = false - }) - }, - goToLogin() { - this.$router.push('/login') - }, - goToSettings() { - this.$router.push('/settings') - }, - async goToProfile() { - if (!authState.loggedIn) { - this.$router.push('/login') - return - } - let id = authState.username || authState.userId - if (!id) { - const user = await loadCurrentUser() - if (user) { - id = user.username || user.id - } - } - if (id) { - this.$router.push(`/users/${id}`).then(() => { - window.location.reload() - }) - } - }, - goToSignup() { - this.$router.push('/signup') - }, - goToLogout() { - clearToken() - this.$router.push('/login') - } - } } diff --git a/frontend_nuxt/components/MenuComponent.vue b/frontend_nuxt/components/MenuComponent.vue index 703a277ed..cda57df0e 100644 --- a/frontend_nuxt/components/MenuComponent.vue +++ b/frontend_nuxt/components/MenuComponent.vue @@ -246,18 +246,12 @@ export default { const value = encodeURIComponent(c.id ?? c.name) this.$router .push({ path: '/', query: { category: value } }) - .then(() => { - window.location.reload() - }) this.handleItemClick() }, gotoTag(t) { const value = encodeURIComponent(t.id ?? t.name) this.$router .push({ path: '/', query: { tags: value } }) - .then(() => { - window.location.reload() - }) this.handleItemClick() } } diff --git a/frontend_nuxt/components/SearchDropdown.vue b/frontend_nuxt/components/SearchDropdown.vue index 33b9b7018..362401507 100644 --- a/frontend_nuxt/components/SearchDropdown.vue +++ b/frontend_nuxt/components/SearchDropdown.vue @@ -92,13 +92,9 @@ export default { router.push(`/posts/${opt.postId}#comment-${opt.id}`) } } else if (opt.type === 'category') { - router.push({ path: '/', query: { category: opt.id } }).then(() => { - window.location.reload() - }) + router.push({ path: '/', query: { category: opt.id } }) } else if (opt.type === 'tag') { - router.push({ path: '/', query: { tags: opt.id } }).then(() => { - window.location.reload() - }) + router.push({ path: '/', query: { tags: opt.id } }) } selected.value = null keyword.value = '' diff --git a/frontend_nuxt/components/UserList.vue b/frontend_nuxt/components/UserList.vue index 38a0dfbbf..37f45c840 100644 --- a/frontend_nuxt/components/UserList.vue +++ b/frontend_nuxt/components/UserList.vue @@ -22,9 +22,7 @@ export default { }, methods: { handleUserClick(user) { - this.$router.push(`/users/${user.id}`).then(() => { - window.location.reload() - }) + this.$router.push(`/users/${user.id}`) } } } diff --git a/frontend_nuxt/pages/users/[id].vue b/frontend_nuxt/pages/users/[id].vue index cedc039f5..5ce1181fc 100644 --- a/frontend_nuxt/pages/users/[id].vue +++ b/frontend_nuxt/pages/users/[id].vue @@ -431,9 +431,7 @@ export default { const gotoTag = tag => { const value = encodeURIComponent(tag.id ?? tag.name) - router.push({ path: '/', query: { tags: value } }).then(() => { - window.location.reload() - }) + router.push({ path: '/', query: { tags: value } }) } const init = async () => { diff --git a/frontend_nuxt/utils/screen.js b/frontend_nuxt/utils/screen.js index 6bacbfe17..3d3aebc03 100644 --- a/frontend_nuxt/utils/screen.js +++ b/frontend_nuxt/utils/screen.js @@ -1,12 +1,14 @@ import { ref, computed } from 'vue' const width = ref(0) +const isClient = ref(false) -if (process.client) { +if (typeof window !== 'undefined') { + isClient.value = true width.value = window.innerWidth window.addEventListener('resize', () => { width.value = window.innerWidth }) } -export const isMobile = computed(() => width.value <= 768) +export const isMobile = computed(() => isClient.value && width.value <= 768)