Skip to content

Commit 51be49a

Browse files
committed
实现免责声明 banner 隐藏状态记忆功能
1 parent db2d294 commit 51be49a

File tree

5 files changed

+65
-26
lines changed

5 files changed

+65
-26
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ const themeConfig: ThemeContext = {
3434
detailHtml: '<p>RLE.wiki「大学指南」中的内容,仅供参考。可能存在过时或不准确的信息,请谨慎甄别。</p>' + //免责声明展开后显示的内容,html 格式
3535
'<p>「大学指南」板块中的内容,多数来自于读者投稿,并经编辑简单整理和形式审查后登载,主要体现其投稿者主观观点。不代表 RLE.wiki 编辑团队及我们的任何相关维护人员立场。</p>' +
3636
'<p>若存在任何有误或不当内容,请联系 <a href="mailto:rlewiki@project-trans.org">rlewiki@project-trans.org</a>。</p>',
37-
},]
37+
},],
38+
disclaimerStatusKey: 'disclaimerStatus', //若要存储免责声明 banner 隐藏状态,需要指定此字段,存储在localStorage中
39+
disclaimerStatusExpiration: 1000 //指定 disclaimerStatus 有效的毫秒数,1000这个值显然太短了,你需要选个更大的数,默认持续生效7天
3840
}
3941

4042
// https://vitepress.dev/reference/site-config

example/docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const themeConfig: ThemeContext = {
7373
},
7474
],
7575
enableDisclaimer: true,
76+
disclaimerStatusKey: 'disclaimerStatus',
7677
}
7778

7879
// https://vitepress.dev/reference/site-config

src/components/Disclaimer.vue

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { DisclaimerPathConfig } from '../utils/themeContext';
77
const props = defineProps<{
88
content?: string
99
}>()
10-
10+
const DEFAULT_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000 // 7 days
1111
const route = useRoute()
1212
const { theme } = useData<PjtsThemeConfig>()
1313
@@ -56,9 +56,9 @@ const shouldRender = computed(() => {
5656
if (!theme.value?.enableDisclaimer) {
5757
return false
5858
}
59-
// if (route.data?.frontmatter?.hideDisclaimer) {
60-
// return false
61-
// }
59+
// if (route.data?.frontmatter?.hideDisclaimer) {
60+
// return false
61+
// }
6262
6363
// Check if a valid configuration is found for the current path
6464
return !!currentDisclaimerConfig.value
@@ -70,14 +70,22 @@ const placeholderHeight = computed(() => {
7070
return shouldRender.value && !isHidden.value ? disclaimerHeight.value : 0
7171
})
7272
73-
// Toggle the hidden state
73+
// Toggle the hidden state and update local storage with timestamp if enabled
7474
const toggleHiddenState = () => {
75+
const localHiddenEnabled = !!theme.value?.disclaimerStatusKey
76+
7577
if (isHidden.value) {
7678
// Show the disclaimer
7779
isHidden.value = false
80+
if (localHiddenEnabled) {
81+
localStorage.removeItem(theme.value?.disclaimerStatusKey!)
82+
}
7883
} else {
7984
// Hide the disclaimer
8085
isHidden.value = true
86+
if (localHiddenEnabled) {
87+
localStorage.setItem(theme.value?.disclaimerStatusKey!, Date.now().toString())
88+
}
8189
}
8290
}
8391
@@ -89,13 +97,37 @@ const calculateHeight = () => {
8997
// Only update if the disclaimer is collapsed OR if we haven't captured a height yet.
9098
// This prevents overwriting the collapsed height when it expands.
9199
if (!isExpanded.value || disclaimerHeight.value === 0) {
92-
disclaimerHeight.value = currentHeight
100+
disclaimerHeight.value = currentHeight
93101
}
94102
}
95103
// No need for an else to set height to 0, the computed property handles that.
96104
}
97105
98106
onMounted(() => {
107+
// Check local storage for hidden state if the feature is enabled
108+
const localHiddenEnabled = !!theme.value?.disclaimerStatusKey
109+
if (localHiddenEnabled) {
110+
const storedTimestampStr = localStorage.getItem(theme.value?.disclaimerStatusKey!)
111+
if (storedTimestampStr) {
112+
try {
113+
const storedTimestamp = parseInt(storedTimestampStr, 10)
114+
const expirationMs = theme.value?.disclaimerStatusExpiration ?? DEFAULT_EXPIRATION_MS
115+
const now = Date.now()
116+
117+
if (now - storedTimestamp <= expirationMs) {
118+
// Timestamp is valid and not expired
119+
isHidden.value = true
120+
} else {
121+
// Timestamp expired, remove it
122+
localStorage.removeItem(theme.value?.disclaimerStatusKey!)
123+
}
124+
}
125+
catch {
126+
localStorage.removeItem(theme.value?.disclaimerStatusKey!)
127+
}
128+
}
129+
}
130+
99131
// Calculate initial height after component mounts and renders
100132
nextTick(calculateHeight)
101133
})
@@ -113,25 +145,19 @@ watch([isExpanded, currentDisclaimerText], () => {
113145

114146
<template>
115147
<!-- Placeholder div to reserve space when the disclaimer is fixed -->
116-
<div
117-
v-if="shouldRender && !isHidden"
118-
class="disclaimer-placeholder"
119-
:style="{ height: placeholderHeight + 'px' }"
120-
></div>
148+
<div v-if="shouldRender && !isHidden" class="disclaimer-placeholder" :style="{ height: placeholderHeight + 'px' }">
149+
</div>
121150

122151
<!-- The actual disclaimer element -->
123-
<div
124-
v-if="shouldRender"
125-
ref="disclaimerElement"
126-
:class="[
127-
'disclaimer',
128-
{ 'is-expanded': isExpanded },
129-
{ 'is-hidden': isHidden }
130-
]"
131-
>
152+
<div v-if="shouldRender" ref="disclaimerElement" :class="[
153+
'disclaimer',
154+
{ 'is-expanded': isExpanded },
155+
{ 'is-hidden': isHidden }
156+
]">
132157
<div class="disclaimer-content">
133158
<!-- Use v-html for rich text content -->
134-
<div class="disclaimer-text" :class="{ 'expanded': isExpanded && !isHidden }" v-html="currentDisclaimerText"></div>
159+
<div class="disclaimer-text" :class="{ 'expanded': isExpanded && !isHidden }" v-html="currentDisclaimerText">
160+
</div>
135161
<div class="disclaimer-actions">
136162
<button v-if="showToggleButton && !isHidden" @click="isExpanded = !isExpanded" class="disclaimer-toggle">
137163
{{ isExpanded ? collapseText : expandText }}
@@ -160,6 +186,8 @@ watch([isExpanded, currentDisclaimerText], () => {
160186
.disclaimer.is-hidden {
161187
position: static;
162188
margin-top: 2rem;
189+
border: 1px solid transparent;
190+
border-radius: 8px;
163191
}
164192
165193
.disclaimer-content {
@@ -212,7 +240,7 @@ watch([isExpanded, currentDisclaimerText], () => {
212240
}
213241
214242
.disclaimer-actions {
215-
margin-top: 0.5rem; /* Add some space when stacked */
243+
margin-top: 0.5rem;
216244
width: 100%;
217245
justify-content: flex-end;
218246
}
@@ -222,8 +250,8 @@ watch([isExpanded, currentDisclaimerText], () => {
222250
.disclaimer-placeholder {
223251
position: relative;
224252
width: 100%;
225-
display: block;
253+
display: block;
226254
margin: 0;
227255
padding: 0;
228256
}
229-
</style>
257+
</style>

src/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export interface PjtsThemeConfig extends DefaultTheme.Config {
2929
disclaimerToggleCollapseText?: string
3030
disclaimerHideText?: string
3131
disclaimerShowText?: string
32+
disclaimerStatusKey?: string
33+
disclaimerStatusExpiration?: number
3234
org?: string
3335
HideReadingTime?: boolean
3436
HideLastUpdated?: boolean
@@ -87,6 +89,8 @@ function genConfig() {
8789
fontsBaseUrl = 'https://fonts.project-trans.org',
8890
enableDisclaimer,
8991
disclaimerPaths,
92+
disclaimerStatusKey,
93+
disclaimerStatusExpiration,
9094
} = themeConfig
9195

9296
return defineConfigWithTheme<PjtsThemeConfig>({
@@ -158,6 +162,8 @@ function genConfig() {
158162
},
159163
enableDisclaimer: enableDisclaimer,
160164
disclaimerPaths: disclaimerPaths,
165+
disclaimerStatusKey: disclaimerStatusKey,
166+
disclaimerStatusExpiration: disclaimerStatusExpiration,
161167
// label localization
162168
outline: { label: '本页大纲', level: 'deep' },
163169
lastUpdated: { text: '最后更新' },

src/utils/themeContext.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export interface ThemeContext {
3232
hostName: string
3333
fontsBaseUrl?: string
3434
enableDisclaimer?: boolean
35-
disclaimerPaths?: DisclaimerPathConfig[]
35+
disclaimerPaths?: DisclaimerPathConfig[],
36+
disclaimerStatusKey?: string
37+
disclaimerStatusExpiration?: number
3638
}
3739

3840
const themeContext = new AsyncLocalStorage<ThemeContext>()

0 commit comments

Comments
 (0)