Files
aurora-admin/site/index.html
T
aurora-admin f1fbfc2ddb
Regression / regression (push) Canceled after 0s
feat(品牌标识): 几何 K 图标(favicon/顶栏标记/theme-color) + 并行会话成果入库
## 品牌标识(本次会话)

起因:品牌此前没有任何图形标识 —— 唯一 favicon 是内联 data-URI 里的字母「A」,
那是 v2.0.0「Aurora Admin → Kole UI」改名漏掉的一处(PC 顶栏也是「A」,
移动端站已是「K」;移动端文档站则完全没有 favicon)。

- 几何:24 网格三个互不接触的笔画(竖 + 两斜),圆头描边;
  描边 2.25 → 16px 标签页尺寸下正好 1.5px = 规范原文「描边1.5px」
- 取色分两套(刻意):favicon 硬编码品牌蓝/白(渲染在浏览器标签栏,不继承 kole-dark);
  顶栏标记走 currentColor(实测暗色下自动转 rgb(20,22,28))
- 新增 theme-color 双条(light #FFFFFF / dark #1C1F26,取 --kole-color-card-bg)
- 修 site/app.js hero 标语 KOLE ADMIN → KOLE UI(改名变形残留)
- 移动端 7 个模板补 favicon(此前计数 0)

验收:门禁 9 条全 OK(site-routing/site-routes/mobile-docs/mobile-site/isolation/
theme/nav/i18n/icons);PC 回归 1464/1464 · 移动端 807/807,各连跑 8 次一致;
两端 favicon 405 字节逐字节一致;PC 站控制台错误 1→0。

## 并行会话成果(本次一并入库)

- 图标系统:2576 图标(TDesign/Element Plus,MIT)+ 11 端注入 + 5 个构建门禁工具
  + IconPreview 预览页 + ICON-SPEC.md 冻结规格
- 移动端平台:47 组件 × 6 端 + 文档站 53 页 + 隔离门禁
- PC 组件:103 个大后台组件 / 组件11 批次
- uni-app:PC 端试点 + 移动端端实现 + 真实编译验证

## 工程

- .gitignore 补 .scratch/ 与 .zcode-preexisting-*.txt(会话中间产物,实测 9.1MB,不入库)
- CHANGELOG 补品牌标识条目
- ROADMAP 登 S8-P4(品牌标识任务包 + og:image/apple-touch-icon 未做部分)
2026-09-21 10:05:48 +08:00

259 lines
21 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">
<meta name="color-scheme" content="light dark">
<title>Kole UI · 组件库文档</title>
<!-- 主题在解析期定型,避免「先白后黑」闪烁:模式存在 localStorage['kole-mode'],
默认 auto(没有显式选择即跟随系统 prefers-color-scheme)。app.js 里的
normalizeMode/readMode 必须与此处同规则,两处任一改动都要同步。 -->
<script>
(function () {
var mode = 'auto';
try { mode = localStorage.getItem('kole-mode') || 'auto'; } catch (e) { /* ignore */ }
if (mode !== 'light' && mode !== 'dark' && mode !== 'auto') mode = 'auto';
var dark = mode === 'dark'
|| (mode === 'auto' && !!(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches));
if (dark) document.documentElement.className += ' kole-dark';
})();
</script>
<!-- 路由是 History API 的无 # 形态:深层 URL 形如 /site/component/button/h5,
磁盘上没有对应文件(服务器回落到本页)。这种 URL 下相对路径会以深层路径为
基准解析而全部失效,所以先算出站点根:既写进 <base>(页面内链接交给它解析),
也把资源地址写成绝对路径再输出。
规则与 site/app.js 的 SITE_BASE 必须一致:取 pathname 里第一段 "/site/",
前缀因此可变(本地/nginx 是 /site/,GitHub Pages 是 /<repo>/site/)。
站点目录必须继续叫 site,改目录名要同时改这里和 app.js。
资源不能写成静态的相对地址:预扫描器在脚本执行前就按深层 URL 预取,
实测会多出 2 个 404 + 2 条控制台报错(脚本那侧更贵 —— data.js 有 900+ KB,
会被整份白取一次)。写成绝对地址后,扫描器不需要 base 也能取对。 -->
<script>
(function () {
var p = location.pathname, i = p.indexOf('/site/');
var base = i >= 0 ? p.slice(0, i + 6) : p.replace(/[^/]*$/, '');
window.KOLE_SITE_BASE = base;
document.write('<base href="' + base + '">'
+ '<link rel="stylesheet" href="' + base + '../.design_library/kole-ui/colors_and_type.css">'
+ '<link rel="stylesheet" href="' + base + 'style.css">');
})();
</script>
<!-- 品牌图标:24 网格圆角方块 + 断笔 K(三笔画互不接触)。
为什么这里硬编码 #2F54EB / #FFFFFF 而不用令牌:favicon 渲染在**浏览器标签栏**,
不继承 html.kole-dark —— 令牌 --kole-color-text-inverse 在暗色下是 #14161C,
走令牌会变成「亮蓝底 + 近黑标记」,浅色标签栏上反而发闷。页面内的顶栏标记走
currentColor(见下方 .logo-mark),那才是需要跟随主题的位置。
描边 2.25 @24 网格 → 16px 标签页尺寸下正好 1.5px,等于规范原文
「线性图标,描边1.5px」(.design_library/kole-ui/specs/组件1.txt)。
移动端文档站各页与 tools/build-mobile.mjs 的 BRAND_FAVICON 用同一份几何。 -->
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Crect%20width='24'%20height='24'%20rx='6'%20fill='%232F54EB'/%3E%3Cg%20fill='none'%20stroke='%23FFFFFF'%20stroke-width='2.25'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M7%205.5V18.5'/%3E%3Cpath%20d='M17%205.5l-6.25%204.06'/%3E%3Cpath%20d='M10.75%2014.44L17%2018.5'/%3E%3C/g%3E%3C/svg%3E">
<!-- 浏览器 UI 着色(移动端地址栏 / 桌面端标题栏):取 --kole-color-card-bg —— 顶栏
background 就是这个令牌(site/style.css 的 .topbar),所以色值与视觉连续。 -->
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1C1F26" media="(prefers-color-scheme: dark)">
</head>
<body>
<!-- 顶部导航 -->
<header class="topbar">
<div class="topbar-inner">
<a class="logo" href="./">
<!-- 品牌标记:几何 K。stroke 走 currentColor → 由 .logo-mark 的
--kole-color-text-inverse 决定(暗色下自动转深色),令牌化行为与
同页其它图标一致;不要在这里硬编码颜色。 -->
<span class="logo-mark" aria-hidden="true"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 5.5V18.5"/><path d="M17 5.5l-6.25 4.06"/><path d="M10.75 14.44L17 18.5"/></svg></span>
<span class="logo-text">Kole UI <em class="logo-sub">组件库</em></span>
</a>
<!-- 版本入口:清单由 site/versions.json 启动时填充(app.js 的 bindVersionSelect)。
下拉菜单必须与触发角标同处一个定位容器 —— 菜单是绝对定位,容器没有
position 时它会锚到页面上而不是角标下方(实测跑到了左上角)。 -->
<div class="ver-picker" id="ver-picker">
<button id="version-trigger" class="ver-trigger" type="button" aria-haspopup="listbox" aria-expanded="false" aria-label="选择版本">
<span id="ver">v1.0.0</span>
<svg class="ver-caret" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div id="version-menu" class="ver-menu hidden" role="listbox" aria-label="文档版本">
<div class="ver-menu-head" id="ver-head">文档版本</div>
</div>
</div>
<button id="search-trigger" class="search-trigger" type="button">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<span class="st-text">搜索组件…</span>
<kbd>Ctrl K</kbd>
</button>
<!-- 技术栈选择器(2026-09-20 美化):原先是一个裸 <select>(系统原生下拉、无悬停/展开态、
与旁边的语言/主题选择器视觉不同源)。改为「胶囊触发器 + 卡片菜单」,与 .lang-select /
.theme-select 同款式:图标 + 当前值 + 箭头,菜单含标题分隔线、每项的端文件名角标与对勾。
原生 <select> 保留在包装内(.fw-native,1px 视觉隐藏)作为状态真源 —— app.js 的
change 管道、localStorage 与既有验证脚本(run-site-smoke 读 inputValue)全部不变。 -->
<div class="fw-select-wrap" id="fw-select-wrap" title="选择你的技术栈,文档将只展示对应框架的内容">
<button id="fw-trigger" class="fw-trigger" type="button" aria-haspopup="listbox" aria-expanded="false" aria-label="框架">
<svg class="fw-glyph" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 3 8.5 4.7L12 12.4 3.5 7.7 12 3z"/><path d="m3.5 12.3 8.5 4.7 8.5-4.7"/></svg>
<span class="fw-cur" id="fw-cur">H5</span>
<svg class="fw-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
</button>
<select id="fw-select" class="fw-native" tabindex="-1" aria-hidden="true">
<option value="h5">H5</option>
<option value="react">React</option>
<option value="vue2">Vue 2</option>
<option value="vue3">Vue 3</option>
</select>
<div id="fw-menu" class="lang-menu fw-menu hidden" role="listbox" aria-label="技术栈">
<div class="lang-head"><span id="fw-head">技术栈</span><span class="fw-head-file" id="fw-head-file">html</span></div>
<button class="lang-opt fw-opt" type="button" role="option" data-fw="h5" aria-selected="true">
<span class="lang-opt-name">H5</span>
<span class="lang-opt-code">html</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
<button class="lang-opt fw-opt" type="button" role="option" data-fw="react" aria-selected="false">
<span class="lang-opt-name">React</span>
<span class="lang-opt-code">jsx</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
<button class="lang-opt fw-opt" type="button" role="option" data-fw="vue2" aria-selected="false">
<span class="lang-opt-name">Vue 2</span>
<span class="lang-opt-code">vue2</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
<button class="lang-opt fw-opt" type="button" role="option" data-fw="vue3" aria-selected="false">
<span class="lang-opt-name">Vue 3</span>
<span class="lang-opt-code">vue3</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
</div>
</div>
<nav class="topnav" id="topnav">
<a href="./" data-nav="home">首页</a>
<a href="overview" data-nav="overview">组件</a>
<a href="guide" data-nav="guide">快速开始</a>
<a href="design" data-nav="design">设计规范</a>
<a href="faq" data-nav="faq">常见问题</a>
<a href="changelog" data-nav="changelog">更新日志</a>
<!-- 抽屉内的版本入口:≤560px 顶栏放不下版本控件(实测溢出),抽屉是这一档的自然位置。
选项由 site/versions.json 填充;清单拿不到版本时整行不显示。 -->
<label class="drawer-ver" id="drawer-ver" hidden>
<span class="drawer-ver-label">版本</span>
<select id="drawer-ver-select" aria-label="选择版本"></select>
</label>
</nav>
<!-- 主题模式(日间 / 夜间 / 自动):顶栏常驻入口,与右下角悬浮按钮共用同一份状态。
菜单选项的 data-mode 是三态的取值来源,改这里要同步 app.js 的 MODE_LABELS。 -->
<div class="theme-select" id="theme-select">
<button id="topbar-mode" class="theme-trigger" type="button" title="主题模式" aria-label="主题模式" aria-expanded="false" aria-haspopup="true">
<svg class="theme-icon" id="tb-icon-moon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
<svg class="theme-icon" id="tb-icon-sun" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:none"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
<svg class="theme-icon" id="tb-icon-auto" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:none"><rect x="3" y="4" width="18" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></svg>
<span class="theme-cur" id="topbar-mode-label">自动模式</span>
<svg class="theme-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div id="topbar-mode-menu" class="mode-menu hidden" role="radiogroup" aria-label="主题模式">
<!-- 菜单头由 app.js 的 updateModeUI 填充(两行:当前选中 / 实际生效),
这里留空 —— 静态占位会在脚本执行前闪现过时文案 -->
<div class="mode-current" id="tb-mode-current" aria-live="polite"></div>
<button type="button" role="radio" data-mode="light" aria-checked="false"><span class="mode-dot mode-dot-light"></span><span data-mode-label="light">日间模式</span></button>
<button type="button" role="radio" data-mode="dark" aria-checked="false"><span class="mode-dot mode-dot-dark"></span><span data-mode-label="dark">夜间模式</span></button>
<button type="button" role="radio" data-mode="auto" aria-checked="false"><span class="mode-dot mode-dot-auto"></span><span data-mode-label="auto">自动模式</span></button>
</div>
</div>
<div class="lang-select" id="lang-select">
<button id="lang-trigger" class="lang-trigger" type="button" title="界面语言" aria-label="选择语言" aria-haspopup="listbox" aria-expanded="false">
<svg class="lang-globe" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
<span class="lang-cur" id="lang-cur">简体中文</span>
<svg class="lang-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div id="lang-menu" class="lang-menu hidden" role="listbox" aria-label="界面语言">
<div class="lang-head">界面语言</div>
<button class="lang-opt" type="button" role="option" data-lang="zh" aria-selected="true">
<span class="lang-opt-name">简体中文</span>
<span class="lang-opt-code">ZH</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
<button class="lang-opt" type="button" role="option" data-lang="en" aria-selected="false">
<span class="lang-opt-name">English</span>
<span class="lang-opt-code">EN</span>
<svg class="lang-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
</button>
</div>
</div>
<!-- 窄屏版本入口:≤900px 时顶栏角标被隐藏(见 style.css),这里改用原生 select 顶上。
选项由 site/versions.json 填充;只有一版时整块不显示。 -->
<label class="ver-select-wrap" id="ver-select-wrap" title="文档版本" hidden>
<select id="ver-select" aria-label="选择版本"></select>
</label>
<button id="nav-toggle" class="nav-toggle" type="button" aria-label="打开导航菜单" aria-controls="topnav" aria-expanded="false">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h18"/><path d="M3 12h18"/><path d="M3 18h18"/></svg>
</button>
</div>
<!-- 窄屏导航抽屉的遮罩:仅 ≤1366px 且抽屉打开时可见。
必须放在 .topbar 内 —— .topbar 有 z-index:100 会形成层叠上下文,
放到外面会让遮罩(110)压住抽屉(120),抽屉可见却点不动。 -->
<div id="nav-backdrop" class="nav-backdrop"></div>
</header>
<div class="body-wrap">
<aside class="sidebar" id="sidebar"></aside>
<main class="content" id="content"></main>
<aside class="toc" id="toc"></aside>
</div>
<!-- 全局搜索弹窗 -->
<div class="modal-mask hidden" id="search-modal">
<div class="modal">
<div class="modal-input-wrap">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input id="search-input" placeholder="搜索组件(中文 / 英文 / slug)" autocomplete="off" spellcheck="false">
</div>
<div id="search-cats" class="search-cats"></div>
<div id="search-results" class="search-results"></div>
<div class="modal-foot"><span>↑↓ 选择</span><span>Enter 跳转</span><span>Esc 关闭</span></div>
</div>
</div>
<div id="fatal" class="fatal hidden"></div>
<!-- 悬浮工具:深色模式 + 主题定制 + 回到顶部 -->
<div class="fab-stack">
<div class="theme-panel hidden" id="theme-panel">
<div class="tp-head">主题定制</div>
<div id="theme-presets" class="tp-presets"></div>
<div id="theme-colors"></div>
<div class="tp-actions">
<button id="theme-reset" class="tp-btn" type="button">重置</button>
<button id="theme-copy" class="tp-btn primary" type="button">复制覆盖代码</button>
</div>
<div class="tp-note">覆盖代码可直接粘贴到令牌文件之后,即完成整站换色。</div>
</div>
<div class="mode-control">
<button id="fab-mode" class="fab" type="button" title="主题模式" aria-label="主题模式" aria-expanded="false" aria-haspopup="true">
<svg id="icon-moon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
<svg id="icon-sun" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
<svg id="icon-auto" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none"><rect x="3" y="4" width="18" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></svg>
</button>
<div id="mode-menu" class="mode-menu hidden" role="radiogroup" aria-label="主题模式">
<div id="mode-current" class="mode-current" aria-live="polite"></div>
<button type="button" role="radio" data-mode="light" aria-checked="false"><span class="mode-dot mode-dot-light"></span><span data-mode-label="light">日间模式</span></button>
<button type="button" role="radio" data-mode="dark" aria-checked="false"><span class="mode-dot mode-dot-dark"></span><span data-mode-label="dark">夜间模式</span></button>
<button type="button" role="radio" data-mode="auto" aria-checked="false"><span class="mode-dot mode-dot-auto"></span><span data-mode-label="auto">自动模式</span></button>
</div>
</div>
<button id="fab-theme" class="fab" type="button" title="主题定制">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 3a9 9 0 0 0 0 18c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01a1.5 1.5 0 0 1 1.12-2.49H16a5 5 0 0 0 5-5c0-4.42-4.03-8-9-8z"/></svg>
</button>
<button id="fab-top" class="fab" type="button" title="回到顶部" style="display:none">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
</div>
<!-- 脚本同样必须写成绝对地址(理由见 <head> 顶部注释)。document.write 在解析期
注入的是 parser-inserted script:按顺序同步执行,且仍是 DOMContentLoaded 的
阻塞项,语义与静态 <script src> 一致。 -->
<script>
(function () {
var b = window.KOLE_SITE_BASE;
['data.js', 'logger.js', 'i18n.js', 'app.js'].forEach(function (f) {
document.write('<script src="' + b + f + '"><\/script>');
});
})();
</script>
</body>
</html>