Files
aurora-admin/frameworks/anchornav.html
T
aurora-admin 382ca79b66 v1.4.0: 组件层全面令牌化(设计系统根基修复)
问题
- 79 个组件的 844 个颜色属性里,只有 2 个(0.2%)引用令牌,
  788 个(93.4%)硬编码 hex
- 后果:改令牌组件不跟着变、主题定制器对组件无效、For Agents 页写的
  「所有色值必须取自 au-* 变量」形同虚设
- 这是本项目第五次「声称≠实现」,且动摇了设计系统的根本

两层令牌化(此前只改了从未被加载的文件,走了弯路)
- 组件样式表 frameworks/*.css:915 处 / 78 文件
- 演示页内嵌 <style>(实际生效的样式层):287 处 / 51 文件
- 内嵌样式层是决定性的:演示页只 link colors_and_type.css + 自己的 CSS,
  而多数页面把关键样式写在 <style> 块里 —— 只改 CSS 文件不生效

安全策略
- 只替换颜色属性值位置的 hex(color/background*/border*/outline*/fill/stroke)
- 跳过 rgba()/渐变/url() 复合值;不动 SVG 属性与 JS 数据(色板数组)
- 歧义色值按属性语义消解(#FFFFFF 作 color→text-inverse,作 background→card-bg)
- 幂等,可重复运行

补齐令牌语义(71 → 74)
- --au-color-text-tertiary #595959(规范未定义、实现补齐,7.00:1)
- --au-color-text-disabled #BFBFBF(规范定义于组件1/2.txt;WCAG 1.4.3 豁免)
- --au-color-border-strong #F0F0F0(规范未定义、实现补齐)
- 同步 legacy 别名;修复 colors_and_type.css 一处重复注释起始行

修复
- Countdown 首帧空白:setInterval(render, 1000) 首次执行要等 1 秒,
  期间容器为空。改为定义函数后立即执行一次再挂 interval

验证(本轮核心验收)
- 逐组件验证「改令牌 → 元素是否跟着变」:79/79 全部响应
- 过程中修正两处测量方法缺陷(初测 40/79 是误报):
  ① 选择器 .demo * 在无 .demo 容器的页面抓不到元素
  ② 探针令牌选错 —— Breadcrumb 用 text-tertiary 而只改了 text-body
- CSS 结构完整:158 个文件括号平衡、var(--*) 引用全部有定义
- 回归保持 100%:961 断言 / 0 失败 / 79 页全通过,三次连跑一致
2026-09-11 17:29:30 +08:00

82 lines
3.7 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aurora Admin · AnchorNav (H5)</title>
<link rel="stylesheet" href="../.design_library/aurora-admin/colors_and_type.css">
<link rel="stylesheet" href="./AnchorNav.css">
<style>
.demo { padding: 24px 200px 400px 24px; background: var(--au-color-page-bg); font-family: var(--font-family); color: var(--au-color-text-body); }
h1 { font-size: 20px; margin: 0 0 24px; color: var(--au-color-text-title); }
.sub { color: var(--au-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
section { background: var(--au-color-card-bg); border: 1px solid var(--au-color-border); border-radius: 8px; padding: 20px 24px; margin-bottom: 24px; scroll-margin-top: 24px; }
section h2 { font-size: 16px; margin: 0 0 8px; }
section p { color: var(--au-color-text-tertiary); line-height: 1.8; margin: 0; }
</style>
</head>
<body>
<div class="demo">
<h1>Aurora Admin · AnchorNav 组件(纯 H5)</h1>
<p class="sub">对齐 AnchorNav 规范:右侧目录、滚动高亮、层级嵌套、点击平滑滚动</p>
<nav class="aa-anchor fixed" id="anchor"></nav>
<section id="intro"><h2>1. 产品简介</h2><p>本系统是一套企业级中后台解决方案……(长文本占位,可滚动测试高亮)</p><p style="margin-top:40px">更多内容用于撑高页面,方便观察当前章节高亮效果。</p></section>
<section id="install"><h2>2. 安装与初始化</h2><p>通过 npm 安装后,在入口文件引入主题与组件库。</p><p style="margin-top:40px">配置项说明略。</p></section>
<section id="guide">
<h2>3. 开发指南</h2>
<p>包含布局、主题与国际化三部分。</p>
<div id="layout" style="margin-top:16px"><h3>3.1 布局</h3><p>侧边栏 + 顶栏的经典后台布局。</p></div>
<div id="theme" style="margin-top:16px"><h3>3.2 主题</h3><p>通过 CSS 变量统一调整品牌色。</p></div>
</section>
<section id="faq"><h2>4. 常见问题</h2><p>收集部署与升级中的高频问题。</p><p style="margin-top:40px">FAQ 列表略。</p></section>
</div>
<script>
const ITEMS = [
{ key: 'intro', label: '产品简介' },
{ key: 'install', label: '安装与初始化' },
{ key: 'guide', label: '开发指南', children: [
{ key: 'layout', label: '布局' },
{ key: 'theme', label: '主题' }
] },
{ key: 'faq', label: '常见问题' }
];
const allKeys = [];
(function collect(list) { list.forEach(i => { allKeys.push(i.key); if (i.children) collect(i.children); }); })(ITEMS);
const anchor = document.getElementById('anchor');
function render() {
anchor.innerHTML = ITEMS.map(it => {
let html = `<button class="aa-anchor-item" role="link" tabindex="0" data-key="${it.key}">${it.label}</button>`;
if (it.children) {
html += '<div class="aa-anchor-sub">' + it.children.map(c => `<button class="aa-anchor-item" role="link" tabindex="0" data-key="${c.key}">${c.label}</button>`).join('') + '</div>';
}
return html;
}).join('');
}
render();
anchor.addEventListener('click', (e) => {
const btn = e.target.closest('.aa-anchor-item');
if (!btn) return;
const el = document.getElementById(btn.dataset.key);
if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 24, behavior: 'smooth' });
});
function updateActive() {
const pos = window.scrollY + 80;
let active = allKeys[0];
for (const k of allKeys) {
const el = document.getElementById(k);
if (el && el.offsetTop <= pos) active = k;
}
anchor.querySelectorAll('.aa-anchor-item').forEach(b => b.classList.toggle('is-active', b.dataset.key === active));
}
window.addEventListener('scroll', updateActive);
updateActive();
</script>
</body>
</html>