Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增字数和预计阅读时间、文档两端对齐,优化作者信息显示逻辑 #411

Merged
merged 9 commits into from
Sep 12, 2024
4 changes: 4 additions & 0 deletions docs/.vitepress/theme/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,7 @@
border-radius: 8px !important;
}

/* 文档两端对齐 */
.vp-doc {
text-align: justify;
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "rle-wiki",
"type": "module",
"version": "1.0.0",
"packageManager": "pnpm@9.9.0",
"packageManager": "pnpm@9.10.0+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c",
"description": "RLE 指北",
"license": "CC-BY-SA-4.0",
"scripts": {
Expand Down
32 changes: 22 additions & 10 deletions packages/vitepress-theme-project-trans/src/components/PageInfo.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
<script setup lang="ts">
import { useData } from 'vitepress'
import { computed, onMounted, ref, watchEffect } from 'vue'
import ReadingTime from './ReadingTime.vue' // 导入 ReadingTime 组件

// 从 VitePress 获取页面数据
const { frontmatter, page, theme, lang } = useData()

// 计算页面的最后更新时间
const date = computed(
() => new Date(frontmatter.value.lastUpdated ?? page.value.lastUpdated),
)

// 计算 ISO 格式的日期时间字符串
const isoDatetime = computed(() => date.value.toISOString())

// 定义一个响应式变量来存储格式化后的日期时间字符串
const datetime = ref('')
// Avoid hydration errors

// 避免 hydration 错误,在组件挂载后执行
onMounted(() => {
watchEffect(() => {
// 使用国际化 API 格式化日期时间
datetime.value = new Intl.DateTimeFormat(
theme.value.lastUpdated?.formatOptions?.forceLocale ? lang.value : undefined,
theme.value.lastUpdated?.formatOptions ?? {
Expand All @@ -23,15 +31,21 @@ onMounted(() => {
})
})

// 计算页面的作者信息
const authors = computed(() => {
let author = (frontmatter.value?.author ?? []) as string[]
if (!Array.isArray(author))
author = [author]
return author
})

if (!author.length)
author = []

return [...author, '匿名']
// 计算显示的作者信息
const displayAuthors = computed(() => {
if (authors.value.length === 0) {
return '匿名'
} else {
return authors.value.join(', ') + ' 等'
}
})
</script>

Expand All @@ -40,17 +54,15 @@ const authors = computed(() => {
<div class="inline-flex items-center gap-1">
<span class="i-octicon:person" />
<span>作者:</span>
<span class="space-x-2">
<span v-for="(author, index) in authors" :key="index">
{{ author }}
</span>
</span>
<span>{{ displayAuthors }}</span>
</div>

<div class="inline-flex items-center gap-1">
<span class="i-octicon:calendar-16" />
<span>{{ theme.lastUpdated?.text || 'Last updated' }}:</span>
<time :datetime="isoDatetime">{{ datetime }}</time>
</div>

<ReadingTime /> <!-- 添加 ReadingTime 组件 -->
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { useRoute } from 'vitepress'
import { nextTick, ref, watch } from 'vue'

// 获取路由信息
const route = useRoute()

// 定义响应式变量
const wordCount = ref(0)
const readingTime = ref(0)
const componentKey = ref(0) // 控制组件重新渲染的 key
const isLoaded = ref(false) // 控制是否加载完成

// 计算字数和预计阅读时间的函数
function calculateReadingTime(content: string) {
const wordsPerMinute = 500 // 假设中文阅读速度为每分钟500字

// 定义一个误差值,因为实际字数比读取出的字数约少77个字
const wordCountOffset = 77

const chineseText = content.replace(/<[^>]*>|[^\u4E00-\u9FA5]/g, '') // 去除 HTML 标签和非中文字符
const wordCount = (chineseText.length - wordCountOffset) // 计算中文字符数
const readingTime = Math.ceil(wordCount / wordsPerMinute) // 计算预计阅读时间
return { wordCount, readingTime }
}

// 更新字数和阅读时间的函数
function updateReadingTime() {
const contentElement = document.querySelector('.VPContent') // 获取文档内容的 DOM 元素
BeiyanYunyi marked this conversation as resolved.
Show resolved Hide resolved
if (contentElement) {
const content = contentElement.textContent || '' // 获取纯文本内容
const { wordCount: wc, readingTime: rt } = calculateReadingTime(content)
wordCount.value = wc
readingTime.value = rt
}
}

// 初始化函数,在页面挂载和路由变化时调用
function initialize() {
isLoaded.value = false // 重置加载状态
componentKey.value += 1
nextTick(() => {
updateReadingTime()
isLoaded.value = true // 设置加载完成
})
}

// 监听路由变化,执行初始化
watch(route, () => {
initialize()
}, { immediate: true })
</script>

<template>
<div v-if="isLoaded" :key="componentKey">
<p>字数: {{ wordCount }} &nbsp; 预计阅读时间: {{ readingTime }} 分钟</p>
</div>
</template>

<style scoped>
/* 这里可以添加样式 */
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ArticlesMenu from './ArticlesMenu.vue'
import CopyrightInfo from './CopyrightInfo.vue'
import HomeContent from './HomeContent.vue'
import PageInfo from './PageInfo.vue'
import ReadingTime from './ReadingTime.vue'


export {
Expand All @@ -14,5 +15,6 @@ export {
ArticlesMenu,
CopyrightInfo,
HomeContent,
PageInfo
PageInfo,
ReadingTime
}
Loading