Files
ONE/frontend/src/ui/yohaku/YohakuToolbar.vue
T
Sakurasan fbda293072 余白 UI:按设计稿模块化还原 + 站主自定义 CSS + 详情 neighbors + 静态缓存头
前端(新增 ui/yohaku/,各视图按 ui_id=vivid 分支渲染;classic 与后台不受影响)
- 令牌层:设计稿数值原样落地,28 个 --v-* 为站主接口(自定义 CSS 可覆盖,
  放 @layer 让出优先级);另加防线,中和 styles.css 裸选择器
  (h1 衬线 / body 行高 / 后台 .stat/.toolbar/.chip 卡片)漏进余白元素
- 顶栏(滚动收缩态)/ 阅读进度(顶部 2px + READ n%)/ 页脚
- 首页:hero(统计条)/ 筛选(类型分段 + 标签 chips + 搜索)/
  长文卡片与短文纸条 / 分页 / 作品展示区(3 件 + 查看所有,参照 diygod.cc);
  面板栅格改 1.6fr 1fr 1fr 且高度自适应内容(标签云明显大一圈)
- 文章页:三栏「纸」—— 左时间线(前后各两篇)/ 中纸张 / 右目录与阅读进度;
  短文详情不显示标题(h1 视觉隐藏保留无障碍)
- 全部规则收敛在 html[data-ui='vivid'] 前缀下;无 !important

后端
- GET /api/posts/:slug 增 neighbors(前后各两篇,详情页侧栏时间线用)
- SPA 缓存头:index.html no-cache,assets/ 带 hash 长期 immutable
  (此前无缓存头,浏览器会一直拿旧构建)

其他
- 站主自定义 CSS 管线(customCss.js + ui/sections.js,按分区注入,仅 vivid)
- 删除旧 vivid 覆盖层实现(VividNav/Hero/Footer/Timeline/Toc、ui/vivid.css)
- 设计稿原型附于仓库根 index.html;作品表清掉外链 diygod.cc 的示例封面,
  改用本地占位图(public/covers/)
2026-09-23 15:37:42 +08:00

70 lines
1.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref } from 'vue'
// 余白筛选条。对应设计稿的 <div class="toolbar">:类型分段 + 标签 chips + 搜索。
// 状态不在组件里 : 全部走路由 query(kind / tag / q / page),
// 这样筛选结果可以直接分享,也和后端分页对得上。
const props = defineProps({
kind: { type: String, default: '' },
tag: { type: String, default: '' },
query: { type: String, default: '' },
tags: { type: Array, default: () => [] }
})
const emit = defineEmits(['update:kind', 'update:tag', 'update:query'])
const kinds = [
{ value: '', label: '全部' },
{ value: 'long', label: '长文' },
{ value: 'short', label: '短文' }
]
const draft = ref(props.query)
function submit() {
emit('update:query', draft.value.trim())
}
function pickKind(v) {
// 设计稿里点类型会清掉标签:「全部」是真正的复位
emit('update:tag', '')
emit('update:kind', v)
}
</script>
<template>
<div class="toolbar">
<div class="seg" role="tablist" aria-label="按类型筛选">
<button
v-for="k in kinds"
:key="k.label"
type="button"
role="tab"
:aria-selected="props.kind === k.value && !props.tag"
:class="{ on: props.kind === k.value && !props.tag }"
@click="pickKind(k.value)"
>{{ k.label }}</button>
</div>
<div class="chips">
<button
v-for="t in props.tags"
:key="t.slug || t.name"
type="button"
class="chip"
:class="{ on: props.tag === t.name }"
@click="emit('update:tag', props.tag === t.name ? '' : t.name)"
>{{ t.name }}</button>
</div>
<label class="search">
<input
v-model="draft"
type="search"
placeholder="搜索…"
aria-label="搜索文章"
@keydown.enter.prevent="submit"
>
<button type="button" aria-label="搜索" @click="submit">⌕</button>
</label>
</div>
</template>