主题功能同步:vivid 页脚补社交按钮排(含源码入口,居中);classic 文章页补右栏目录(滚动高亮)与顶部阅读进度条——快发盒经核实两套 UI 均已存在,无需补
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { publicApi } from '../api'
|
||||
import { site } from '../site'
|
||||
import { socialIcon } from '../socialIcons'
|
||||
@@ -8,6 +8,35 @@ import { relativeDate, stripTags, thumbURL } from '../utils'
|
||||
// vivid 是单栏布局,右栏整体不渲染(省掉 latest/tags 两次请求)。
|
||||
const isVivid = computed(() => site.ui_id === 'vivid')
|
||||
|
||||
// 文章页目录(PostView 传入 headings;空数组时不渲染这张卡)。
|
||||
// 高亮跟随滚动:视口上方最近的那个标题算「当前」。
|
||||
const props = defineProps({
|
||||
toc: { type: Array, default: () => [] }
|
||||
})
|
||||
const activeId = ref('')
|
||||
let tocObserver = null
|
||||
|
||||
function watchToc() {
|
||||
if (tocObserver) tocObserver.disconnect()
|
||||
if (!props.toc.length) return
|
||||
tocObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const e of entries) {
|
||||
if (e.isIntersecting) activeId.value = e.target.id
|
||||
}
|
||||
},
|
||||
{ rootMargin: '0px 0px -65% 0px' }
|
||||
)
|
||||
nextTick(() => {
|
||||
for (const t of props.toc) {
|
||||
const el = document.getElementById(t.id)
|
||||
if (el) tocObserver.observe(el)
|
||||
}
|
||||
})
|
||||
}
|
||||
watch(() => props.toc, watchToc, { deep: false })
|
||||
onBeforeUnmount(() => tocObserver && tocObserver.disconnect())
|
||||
|
||||
// 项目源码仓库是固定入口(本站 git remote),不来自后台配置 —— 和版权一样
|
||||
// 固定渲染在自己的那排;后台填的社交账号单独一排,URL 撞车的去重。
|
||||
const PROJECT_REPO = 'https://git.gopher.ink/mirrors2/ONE'
|
||||
@@ -62,6 +91,15 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<aside v-if="!isVivid" class="rail-right">
|
||||
<section v-if="toc.length" class="card toc-card">
|
||||
<p class="eyebrow">目录</p>
|
||||
<ul class="toc-list">
|
||||
<li v-for="t in toc" :key="t.id" :class="{ h3: t.level >= 3, on: activeId === t.id }">
|
||||
<a :href="'#' + t.id" :class="{ on: activeId === t.id }">{{ t.text }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<p class="eyebrow">关于这里</p>
|
||||
<p class="bio">{{ site.author_bio || site.site_desc }}</p>
|
||||
@@ -174,6 +212,24 @@ onMounted(async () => {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* 文章目录:当前小节高亮,层级缩进 */
|
||||
.toc-list {
|
||||
list-style: none;
|
||||
margin: 8px 0 0;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.toc-list li {margin: 2px 0;
|
||||
border-left: 2px solid transparent;
|
||||
padding-left: 8px;}
|
||||
.toc-list li.h3 {padding-left: 20px;
|
||||
font-size: 12.5px;}
|
||||
.toc-list li.on {border-left-color: var(--accent);}
|
||||
.toc-list a {color: var(--muted);
|
||||
text-decoration: none;}
|
||||
.toc-list li.on a, .toc-list a:hover {color: var(--accent);}
|
||||
|
||||
.list {
|
||||
list-style: none;
|
||||
margin: 8px 0 0;
|
||||
|
||||
Reference in New Issue
Block a user