/* Aurora Admin 组件库文档 — 交互逻辑(无依赖 vanilla JS) 布局与交互对齐 Element 文档:首页落地页 / 快速开始 / 分类侧栏 / 多演示块样式(居中箭头展开)/ 右侧锚点目录 / Ctrl+K 搜索 */ (function () { 'use strict'; var LIB_ROOT = '../.design_library/aurora-admin/'; var SPEC_ROOT = '../'; var TAB_ORDER = ['html', 'css', 'jsx', 'vue2', 'vue3']; var TAB_LABELS = { html: 'H5 HTML', css: 'CSS', jsx: 'React JSX', vue2: 'Vue 2', vue3: 'Vue 3' }; var BATCH_LABELS = { 1: '核心规范', 2: '第二批', 3: '第三批', 4: '第四批', 5: '第五批', 6: '第六批', 7: '第七批', 8: '第八批', 9: '第九批', 10: '第十批' }; var CAT_LABELS = { general: '通用', navigation: '导航', input: '数据录入', display: '数据展示', feedback: '反馈', system: '工具与系统' }; var CAT_EN = { general: 'General', navigation: 'Navigation', input: 'Data Entry', display: 'Data Display', feedback: 'Feedback', system: 'System' }; var CAT_ORDER = ['general', 'navigation', 'input', 'display', 'feedback', 'system']; var KIND_LABELS = { html: 'H5 静态页', css: '样式表', jsx: 'React 组件', vue2: 'Vue 2 组件', vue3: 'Vue 3 组件' }; /* 框架感知:每种技术栈需要的文件形态 */ var FRAMEWORKS = { h5: 'H5', react: 'React', vue2: 'Vue 2', vue3: 'Vue 3' }; var FW_FILES = { h5: ['html', 'css'], react: ['jsx', 'css'], vue2: ['vue2'], vue3: ['vue3'] }; var data = window.AA_DATA; var $ = function (id) { return document.getElementById(id); }; function fatal(msg) { var el = $('fatal'); el.textContent = msg; el.classList.remove('hidden'); } if (!data || !data.components || !data.components.length) { fatal('数据加载失败:site/data.js 缺失或为空。请先在仓库根目录运行 build-site.ps1 重新生成。'); return; } var comps = data.components; var bySlugMap = {}; comps.forEach(function (c) { bySlugMap[c.slug] = c; }); var state = { route: { page: 'home', slug: null }, query: '', ovCat: '', ovQ: '', framework: 'h5', searchCat: '' }; var thumbObserver = null; function loadFramework() { try { var saved = localStorage.getItem('aa-framework'); if (saved && FRAMEWORKS[saved]) return saved; } catch (e) { /* ignore */ } return 'h5'; } /* ---------- 工具 ---------- */ function el(tag, cls, html) { var e = document.createElement(tag); if (cls) e.className = cls; if (html != null) e.innerHTML = html; return e; } function esc(s) { return String(s == null ? '' : s) .replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } function splitName(name) { var m = name.match(/^(.+?)\s+([A-Za-z0-9].*)$/); return m ? { zh: m[1], en: m[2] } : { zh: name, en: '' }; } function batchLabel(b) { return BATCH_LABELS[b] || ('第' + b + '批'); } function catLabel(key) { return CAT_LABELS[key] || key || '未分类'; } function catEn(key) { return CAT_EN[key] || ''; } function fmtSize(bytes) { if (bytes == null) return '—'; if (bytes < 1024) return bytes + ' B'; return (bytes / 1024).toFixed(1) + ' KB'; } function specLink(file) { return SPEC_ROOT + file; } function cleanSummary(s) { return (s || '').replace(/^[-•·]\s*/, '').trim(); } /* ---------- 路由 ---------- */ function parseHash() { var h = location.hash.replace(/^#/, ''); if (!h || h === '/') return { page: 'home', slug: null }; if (h === '/overview') return { page: 'overview', slug: null }; if (h === '/guide') return { page: 'guide', slug: null }; if (h === '/design') return { page: 'design', slug: null }; if (h === '/agents') return { page: 'agents', slug: null }; if (h === '/changelog') return { page: 'changelog', slug: null }; var m = h.match(/^\/component\/([a-z0-9-]+)/i); if (m && bySlugMap[m[1]]) return { page: 'component', slug: m[1] }; return { page: 'home', slug: null }; } function navigate(opts) { var fwOnly = opts && opts.fwOnly; state.route = parseHash(); closeSearch(); renderSidebar(); renderTopnav(); renderToc([]); var content = $('content'); if (state.route.page === 'home') renderHome(content); else if (state.route.page === 'overview') renderOverview(content); else if (state.route.page === 'guide') renderGuide(content); else if (state.route.page === 'design') renderDesign(content); else if (state.route.page === 'agents') renderAgents(content); else if (state.route.page === 'changelog') renderChangelog(content); else renderComponent(content, state.route.slug); /* 仅切换框架时不滚到顶部,避免用户感觉"页面没切换" */ if (!fwOnly) window.scrollTo(0, 0); if (window.aaLogger) { window.aaLogger.render(state.route.page || 'unknown', { slug: state.route.slug || null, framework: state.framework }); } } function renderTopnav() { var r = state.route.page; document.querySelectorAll('.topnav a').forEach(function (a) { var nav = a.getAttribute('data-nav'); var active = (nav === r) || (nav === 'overview' && r === 'component'); a.classList.toggle('active', active); }); } /* ---------- 侧边栏 ---------- */ function renderSidebar() { var sb = $('sidebar'); sb.innerHTML = ''; var r = state.route.page; var links = [ { label: '组件总览', hash: '#/overview', active: r === 'overview' || r === 'component' }, { label: '快速开始', hash: '#/guide', active: r === 'guide' }, { label: '设计规范', hash: '#/design', active: r === 'design' } ]; links.forEach(function (L) { var a = el('a', 'side-link' + (L.active ? ' active' : ''), esc(L.label)); a.href = L.hash; sb.appendChild(a); }); CAT_ORDER.forEach(function (cat) { var items = comps.filter(function (c) { return c.category === cat; }); if (!items.length) return; var g = el('div', 'side-group'); g.innerHTML = '' + items.length + ''; g.querySelector('.cat-zh').textContent = catLabel(cat); g.querySelector('.cat-en').textContent = catEn(cat); sb.appendChild(g); items.forEach(function (c) { var n = splitName(c.name); var b = el('button', 'side-item'); b.type = 'button'; b.setAttribute('data-slug', c.slug); b.innerHTML = ''; b.querySelector('.zh').textContent = n.zh; b.querySelector('.en').textContent = n.en; if (r === 'component' && state.route.slug === c.slug) b.classList.add('active'); b.addEventListener('click', function () { location.hash = '#/component/' + c.slug; }); sb.appendChild(b); }); }); } /* ---------- 右侧目录 ---------- */ function renderToc(items) { var toc = $('toc'); toc.innerHTML = ''; if (!items.length) { toc.style.display = 'none'; return; } toc.style.display = ''; toc.appendChild(el('div', 'toc-title', '本页目录')); items.forEach(function (it) { var a = el('a', null, esc(it.label)); a.setAttribute('data-anchor', it.id); a.addEventListener('click', function (e) { e.preventDefault(); var target = document.getElementById(it.id); if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' }); }); toc.appendChild(a); }); setupScrollSpy(items); } var spyHandler = null; function setupScrollSpy(items) { if (spyHandler) window.removeEventListener('scroll', spyHandler); spyHandler = function () { var pos = window.scrollY + 120; var current = items[0] && items[0].id; items.forEach(function (it) { var node = document.getElementById(it.id); if (node && node.offsetTop <= pos) current = it.id; }); document.querySelectorAll('.toc a').forEach(function (a) { a.classList.toggle('active', a.getAttribute('data-anchor') === current); }); }; window.addEventListener('scroll', spyHandler, { passive: true }); spyHandler(); } /* ---------- 首页(落地页) ---------- */ function renderHome(content) { content.innerHTML = ''; var inner = el('div', 'page-inner home'); /* Hero stats 第三项加入"测试" */ var hero = el('div', 'hero'); hero.innerHTML = '
理性、高效、克制的 B 端中后台设计系统——信息密度适中,层级清晰,交互反馈即时。
' + '' + 'css.json;聚合组件样式见 components.css。'));
inner.appendChild(s1);
tocItems.push({ id: 'install', label: '引入设计令牌' });
/* 2. 按端使用组件 */
var s2 = el('div', 'sec'); s2.id = 'usage';
s2.appendChild(el('h2', null, '按端使用组件'));
s2.appendChild(el('p', 'guide-p', '每个组件在 frameworks/ 下有五种形态(H5 / CSS / React / Vue 2 / Vue 3),按你的技术栈取用:'));
var tbl = el('table', 'res-table');
var thead = el('thead');
var trh = el('tr');
['端', '文件', '使用方式'].forEach(function (t) { trh.appendChild(el('th', null, t)); });
thead.appendChild(trh); tbl.appendChild(thead);
var tbody = el('tbody');
[
['H5 静态页', 'Button.html', '直接在浏览器打开即为完整演示页;将结构与内联样式拷贝进你的页面'],
['React', 'Button.jsx + Button.css', '将 JSX 与 CSS 拷入工程,按需改造数据绑定'],
['Vue 2', 'Button.vue2.vue', 'Options API 单文件组件,直接注册使用'],
['Vue 3', 'Button.vue3.vue', '