diff --git a/backend/src/main/java/com/openisle/config/SecurityConfig.java b/backend/src/main/java/com/openisle/config/SecurityConfig.java index 852ea1c5c..5c9572837 100644 --- a/backend/src/main/java/com/openisle/config/SecurityConfig.java +++ b/backend/src/main/java/com/openisle/config/SecurityConfig.java @@ -77,8 +77,8 @@ public class SecurityConfig { "http://127.0.0.1", "http://localhost:8080", "http://localhost", - "http://30.211.97.254:8080", - "http://30.211.97.254", + "http://30.211.98.193:8080", + "http://30.211.98.193", "http://192.168.7.70", "http://192.168.7.70:8080", websiteUrl, diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json index 5bc639a6d..4504e9927 100644 --- a/frontend/public/manifest.json +++ b/frontend/public/manifest.json @@ -2,7 +2,7 @@ "name": "OpenIsle", "short_name": "OpenIsle", "start_url": "/", - "display": "standalone", + "display": "fullscreen", "icons": [ { "src": "/icon-192.png", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index f60db5054..0fb771ef4 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -68,9 +68,13 @@ export default { .menu-container {} .content { + /* height: calc(100vh - var(--header-height)); */ + padding-top: var(--header-height); flex: 1; max-width: 100%; transition: max-width 0.3s ease; + background-color: var(--background-color); + min-height: calc(100vh - var(--header-height)); } .content.menu-open { diff --git a/frontend/src/assets/global.css b/frontend/src/assets/global.css index 5f0786489..79965aa33 100644 --- a/frontend/src/assets/global.css +++ b/frontend/src/assets/global.css @@ -8,7 +8,8 @@ --header-text-color: black; --menu-background-color: white; --background-color: white; - --background-color-blur: rgba(255, 255, 255, 0.57); + /* --background-color-blur: rgba(255, 255, 255, 0.57); */ + --background-color-blur: var(--background-color); --menu-border-color: lightgray; --normal-border-color: lightgray; --menu-selected-background-color: rgba(208, 250, 255, 0.659); @@ -34,7 +35,8 @@ --header-text-color: white; --menu-background-color: #333; --background-color: #333; - --background-color-blur: #333333a4; + /* --background-color-blur: #333333a4; */ + --background-color-blur: var(--background-color); --menu-border-color: #555; --normal-border-color: #555; --menu-selected-background-color: rgba(255, 255, 255, 0.1); @@ -54,10 +56,10 @@ body { font-family: 'Roboto', sans-serif; background-color: var(--normal-background-color); color: var(--text-color); - overflow: hidden; /* 禁止滚动 */ + /* 禁止滚动 */ + /* overflow: hidden; */ } - /************************* * Vditor 自定义皮肤覆写 *************************/ diff --git a/frontend/src/components/CallbackPage.vue b/frontend/src/components/CallbackPage.vue index 003d12a62..764b15a11 100644 --- a/frontend/src/components/CallbackPage.vue +++ b/frontend/src/components/CallbackPage.vue @@ -18,8 +18,6 @@ export default { diff --git a/frontend/src/views/LoginPageView.vue b/frontend/src/views/LoginPageView.vue index 4a33fb508..26d926a90 100644 --- a/frontend/src/views/LoginPageView.vue +++ b/frontend/src/views/LoginPageView.vue @@ -125,8 +125,7 @@ export default { flex-direction: row; align-items: center; justify-content: center; - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; width: 100%; background-color: var(--background-color); } diff --git a/frontend/src/views/MessagePageView.vue b/frontend/src/views/MessagePageView.vue index 75c5a357c..03b79d59f 100644 --- a/frontend/src/views/MessagePageView.vue +++ b/frontend/src/views/MessagePageView.vue @@ -626,12 +626,8 @@ export default { height: 300px; } - .message-page { background-color: var(--background-color); - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); - overflow-y: auto; } .message-page-header { @@ -639,7 +635,6 @@ export default { top: 1px; z-index: 200; background-color: var(--background-color-blur); - backdrop-filter: blur(10px); display: flex; flex-direction: row; justify-content: space-between; diff --git a/frontend/src/views/NewPostPageView.vue b/frontend/src/views/NewPostPageView.vue index 83aff279d..1038df159 100644 --- a/frontend/src/views/NewPostPageView.vue +++ b/frontend/src/views/NewPostPageView.vue @@ -261,8 +261,7 @@ export default { display: flex; justify-content: center; background-color: var(--background-color); - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; padding-right: 20px; padding-left: 20px; overflow-y: auto; diff --git a/frontend/src/views/NotFoundPageView.vue b/frontend/src/views/NotFoundPageView.vue index 86304faa9..5b623cafe 100644 --- a/frontend/src/views/NotFoundPageView.vue +++ b/frontend/src/views/NotFoundPageView.vue @@ -17,8 +17,7 @@ export default { display: flex; flex-direction: column; align-items: center; - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; text-align: center; background-color: var(--background-color); } diff --git a/frontend/src/views/PostPageView.vue b/frontend/src/views/PostPageView.vue index 5e16bdd72..c4f9107a3 100644 --- a/frontend/src/views/PostPageView.vue +++ b/frontend/src/views/PostPageView.vue @@ -3,7 +3,7 @@
-
+
{{ title }}
@@ -156,6 +156,7 @@ export default { const defaultTitle = document.title const metaDescriptionEl = document.querySelector('meta[name="description"]') const defaultDescription = metaDescriptionEl ? metaDescriptionEl.getAttribute('content') : '' + const headerHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0 watch(title, t => { document.title = `OpenIsle - ${t}` @@ -170,6 +171,7 @@ export default { onBeforeUnmount(() => { document.title = defaultTitle if (metaDescriptionEl) metaDescriptionEl.setAttribute('content', defaultDescription) + window.removeEventListener('scroll', updateCurrentIndex) }) const lightboxVisible = ref(false) @@ -202,12 +204,12 @@ export default { const items = [] if (mainContainer.value) { const main = mainContainer.value.querySelector('.info-content-container') - if (main) items.push({ el: main, top: 0 }) + if (main) items.push({ el: main, top: getTop(main) }) for (const c of comments.value) { const el = document.getElementById('comment-' + c.id) if (el) { - items.push({ el, top: getTopRelativeTo(el, mainContainer.value) }) + items.push({ el, top: getTop(el) }) } } // 根据 top 排序,防止评论异步插入后顺序错乱 @@ -230,11 +232,8 @@ export default { parentUserName: parentUserName }) - const getTopRelativeTo = (el, container) => { - const elRect = el.getBoundingClientRect() - const parentRect = container.getBoundingClientRect() - // 加上 scrollTop,得到相对于 container 内部顶部的距离 - return elRect.top - parentRect.top + container.scrollTop + const getTop = (el) => { + return el.getBoundingClientRect().top + window.scrollY } const findCommentPath = (id, list) => { @@ -336,19 +335,16 @@ export default { async () => { await nextTick() gatherPostItems() + updateCurrentIndex() } ) const updateCurrentIndex = () => { - const container = mainContainer.value - if (!container) return - - const scrollTop = container.scrollTop + const scrollTop = window.scrollY for (let i = 0; i < postItems.value.length; i++) { const el = postItems.value[i] - // 计算元素相对 container 顶部的 top - const top = getTopRelativeTo(el, container) + const top = getTop(el) const bottom = top + el.offsetHeight if (bottom > scrollTop) { @@ -362,9 +358,9 @@ export default { const index = Number(e.target.value) currentIndex.value = index const target = postItems.value[index - 1] - if (target && mainContainer.value) { - const top = getTopRelativeTo(target, mainContainer.value) - mainContainer.value.scrollTo({ top, behavior: 'instant' }) + if (target) { + const top = getTop(target) - headerHeight - 20 // 20 for beauty + window.scrollTo({ top, behavior: 'auto' }) } } @@ -570,12 +566,14 @@ export default { const hash = location.hash if (hash.startsWith('#comment-')) { const id = hash.substring('#comment-'.length) - await nextTick() + // 不清楚啥原因,先wait一下子不然会定不准 😅 + await new Promise(resolve => setTimeout(resolve, 500)) const el = document.getElementById('comment-' + id) - if (el && mainContainer.value) { - mainContainer.value.scrollTo({ top: getTopRelativeTo(el, mainContainer.value), behavior: 'instant' }) + if (el) { + const top = el.getBoundingClientRect().top + window.scrollY - headerHeight - 20 // 20 for beauty + window.scrollTo({ top, behavior: 'smooth' }) el.classList.add('comment-highlight') - setTimeout(() => el.classList.remove('comment-highlight'), 2000) + setTimeout(() => el.classList.remove('comment-highlight'), 4000) } } } @@ -590,6 +588,7 @@ export default { await fetchPost() if (id) expandCommentPath(id) updateCurrentIndex() + window.addEventListener('scroll', updateCurrentIndex) await jumpToHashComment() }) @@ -612,7 +611,6 @@ export default { postId, postComment, onSliderInput, - onScroll: updateCurrentIndex, copyPostLink, subscribePost, unsubscribePost, @@ -650,7 +648,7 @@ export default { background-color: var(--background-color); display: flex; flex-direction: row; - height: 100vh; + height: 100%; } .loading-container { @@ -662,19 +660,18 @@ export default { } .post-page-main-container { - overflow-y: auto; scrollbar-width: none; padding: 20px; - height: calc(100% - 40px - var(--header-height)); width: calc(85% - 40px); - padding-top: calc(var(--header-height) + 20px); } .post-page-scroller-container { - padding-top: var(--header-height); display: flex; flex-direction: column; width: 15%; + position: sticky; + top: var(--header-height); + align-self: flex-start; } .comment-config-container { @@ -974,7 +971,6 @@ export default { .post-page-main-container { width: calc(100% - 20px); padding: 10px; - padding-top: calc(var(--header-height) + 10px); } .article-title { diff --git a/frontend/src/views/ProfileView.vue b/frontend/src/views/ProfileView.vue index 538830a6c..4470100dd 100644 --- a/frontend/src/views/ProfileView.vue +++ b/frontend/src/views/ProfileView.vue @@ -282,7 +282,7 @@ export default { const isLoading = ref(true) const tabLoading = ref(false) const selectedTab = ref('summary') - const followTab = ref('followers') + const followTab = ref('followers') const levelInfo = computed(() => { const exp = user.value.experience || 0 @@ -336,9 +336,11 @@ export default { } const fetchTimeline = async () => { - const postsRes = await fetch(`${API_BASE_URL}/api/users/${username}/posts?limit=50`) - const repliesRes = await fetch(`${API_BASE_URL}/api/users/${username}/replies?limit=50`) - const tagsRes = await fetch(`${API_BASE_URL}/api/users/${username}/tags?limit=50`) + const [postsRes, repliesRes, tagsRes] = await Promise.all([ + fetch(`${API_BASE_URL}/api/users/${username}/posts?limit=50`), + fetch(`${API_BASE_URL}/api/users/${username}/replies?limit=50`), + fetch(`${API_BASE_URL}/api/users/${username}/tags?limit=50`) + ]) const posts = postsRes.ok ? await postsRes.json() : [] const replies = repliesRes.ok ? await repliesRes.json() : [] const tags = tagsRes.ok ? await tagsRes.json() : [] @@ -367,8 +369,10 @@ export default { } const fetchFollowUsers = async () => { - const followerRes = await fetch(`${API_BASE_URL}/api/users/${username}/followers`) - const followingRes = await fetch(`${API_BASE_URL}/api/users/${username}/following`) + const [followerRes, followingRes] = await Promise.all([ + fetch(`${API_BASE_URL}/api/users/${username}/followers`), + fetch(`${API_BASE_URL}/api/users/${username}/following`) + ]) followers.value = followerRes.ok ? await followerRes.json() : [] followings.value = followingRes.ok ? await followingRes.json() : [] } @@ -493,8 +497,7 @@ export default { .profile-page { background-color: var(--background-color); - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; overflow-y: auto; overflow-x: hidden; } @@ -639,7 +642,6 @@ export default { top: 1px; z-index: 200; background-color: var(--background-color-blur); - backdrop-filter: blur(10px); display: flex; flex-direction: row; padding: 0 20px; diff --git a/frontend/src/views/SettingsPageView.vue b/frontend/src/views/SettingsPageView.vue index 74ef61422..089ef7a77 100644 --- a/frontend/src/views/SettingsPageView.vue +++ b/frontend/src/views/SettingsPageView.vue @@ -239,8 +239,7 @@ export default { .settings-page { background-color: var(--background-color); padding: 40px; - height: calc(100vh - var(--header-height) - 80px); - padding-top: calc(var(--header-height) + 40px); + height: calc(100% - 80px); overflow-y: auto; } diff --git a/frontend/src/views/SignupPageView.vue b/frontend/src/views/SignupPageView.vue index eea683ebd..0868b5923 100644 --- a/frontend/src/views/SignupPageView.vue +++ b/frontend/src/views/SignupPageView.vue @@ -222,8 +222,7 @@ export default { flex-direction: row; align-items: center; justify-content: center; - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; width: 100%; background-color: var(--background-color); } diff --git a/frontend/src/views/SignupReasonPageView.vue b/frontend/src/views/SignupReasonPageView.vue index 3f76bbea3..1bd4183e4 100644 --- a/frontend/src/views/SignupReasonPageView.vue +++ b/frontend/src/views/SignupReasonPageView.vue @@ -82,8 +82,7 @@ export default { justify-content: center; align-items: center; background-color: var(--background-color); - height: calc(100vh - var(--header-height)); - padding-top: var(--header-height); + height: 100%; } .reason-title { diff --git a/frontend/src/views/SiteStatsPageView.vue b/frontend/src/views/SiteStatsPageView.vue index aab6bca2d..f0c1904b1 100644 --- a/frontend/src/views/SiteStatsPageView.vue +++ b/frontend/src/views/SiteStatsPageView.vue @@ -48,7 +48,6 @@ onMounted(loadData) max-width: var(--page-max-width); background-color: var(--background-color); margin: 0 auto; - height: calc(100vh - var(--header-height) - 40px); - padding-top: calc(var(--header-height) + 20px); + height: 100%; }