feat(about): 用户选定方案 A——关于页改「白纸直编」单字段(5k T1/T2 落地)

用户在 /about-preview/ 五案中选 A。落地:
- siteAbout schema 增 `doc`(双语整页 markdown);about.yaml 现有内容已合成
  doc(身份语 + 关于我 + 找到我 + 本站如何构建,双语齐备)
- AboutPage 四级回落:**doc 白纸直编 → blocks 块式 → intro → 内置默认**
  (doc 非空时整页只渲染它,IdCard 仍在顶部;blocks 降为 legacy 通道)
- 后台「关于页」最顶部即「整页正文」markdown 字段(这就是方案 A 的编辑模型),
  块式结构标注 legacy
- 删除两个已完成的预览路由(/about-preview/、/heatmap-preview/)与 HeatGrid
  预览组件、content-lint 白名单整体移除
- docs/管理台 新增「关于页正文」一节(四级回落说明)

验证: 构建 50 页 exit 0;content-lint 51 页 0/0/0;config-check 234 字段/74 hint;
      产物断言 doc 渲染(汇文+红身份语 / 找到我链接 / mono 小标题);
      E2E 56/56(含书架开合翻转与 5j 数据板口径更新)

Spec: 2026-11-04_blog-5k-about-designs (T1/T2)

Co-authored-by: GLM-5.3
This commit is contained in:
wait4xandGLM-5.3 committed 2026-11-04 23:22:41 +08:00
1 parent b41b4ba8a5
commit 4153c6d33f
11 files changed
+108 -793

No files matched your search

-58
View File
@@ -1,58 +0,0 @@
---
/**
* 热力图网格(可复用渲染件):给 5 个动效方案预览共用,避免把 371 个格子抄五遍。
*
* 每格带 `data-c/--c`(列=周)与 `data-r/--r`(行=星期),动效方案靠这两个自定义属性
* 算错峰延迟;`data-l` 是灰阶档(0–4,复用 tokens 的 --ink-1..4)。
* 全部格子 aria-hidden:语义由外层 role="img" + aria-label 概括(371 个 aria 节点是噪音)。
*/
import { levelOf, type HeatDay } from '../../lib/heatmap';
interface Props {
weeks: HeatDay[][];
/** 网格类型,仅用于选择器命名(不动行为) */
variant: string;
/** 单元格错峰延迟基数(ms),0 = 不设延迟 */
step?: number;
}
const { weeks, variant, step = 0 } = Astro.props;
---
<div class={`hg hg-${variant}`} data-hg={variant}>
{weeks.map((week, ci) =>
week.map((day, ri) => (
<span
class={`hg-c hg-l${levelOf(day.count)}`}
data-c={ci}
data-r={ri}
data-count={day.count}
data-date={day.date}
style={step ? `--c:${ci};--r:${ri};--d:${(ci + ri) * step}ms` : `--c:${ci};--r:${ri}`}
aria-hidden="true"
/>
)),
)}
</div>
<style>
.hg {
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(7, 10px);
grid-auto-columns: 10px;
gap: 3px;
}
.hg-c {
width: 10px;
height: 10px;
border-radius: 2px;
/* 与线上热力图同口径:空格用 hairline 描边、四档用 ink 灰阶(亮暗自动跟随),
accent 只留给各方案的"高亮"(glow / flow / 连续数字),不参与数据编码 */
}
.hg-l0 { border: 1px solid var(--line); }
.hg-l1 { background: var(--ink-4); }
.hg-l2 { background: var(--ink-3); }
.hg-l3 { background: var(--ink-2); }
.hg-l4 { background: var(--ink-1); }
</style>
+24 -3
View File
@@ -5,6 +5,8 @@ import { t } from '../../i18n/ui';
import type { Locale } from '../../lib/locale';
import { aboutIntroMarkdown, pageTypography, renderMarkdown } from '../../lib/site-content';
import { getAboutPage } from '../../lib/page-blocks';
import { getCollection } from 'astro:content';
import { pickBi } from '../../lib/site-content';
import BlockRenderer from '../blocks/BlockRenderer.astro';
// /en/ 侧由 T4 薄页传 locale='en';zh 路由无人传参,默认 zh 零回归
@@ -12,10 +14,14 @@ interface Props {
locale?: Locale;
}
const { locale = 'zh' } = Astro.props;
// 三级回落(零回归):blocks 驱动 → intro markdown → 内置默认文案
// 四级回落(Phase 5k 方案 A):doc 白纸直编 → blocks 块式 → intro markdown → 内置默认
// doc 非空时整页就是这一段 markdown(用户拍板的编辑模型:想写什么写什么)
const entry = (await getCollection('siteAbout'))[0];
const { blocks, showIdCard } = await getAboutPage(locale);
const docMd = pickBi(entry?.data.doc, { zh: '', en: '' }, locale);
const docHtml = docMd.trim() ? await renderMarkdown(docMd) : '';
const introHtml =
blocks.length === 0 ? await renderMarkdown(await aboutIntroMarkdown(locale)) : '';
!docHtml && blocks.length === 0 ? await renderMarkdown(await aboutIntroMarkdown(locale)) : '';
const typo = await pageTypography('siteAbout', 'about');
---
@@ -23,7 +29,12 @@ const typo = await pageTypography('siteAbout', 'about');
<h1 class="page-title">{t('about_title', locale)}</h1>
<div class={typo.className || undefined} style={typo.style || undefined}>
{blocks.length > 0 ? (
{docHtml ? (
<>
{showIdCard && <IdCard />}
<article class="about-doc rich" set:html={docHtml} />
</>
) : blocks.length > 0 ? (
<>
{blocks.map((block) => <BlockRenderer block={block} />)}
{showIdCard && <IdCard />}
@@ -157,4 +168,14 @@ const typo = await pageTypography('siteAbout', 'about');
color: var(--ink-2);
max-width: var(--measure);
}
/* 方案 A 白纸直编:单栏、行距放宽,交给全局 .rich 排版体系 */
.about-doc { max-width: var(--measure); }
.about-doc :global(h2) {
font-size: 15px;
font-family: var(--font-mono);
color: var(--ink-3);
letter-spacing: 0.06em;
margin: var(--space-6) 0 var(--space-3);
}
.about-doc :global(p) { line-height: 1.85; }
</style>