471b980179
- 引入 Eleventy 静态站点生成器,页面统一使用 Nunjucks 模板 - base.njk 提供公共 nav / footer / CSS,消除三个页面间的重复代码 - 抽取 color.css(设计 token)+ style.css(公共组件 + utility 类) - index.njk:首页迁移,用 utility class 替换大量页面私有 CSS - download.njk:下载页重构,版本号/更新日志从 CHANGELOG.md 构建时解析,OS 自动识别 - docs.njk:文档页重构,12 章内容从 web/content/docs.md 构建时渲染,三列布局保留 - docs.css 单独提取,docs 专有样式不污染公共 CSS - 内容面向非技术用户重写,去除技术术语和内部路径引用 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
195 lines
6.4 KiB
Plaintext
195 lines
6.4 KiB
Plaintext
---
|
|
layout: base.njk
|
|
title: 使用手册
|
|
description: 岩美酒库管理系统使用手册,覆盖入库、出库、库存、财务等全功能操作说明。
|
|
pageExtraCss: /assets/docs.css
|
|
---
|
|
|
|
<!-- ============================== DOCS SUB-NAV ============================== -->
|
|
<div class="docs-subnav">
|
|
<div class="docs-subnav-inner">
|
|
<nav class="breadcrumb">
|
|
<a href="/">岩美</a>
|
|
<span class="sep">/</span>
|
|
<span class="current">使用手册</span>
|
|
</nav>
|
|
|
|
<div class="docs-search">
|
|
<i data-lucide="search" class="search-icon icon"></i>
|
|
<input type="text" placeholder="搜索文档..." id="docs-search-input" />
|
|
<span class="kbd">⌘K</span>
|
|
</div>
|
|
|
|
<div class="docs-version">
|
|
<i data-lucide="tag" class="icon"></i>
|
|
<span class="docs-version-label">版本</span>
|
|
<span>v{{ changelog[0].version }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================== THREE-COLUMN LAYOUT ============================== -->
|
|
<div class="docs-layout">
|
|
|
|
<!-- Left TOC -->
|
|
<aside class="docs-toc" id="docs-toc">
|
|
{% for group in docs.toc %}
|
|
<div class="toc-section">
|
|
<div class="toc-section-title">{{ group.group }}</div>
|
|
{% for item in group.items %}
|
|
<a href="#{{ item.id }}" class="toc-link" data-chapter="{{ item.id }}">
|
|
<span class="toc-num">{{ item.num }}</span>
|
|
{{ item.title }}
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
{% endfor %}
|
|
</aside>
|
|
|
|
<!-- Main content -->
|
|
<main class="docs-main" id="docs-main">
|
|
{% for chapter in docs.chapters %}
|
|
<section class="docs-chapter" id="{{ chapter.id }}">
|
|
<h2>{{ chapter.num }}. {{ chapter.title }}</h2>
|
|
{{ chapter.html | safe }}
|
|
</section>
|
|
{% endfor %}
|
|
|
|
<div class="docs-feedback">
|
|
<span class="feedback-q">这篇文档对您有帮助吗?</span>
|
|
<div class="feedback-actions">
|
|
<button class="feedback-btn" onclick="sendFeedback('yes')">
|
|
<i data-lucide="thumbs-up" class="icon"></i>有帮助
|
|
</button>
|
|
<button class="feedback-btn" onclick="sendFeedback('no')">
|
|
<i data-lucide="thumbs-down" class="icon"></i>需要改进
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Right rail -->
|
|
<aside class="docs-rail" id="docs-rail">
|
|
<div class="rail-title">本页目录</div>
|
|
<ul class="rail-list" id="rail-list"></ul>
|
|
|
|
<div class="rail-actions">
|
|
<button class="rail-action" onclick="window.print()">
|
|
<i data-lucide="printer" class="icon"></i>打印此页
|
|
</button>
|
|
<button class="rail-action" id="copy-link-btn">
|
|
<i data-lucide="link" class="icon"></i>复制链接
|
|
</button>
|
|
<a class="rail-action" href="#ch-1">
|
|
<i data-lucide="arrow-up" class="icon"></i>回到顶部
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
var chapters = document.querySelectorAll('.docs-chapter');
|
|
var tocLinks = document.querySelectorAll('.toc-link');
|
|
var railList = document.getElementById('rail-list');
|
|
|
|
// Build right rail from all chapter h2+h3 headings
|
|
function buildRail() {
|
|
var items = [];
|
|
chapters.forEach(function(ch) {
|
|
var chId = ch.id;
|
|
var chTitle = ch.querySelector('h2');
|
|
if (chTitle) {
|
|
items.push({ id: chId, text: chTitle.textContent, level: 2 });
|
|
}
|
|
ch.querySelectorAll('h3').forEach(function(h3) {
|
|
if (!h3.id) {
|
|
h3.id = chId + '-' + h3.textContent.replace(/\s+/g, '-').replace(/[^\w\-]/g, '').toLowerCase();
|
|
}
|
|
items.push({ id: h3.id, text: h3.textContent, level: 3 });
|
|
});
|
|
});
|
|
railList.innerHTML = items.map(function(item) {
|
|
var indent = item.level === 3 ? ' style="padding-left:20px;"' : '';
|
|
return '<li><a href="#' + item.id + '"' + indent + '>' + item.text + '</a></li>';
|
|
}).join('');
|
|
}
|
|
|
|
// Scrollspy: highlight active TOC link and rail link
|
|
function setupScrollspy() {
|
|
if (!window.IntersectionObserver) return;
|
|
var activeChapterId = null;
|
|
|
|
var observer = new IntersectionObserver(function(entries) {
|
|
entries.forEach(function(entry) {
|
|
if (entry.isIntersecting) {
|
|
activeChapterId = entry.target.id;
|
|
}
|
|
});
|
|
if (!activeChapterId) return;
|
|
|
|
// Update left TOC
|
|
tocLinks.forEach(function(link) {
|
|
var isActive = link.getAttribute('data-chapter') === activeChapterId;
|
|
link.classList.toggle('active', isActive);
|
|
});
|
|
|
|
// Update rail links
|
|
railList.querySelectorAll('a').forEach(function(a) {
|
|
a.classList.remove('active');
|
|
if (a.getAttribute('href') === '#' + activeChapterId) {
|
|
a.classList.add('active');
|
|
}
|
|
});
|
|
}, { rootMargin: '-20% 0px -70% 0px', threshold: 0 });
|
|
|
|
chapters.forEach(function(ch) { observer.observe(ch); });
|
|
}
|
|
|
|
// Simple search: highlight matching text in main content
|
|
var searchInput = document.getElementById('docs-search-input');
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', function() {
|
|
var q = this.value.trim().toLowerCase();
|
|
if (!q) {
|
|
chapters.forEach(function(ch) { ch.style.display = ''; });
|
|
return;
|
|
}
|
|
chapters.forEach(function(ch) {
|
|
var text = ch.textContent.toLowerCase();
|
|
ch.style.display = text.includes(q) ? '' : 'none';
|
|
});
|
|
});
|
|
}
|
|
|
|
// Copy link button
|
|
var copyBtn = document.getElementById('copy-link-btn');
|
|
if (copyBtn) {
|
|
copyBtn.addEventListener('click', function() {
|
|
navigator.clipboard.writeText(window.location.href).then(function() {
|
|
copyBtn.querySelector('span, .icon') && null;
|
|
var orig = copyBtn.innerHTML;
|
|
copyBtn.innerHTML = '<i data-lucide="check" class="icon"></i>已复制';
|
|
if (window.lucide) lucide.createIcons();
|
|
setTimeout(function() { copyBtn.innerHTML = orig; if (window.lucide) lucide.createIcons(); }, 2000);
|
|
});
|
|
});
|
|
}
|
|
|
|
function sendFeedback(val) {
|
|
// Fire-and-forget; no user-visible side effect needed
|
|
try { fetch('/api/v1/public/feedback', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ helpful: val === 'yes' }) }); } catch(e) {}
|
|
var fb = document.querySelector('.docs-feedback');
|
|
if (fb) fb.innerHTML = '<span style="color:var(--success-700);font-size:var(--text-md);">感谢您的反馈!</span>';
|
|
}
|
|
window.sendFeedback = sendFeedback;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
buildRail();
|
|
setupScrollspy();
|
|
if (window.lucide) lucide.createIcons();
|
|
});
|
|
})();
|
|
</script>
|