refactor(web): 营销站重构为 Eleventy SSG,内容迁移至 Markdown

- 引入 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>
This commit is contained in:
wangjia
2026-05-26 12:24:14 +08:00
parent 3d1fc0d4ba
commit 471b980179
25 changed files with 5118 additions and 4245 deletions
+22
View File
@@ -0,0 +1,22 @@
module.exports = function(cfg) {
// 静态资源直接复制
cfg.addPassthroughCopy("assets");
// scan.html 面向消费者,独立维护,直接复制不经模板
cfg.addPassthroughCopy("scan.html");
cfg.addPassthroughCopy("features");
return {
dir: {
input: ".",
output: "dist",
includes: "_includes",
data: "_data",
layouts: "_includes",
},
// 同时支持 .html 和 .njk 作为模板格式
templateFormats: ["njk", "html", "md"],
htmlTemplateEngine: "njk",
markdownTemplateEngine: "njk",
};
};
+6
View File
@@ -0,0 +1,6 @@
scan.html
content/
features/approval.html
features/inventory.html
node_modules
dist
+44
View File
@@ -0,0 +1,44 @@
const fs = require('fs');
const path = require('path');
module.exports = function() {
const raw = fs.readFileSync(path.join(__dirname, '../../CHANGELOG.md'), 'utf8');
const lines = raw.split('\n');
const versions = [];
let current = null;
let currentSection = null;
for (const line of lines) {
const versionMatch = line.match(/^## \[([^\]]+)\] - (\d{4}-\d{2}-\d{2})/);
if (versionMatch) {
if (current) versions.push(current);
if (versions.length >= 3) break;
current = { version: versionMatch[1], date: versionMatch[2], sections: [], intro: '' };
currentSection = null;
continue;
}
const sectionMatch = line.match(/^### (.+)/);
if (sectionMatch && current) {
currentSection = { type: sectionMatch[1], items: [] };
current.sections.push(currentSection);
continue;
}
const itemMatch = line.match(/^- (.+)/);
if (itemMatch && current) {
if (currentSection) {
currentSection.items.push(itemMatch[1]);
}
continue;
}
// Free-form text before first section (e.g. v1.0.0 intro paragraph)
if (line.trim() && current && !currentSection && !line.startsWith('#')) {
current.intro = current.intro ? current.intro + ' ' + line.trim() : line.trim();
}
}
if (current && versions.length < 3) versions.push(current);
return versions;
};
+51
View File
@@ -0,0 +1,51 @@
const fs = require('fs');
const path = require('path');
const md = require('markdown-it')({ html: false, breaks: false, linkify: false });
const TOC_GROUPS = [
{ group: '快速开始', nums: [1, 2, 3] },
{ group: '业务操作', nums: [4, 5, 6, 7, 8, 9] },
{ group: '基础设置', nums: [10, 11, 12] },
];
module.exports = function() {
const raw = fs.readFileSync(path.join(__dirname, '../content/docs.md'), 'utf8');
const lines = raw.split('\n');
// Split into chapters by "## {n}. {title}" headings
const chapters = [];
let current = null;
for (const line of lines) {
const match = line.match(/^## (\d+)\. (.+)/);
if (match) {
if (current) chapters.push(current);
const num = parseInt(match[1], 10);
current = { num, id: 'ch-' + num, title: match[2].trim(), bodyLines: [] };
} else if (current) {
current.bodyLines.push(line);
}
}
if (current) chapters.push(current);
// Render each chapter's body to HTML
const rendered = chapters.map(ch => ({
num: ch.num,
id: ch.id,
title: ch.title,
html: md.render(ch.bodyLines.join('\n')),
}));
// Build TOC
const chapterMap = {};
rendered.forEach(ch => { chapterMap[ch.num] = ch; });
const toc = TOC_GROUPS.map(g => ({
group: g.group,
items: g.nums
.filter(n => chapterMap[n])
.map(n => ({ id: chapterMap[n].id, num: n, title: chapterMap[n].title })),
}));
return { toc, chapters: rendered };
};
+12
View File
@@ -0,0 +1,12 @@
{
"name": "岩美酒库管理系统",
"tagline": "为酒行与酒店设计的库存管理平台",
"copyright": "© 2026 岩美科技 · 保留所有权利",
"icp": "沪 ICP 备 2026000000 号 · 沪公网安备 31010000000000 号",
"support": {
"email": "support@yanmei.app",
"phone": "400-880-8888"
},
"appUrl": "/app/",
"lucideVersion": "0.469.0"
}
+8
View File
@@ -0,0 +1,8 @@
const fs = require('fs');
const path = require('path');
const md = require('markdown-it')({ html: false, breaks: false });
module.exports = function() {
const content = fs.readFileSync(path.join(__dirname, '../content/system-requirements.md'), 'utf8');
return md.render(content);
};
+28
View File
@@ -0,0 +1,28 @@
<!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" />
<title>{% if title %}{{ title }} · {% endif %}{{ site.name }}</title>
{% if description %}<meta name="description" content="{{ description }}" />{% endif %}
<link rel="stylesheet" href="/assets/color.css" />
<link rel="stylesheet" href="/assets/style.css" />
{% if pageExtraCss %}<link rel="stylesheet" href="{{ pageExtraCss }}" />{% endif %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@{{ site.lucideVersion }}/dist/umd/lucide.min.js"></script>
{% if pageStyle %}<style>{{ pageStyle | safe }}</style>{% endif %}
</head>
<body>
{% include "nav.njk" %}
{{ content | safe }}
{% include "footer.njk" %}
<script src="/assets/nav.js"></script>
</body>
</html>
+55
View File
@@ -0,0 +1,55 @@
<footer>
<div class="container">
<div class="footer-grid">
<div class="footer-brand">
<img src="/assets/logo-full.svg" alt="岩美" />
<p>为酒行与酒店设计的库存、审核、财务一体化管理平台。</p>
<div class="footer-contact">
<div>{{ site.support.email }}</div>
<div>{{ site.support.phone }}</div>
</div>
</div>
<div class="footer-col">
<h5>产品</h5>
<ul>
<li><a href="/#modules">核心模块</a></li>
<li><a href="/#platforms">多端覆盖</a></li>
<li><a href="/#reports">数据洞察</a></li>
<li><a href="/#pricing">价格方案</a></li>
<li><a href="#">版本更新</a></li>
</ul>
</div>
<div class="footer-col">
<h5>资源</h5>
<ul>
<li><a href="/docs/">使用手册</a></li>
<li><a href="#">API 文档</a></li>
<li><a href="#">视频教程</a></li>
<li><a href="#">数据导入模板</a></li>
</ul>
</div>
<div class="footer-col">
<h5>客户支持</h5>
<ul>
<li><a href="/#faq">常见问题</a></li>
<li><a href="#">提交工单</a></li>
<li><a href="#">技术支持</a></li>
<li><a href="#">服务等级</a></li>
</ul>
</div>
<div class="footer-col">
<h5>公司</h5>
<ul>
<li><a href="#">关于岩美</a></li>
<li><a href="#">客户案例</a></li>
<li><a href="#">招贤纳士</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<div>{{ site.copyright }}</div>
<div>{{ site.icp }}</div>
</div>
</div>
</footer>
+15
View File
@@ -0,0 +1,15 @@
<nav class="topnav">
<div class="topnav-inner">
<a href="/" class="topnav-brand">
<img src="/assets/logo-full.svg" alt="岩美" />
</a>
<div class="topnav-links">
<a href="/#modules">产品</a>
<a href="/#pricing">价格</a>
<a href="/download/">下载</a>
<a href="/docs/">文档</a>
<a href="/#faq">支持</a>
</div>
<div class="topnav-cta" id="nav-cta"></div>
</div>
</nav>
+261
View File
@@ -0,0 +1,261 @@
/* =========================================================================
岩美 Design System — Foundations
Tokens for color, type, spacing, radius, shadow.
Import once at root: <link rel="stylesheet" href="colors_and_type.css">
========================================================================= */
:root {
color-scheme: light;
/* ---------- Brand: Primary (Slate Blue) ---------- */
/* Trustworthy enterprise blue with a slight slate cast. */
--brand-50: #EEF4FB;
--brand-100: #D6E5F5;
--brand-200: #ADC9EA;
--brand-300: #7FA8DA;
--brand-400: #4F86C6;
--brand-500: #2563AC; /* Primary action */
--brand-600: #1B4F8E; /* Hover */
--brand-700: #154072; /* Pressed */
--brand-800: #0F3057;
--brand-900: #0A1F3B; /* Brand ink — headers, logo on light bg */
/* ---------- Neutrals (cool slate gray) ---------- */
--gray-0: #FFFFFF;
--gray-25: #FBFCFD;
--gray-50: #F5F7FA;
--gray-100: #ECEFF4;
--gray-200: #DCE2EB;
--gray-300: #C2CAD6;
--gray-400: #99A3B3;
--gray-500: #6E7888;
--gray-600: #4F5867;
--gray-700: #353C48;
--gray-800: #232934;
--gray-900: #141821;
/* ---------- Accent (bordeaux / 酒红) ---------- */
/* Used sparingly: brand context cue (wine), key highlights, marketing only. */
--accent-50: #FAEEF0;
--accent-100: #F1D2D7;
--accent-300: #C97B86;
--accent-500: #8B2331;
--accent-700: #5F1621;
/* ---------- Semantic ---------- */
--success-50: #E8F5EE;
--success-500: #2E8B57;
--success-700: #1F6B41;
--warning-50: #FFF4DB;
--warning-500: #E08E00;
--warning-700: #A66700;
--danger-50: #FDECEC;
--danger-500: #D14343;
--danger-700: #9E2A2A;
--info-50: #E5F1FB;
--info-500: #2F7BD0;
--info-700: #1F5C9F;
/* ---------- Semantic foreground / background ---------- */
--bg-app: var(--gray-50);
--bg-surface: var(--gray-0);
--bg-raised: var(--gray-0);
--bg-sunken: var(--gray-100);
--bg-overlay: rgba(20, 24, 33, 0.45);
--fg-default: var(--gray-800);
--fg-muted: var(--gray-600);
--fg-subtle: var(--gray-500);
--fg-disabled: var(--gray-400);
--fg-on-brand: #FFFFFF;
--fg-link: var(--brand-500);
--border-subtle: var(--gray-100);
--border-default: var(--gray-200);
--border-strong: var(--gray-300);
--border-focus: var(--brand-500);
/* ---------- Typography ---------- */
/* Chinese-primary stack with PingFang on macOS/iOS, Microsoft YaHei on Windows,
Noto Sans SC as web fallback (loaded via Google Fonts in index files). */
--font-sans: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
"Source Han Sans CN", "Noto Sans SC", -apple-system,
BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-display: var(--font-sans);
--font-mono: "JetBrains Mono", "SF Mono", "Roboto Mono", Menlo, Consolas,
"Microsoft YaHei", monospace;
/* Type scale — mobile-first, scales up for desktop dashboards */
--text-2xs: 11px;
--text-xs: 12px;
--text-sm: 13px;
--text-md: 14px; /* dashboard body default */
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 22px;
--text-3xl: 28px;
--text-4xl: 36px;
--text-5xl: 48px;
--leading-tight: 1.25;
--leading-snug: 1.4;
--leading-normal: 1.55;
--leading-loose: 1.75;
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
/* Tracking — Chinese reads better with subtle positive tracking */
--tracking-tight: -0.01em;
--tracking-normal: 0;
--tracking-wide: 0.02em;
--tracking-cn-display: 0.04em; /* Chinese display headers */
/* ---------- Spacing (4px base) ---------- */
--space-0: 0;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
--space-20: 80px;
--space-24: 96px;
/* ---------- Radius — restrained, enterprise-grade ---------- */
--radius-xs: 2px;
--radius-sm: 4px;
--radius-md: 6px; /* default for inputs, buttons, badges */
--radius-lg: 10px; /* cards */
--radius-xl: 14px;
--radius-pill: 999px;
/* ---------- Elevation — soft, neutral, no colored shadows ---------- */
--shadow-xs: 0 1px 2px rgba(20, 24, 33, 0.04);
--shadow-sm: 0 1px 2px rgba(20, 24, 33, 0.06), 0 1px 3px rgba(20, 24, 33, 0.04);
--shadow-md: 0 2px 4px rgba(20, 24, 33, 0.06), 0 4px 8px rgba(20, 24, 33, 0.05);
--shadow-lg: 0 4px 12px rgba(20, 24, 33, 0.08), 0 12px 24px rgba(20, 24, 33, 0.06);
--shadow-xl: 0 8px 20px rgba(20, 24, 33, 0.10), 0 20px 40px rgba(20, 24, 33, 0.08);
--shadow-inset: inset 0 1px 0 rgba(255,255,255,0.6), inset 0 -1px 0 rgba(20,24,33,0.04);
--ring-focus: 0 0 0 3px rgba(37, 99, 172, 0.22);
/* ---------- Motion ---------- */
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--ease-emphasized: cubic-bezier(0.2, 0, 0, 1.2);
--ease-decelerate: cubic-bezier(0, 0, 0.2, 1);
--duration-fast: 120ms;
--duration-base: 180ms;
--duration-slow: 240ms;
/* ---------- Layout ---------- */
--layout-sidebar: 240px;
--layout-sidebar-collapsed: 64px;
--layout-topbar: 56px;
--layout-content-max: 1440px;
}
/* =========================================================================
Semantic element styles — apply to base elements within design system docs.
These do NOT bleed into ui_kits / pages with their own styles.
========================================================================= */
.ds-typography {
font-family: var(--font-sans);
color: var(--fg-default);
font-feature-settings: "tnum" 1, "ss01" 1;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
.ds-typography h1,
.ds-h1 {
font-size: var(--text-4xl);
font-weight: var(--weight-semibold);
line-height: var(--leading-tight);
letter-spacing: var(--tracking-cn-display);
color: var(--brand-900);
margin: 0 0 var(--space-4);
}
.ds-typography h2,
.ds-h2 {
font-size: var(--text-3xl);
font-weight: var(--weight-semibold);
line-height: var(--leading-tight);
letter-spacing: var(--tracking-cn-display);
color: var(--brand-900);
margin: 0 0 var(--space-3);
}
.ds-typography h3,
.ds-h3 {
font-size: var(--text-2xl);
font-weight: var(--weight-semibold);
line-height: var(--leading-snug);
color: var(--gray-900);
margin: 0 0 var(--space-3);
}
.ds-typography h4,
.ds-h4 {
font-size: var(--text-xl);
font-weight: var(--weight-semibold);
line-height: var(--leading-snug);
color: var(--gray-900);
margin: 0 0 var(--space-2);
}
.ds-typography h5,
.ds-h5 {
font-size: var(--text-lg);
font-weight: var(--weight-semibold);
line-height: var(--leading-snug);
color: var(--gray-800);
margin: 0 0 var(--space-2);
}
.ds-typography p,
.ds-body {
font-size: var(--text-md);
font-weight: var(--weight-regular);
line-height: var(--leading-normal);
color: var(--fg-default);
margin: 0 0 var(--space-3);
}
.ds-typography small,
.ds-caption {
font-size: var(--text-xs);
color: var(--fg-muted);
line-height: var(--leading-snug);
}
.ds-typography code,
.ds-mono {
font-family: var(--font-mono);
font-size: 0.93em;
background: var(--gray-100);
padding: 1px 6px;
border-radius: var(--radius-sm);
color: var(--gray-800);
}
.ds-num {
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum" 1;
}
.ds-label {
font-size: var(--text-xs);
font-weight: var(--weight-medium);
letter-spacing: var(--tracking-wide);
text-transform: none; /* Chinese never uppercases */
color: var(--fg-muted);
}
/* Focus ring shared across the system */
.ds-focusable:focus-visible,
:focus-visible {
outline: none;
box-shadow: var(--ring-focus);
border-color: var(--border-focus);
}
+347
View File
@@ -0,0 +1,347 @@
/* ====================================================================
DOCS SUB-HEADER
==================================================================== */
.docs-subnav {
background: var(--gray-25);
border-bottom: 1px solid var(--border-subtle);
position: sticky;
top: 64px;
z-index: 40;
}
.docs-subnav-inner {
max-width: 1440px;
margin: 0 auto;
padding: 12px 32px;
display: flex; align-items: center; gap: 24px;
}
.breadcrumb {
display: flex; align-items: center; gap: 8px;
font-size: var(--text-sm);
color: var(--fg-muted);
}
.breadcrumb .sep { color: var(--gray-300); }
.breadcrumb a { color: var(--fg-muted); }
.breadcrumb a:hover { color: var(--brand-500); }
.breadcrumb .current { color: var(--gray-900); font-weight: 500; }
.docs-search {
flex: 1; max-width: 480px;
position: relative;
}
.docs-search input {
width: 100%;
height: 36px;
padding: 0 12px 0 38px;
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
background: var(--gray-0);
font-family: inherit;
font-size: var(--text-sm);
color: var(--gray-800);
outline: none;
transition: border-color var(--duration-fast) var(--ease-standard),
box-shadow var(--duration-fast) var(--ease-standard);
}
.docs-search input:focus { border-color: var(--brand-500); box-shadow: var(--ring-focus); }
.docs-search input::placeholder { color: var(--fg-subtle); }
.docs-search .search-icon {
position: absolute;
left: 12px; top: 50%;
transform: translateY(-50%);
width: 16px; height: 16px;
color: var(--fg-subtle);
}
.docs-search .kbd {
position: absolute;
right: 8px; top: 50%;
transform: translateY(-50%);
background: var(--gray-100);
border: 1px solid var(--border-default);
border-radius: 3px;
padding: 2px 6px;
font-size: 11px;
color: var(--fg-muted);
font-family: var(--font-mono);
}
.docs-version {
display: flex; align-items: center; gap: 6px;
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
padding: 6px 12px;
font-size: var(--text-sm);
color: var(--gray-700);
}
.docs-version .icon { width: 14px; height: 14px; }
.docs-version-label { color: var(--fg-subtle); font-size: var(--text-xs); }
/* ====================================================================
DOCS LAYOUT (three-column)
==================================================================== */
.docs-layout {
max-width: 1440px;
margin: 0 auto;
padding: 32px;
display: grid;
grid-template-columns: 240px 1fr 240px;
gap: 48px;
align-items: start;
}
/* ====================================================================
LEFT TOC
==================================================================== */
.docs-toc {
position: sticky;
top: 132px;
max-height: calc(100vh - 152px);
overflow-y: auto;
font-size: var(--text-sm);
}
.toc-section { margin-bottom: 18px; }
.toc-section-title {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
color: var(--fg-subtle);
text-transform: uppercase;
margin: 0 0 10px;
padding-left: 12px;
}
.toc-link {
display: flex; align-items: center; gap: 10px;
padding: 7px 12px;
border-radius: var(--radius-sm);
color: var(--gray-700);
font-weight: 400;
transition: background var(--duration-fast) var(--ease-standard),
color var(--duration-fast) var(--ease-standard);
}
.toc-link:hover { background: var(--gray-100); color: var(--brand-900); }
.toc-link .toc-num {
font-family: var(--font-mono);
font-size: 11px;
color: var(--fg-subtle);
min-width: 16px;
font-weight: 500;
}
.toc-link.active {
background: var(--brand-50);
color: var(--brand-700);
font-weight: 500;
}
.toc-link.active .toc-num { color: var(--brand-500); }
/* ====================================================================
MAIN CONTENT
==================================================================== */
.docs-main { min-width: 0; max-width: 760px; }
.docs-chapter { padding-bottom: 48px; border-bottom: 1px solid var(--border-subtle); margin-bottom: 48px; }
.docs-chapter:last-child { border-bottom: none; margin-bottom: 0; }
.docs-main h2 {
font-size: var(--text-2xl);
font-weight: 600;
color: var(--brand-900);
margin: 0 0 16px;
letter-spacing: 0.02em;
scroll-margin-top: 132px;
padding-bottom: 12px;
border-bottom: 2px solid var(--brand-100);
}
.docs-main h3 {
font-size: var(--text-lg);
font-weight: 600;
color: var(--gray-900);
margin: 32px 0 12px;
scroll-margin-top: 132px;
}
.docs-main p {
font-size: var(--text-md);
color: var(--gray-700);
line-height: 1.75;
margin: 0 0 16px;
}
.docs-main strong { color: var(--brand-900); font-weight: 600; }
.docs-main em { color: var(--brand-700); font-style: normal; font-weight: 500; }
.docs-main code {
font-family: var(--font-mono);
font-size: 0.92em;
background: var(--gray-100);
color: var(--brand-700);
padding: 1px 6px;
border-radius: var(--radius-sm);
}
.docs-main a {
color: var(--brand-500);
font-weight: 500;
border-bottom: 1px solid var(--brand-200);
}
.docs-main a:hover { color: var(--brand-700); border-color: var(--brand-500); }
.docs-main ol, .docs-main ul {
margin: 0 0 16px;
padding-left: 24px;
}
.docs-main li {
font-size: var(--text-md);
color: var(--gray-700);
line-height: 1.75;
margin-bottom: 6px;
}
.docs-main ol li::marker {
color: var(--brand-500);
font-weight: 600;
}
/* Rendered markdown tables */
.docs-main table {
width: 100%;
border-collapse: collapse;
margin: 16px 0 24px;
font-size: var(--text-sm);
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
overflow: hidden;
}
.docs-main th, .docs-main td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid var(--border-subtle);
line-height: 1.55;
}
.docs-main thead th {
background: var(--gray-50);
font-size: var(--text-xs);
font-weight: 600;
color: var(--gray-700);
letter-spacing: 0.02em;
text-transform: uppercase;
border-bottom: 1px solid var(--border-default);
}
.docs-main tbody tr:last-child td { border-bottom: none; }
.docs-main tbody tr:hover { background: var(--gray-25); }
/* Rendered markdown code blocks */
.docs-main pre {
background: var(--gray-25);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
padding: 16px 20px;
overflow-x: auto;
margin: 16px 0 24px;
}
.docs-main pre code {
background: none;
color: var(--gray-800);
padding: 0;
font-size: var(--text-sm);
line-height: 1.6;
border-radius: 0;
}
/* Blockquote → callout-style */
.docs-main blockquote {
background: var(--info-50);
border-left: 3px solid var(--info-500);
border-radius: var(--radius-md);
padding: 14px 18px;
margin: 16px 0 24px;
color: var(--info-700);
}
.docs-main blockquote p { color: var(--gray-700); margin: 0; font-size: var(--text-sm); line-height: 1.6; }
/* ====================================================================
RIGHT RAIL
==================================================================== */
.docs-rail {
position: sticky;
top: 132px;
font-size: var(--text-sm);
}
.rail-title {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.06em;
color: var(--fg-subtle);
text-transform: uppercase;
margin: 0 0 12px;
}
.rail-list { display: flex; flex-direction: column; gap: 2px; list-style: none; padding: 0; margin: 0 0 24px; }
.rail-list a {
display: block;
padding: 5px 10px;
border-radius: var(--radius-sm);
color: var(--fg-muted);
font-size: 13px;
border-left: 2px solid transparent;
}
.rail-list a:hover { color: var(--brand-700); }
.rail-list a.active {
color: var(--brand-700);
border-left-color: var(--brand-500);
font-weight: 500;
}
.rail-actions {
padding-top: 16px;
border-top: 1px solid var(--border-subtle);
display: flex; flex-direction: column; gap: 6px;
}
.rail-action {
display: flex; align-items: center; gap: 8px;
padding: 6px 10px;
font-size: 13px;
color: var(--fg-muted);
border-radius: var(--radius-sm);
cursor: pointer;
background: none;
border: none;
font-family: inherit;
width: 100%;
text-align: left;
}
.rail-action:hover { background: var(--gray-50); color: var(--brand-700); }
.rail-action .icon { width: 14px; height: 14px; }
/* ====================================================================
FEEDBACK WIDGET
==================================================================== */
.docs-feedback {
margin-top: 40px;
padding: 24px;
background: var(--gray-25);
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: space-between;
}
.feedback-q { font-size: var(--text-md); color: var(--gray-800); }
.feedback-actions { display: flex; gap: 8px; }
.feedback-btn {
display: inline-flex; align-items: center; gap: 6px;
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
padding: 6px 14px;
font-size: var(--text-sm);
color: var(--gray-700);
cursor: pointer;
font-family: inherit;
}
.feedback-btn:hover { border-color: var(--brand-500); color: var(--brand-700); }
.feedback-btn .icon { width: 14px; height: 14px; }
/* ====================================================================
RESPONSIVE
==================================================================== */
@media (max-width: 1200px) {
.docs-layout { grid-template-columns: 220px 1fr; gap: 32px; }
.docs-rail { display: none; }
}
@media (max-width: 880px) {
.docs-layout { grid-template-columns: 1fr; gap: 24px; padding: 16px; }
.docs-toc { position: static; max-height: none; border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: 16px; margin-bottom: 8px; }
.docs-subnav-inner { padding: 10px 16px; }
.docs-search { max-width: none; }
}
+90
View File
@@ -0,0 +1,90 @@
(function() {
var KEYS = ['access_token','refresh_token','username','real_name','shop_no','shop_id','role'];
function getAuthUser() {
var token = localStorage.getItem('flutter.access_token');
var username = localStorage.getItem('flutter.username');
if (!token || !username) return null;
return {
username: username,
realName: localStorage.getItem('flutter.real_name') || '',
role: localStorage.getItem('flutter.role') || '',
shopNo: localStorage.getItem('flutter.shop_no') || '',
};
}
function doLogout() {
KEYS.forEach(function(k) { localStorage.removeItem('flutter.' + k); });
location.reload();
}
function toggleUserMenu() {
var el = document.getElementById('userDropdown');
if (el) el.classList.toggle('open');
}
// 点击外部关闭 dropdown
document.addEventListener('click', function(e) {
var menu = document.getElementById('userDropdown');
if (!menu) return;
var navUser = menu.closest('.nav-user');
if (navUser && !navUser.contains(e.target)) menu.classList.remove('open');
});
function renderNav() {
var cta = document.getElementById('nav-cta');
if (!cta) return;
var user = getAuthUser();
if (user) {
var display = user.realName || user.username;
var initial = display.charAt(0).toUpperCase();
var roleMap = { admin: '管理员', user: '成员', readonly: '只读' };
var roleLabel = roleMap[user.role] || user.role;
cta.innerHTML =
'<div class="nav-user">'
+ '<button class="nav-user-btn" onclick="toggleUserMenu()">'
+ '<div class="nav-avatar">' + initial + '</div>'
+ '<span>' + display + '</span>'
+ '<i data-lucide="chevron-down" class="icon"></i>'
+ '</button>'
+ '<div class="nav-dropdown" id="userDropdown">'
+ '<div style="padding:10px 14px 6px;border-bottom:1px solid var(--border-subtle);margin-bottom:4px">'
+ '<div style="font-size:13px;font-weight:600;color:var(--brand-900)">' + display + '</div>'
+ '<div style="font-size:11px;color:var(--fg-muted);margin-top:2px">'
+ (user.shopNo ? user.shopNo + ' · ' : '') + roleLabel
+ '</div>'
+ '</div>'
+ '<a href="/app/"><i data-lucide="layout-dashboard" class="icon"></i>进入管理端</a>'
+ '<div class="nav-dropdown-divider"></div>'
+ '<button class="logout" onclick="doLogout()"><i data-lucide="log-out" class="icon"></i>退出登录</button>'
+ '</div></div>';
} else {
cta.innerHTML =
'<a href="/app/" class="btn btn-ghost">登录</a>'
+ '<a href="/app/" class="btn btn-primary">免费试用</a>';
}
if (window.lucide) lucide.createIcons();
}
// 暴露给 onclick 调用
window.toggleUserMenu = toggleUserMenu;
window.doLogout = doLogout;
document.addEventListener('DOMContentLoaded', function() {
renderNav();
if (window.lucide) lucide.createIcons();
// 页内锚点平滑滚动
document.querySelectorAll('a[href^="#"]').forEach(function(a) {
a.addEventListener('click', function(e) {
var id = a.getAttribute('href');
if (!id || id.length < 2) return;
var target = document.querySelector(id);
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
});
})();
+183
View File
@@ -0,0 +1,183 @@
/* ================================================================
shared.css — 跨页面公用样式
设计 token 由 colors_and_type.css 提供
================================================================ */
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0;
font-family: var(--font-sans);
color: var(--fg-default);
background: var(--gray-25);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-feature-settings: "tnum" 1;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
/* ----------------------------------------------------------------
Buttons
---------------------------------------------------------------- */
.btn {
display: inline-flex; align-items: center; gap: 8px;
height: 40px; padding: 0 18px;
border-radius: var(--radius-md);
font-size: var(--text-md); font-weight: 500;
border: 1px solid transparent;
transition: background var(--duration-fast) var(--ease-standard),
border-color var(--duration-fast) var(--ease-standard),
color var(--duration-fast) var(--ease-standard);
white-space: nowrap;
}
.btn-primary { background: var(--brand-500); color: #fff; }
.btn-primary:hover { background: var(--brand-600); }
.btn-primary:active { background: var(--brand-700); }
.btn-secondary { background: var(--gray-0); color: var(--brand-900); border-color: var(--border-default); }
.btn-secondary:hover { background: var(--gray-50); border-color: var(--border-strong); }
.btn-ghost { background: transparent; color: var(--fg-default); }
.btn-ghost:hover { background: var(--gray-100); }
.btn-lg { height: 48px; padding: 0 24px; font-size: var(--text-lg); }
.btn .icon { width: 18px; height: 18px; }
/* ----------------------------------------------------------------
Layout helpers
---------------------------------------------------------------- */
.container {
max-width: 1280px;
margin: 0 auto;
padding: 0 32px;
}
.section { padding: 96px 0; }
.section-tight { padding: 64px 0; }
.eyebrow {
font-size: var(--text-xs);
font-weight: 600;
letter-spacing: 0.12em;
color: var(--brand-500);
text-transform: uppercase;
margin: 0 0 12px;
}
.section-title {
font-size: var(--text-4xl);
font-weight: 600;
line-height: 1.18;
letter-spacing: var(--tracking-cn-display);
color: var(--brand-900);
margin: 0 0 16px;
max-width: 720px;
}
.section-sub {
font-size: var(--text-lg);
line-height: 1.6;
color: var(--fg-muted);
margin: 0;
max-width: 640px;
}
/* ----------------------------------------------------------------
Top Nav
---------------------------------------------------------------- */
.topnav {
position: sticky; top: 0; z-index: 50;
background: rgba(255,255,255,0.85);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-subtle);
}
.topnav-inner {
height: 64px;
display: flex; align-items: center; justify-content: space-between;
max-width: 1440px; margin: 0 auto; padding: 0 32px;
}
.topnav-brand { display: flex; align-items: center; gap: 10px; }
.topnav-brand img { height: 32px; }
.topnav-links {
display: flex; align-items: center; gap: 4px;
font-size: var(--text-md); color: var(--gray-700);
}
.topnav-links a {
padding: 8px 14px;
border-radius: var(--radius-md);
transition: background var(--duration-fast) var(--ease-standard);
}
.topnav-links a:hover { background: var(--gray-100); color: var(--brand-900); }
.topnav-cta { display: flex; gap: 10px; align-items: center; }
/* Nav user dropdown */
.nav-user { position: relative; }
.nav-user-btn {
display: flex; align-items: center; gap: 8px;
height: 36px; padding: 0 12px;
background: var(--gray-0); border: 1px solid var(--border-default);
border-radius: var(--radius-pill); cursor: pointer;
font-size: var(--text-md); color: var(--gray-800); font-weight: 500;
transition: border-color var(--duration-fast) var(--ease-standard);
}
.nav-user-btn:hover { border-color: var(--border-strong); }
.nav-avatar {
width: 22px; height: 22px; border-radius: 50%;
background: var(--brand-500); color: #fff;
display: grid; place-items: center;
font-size: 10px; font-weight: 700; flex-shrink: 0;
}
.nav-user-btn .icon { width: 14px; height: 14px; color: var(--fg-muted); }
.nav-dropdown {
display: none; position: absolute; top: calc(100% + 8px); right: 0;
min-width: 160px; background: var(--gray-0);
border: 1px solid var(--border-default); border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg); overflow: hidden; z-index: 100;
}
.nav-dropdown.open { display: block; }
.nav-dropdown a, .nav-dropdown button {
display: flex; align-items: center; gap: 8px;
width: 100%; padding: 10px 14px;
font-size: var(--text-sm); color: var(--gray-800);
background: none; border: none; cursor: pointer;
text-decoration: none; font-family: inherit;
transition: background var(--duration-fast) var(--ease-standard);
}
.nav-dropdown a:hover, .nav-dropdown button:hover { background: var(--gray-50); }
.nav-dropdown .icon { width: 14px; height: 14px; color: var(--fg-muted); }
.nav-dropdown-divider { height: 1px; background: var(--border-subtle); margin: 4px 0; }
.nav-dropdown .logout { color: var(--danger-600); }
/* ----------------------------------------------------------------
Footer
---------------------------------------------------------------- */
footer {
background: var(--gray-25);
border-top: 1px solid var(--border-subtle);
padding: 64px 0 40px;
}
.footer-grid {
display: grid;
grid-template-columns: 1.5fr repeat(4, 1fr);
gap: 48px;
margin-bottom: 48px;
}
.footer-brand img { height: 32px; margin-bottom: 16px; }
.footer-brand p { margin: 0 0 16px; max-width: 320px; line-height: 1.6; color: var(--fg-muted); }
.footer-contact { font-size: var(--text-sm); color: var(--gray-700); line-height: 1.8; }
.footer-col h5 {
font-size: var(--text-xs); font-weight: 600;
color: var(--brand-900); letter-spacing: 0.06em;
margin: 0 0 16px; text-transform: uppercase;
}
.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.footer-col li a { color: var(--gray-600); }
.footer-col li a:hover { color: var(--brand-500); }
.footer-bottom {
border-top: 1px solid var(--border-subtle); padding-top: 24px;
display: flex; justify-content: space-between;
font-size: var(--text-xs); color: var(--fg-subtle);
}
/* ----------------------------------------------------------------
Responsive
---------------------------------------------------------------- */
@media (max-width: 1024px) {
.footer-grid { grid-template-columns: 1fr 1fr; }
.container { padding: 0 20px; }
}
+459
View File
@@ -0,0 +1,459 @@
/* ================================================================
style.css — 全局样式
Token 由 color.css 提供
分三层:① Reset & 基础 ② 组件 ③ 工具类
================================================================ */
/* ----------------------------------------------------------------
① Reset & 基础
---------------------------------------------------------------- */
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0;
font-family: var(--font-sans);
color: var(--fg-default);
background: var(--gray-25);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-feature-settings: "tnum" 1;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
/* ----------------------------------------------------------------
② 组件
---------------------------------------------------------------- */
/* -- Buttons -- */
.btn {
display: inline-flex; align-items: center; gap: 8px;
height: 40px; padding: 0 18px;
border-radius: var(--radius-md);
font-size: var(--text-md); font-weight: 500;
border: 1px solid transparent;
transition: background var(--duration-fast) var(--ease-standard),
border-color var(--duration-fast) var(--ease-standard),
color var(--duration-fast) var(--ease-standard);
white-space: nowrap;
}
.btn-primary { background: var(--brand-500); color: #fff; }
.btn-primary:hover { background: var(--brand-600); }
.btn-primary:active { background: var(--brand-700); }
.btn-secondary { background: var(--gray-0); color: var(--brand-900); border-color: var(--border-default); }
.btn-secondary:hover { background: var(--gray-50); border-color: var(--border-strong); }
.btn-ghost { background: transparent; color: var(--fg-default); }
.btn-ghost:hover { background: var(--gray-100); }
.btn-lg { height: 48px; padding: 0 24px; font-size: var(--text-lg); }
.btn .icon { width: 18px; height: 18px; }
/* -- Layout helpers -- */
.container { max-width: 1280px; margin: 0 auto; padding: 0 32px; }
.section { padding: 96px 0; }
.section-tight { padding: 64px 0; }
.eyebrow {
font-size: var(--text-xs); font-weight: 600;
letter-spacing: 0.12em; color: var(--brand-500);
text-transform: uppercase; margin: 0 0 12px;
}
.section-title {
font-size: var(--text-4xl); font-weight: 600;
line-height: 1.18; letter-spacing: var(--tracking-cn-display);
color: var(--brand-900); margin: 0 0 16px; max-width: 720px;
}
.section-sub {
font-size: var(--text-lg); line-height: 1.6;
color: var(--fg-muted); margin: 0; max-width: 640px;
}
/* -- Top Nav -- */
.topnav {
position: sticky; top: 0; z-index: 50;
background: rgba(255,255,255,0.85);
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-subtle);
}
.topnav-inner {
height: 64px; display: flex; align-items: center; justify-content: space-between;
max-width: 1440px; margin: 0 auto; padding: 0 32px;
}
.topnav-brand { display: flex; align-items: center; gap: 10px; }
.topnav-brand img { height: 32px; }
.topnav-links {
display: flex; align-items: center; gap: 4px;
font-size: var(--text-md); color: var(--gray-700);
}
.topnav-links a {
padding: 8px 14px; border-radius: var(--radius-md);
transition: background var(--duration-fast) var(--ease-standard);
}
.topnav-links a:hover { background: var(--gray-100); color: var(--brand-900); }
.topnav-cta { display: flex; gap: 10px; align-items: center; }
/* Nav user dropdown */
.nav-user { position: relative; }
.nav-user-btn {
display: flex; align-items: center; gap: 8px;
height: 36px; padding: 0 12px;
background: var(--gray-0); border: 1px solid var(--border-default);
border-radius: var(--radius-pill); cursor: pointer;
font-size: var(--text-md); color: var(--gray-800); font-weight: 500;
transition: border-color var(--duration-fast) var(--ease-standard);
}
.nav-user-btn:hover { border-color: var(--border-strong); }
.nav-avatar {
width: 22px; height: 22px; border-radius: 50%;
background: var(--brand-500); color: #fff;
display: grid; place-items: center;
font-size: 10px; font-weight: 700; flex-shrink: 0;
}
.nav-user-btn .icon { width: 14px; height: 14px; color: var(--fg-muted); }
.nav-dropdown {
display: none; position: absolute; top: calc(100% + 8px); right: 0;
min-width: 160px; background: var(--gray-0);
border: 1px solid var(--border-default); border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg); overflow: hidden; z-index: 100;
}
.nav-dropdown.open { display: block; }
.nav-dropdown a, .nav-dropdown button {
display: flex; align-items: center; gap: 8px;
width: 100%; padding: 10px 14px;
font-size: var(--text-sm); color: var(--gray-800);
background: none; border: none; cursor: pointer;
text-decoration: none; font-family: inherit;
transition: background var(--duration-fast) var(--ease-standard);
}
.nav-dropdown a:hover, .nav-dropdown button:hover { background: var(--gray-50); }
.nav-dropdown .icon { width: 14px; height: 14px; color: var(--fg-muted); }
.nav-dropdown-divider { height: 1px; background: var(--border-subtle); margin: 4px 0; }
.nav-dropdown .logout { color: var(--danger-600); }
/* -- Footer -- */
footer {
background: var(--gray-25);
border-top: 1px solid var(--border-subtle);
padding: 64px 0 40px;
}
.footer-grid {
display: grid; grid-template-columns: 1.5fr repeat(4, 1fr);
gap: 48px; margin-bottom: 48px;
}
.footer-brand img { height: 32px; margin-bottom: 16px; }
.footer-brand p { margin: 0 0 16px; max-width: 320px; line-height: 1.6; color: var(--fg-muted); }
.footer-contact { font-size: var(--text-sm); color: var(--gray-700); line-height: 1.8; }
.footer-col h5 {
font-size: var(--text-xs); font-weight: 600;
color: var(--brand-900); letter-spacing: 0.06em;
margin: 0 0 16px; text-transform: uppercase;
}
.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.footer-col li a { color: var(--gray-600); }
.footer-col li a:hover { color: var(--brand-500); }
.footer-bottom {
border-top: 1px solid var(--border-subtle); padding-top: 24px;
display: flex; justify-content: space-between;
font-size: var(--text-xs); color: var(--fg-subtle);
}
/* ----------------------------------------------------------------
③ 工具类
命名规则:{属性}-{值}
间距值直接对应像素:p-8 = padding:8pxgap-16 = gap:16px
---------------------------------------------------------------- */
/* -- Display -- */
.d-flex { display: flex }
.d-inline-flex { display: inline-flex }
.d-grid { display: grid }
.d-block { display: block }
.d-inline { display: inline }
.d-inline-block{ display: inline-block }
.d-none { display: none }
.place-center { display: grid; place-items: center } /* 图标容器常用 */
/* -- Flex -- */
.flex-col { flex-direction: column }
.flex-wrap { flex-wrap: wrap }
.flex-1 { flex: 1 }
.flex-shrink-0 { flex-shrink: 0 }
.items-center { align-items: center }
.items-start { align-items: flex-start }
.items-end { align-items: flex-end }
.items-baseline { align-items: baseline }
.justify-center { justify-content: center }
.justify-between { justify-content: space-between }
.justify-end { justify-content: flex-end }
.justify-start { justify-content: flex-start }
/* -- Grid 列模板 -- */
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr) }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr) }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr) }
.grid-5 { display: grid; grid-template-columns: repeat(5, 1fr) }
/* -- Gap -- */
.gap-2 { gap: 2px }
.gap-4 { gap: 4px }
.gap-6 { gap: 6px }
.gap-8 { gap: 8px }
.gap-10 { gap: 10px }
.gap-12 { gap: 12px }
.gap-14 { gap: 14px }
.gap-16 { gap: 16px }
.gap-18 { gap: 18px }
.gap-24 { gap: 24px }
.gap-32 { gap: 32px }
.gap-48 { gap: 48px }
.gap-64 { gap: 64px }
/* -- Padding(全方向) -- */
.p-0 { padding: 0 }
.p-4 { padding: 4px }
.p-6 { padding: 6px }
.p-8 { padding: 8px }
.p-10 { padding: 10px }
.p-12 { padding: 12px }
.p-14 { padding: 14px }
.p-16 { padding: 16px }
.p-18 { padding: 18px }
.p-20 { padding: 20px }
.p-24 { padding: 24px }
.p-28 { padding: 28px }
.p-32 { padding: 32px }
.p-48 { padding: 48px }
.p-56 { padding: 56px }
.p-64 { padding: 64px }
/* px / py */
.px-4 { padding-left: 4px; padding-right: 4px }
.px-6 { padding-left: 6px; padding-right: 6px }
.px-8 { padding-left: 8px; padding-right: 8px }
.px-10 { padding-left: 10px; padding-right: 10px }
.px-12 { padding-left: 12px; padding-right: 12px }
.px-14 { padding-left: 14px; padding-right: 14px }
.px-16 { padding-left: 16px; padding-right: 16px }
.px-20 { padding-left: 20px; padding-right: 20px }
.px-24 { padding-left: 24px; padding-right: 24px }
.px-28 { padding-left: 28px; padding-right: 28px }
.px-32 { padding-left: 32px; padding-right: 32px }
.py-2 { padding-top: 2px; padding-bottom: 2px }
.py-4 { padding-top: 4px; padding-bottom: 4px }
.py-6 { padding-top: 6px; padding-bottom: 6px }
.py-8 { padding-top: 8px; padding-bottom: 8px }
.py-10 { padding-top: 10px; padding-bottom: 10px }
.py-12 { padding-top: 12px; padding-bottom: 12px }
.py-14 { padding-top: 14px; padding-bottom: 14px }
.py-16 { padding-top: 16px; padding-bottom: 16px }
.py-20 { padding-top: 20px; padding-bottom: 20px }
.py-24 { padding-top: 24px; padding-bottom: 24px }
.py-32 { padding-top: 32px; padding-bottom: 32px }
/* pt / pb / pl / pr */
.pt-4 { padding-top: 4px } .pb-4 { padding-bottom: 4px }
.pt-6 { padding-top: 6px } .pb-6 { padding-bottom: 6px }
.pt-8 { padding-top: 8px } .pb-8 { padding-bottom: 8px }
.pt-12 { padding-top: 12px } .pb-12 { padding-bottom: 12px }
.pt-14 { padding-top: 14px } .pb-14 { padding-bottom: 14px }
.pt-16 { padding-top: 16px } .pb-16 { padding-bottom: 16px }
.pt-24 { padding-top: 24px } .pb-24 { padding-bottom: 24px }
.pt-32 { padding-top: 32px } .pb-32 { padding-bottom: 32px }
.pl-12 { padding-left: 12px } .pr-12 { padding-right: 12px }
.pl-16 { padding-left: 16px } .pr-16 { padding-right: 16px }
.pl-24 { padding-left: 24px } .pr-24 { padding-right: 24px }
/* -- Margin -- */
.m-0 { margin: 0 }
.mx-auto { margin-left: auto; margin-right: auto }
.mb-0 { margin-bottom: 0 }
.mb-2 { margin-bottom: 2px }
.mb-4 { margin-bottom: 4px }
.mb-6 { margin-bottom: 6px }
.mb-8 { margin-bottom: 8px }
.mb-10 { margin-bottom: 10px }
.mb-12 { margin-bottom: 12px }
.mb-14 { margin-bottom: 14px }
.mb-16 { margin-bottom: 16px }
.mb-18 { margin-bottom: 18px }
.mb-24 { margin-bottom: 24px }
.mb-32 { margin-bottom: 32px }
.mb-48 { margin-bottom: 48px }
.mt-2 { margin-top: 2px }
.mt-4 { margin-top: 4px }
.mt-6 { margin-top: 6px }
.mt-8 { margin-top: 8px }
.mt-12 { margin-top: 12px }
.mt-16 { margin-top: 16px }
.mt-24 { margin-top: 24px }
.mt-32 { margin-top: 32px }
.mt-48 { margin-top: 48px }
.ml-4 { margin-left: 4px }
.ml-8 { margin-left: 8px }
.mr-4 { margin-right: 4px }
.mr-8 { margin-right: 8px }
/* -- Font size(复用 token -- */
.fs-xs { font-size: var(--text-xs) }
.fs-sm { font-size: var(--text-sm) }
.fs-md { font-size: var(--text-md) }
.fs-lg { font-size: var(--text-lg) }
.fs-xl { font-size: var(--text-xl) }
.fs-2xl { font-size: var(--text-2xl) }
.fs-3xl { font-size: var(--text-3xl) }
.fs-4xl { font-size: var(--text-4xl) }
/* -- Font weight -- */
.fw-4 { font-weight: 400 }
.fw-5 { font-weight: 500 }
.fw-6 { font-weight: 600 }
.fw-7 { font-weight: 700 }
/* -- Line height -- */
.lh-1 { line-height: 1 }
.lh-12 { line-height: 1.2 }
.lh-14 { line-height: 1.4 }
.lh-15 { line-height: 1.5 }
.lh-16 { line-height: 1.6 }
.lh-17 { line-height: 1.7 }
.lh-18 { line-height: 1.8 }
/* -- Letter spacing -- */
.ls-1 { letter-spacing: 0.04em }
.ls-2 { letter-spacing: 0.06em }
.ls-3 { letter-spacing: 0.10em }
.ls-4 { letter-spacing: 0.12em }
.ls-disp { letter-spacing: var(--tracking-cn-display) }
/* -- Text color -- */
.text-brand { color: var(--brand-500) }
.text-brand-hi { color: var(--brand-700) }
.text-brand-900{ color: var(--brand-900) }
.text-default { color: var(--fg-default) }
.text-muted { color: var(--fg-muted) }
.text-subtle { color: var(--fg-subtle) }
.text-gray-6 { color: var(--gray-600) }
.text-gray-7 { color: var(--gray-700) }
.text-gray-8 { color: var(--gray-800) }
.text-gray-9 { color: var(--gray-900) }
.text-white { color: #fff }
.text-success { color: var(--success-700) }
.text-warning { color: var(--warning-700) }
.text-danger { color: var(--danger-700) }
.text-info { color: var(--info-700) }
/* -- Background -- */
.bg-0 { background: var(--gray-0) }
.bg-25 { background: var(--gray-25) }
.bg-50 { background: var(--gray-50) }
.bg-100 { background: var(--gray-100) }
.bg-brand { background: var(--brand-500) }
.bg-brand-50 { background: var(--brand-50) }
.bg-brand-900{ background: var(--brand-900) }
.bg-success-50 { background: var(--success-50) }
.bg-warning-50 { background: var(--warning-50) }
.bg-danger-50 { background: var(--danger-50) }
.bg-info-50 { background: var(--info-50) }
/* -- Border -- */
.border { border: 1px solid var(--border-default) }
.border-top { border-top: 1px solid var(--border-default) }
.border-bottom { border-bottom: 1px solid var(--border-default) }
.border-left { border-left: 1px solid var(--border-default) }
.border-subtle { border-color: var(--border-subtle) }
.border-strong { border-color: var(--border-strong) }
.border-brand { border-color: var(--brand-500) }
.border-0 { border: none }
/* -- Border radius -- */
.rounded-sm { border-radius: var(--radius-sm) }
.rounded-md { border-radius: var(--radius-md) }
.rounded-lg { border-radius: var(--radius-lg) }
.rounded-xl { border-radius: var(--radius-xl) }
.rounded-pill { border-radius: var(--radius-pill) }
.rounded-full { border-radius: 50% }
/* -- Shadow -- */
.shadow-sm { box-shadow: var(--shadow-sm) }
.shadow-md { box-shadow: var(--shadow-md) }
.shadow-lg { box-shadow: var(--shadow-lg) }
.shadow-xl { box-shadow: var(--shadow-xl) }
/* -- Text helpers -- */
.text-upper { text-transform: uppercase }
.text-center { text-align: center }
.text-right { text-align: right }
.text-nowrap { white-space: nowrap }
.font-mono { font-family: var(--font-mono) }
.tabular { font-variant-numeric: tabular-nums }
/* -- Sizing & position -- */
.w-full { width: 100% }
.h-full { height: 100% }
.min-w-0 { min-width: 0 }
.pos-relative { position: relative }
.pos-absolute { position: absolute }
.pos-sticky { position: sticky }
.overflow-hidden { overflow: hidden }
.overflow-x-auto { overflow-x: auto }
/* -- Transition(常用属性组合) -- */
.transition {
transition: background var(--duration-fast) var(--ease-standard),
border-color var(--duration-fast) var(--ease-standard),
color var(--duration-fast) var(--ease-standard),
box-shadow var(--duration-fast) var(--ease-standard);
}
/* ----------------------------------------------------------------
Card & Badge 高频组合
---------------------------------------------------------------- */
/* cardbg-0 + border + rounded-lg,三个页面共用 15+ 次 */
.card {
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
}
/* badge:状态标签小胶囊 */
.badge {
display: inline-block;
padding: 2px 10px;
border-radius: var(--radius-pill);
font-size: var(--text-xs);
font-weight: 600;
}
.badge-brand { background: var(--brand-50); color: var(--brand-700) }
.badge-success { background: var(--success-50); color: var(--success-700) }
.badge-warning { background: var(--warning-50); color: var(--warning-700) }
.badge-danger { background: var(--danger-50); color: var(--danger-700) }
.badge-info { background: var(--info-50); color: var(--info-700) }
.badge-gray { background: var(--gray-100); color: var(--gray-700) }
.badge-solid { background: var(--brand-500); color: #fff }
/* icon 尺寸 */
.icon-sm { width: 14px; height: 14px }
.icon-md { width: 18px; height: 18px }
.icon-lg { width: 22px; height: 22px }
.icon-xl { width: 28px; height: 28px }
.icon-2xl { width: 36px; height: 36px }
/* icon-box:方形图标容器(带背景色时使用) */
.icon-box-sm { width: 28px; height: 28px; border-radius: var(--radius-sm); display: grid; place-items: center }
.icon-box-md { width: 36px; height: 36px; border-radius: 8px; display: grid; place-items: center }
.icon-box-lg { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center }
.icon-box-xl { width: 56px; height: 56px; border-radius: var(--radius-md); display: grid; place-items: center }
/* ----------------------------------------------------------------
Responsive
---------------------------------------------------------------- */
@media (max-width: 1024px) {
.footer-grid { grid-template-columns: 1fr 1fr; }
.container { padding: 0 20px; }
}
@media (max-width: 768px) {
.grid-3, .grid-4, .grid-5 { grid-template-columns: repeat(2, 1fr); }
}
+487
View File
@@ -0,0 +1,487 @@
# 岩美酒库管理系统 · 使用手册
> 适用版本:v1.x · 受众:酒行管理员及工作人员
---
## 1. 系统概述
岩美酒库管理系统专为酒行门店设计,将入库、出库、库存查询、财务往来等日常业务整合到一个平台,支持多人协同操作,数据实时同步。
**核心功能一览**
| 模块 | 主要用途 |
|------|---------|
| 入库管理 | 新建入库单、提交审核、审批通过后自动更新库存 |
| 出库管理 | 新建出库单、提交审核、审批时自动扣减库存 |
| 库存管理 | 查询实时库存、库存盘点、打印标签 |
| 财务管理 | 查看应付款(欠供应商)和应收款(客户欠款)、标记结清 |
| 往来单位 | 管理供应商和客户的基本信息 |
| 基础数据 | 维护商品名称、系列、规格字典 |
| 系统设置 | 用户管理、仓库管理、编号规则、数据导入 |
**支持平台**:Web 浏览器(现已上线);Windows、macOS、iOS、Android 客户端即将推出。
---
## 2. 登录与退出
### 2.1 登录
1. 打开系统,进入登录页面。
2. 在「门店编号」栏输入酒行的门店代号(例如 `S001`)。
3. 输入「用户名」和「密码」。
4. 点击「登录」按钮。
登录成功后,系统自动跳转到「入库管理」页面。
**提示**:系统会记录最近登录过的用户名,点击输入框可从候选列表中快速选择。
### 2.2 退出登录
点击顶部右侧用户名旁的下拉箭头,选择「退出登录」。
### 2.3 查看当前登录信息
点击顶部左侧「岩美」标题或右侧「门店编号」区域,弹出门店信息面板,显示门店编号、登录账号、姓名、系统版本。
---
## 3. 界面说明
系统主界面由三个区域组成:
```
┌──────────────────────────────────────────────────────────┐
│ 顶部导航栏(标题、门店编号、用户名、退出) │
├──────────┬───────────────────────────────────────────────┤
│ │ │
│ 左侧 │ 主内容区域 │
│ 侧边栏 │ │
│ │ │
├──────────┴───────────────────────────────────────────────┤
│ 状态栏(门店、用户、登录时间、当前时间、连接状态) │
└──────────────────────────────────────────────────────────┘
```
**左侧侧边栏导航项**
| 导航项 | 功能 |
|--------|------|
| 入库管理 | 入库单录入与审核 |
| 出库管理 | 出库单录入与审核 |
| 库存管理 | 库存查询与盘点 |
| 财务管理 | 应付款和应收款 |
| 往来单位 | 供应商与客户 |
| 基础数据 | 商品名称、系列、规格字典 |
| 系统设置 | 用户、仓库、编号规则等配置 |
点击侧边栏顶部的菜单图标可收起或展开侧边栏,节省屏幕空间。
**更新提示**:有新版本时,内容区顶部会显示黄色提示横幅;如果是必须更新的版本,会弹出对话框要求立即更新。
**离线提示**:网络断开时,顶部显示红色横幅「网络连接已断开」,状态栏变红,此时展示上次加载的缓存数据。
---
## 4. 角色与权限
系统有四种角色,权限从高到低依次为:
| 角色 | 说明 | 可执行操作 |
|------|------|------------|
| 超级管理员 | 系统最高权限账号 | 全部操作,含数据清空 |
| 管理员 | 门店管理人员 | 全部操作,含用户管理、酒行信息编辑 |
| 操作员 | 日常录入审核人员 | 新建、编辑、提交、审核单据,查询数据 |
| 只读 | 仅查看数据 | 只能查看,不能新建、修改、删除任何数据 |
**权限说明**
- 只读账号点击任何写操作按钮时,系统将直接提示「无权限」。
- 新增或编辑用户、重置密码仅管理员可操作。
- 修改酒行基本信息仅管理员可操作。
- 数据清空仅超级管理员可操作。
---
## 5. 入库管理
入库管理页面包含两个标签页:**入库审核**(新建和待审核)和**入库单**(已完成记录)。
### 5.1 入库单状态说明
单据状态按以下流程流转:
**草稿****待审核****已审批**(库存增加)
待审核阶段也可被拒绝,变为**已拒绝**状态(库存不变)。
| 状态 | 含义 |
|------|------|
| 草稿 | 已保存但未提交,可继续编辑或删除 |
| 待审核 | 已提交等待审批,不可再编辑 |
| 已审批 | 审批通过,库存已增加,同时生成应付账款记录 |
| 已拒绝 | 审批不通过,库存不变 |
### 5.2 新建入库单
1. 点击左侧「入库管理」,切换到「入库审核」标签页。
2. 点击右上角「新建入库审核单」按钮。
3. 填写入库基本信息:
- **仓库**(必填):选择货物入库的目标仓库。
- **供应商**(必填):选择供货的往来单位。
- **入库日期**(必填):默认为今天,可修改。
- **备注**(选填):填写本批次入库说明。
4. 在商品明细区域填写每一行商品:
- **商品名称**(必填):从字典中选择或直接输入。
- **系列**(必填):选择商品系列。
- **规格**(必填):选择商品规格,如 500ml×6。
- **生产日期**(必填):点击日历图标选择。
- **批次号**(选填):填写批次编号,用于后续追踪查询。
- **数量**(必填):填写入库数量。
- **单价**(必填):填写进货单价,系统自动计算总金额。
5. 点击「添加商品」可继续增加商品行,点击行末「删除」可移除该行。
6. 完成后选择操作:
- **保存草稿**:保存后可以继续修改。
- **保存并提交审核**:提交后进入待审核状态,不可再编辑。
### 5.3 提交审核
草稿状态的入库单,在列表中点击「提交」按钮,确认后单据进入「待审核」状态。
### 5.4 审批入库单
操作员及以上权限的用户均可审批。
1. 在「入库审核」标签页中找到待审核的入库单。
2. 点击「通过」:弹窗确认,确认后系统自动将商品入库,库存增加,同时生成一笔应付账款记录。
3. 点击「拒绝」:弹窗确认,拒绝后库存不变,单据进入「已拒绝」状态。
**注意**:审批通过后操作不可撤销,请仔细核对商品数量和单价后再确认。
### 5.5 查看入库单详情
点击入库单号(蓝色链接)可弹出详情页,显示完整的商品明细、数量、金额及审核信息。详情页右上角有打印按钮,可直接打印入库单。
### 5.6 打印入库单
在列表中点击对应行的「打印」按钮,直接调用打印机打印入库单据。
### 5.7 打印商品标签
1. 在列表中点击对应行的「打标签」按钮。
2. 弹出商品标签打印对话框,列出本次入库的所有商品。
3. 勾选需要打印标签的商品(默认全选)。
4. 点击「打印选中」,系统逐张打印选中商品的标签。
标签内容包括:商品名称、编码、系列、规格、批次号、生产日期、酒行名称及联系方式、二维码。
### 5.8 标记货款结清
审批通过的入库单会自动生成应付账款记录。货款付清后,在列表中点击「结清」按钮,确认后将对应财务记录标记为已结清。
### 5.9 筛选与导出
- **仓库筛选**:点击列头「仓库」的筛选图标,选择仓库进行过滤。
- **供应商筛选**:点击列头「供应商」的筛选图标,选择供应商进行过滤。
- **日期筛选**:点击「选择日期」按钮,选择日期范围。
- **导出**:点击「导出」按钮,将当前列表导出为 Excel 文件。
---
## 6. 出库管理
出库管理与入库管理操作流程类似,包含**出库审核**(待处理)和**出库单**(已完成)两个标签页。
### 6.1 出库单状态说明
出库单状态流转与入库单相同:草稿 → 待审核 → 已审批或已拒绝。
审批通过后:
- 系统会先检查库存是否充足,库存不足时审批失败并给出提示,库存不变。
- 库存充足时自动扣减库存,并生成应收账款记录。
### 6.2 新建出库单
1. 点击左侧「出库管理」,切换到「出库审核」标签页。
2. 点击右上角「新建出库审核单」按钮。
3. 填写基本信息:
- **仓库**(必填):选择出货仓库。
- **客户**(必填):选择购买方(往来单位中的客户类型)。
- **出库日期**(必填):默认今天,可修改。
4. 填写商品明细:商品名称、系列、规格、数量、单价(操作方式同入库单)。
5. 保存草稿或保存并提交审核。
**注意**:出库数量不能超过当前库存,审批时系统会自动检查,库存不足会提示失败。
### 6.3 审批出库单
操作步骤与入库审批相同。审批通过后库存自动扣减,同时生成应收账款记录。
### 6.4 打印出库单
在列表中点击「打印」按钮,打印出库单据。
### 6.5 标记货款结清
出库单审批通过后生成应收账款。收到货款后,在列表中点击「结清」按钮,将对应财务记录标记为已结清。
---
## 7. 库存管理
### 7.1 查询库存
点击左侧「库存管理」进入库存列表。
列表显示每个商品的实时库存数量、所在仓库、单价、金额、生产日期、批次等信息。
- **搜索**:在搜索框输入商品名称关键字(也支持拼音或拼音首字母),实时过滤结果。
- **仓库筛选**:点击列头「仓库」的筛选图标,按仓库查看库存。
- **导出**:点击「导出」按钮,将当前库存列表导出为 Excel 文件。
### 7.2 修改备注
在库存列表中,点击「备注」列对应单元格(显示铅笔图标或现有备注内容),弹出编辑框,填写后点击「保存」即可。
### 7.3 打印商品标签
在库存列表中点击某商品行的「打印标签」按钮,可单独打印该商品的标签。
### 7.4 库存盘点
1. 在库存管理页面切换到「库存盘点」标签页。
2. 选择要盘点的**仓库**,系统自动加载该仓库所有商品的账面库存数量。
3. 选择盘点类型(全盘)。
4. 逐行填写**实际盘点数量**(与账面不符时修改数量)。
5. 点击「提交盘点」完成。
盘点单编号由系统自动生成。
### 7.5 库存流水
「库存流水」标签页可查看每次库存变动记录,包括入库、出库的时间、变动数量等。
---
## 8. 财务管理
### 8.1 财务记录说明
系统在以下情况自动生成财务记录:
- 入库单审批通过 → 自动生成**应付账款**(欠供应商的货款)
- 出库单审批通过 → 自动生成**应收账款**(客户欠的货款)
点击左侧「财务管理」进入财务页面,包含三个标签:
| 标签 | 内容 |
|------|------|
| 全部记录 | 所有财务流水 |
| 应付账款 | 需要向供应商付款的记录 |
| 应收账款 | 客户尚未付款的记录 |
### 8.2 查看财务记录
- 默认显示当前月份的记录,可通过月份选择器查看历史月份。
- 支持按「类型」和「往来单位」列头筛选。
- 点击「导出」可导出当月数据为 Excel 文件。
### 8.3 标记结清
**方式一**:在入库单或出库单列表中点击「结清」按钮,直接结清该单据对应的账款。
**方式二**:在财务管理列表中找到对应记录,点击「结清」按钮,单笔结清。
结清后该记录状态从「未结清」变为「已结清」。
### 8.4 财务汇总
财务管理页面显示当期应付和应收总额,便于掌握资金往来概况。
---
## 9. 往来单位
往来单位管理**供应商**和**客户**两类信息,新建入库单时选择供应商,新建出库单时选择客户。
### 9.1 查看往来单位
点击左侧「往来单位」,通过「供应商」和「客户」标签页分别查看。列表支持按名称搜索和导出。
### 9.2 新建往来单位
1. 在对应标签页点击右上角「新建」按钮。
2. 填写信息:
- **名称**(必填)
- **联系电话**(选填)
- **地址**(选填)
- **卡号**(选填,如有账户绑定)
- **初始余额**(选填,导入历史数据时填写)
- **备注**(选填)
3. 点击「保存」。
### 9.3 编辑往来单位
在列表中点击「编辑」按钮,修改信息后保存。
### 9.4 删除往来单位
在列表中点击「删除」按钮,确认后删除。
**注意**:已关联入库单或出库单的往来单位不可删除。
---
## 10. 基础数据(商品管理)
点击左侧「基础数据」,进入商品字典管理页面,包含三个标签:**商品名称**、**系列**、**规格**。
这些字典数据是新建入库或出库单时选择商品的基础,需要先在此处维护好商品信息。
### 10.1 商品名称管理
商品名称是酒品的主名称,例如「茅台飞天 53°」。
1. 在「商品名称」标签页,点击「新建」按钮。
2. 填写商品名称(必填)、编号(选填)、备注(选填)。
3. 点击「保存」。
支持按名称或编号搜索,支持分页浏览,支持编辑和删除。
### 10.2 系列管理
系列是商品所属的系列或品牌线,例如「飞天系列」「王子系列」。操作步骤与商品名称相同。
### 10.3 规格管理
规格用于描述包装规格,例如「500ml×6」「1000ml×1」。新建时可填写「单品数量」(即一箱包含的单瓶数量)。
### 10.4 商品详情与二维码
每个商品都有唯一的二维码,可通过扫码访问商品公开信息页面。在商品详情页可查看或上传商品图片。
---
## 11. 系统设置
点击左侧「系统设置」,包含七个标签页。
### 11.1 酒行信息
显示本门店的基本信息:门店编号、门店名称、地址、联系电话、负责人。
**编辑**(仅管理员):点击「编辑信息」按钮,修改门店名称、地址、电话、负责人后保存。门店编号不可修改。
### 11.2 用户管理(仅管理员)
**查看用户**:显示本门店所有用户的姓名、用户名、角色、启用状态。
**新增用户**
1. 点击「新增用户」按钮。
2. 填写用户名(登录账号,不可重复)、姓名、手机号、初始密码。
3. 选择角色(操作员、管理员、只读、超级管理员)。
4. 点击「保存」。
**编辑用户**:点击用户行的「编辑」按钮,可修改姓名、手机号、角色(用户名不可修改)。
**重置密码**:点击「重置密码」按钮,输入新密码后确认,下次登录时使用新密码。
**启用或停用**:在用户列表中拨动状态开关。停用后该用户无法登录。
### 11.3 仓库管理
**查看仓库**:显示所有仓库名称、位置、是否为默认仓库。
**新建仓库**
1. 点击「新建」按钮。
2. 填写仓库名称(必填)、位置(选填)。
3. 可勾选「设为默认仓库」,新建单据时将自动选择此仓库。
4. 点击「保存」。
**编辑或删除**:点击对应按钮操作。已有库存的仓库不可删除。
### 11.4 编号规则
系统为每类单据自动生成唯一编号,格式由前缀、日期和序号组成,例如入库单编号 `RK20260523001`
**查看当前规则**:列表显示每种单据的前缀、当前序号及下一编号示例。
**修改规则**
1. 点击对应规则行的「编辑」按钮。
2. 可修改「前缀」和「当前序号」。
3. 点击「保存」,修改后对新建单据生效。
**注意**:请勿将序号调小至已使用过的范围,否则可能导致编号重复。
### 11.5 系统参数
配置系统的全局参数:
- **系统名称、货币单位、日期格式、时区**(通常无需修改)
- **入库单需要审核**:关闭后提交即视为通过,无需审批
- **出库单需要审核**:关闭后同上
- **允许超量出库**:开启后,出库数量超过库存时仍可审批通过
修改后点击「保存设置」生效,点击「重置默认」恢复出厂默认值。
### 11.6 数据导入
通过 Excel 文件批量导入历史数据。支持以下数据类型:往来单位、商品名称、商品系列、商品规格、商品编码、库存。
各类型的 Excel 格式要求详见系统内「系统设置 → 数据导入」页面说明。
**操作步骤**
1. 在对应数据类型行点击「选择文件」,选择 Excel(.xls 或 .xlsx)文件。
2. 全部文件选择完成后,点击「全部导入」按钮。
3. 系统依次处理每个文件并显示导入结果(新增、跳过重复、失败数量)。
4. 如有失败,根据错误提示修正文件后重新导入。
**导入规则**:以名称去重,已存在的记录不重复导入。导入过程中请勿切换页面。
**数据清空(仅超级管理员)**:在数据导入页面下方「危险操作」区域,选择要清空的数据表,点击确认后输入「确认清空」完成操作。**此操作不可撤销,请务必提前做好数据备份。**
### 11.7 关于
- **版本信息**:显示当前系统版本。有新版本时可点击「立即更新」。
- **授权信息**:显示授权类型(试用、月付、年付、买断)、授权状态、到期时间。授权剩余不足 30 天时会显示倒计时提醒。
- **意见反馈**:点击「反馈 Bug」或「功能建议」,通过邮件向开发团队反馈。
---
## 12. 常见问题
**Q:入库单提交后发现填错了,怎么办?**
单据提交(待审核状态)后不可再修改。请联系管理员将该单据拒绝,然后重新新建一张正确的入库单。
**Q:出库审批时提示「库存不足」,怎么处理?**
出库数量超过当前仓库库存时,系统会拒绝审批。请检查出库数量,或确认对应商品的入库单是否已审批通过、库存已更新。
**Q:结清了财务记录但发现结清错了,如何撤销?**
目前系统不支持撤销结清操作。如需处理,请联系技术支持。
**Q:如何查找某批商品是从哪张入库单入库的?**
在库存管理列表中查看商品的批次号,然后在入库管理中按批次号搜索对应的入库单。
**Q:导入数据时提示「格式错误」,怎么处理?**
请检查 Excel 文件的列顺序是否与「系统设置 → 数据导入」页面说明的格式一致,且第一行为数据行(无需填写表头)。如问题持续,可将文件发送给技术支持排查。
**Q:用户无法登录,怎么处理?**
请管理员在「系统设置 → 用户管理」中检查该用户是否处于启用状态,并使用「重置密码」功能为其设置新密码。
**Q:操作时提示「无权限」,是什么原因?**
当前账号角色为「只读」,不允许执行写操作。如需操作,请联系管理员调整账号角色。
**Q:系统显示「网络连接已断开」,数据还准确吗?**
网络断开时,系统展示上次加载的缓存数据,可能不是最新状态。请恢复网络连接后刷新页面获取最新数据。
**Q:如何联系技术支持?**
进入「系统设置 → 关于」查看联系邮箱和技术支持时间。工作日(周一至周五)9:00 - 18:00 可获得响应。
+36
View File
@@ -0,0 +1,36 @@
## Web 版(已上线)
| 要求 | 最低 | 推荐 |
|---|---|---|
| 浏览器 | Chrome 90 / Firefox 90 / Safari 15 / Edge 90 | 最新稳定版 |
| 网络 | 任意宽带 | 10 Mbps+ |
## Windows(敬请期待)
| 要求 | 版本 |
|---|---|
| 系统 | Windows 1064 位)及以上 |
| 内存 | 4 GB RAM |
| 存储 | 500 MB 可用空间 |
## macOS(敬请期待)
| 要求 | 版本 |
|---|---|
| 系统 | macOS 12 及以上 |
| 内存 | 4 GB RAM |
| 存储 | 500 MB 可用空间 |
## iOS(敬请期待)
| 要求 | 版本 |
|---|---|
| 系统 | iOS 15 及以上 |
| 设备 | iPhone 8 / iPad 第 6 代及以上 |
## Android(敬请期待)
| 要求 | 版本 |
|---|---|
| 系统 | Android 9 及以上 |
| 内存 | 3 GB RAM |
-1167
View File
File diff suppressed because it is too large Load Diff
+194
View File
@@ -0,0 +1,194 @@
---
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>
-1218
View File
File diff suppressed because it is too large Load Diff
+506
View File
@@ -0,0 +1,506 @@
---
layout: base.njk
title: 下载
description: 下载岩美酒库管理系统,Web 版现已上线,Windows / macOS / iOS / Android 客户端即将推出。
pageStyle: |
/* ── Page header ── */
.page-header {
padding: 72px 0 56px;
background:
radial-gradient(700px 360px at 80% 20%, rgba(37, 99, 172, 0.06), transparent 60%),
linear-gradient(180deg, #FBFCFD 0%, #FFFFFF 80%);
border-bottom: 1px solid var(--border-subtle);
}
.ph-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 64px;
align-items: center;
}
.ph-eyebrow {
font-size: var(--text-xs); font-weight: 600;
letter-spacing: 0.12em; color: var(--brand-500);
text-transform: uppercase;
margin: 0 0 12px;
display: flex; align-items: center; gap: 8px;
}
.ph-eyebrow .version-badge {
background: var(--brand-500); color: #fff;
padding: 3px 8px; border-radius: var(--radius-sm);
font-family: var(--font-mono);
letter-spacing: 0.02em; font-size: 11px;
}
.ph-title {
font-size: 44px; font-weight: 700; line-height: 1.15;
letter-spacing: var(--tracking-cn-display);
color: var(--brand-900); margin: 0 0 18px;
}
.ph-lead {
font-size: var(--text-lg); color: var(--gray-600);
line-height: 1.6; margin: 0 0 24px; max-width: 480px;
}
.ph-meta {
display: flex; gap: 24px;
font-size: var(--text-sm); color: var(--fg-muted);
border-top: 1px solid var(--border-subtle);
padding-top: 16px;
}
.ph-meta-item { display: flex; flex-direction: column; gap: 2px; }
.ph-meta-label { font-size: 11px; color: var(--fg-subtle); letter-spacing: 0.04em; }
.ph-meta-val { font-size: var(--text-sm); color: var(--gray-800); font-weight: 500; }
/* ── Auto-detect card ── */
.detect-card {
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
overflow: hidden;
}
.detect-card-head {
padding: 14px 20px;
background: var(--gray-50);
border-bottom: 1px solid var(--border-subtle);
font-size: var(--text-xs); color: var(--fg-muted);
display: flex; justify-content: space-between; align-items: center;
}
.detect-card-head .head-left { display: flex; align-items: center; gap: 6px; }
.detect-card-head .head-left svg { width: 14px; height: 14px; color: var(--success-500); }
.detect-card-body {
padding: 28px;
display: flex; gap: 24px; align-items: center;
}
.detect-icon {
width: 72px; height: 72px;
background: var(--brand-50); border-radius: 16px;
display: grid; place-items: center;
color: var(--brand-500); flex-shrink: 0;
}
.detect-icon svg { width: 38px; height: 38px; }
.detect-info { flex: 1; }
.detect-info h3 { margin: 0 0 4px; font-size: var(--text-xl); font-weight: 600; color: var(--brand-900); }
.detect-info p { margin: 0; font-size: var(--text-sm); color: var(--fg-muted); }
.detect-card-actions { padding: 0 28px 28px; display: flex; gap: 8px; }
.detect-card-actions .btn-primary { flex: 1; justify-content: center; }
/* ── Platform grid ── */
.dl-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
margin-top: 32px;
}
.dl-card {
background: var(--gray-0);
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
padding: 20px;
display: flex; flex-direction: column;
transition: border-color var(--duration-base) var(--ease-standard),
box-shadow var(--duration-base) var(--ease-standard);
}
.dl-card:hover { border-color: var(--brand-300); box-shadow: var(--shadow-sm); }
.dl-card.detected { border-color: var(--brand-400); box-shadow: var(--shadow-md); }
.dl-card.coming-soon { opacity: 0.65; }
.dl-card-icon {
width: 48px; height: 48px;
background: var(--brand-50); border-radius: var(--radius-md);
display: grid; place-items: center; color: var(--brand-500);
margin-bottom: 12px;
}
.dl-card-icon svg { width: 24px; height: 24px; }
.dl-card-name { font-size: var(--text-md); font-weight: 600; color: var(--brand-900); margin: 0 0 4px; }
.dl-card-desc { font-size: var(--text-xs); color: var(--fg-muted); margin: 0 0 14px; line-height: 1.5; flex: 1; }
.dl-status {
display: inline-flex; align-items: center; gap: 4px;
font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
padding: 3px 8px; border-radius: var(--radius-pill); margin-bottom: 12px;
}
.dl-status.available { background: var(--success-50); color: var(--success-700); }
.dl-status.soon { background: var(--gray-100); color: var(--fg-muted); }
.dl-card-btn {
display: flex; align-items: center; justify-content: center; gap: 6px;
height: 34px; padding: 0 14px;
border-radius: var(--radius-md);
font-size: var(--text-sm); font-weight: 500;
border: 1px solid transparent;
cursor: pointer; width: 100%;
transition: background var(--duration-fast) var(--ease-standard);
text-decoration: none;
}
.dl-card-btn.primary { background: var(--brand-500); color: #fff; }
.dl-card-btn.primary:hover { background: var(--brand-600); }
.dl-card-btn.disabled {
background: var(--gray-100); color: var(--fg-muted);
cursor: default; pointer-events: none;
border-color: var(--border-subtle);
}
.dl-card-btn svg { width: 14px; height: 14px; }
/* ── System requirements (rendered markdown) ── */
.sysreq-content h2 {
font-size: var(--text-xl); font-weight: 600;
color: var(--brand-900); margin: 28px 0 12px;
letter-spacing: var(--tracking-cn-display);
padding-bottom: 8px;
border-bottom: 1px solid var(--border-subtle);
}
.sysreq-content h2:first-child { margin-top: 0; }
.sysreq-content table {
width: 100%; border-collapse: collapse;
font-size: var(--text-sm); color: var(--gray-800);
margin-bottom: 8px;
}
.sysreq-content th {
text-align: left; font-size: 11px; font-weight: 600;
letter-spacing: 0.04em; text-transform: uppercase;
color: var(--fg-muted); padding: 8px 12px;
background: var(--gray-50);
border: 1px solid var(--border-subtle);
}
.sysreq-content td {
padding: 10px 12px;
border: 1px solid var(--border-subtle);
vertical-align: top;
}
.sysreq-content tr:hover td { background: var(--gray-25); }
.sysreq-content p { font-size: var(--text-sm); color: var(--fg-muted); margin: 8px 0 0; }
/* ── Changelog timeline ── */
.changelog {
display: grid;
grid-template-columns: 180px 1fr;
gap: 0;
margin-top: 40px;
border-left: 1px solid var(--border-subtle);
}
.changelog-entry { display: contents; }
.changelog-meta {
padding: 28px 24px 28px 32px;
position: relative;
border-bottom: 1px solid var(--border-subtle);
}
.changelog-meta::before {
content: '';
position: absolute; left: -7px; top: 36px;
width: 13px; height: 13px; border-radius: 50%;
background: var(--gray-0); border: 3px solid var(--gray-300);
}
.changelog-entry.current .changelog-meta::before {
background: var(--brand-500); border-color: var(--brand-100);
box-shadow: 0 0 0 4px var(--brand-50);
}
.changelog-version {
font-family: var(--font-mono); font-size: var(--text-md); font-weight: 600;
color: var(--brand-900); margin-bottom: 4px;
}
.changelog-date { font-size: var(--text-xs); color: var(--fg-muted); }
.changelog-tag {
display: inline-block; font-size: 10px;
background: var(--success-50); color: var(--success-700);
padding: 2px 8px; border-radius: var(--radius-pill);
font-weight: 500; margin-top: 8px;
}
.changelog-body {
padding: 28px 0 28px 32px;
border-bottom: 1px solid var(--border-subtle);
border-left: 1px solid var(--border-subtle);
margin-left: -1px;
}
.changelog-entry:last-child .changelog-meta,
.changelog-entry:last-child .changelog-body { border-bottom: none; }
.changelog-intro {
font-size: var(--text-sm); color: var(--gray-700);
line-height: 1.6; margin: 0 0 16px;
}
.changelog-cat { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.changelog-cat-label {
font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
color: var(--fg-muted); text-transform: uppercase;
display: flex; align-items: center; gap: 6px; margin-bottom: 2px;
}
.changelog-cat-label .dot { width: 6px; height: 6px; border-radius: 50%; }
.dot-feature { background: var(--brand-500); }
.dot-improve { background: var(--success-500); }
.dot-fix { background: var(--warning-500); }
.changelog-cat ul {
margin: 0; padding: 0; list-style: none;
font-size: var(--text-sm); color: var(--gray-700); line-height: 1.6;
}
.changelog-cat ul li {
padding: 3px 0 3px 16px; position: relative;
}
.changelog-cat ul li::before {
content: ''; position: absolute; left: 0; top: 11px;
width: 6px; height: 1px; background: var(--gray-400);
}
/* ── Responsive ── */
@media (max-width: 1024px) {
.ph-inner { grid-template-columns: 1fr; gap: 32px; }
.ph-title { font-size: 36px; }
.dl-grid { grid-template-columns: repeat(3, 1fr); }
.changelog { grid-template-columns: 120px 1fr; }
}
@media (max-width: 768px) {
.dl-grid { grid-template-columns: repeat(2, 1fr); }
.page-header { padding: 48px 0 40px; }
}
---
<!-- ============================== PAGE HEADER ============================== -->
<section class="page-header">
<div class="container ph-inner">
<div>
<div class="ph-eyebrow">
<span class="version-badge">v{{ changelog[0].version }}</span>
<span>下载岩美</span>
</div>
<h1 class="ph-title">随时随地,<br/>轻松管理酒库。</h1>
<p class="ph-lead">
Web 版已正式上线,浏览器直接访问,无需安装。Windows、macOS、iOS、Android 客户端即将推出。
</p>
<div class="ph-meta">
<div class="ph-meta-item">
<div class="ph-meta-label">最新版本</div>
<div class="ph-meta-val version-badge">v{{ changelog[0].version }}</div>
</div>
<div class="ph-meta-item">
<div class="ph-meta-label">发布日期</div>
<div class="ph-meta-val">{{ changelog[0].date }}</div>
</div>
<div class="ph-meta-item">
<div class="ph-meta-label">可用平台</div>
<div class="ph-meta-val">Web 浏览器</div>
</div>
</div>
</div>
<!-- Auto-detect card -->
<div class="detect-card">
<div class="detect-card-head">
<span class="head-left">
<i data-lucide="zap" class="icon"></i>
已自动识别您的环境
</span>
<span style="font-family: var(--font-mono); color: var(--fg-subtle);">推荐</span>
</div>
<div class="detect-card-body">
<div class="detect-icon" id="detect-icon">
<i data-lucide="globe" class="icon"></i>
</div>
<div class="detect-info">
<h3 id="detect-name">Web 版</h3>
<p id="detect-desc">浏览器直接访问,功能完整,无需下载安装。</p>
</div>
</div>
<div class="detect-card-actions">
<a href="https://jiu.51yanmei.com/app/" class="btn btn-primary btn-lg" id="detect-btn">
<i data-lucide="arrow-right" class="icon"></i>
立即使用 Web 版
</a>
</div>
</div>
</div>
</section>
<!-- ============================== PLATFORM GRID ============================== -->
<section class="section">
<div class="container">
<h2 class="fs-3xl fw-6 text-brand-900 m-0 mb-6" style="letter-spacing: var(--tracking-cn-display);">支持的平台</h2>
<p class="fs-md text-muted m-0 mb-8">Web 版现已可用,其余平台正在开发中。</p>
<div class="dl-grid" id="platform-grid">
<!-- Web -->
<div class="dl-card" data-platform="web">
<div class="dl-card-icon"><i data-lucide="globe" class="icon"></i></div>
<h3 class="dl-card-name">Web 版</h3>
<p class="dl-card-desc">浏览器直接访问,功能完整,无需安装,支持 PC 与平板。</p>
<span class="dl-status available">✓ 已上线</span>
<a href="https://jiu.51yanmei.com/app/" class="dl-card-btn primary">
<i data-lucide="arrow-right" class="icon"></i>立即使用
</a>
</div>
<!-- Windows -->
<div class="dl-card coming-soon" data-platform="windows">
<div class="dl-card-icon"><i data-lucide="monitor" class="icon"></i></div>
<h3 class="dl-card-name">Windows</h3>
<p class="dl-card-desc">原生桌面客户端,支持离线模式与本地打印。</p>
<span class="dl-status soon">敬请期待</span>
<span class="dl-card-btn disabled">
<i data-lucide="clock" class="icon"></i>即将推出
</span>
</div>
<!-- macOS -->
<div class="dl-card coming-soon" data-platform="macos">
<div class="dl-card-icon"><i data-lucide="laptop" class="icon"></i></div>
<h3 class="dl-card-name">macOS</h3>
<p class="dl-card-desc">支持 Apple Silicon 与 Intel 芯片,通用版本。</p>
<span class="dl-status soon">敬请期待</span>
<span class="dl-card-btn disabled">
<i data-lucide="clock" class="icon"></i>即将推出
</span>
</div>
<!-- iOS -->
<div class="dl-card coming-soon" data-platform="ios">
<div class="dl-card-icon"><i data-lucide="smartphone" class="icon"></i></div>
<h3 class="dl-card-name">iOS</h3>
<p class="dl-card-desc">iPhone 与 iPad 通用,支持扫码与推送通知。</p>
<span class="dl-status soon">敬请期待</span>
<span class="dl-card-btn disabled">
<i data-lucide="clock" class="icon"></i>即将推出
</span>
</div>
<!-- Android -->
<div class="dl-card coming-soon" data-platform="android">
<div class="dl-card-icon"><i data-lucide="tablet-smartphone" class="icon"></i></div>
<h3 class="dl-card-name">Android</h3>
<p class="dl-card-desc">手机与平板通用,支持主流应用商店及 APK 安装。</p>
<span class="dl-status soon">敬请期待</span>
<span class="dl-card-btn disabled">
<i data-lucide="clock" class="icon"></i>即将推出
</span>
</div>
</div>
</div>
</section>
<!-- ============================== SYSTEM REQUIREMENTS ============================== -->
<section class="section bg-25">
<div class="container">
<h2 class="fs-3xl fw-6 text-brand-900 m-0 mb-6" style="letter-spacing: var(--tracking-cn-display);">系统要求</h2>
<p class="fs-md text-muted m-0 mb-32">在以下环境中均经过测试与验证。</p>
<div class="card p-32 sysreq-content">
{{ sysreq | safe }}
</div>
</div>
</section>
<!-- ============================== CHANGELOG ============================== -->
<section class="section">
<div class="container">
<h2 class="fs-3xl fw-6 text-brand-900 m-0 mb-6" style="letter-spacing: var(--tracking-cn-display);">版本更新日志</h2>
<p class="fs-md text-muted m-0">最近 {{ changelog | length }} 个版本。</p>
<div class="changelog">
{% for entry in changelog %}
<div class="changelog-entry{% if loop.first %} current{% endif %}">
<div class="changelog-meta">
<div class="changelog-version">v{{ entry.version }}</div>
<div class="changelog-date">{{ entry.date }}</div>
{% if loop.first %}<span class="changelog-tag">当前版本</span>{% endif %}
</div>
<div class="changelog-body">
{% if entry.intro %}
<p class="changelog-intro">{{ entry.intro }}</p>
{% endif %}
{% for section in entry.sections %}
<div class="changelog-cat">
<div class="changelog-cat-label">
{% if section.type == "新功能" %}
<span class="dot dot-feature"></span>新功能
{% elif section.type == "改进" %}
<span class="dot dot-improve"></span>改进
{% elif section.type == "修复" %}
<span class="dot dot-fix"></span>问题修复
{% else %}
<span class="dot dot-improve"></span>{{ section.type }}
{% endif %}
</div>
<ul>
{% for item in section.items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<script>
(function() {
var platforms = {
web: { name: 'Web 版', desc: '浏览器直接访问,功能完整,无需下载安装。', icon: 'globe', btnText: '立即使用 Web 版', btnHref: 'https://jiu.51yanmei.com/app/', available: true },
ios: { name: 'iOS', desc: 'iOS 客户端正在开发中,敬请期待。', icon: 'smartphone', btnText: '敬请期待', available: false },
android: { name: 'Android', desc: 'Android 客户端正在开发中,敬请期待。', icon: 'tablet-smartphone', btnText: '敬请期待', available: false },
windows: { name: 'Windows 桌面', desc: 'Windows 客户端正在开发中,敬请期待。', icon: 'monitor', btnText: '敬请期待', available: false },
macos: { name: 'macOS 桌面', desc: 'macOS 客户端正在开发中,敬请期待。', icon: 'laptop', btnText: '敬请期待', available: false }
};
function detectPlatform() {
var ua = navigator.userAgent;
if (/iPhone|iPad|iPod/.test(ua)) return 'ios';
if (/Android/.test(ua)) return 'android';
var platform = navigator.platform || '';
if (/Win/.test(platform) || /Win/.test(ua)) return 'windows';
if (/Mac/.test(platform) || /Mac/.test(ua)) return 'macos';
return 'web';
}
function updateDetectCard(p) {
var info = platforms[p];
var nameEl = document.getElementById('detect-name');
var descEl = document.getElementById('detect-desc');
var btnEl = document.getElementById('detect-btn');
var iconEl = document.getElementById('detect-icon');
if (nameEl) nameEl.textContent = info.name;
if (descEl) descEl.textContent = info.desc;
if (btnEl) {
if (info.available) {
btnEl.href = info.btnHref;
btnEl.style.opacity = '';
btnEl.style.pointerEvents = '';
btnEl.querySelector('span') && (btnEl.querySelector('span').textContent = info.btnText);
} else {
btnEl.href = '#';
btnEl.style.opacity = '0.5';
btnEl.style.pointerEvents = 'none';
}
btnEl.childNodes.forEach(function(n) {
if (n.nodeType === 3) n.textContent = ' ' + info.btnText;
});
}
if (iconEl && window.lucide) {
iconEl.innerHTML = '';
var svg = document.createElement('i');
svg.setAttribute('data-lucide', info.icon);
svg.className = 'icon';
iconEl.appendChild(svg);
lucide.createIcons();
}
}
function highlightPlatformCard(p) {
document.querySelectorAll('#platform-grid .dl-card').forEach(function(el) {
el.classList.remove('detected');
});
var card = document.querySelector('#platform-grid [data-platform="' + p + '"]');
if (card) card.classList.add('detected');
}
function updateVersionBadges(version) {
document.querySelectorAll('.version-badge').forEach(function(el) {
el.textContent = 'v' + version;
});
}
document.addEventListener('DOMContentLoaded', function() {
var detected = detectPlatform();
updateDetectCard(detected);
highlightPlatformCard(detected);
fetch('https://jiu.51yanmei.com/api/v1/public/release')
.then(function(r) { return r.json(); })
.then(function(data) { if (data && data.version) updateVersionBadges(data.version); })
.catch(function() {});
});
})();
</script>
-1860
View File
File diff suppressed because it is too large Load Diff
+627
View File
@@ -0,0 +1,627 @@
---
layout: base.njk
title: 为酒行与酒店设计的库存管理平台
description: 岩美酒库管理系统,审核驱动业务流,库存与账款自动同步,五端无缝接入。
---
<style>
/* HERO --------------------------------------------------------- */
.hero {
position: relative; overflow: hidden; padding: 88px 0 64px;
background:
radial-gradient(900px 480px at 78% 12%, rgba(37,99,172,0.06), transparent 60%),
linear-gradient(180deg,#FBFCFD 0%,#FFFFFF 80%);
}
.hero-inner { display: grid; grid-template-columns: 1.05fr 1.25fr; gap: 64px; align-items: center; }
.hero h1 { font-size: 52px; line-height: 1.12; letter-spacing: var(--tracking-cn-display); color: var(--brand-900); font-weight: 700; margin: 0 0 20px; }
.hero h1 em { font-style: normal; color: var(--brand-500); position: relative; }
.hero h1 em::after { content: ''; position: absolute; left: 0; right: 0; bottom: 4px; height: 10px; background: var(--brand-100); z-index: -1; border-radius: 2px; }
.hero p.lead { font-size: var(--text-xl); line-height: 1.6; color: var(--gray-600); margin: 0 0 32px; }
.hero-mini-item .icon { width: 14px; height: 14px; color: var(--success-500); }
/* Preview mock UI ---------------------------------------------- */
.preview-shell { background: var(--gray-0); border: 1px solid var(--border-default); border-radius: 14px; box-shadow: var(--shadow-xl); overflow: hidden; }
.preview-titlebar { height: 36px; display: flex; align-items: center; padding: 0 14px; background: var(--gray-50); border-bottom: 1px solid var(--border-subtle); gap: 8px; }
.preview-dots { display: flex; gap: 6px; }
.preview-dots span { width: 10px; height: 10px; border-radius: 50%; background: var(--gray-300); }
.preview-url { flex: 1; text-align: center; font-size: var(--text-xs); color: var(--fg-subtle); font-family: var(--font-mono); }
.mock-app { display: grid; grid-template-columns: 180px 1fr; height: 540px; }
.mock-sidebar { background: var(--brand-900); color: #DCE2EB; padding: 20px 12px; font-size: var(--text-sm); }
.mock-sidebar-brand { font-size: 13px; font-weight: 600; letter-spacing: 0.1em; color: #fff; padding: 0 8px 16px; border-bottom: 1px solid rgba(255,255,255,0.08); margin-bottom: 12px; }
.mock-nav-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--radius-sm); margin-bottom: 2px; color: #ADC9EA; font-size: 13px; }
.mock-nav-item .icon { width: 16px; height: 16px; }
.mock-nav-item.active { background: rgba(255,255,255,0.08); color: #fff; }
.mock-main { background: var(--gray-50); padding: 20px; overflow: hidden; }
.mock-topbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.mock-tabs { display: flex; gap: 4px; background: var(--gray-0); padding: 4px; border-radius: var(--radius-md); border: 1px solid var(--border-default); }
.mock-tab { padding: 6px 14px; font-size: 13px; color: var(--gray-600); border-radius: var(--radius-sm); }
.mock-tab.active { background: var(--brand-500); color: #fff; font-weight: 500; }
.mock-actions { display: flex; gap: 8px; }
.mock-mini-btn { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-sm); font-size: 12px; color: var(--gray-700); }
.mock-mini-btn .icon { width: 13px; height: 13px; }
.mock-mini-btn.primary { background: var(--brand-500); color: #fff; border-color: var(--brand-500); }
.mock-stats { display: grid; grid-template-columns: repeat(4,1fr); gap: 10px; margin-bottom: 16px; }
.mock-stat { background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 12px 14px; }
.mock-stat-label { font-size: 11px; color: var(--fg-muted); margin-bottom: 4px; }
.mock-stat-value { font-size: 20px; font-weight: 600; color: var(--brand-900); font-variant-numeric: tabular-nums; }
.mock-stat-delta { font-size: 11px; margin-top: 2px; font-variant-numeric: tabular-nums; }
.mock-stat-delta.up { color: var(--success-500); }
.mock-stat-delta.down { color: var(--danger-500); }
.mock-table-card { background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
.mock-table-head { display: grid; grid-template-columns: 110px 1fr 60px 70px 80px 70px; padding: 10px 14px; background: var(--gray-50); border-bottom: 1px solid var(--border-subtle); font-size: 11px; color: var(--fg-muted); font-weight: 500; }
.mock-table-row { display: grid; grid-template-columns: 110px 1fr 60px 70px 80px 70px; padding: 10px 14px; border-bottom: 1px solid var(--border-subtle); font-size: 12px; color: var(--gray-800); align-items: center; font-variant-numeric: tabular-nums; }
.mock-table-row:last-child { border-bottom: none; }
.mock-table-row .sku { font-family: var(--font-mono); color: var(--brand-500); font-size: 11px; }
.mock-pill { display: inline-block; padding: 1px 8px; border-radius: var(--radius-pill); font-size: 10px; font-weight: 500; }
.mock-pill.ok { background: var(--success-50); color: var(--success-700); }
.mock-pill.warn { background: var(--warning-50); color: var(--warning-700); }
.mock-pill.pending { background: var(--info-50); color: var(--info-700); }
.hero-toast { position: absolute; bottom: -28px; right: -36px; background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: 14px 16px; width: 260px; display: flex; gap: 12px; align-items: flex-start; z-index: 2; }
.hero-toast-icon { width: 36px; height: 36px; border-radius: 8px; background: var(--success-50); display: grid; place-items: center; flex-shrink: 0; }
.hero-toast-icon .icon { color: var(--success-500); }
/* Trust strip -------------------------------------------------- */
.trust { border-top: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); background: var(--gray-25); padding: 32px 0; }
.trust-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr; align-items: center; gap: 32px; }
.trust-stat-num { font-size: 28px; font-weight: 600; color: var(--brand-900); font-variant-numeric: tabular-nums; line-height: 1; }
.trust-stat-num sup { font-size: 14px; color: var(--brand-500); margin-left: 2px; font-weight: 500; }
/* Modules ------------------------------------------------------ */
.module-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.module-card.feature-card { grid-column: span 2; background: linear-gradient(180deg,#FBFCFD 0%,#FFFFFF 100%); }
.module-card.feature-card .icon-box-lg { background: var(--brand-500); color: #fff; }
.module-card ul { margin: 16px 0 0; padding: 0; list-style: none; font-size: var(--text-sm); color: var(--gray-700); }
.module-card ul li { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-top: 1px solid var(--border-subtle); }
.module-card ul li:first-child { border-top: none; }
.module-card ul li .icon { width: 14px; height: 14px; color: var(--brand-500); }
/* Workflow ----------------------------------------------------- */
.workflow-grid { display: grid; grid-template-columns: 1fr 1.1fr; gap: 64px; align-items: center; margin-top: 48px; }
.wf-step { display: grid; grid-template-columns: 32px 1fr; gap: 14px; align-items: start; }
.wf-num { width: 32px; height: 32px; border-radius: var(--radius-pill); background: var(--brand-50); color: var(--brand-700); display: grid; place-items: center; font-size: 13px; font-weight: 600; }
.wf-step.active .wf-num { background: var(--brand-500); color: #fff; }
.flow-vis { background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); padding: 28px; }
.flow-doc { background: var(--gray-50); border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 16px 18px; margin-bottom: 14px; }
.flow-doc-head { display: flex; justify-content: space-between; margin-bottom: 12px; }
.flow-doc-id { font-family: var(--font-mono); font-size: 12px; color: var(--brand-500); }
.flow-doc-status { font-size: 11px; font-weight: 500; padding: 2px 10px; border-radius: var(--radius-pill); background: var(--info-50); color: var(--info-700); }
.flow-doc-status.approved { background: var(--success-50); color: var(--success-700); }
.flow-row { display: grid; grid-template-columns: 70px 1fr 70px 70px; gap: 8px; font-size: 12px; padding: 6px 0; color: var(--gray-700); font-variant-numeric: tabular-nums; }
.flow-row.head { font-weight: 500; color: var(--fg-muted); font-size: 11px; padding: 0 0 6px; border-bottom: 1px solid var(--border-subtle); margin-bottom: 4px; }
.flow-row.foot { border-top: 1px solid var(--border-default); margin-top: 6px; padding-top: 8px; font-weight: 600; color: var(--brand-900); }
.flow-arrow { display: flex; align-items: center; justify-content: center; padding: 12px 0; color: var(--gray-400); }
.flow-arrow .icon { width: 18px; height: 18px; }
.flow-effects { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.flow-effect { background: #fff; border: 1px solid var(--border-default); border-radius: var(--radius-md); padding: 12px 14px; }
.flow-effect-label { font-size: 11px; color: var(--fg-muted); display: flex; align-items: center; gap: 6px; }
.flow-effect-label .icon { width: 12px; height: 12px; color: var(--success-500); }
.flow-effect-val { font-size: 18px; font-weight: 600; color: var(--brand-900); margin-top: 4px; font-variant-numeric: tabular-nums; }
/* Platforms ---------------------------------------------------- */
.platform-card:hover { border-color: var(--brand-300); }
.platforms-visual { margin-top: 56px; background: var(--brand-900); border-radius: var(--radius-xl); padding: 56px 48px; position: relative; overflow: hidden; color: #fff; display: grid; grid-template-columns: 1fr 1.2fr; gap: 48px; align-items: center; }
.platforms-visual::before { content: ''; position: absolute; inset: 0; background: radial-gradient(600px 320px at 80% 10%,rgba(79,134,198,0.20),transparent 60%); pointer-events: none; }
.pv-text h3 { font-size: 32px; font-weight: 600; letter-spacing: var(--tracking-cn-display); margin: 0 0 16px; }
.pv-text p { font-size: var(--text-lg); color: #ADC9EA; margin: 0 0 24px; line-height: 1.6; }
.pv-feature { display: flex; align-items: center; gap: 10px; font-size: var(--text-md); color: #DCE2EB; }
.pv-feature .icon { width: 16px; height: 16px; color: var(--brand-300); }
.device-stack { position: relative; height: 320px; z-index: 1; }
.device-laptop { position: absolute; width: 100%; bottom: 0; background: #0A1F3B; border: 1px solid rgba(255,255,255,0.08); border-radius: 8px 8px 4px 4px; box-shadow: var(--shadow-xl); }
.device-laptop::after { content: ''; position: absolute; bottom: -10px; left: -16px; right: -16px; height: 10px; background: linear-gradient(180deg,#232934 0%,#141821 100%); border-radius: 0 0 8px 8px; }
.device-laptop-screen { background: var(--gray-50); margin: 8px; height: 200px; border-radius: 4px; padding: 10px; overflow: hidden; }
.device-laptop-mock-row { height: 12px; background: var(--gray-200); border-radius: 2px; margin-bottom: 6px; }
.device-laptop-mock-row.short { width: 60%; }
.device-laptop-mock-row.brand { background: var(--brand-300); width: 30%; }
.device-phone { position: absolute; right: 32px; bottom: -8px; width: 110px; height: 220px; background: #0A1F3B; border: 2px solid rgba(255,255,255,0.10); border-radius: 16px; padding: 4px; box-shadow: var(--shadow-xl); z-index: 2; }
.device-phone-screen { background: var(--gray-50); border-radius: 12px; height: 100%; padding: 8px; overflow: hidden; font-size: 8px; }
.device-phone-screen .top { height: 14px; background: var(--brand-500); border-radius: 4px; margin-bottom: 6px; }
/* Reports ------------------------------------------------------ */
.reports-grid { display: grid; grid-template-columns: 1.05fr 1fr; gap: 64px; align-items: center; margin-top: 48px; }
.report-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 18px; }
.report-tabs { display: flex; gap: 4px; }
.report-tab { padding: 4px 10px; font-size: 11px; color: var(--fg-muted); border-radius: var(--radius-sm); cursor: pointer; }
.report-tab.active { background: var(--gray-100); color: var(--gray-900); }
.chart { position: relative; height: 200px; margin: 8px 0 0; }
.chart svg { width: 100%; height: 100%; }
.chart-stats { display: grid; grid-template-columns: repeat(3,1fr); gap: 12px; border-top: 1px solid var(--border-subtle); padding-top: 18px; margin-top: 8px; }
.chart-stat-val small { font-size: var(--text-xs); color: var(--success-500); margin-left: 4px; font-weight: 500; }
/* Security ----------------------------------------------------- */
.roles-table { margin-top: 32px; background: var(--gray-0); border: 1px solid var(--border-default); border-radius: var(--radius-lg); overflow: hidden; }
.roles-row { display: grid; grid-template-columns: 180px 1fr 80px 80px 80px 80px; align-items: center; padding: 14px 24px; border-bottom: 1px solid var(--border-subtle); font-size: var(--text-sm); }
.roles-row:last-child { border-bottom: none; }
.roles-row.head { background: var(--gray-50); color: var(--fg-muted); font-size: 12px; font-weight: 500; }
.role-check { text-align: center; }
.role-check .icon { width: 16px; height: 16px; color: var(--success-500); display: inline-block; }
.role-check.no .icon { color: var(--gray-300); }
/* Pricing ------------------------------------------------------ */
.price-card.featured { border-color: var(--brand-500); box-shadow: 0 0 0 4px rgba(37,99,172,0.08), var(--shadow-md); position: relative; }
.price-card.featured::before { content: '推荐'; position: absolute; top: -1px; right: 24px; background: var(--brand-500); color: #fff; padding: 4px 12px; border-radius: 0 0 var(--radius-sm) var(--radius-sm); font-size: 11px; font-weight: 500; letter-spacing: 0.06em; }
.price-amount { display: flex; align-items: baseline; gap: 4px; margin-bottom: 8px; }
.price-amount .currency { font-size: 18px; color: var(--gray-700); font-weight: 500; }
.price-amount .num { font-size: 42px; font-weight: 700; color: var(--brand-900); font-variant-numeric: tabular-nums; line-height: 1; }
.price-amount .unit { font-size: 14px; color: var(--fg-muted); margin-left: 4px; }
.price-card.custom .num { font-size: 32px; }
/* FAQ ---------------------------------------------------------- */
.faq-q { display: flex; justify-content: space-between; align-items: center; padding: 20px 24px; cursor: pointer; font-size: var(--text-lg); font-weight: 500; color: var(--brand-900); list-style: none; }
.faq-q::-webkit-details-marker { display: none; }
.faq-q .icon { width: 18px; height: 18px; color: var(--fg-muted); transition: transform var(--duration-base) var(--ease-standard); }
details[open] .faq-q .icon { transform: rotate(45deg); }
/* CTA banner --------------------------------------------------- */
.cta-banner {
background: radial-gradient(800px 360px at 80% 30%,rgba(37,99,172,0.40),transparent 60%), linear-gradient(135deg,#0A1F3B 0%,#15407D 100%);
color: #fff; border-radius: var(--radius-xl); padding: 64px 56px;
display: grid; grid-template-columns: 1.4fr 1fr; gap: 48px; align-items: center; margin: 96px 0;
}
.cta-banner h2 { font-size: 36px; font-weight: 600; letter-spacing: var(--tracking-cn-display); margin: 0 0 16px; line-height: 1.25; }
.cta-banner p { font-size: var(--text-lg); color: #ADC9EA; margin: 0; line-height: 1.6; }
.cta-banner .btn-primary { background: #fff; color: var(--brand-700); }
.cta-banner .btn-primary:hover { background: #DCE2EB; }
.cta-banner .btn-secondary { background: transparent; color: #fff; border-color: rgba(255,255,255,0.30); }
.cta-banner .btn-secondary:hover { background: rgba(255,255,255,0.10); }
/* Responsive --------------------------------------------------- */
@media (max-width: 1024px) {
.hero-inner, .workflow-grid, .reports-grid, .platforms-visual, .cta-banner { grid-template-columns: 1fr; }
.module-card.feature-card { grid-column: span 2; }
.hero h1 { font-size: 40px; }
.roles-row { grid-template-columns: 140px 1fr repeat(4, 60px); padding: 12px 16px; }
}
</style>
<!-- ====================== HERO ====================== -->
<section class="hero">
<div class="container hero-inner">
<div>
<div class="d-inline-flex items-center gap-8 bg-0 border rounded-pill fs-sm text-gray-7 mb-24" style="padding: 6px 14px 6px 8px;">
<span class="badge badge-brand">v1.6</span>
<span>新增多仓库联动盘点 ·</span>
<span class="text-brand fw-5">查看更新</span>
</div>
<h1>从入库到出库,<br/><em>一套系统</em>管到底。</h1>
<p class="lead">岩美酒库管理系统,为酒行与酒店设计的库存、审核、财务一体化平台。审核驱动业务流,库存与账款自动同步,五端无缝接入。</p>
<div class="d-flex gap-12 mb-28">
<a href="/app/" class="btn btn-primary btn-lg">免费试用 30 天<i data-lucide="arrow-right" class="icon"></i></a>
<a href="/app/" class="btn btn-secondary btn-lg"><i data-lucide="play-circle" class="icon"></i>观看演示</a>
</div>
<div class="d-flex items-center gap-18 text-muted fs-sm">
<div class="hero-mini-item d-flex items-center gap-6"><i data-lucide="check" class="icon"></i>无需安装</div>
<div class="hero-mini-item d-flex items-center gap-6"><i data-lucide="check" class="icon"></i>30 天免费</div>
<div class="hero-mini-item d-flex items-center gap-6"><i data-lucide="check" class="icon"></i>支持私有部署</div>
</div>
</div>
<div class="pos-relative">
<div class="preview-shell">
<div class="preview-titlebar">
<div class="preview-dots"><span></span><span></span><span></span></div>
<div class="preview-url">yanmei.app/inventory</div>
</div>
<div class="mock-app">
<aside class="mock-sidebar">
<div class="mock-sidebar-brand">金樽酒行 · S001</div>
<div class="mock-nav-item"><i data-lucide="package-plus" class="icon"></i>入库管理</div>
<div class="mock-nav-item"><i data-lucide="package-minus" class="icon"></i>出库管理</div>
<div class="mock-nav-item active"><i data-lucide="package" class="icon"></i>库存管理</div>
<div class="mock-nav-item"><i data-lucide="wallet" class="icon"></i>财务管理</div>
<div class="mock-nav-item"><i data-lucide="truck" class="icon"></i>往来单位</div>
<div class="mock-nav-item"><i data-lucide="database" class="icon"></i>基础数据</div>
<div class="mock-nav-item"><i data-lucide="settings" class="icon"></i>系统设置</div>
</aside>
<main class="mock-main">
<div class="mock-topbar">
<div class="mock-tabs">
<div class="mock-tab active">库存列表</div>
<div class="mock-tab">库存盘点</div>
<div class="mock-tab">库存流水</div>
</div>
<div class="mock-actions">
<div class="mock-mini-btn"><i data-lucide="download" class="icon"></i>导出</div>
<div class="mock-mini-btn primary"><i data-lucide="clipboard-list" class="icon"></i>新建盘点</div>
</div>
</div>
<div class="mock-stats">
<div class="mock-stat">
<div class="mock-stat-label">库存总量</div>
<div class="mock-stat-value">2,816 <span style="font-size:12px;color:var(--fg-muted);font-weight:400">瓶</span></div>
<div class="mock-stat-delta up">↑ 4.2% 较上月</div>
</div>
<div class="mock-stat">
<div class="mock-stat-label">库存金额</div>
<div class="mock-stat-value">¥486,290</div>
<div class="mock-stat-delta up">↑ 2.8% 较上月</div>
</div>
<div class="mock-stat">
<div class="mock-stat-label">本月入库</div>
<div class="mock-stat-value">128 <span style="font-size:12px;color:var(--fg-muted);font-weight:400">单</span></div>
<div class="mock-stat-delta up">↑ 12 单</div>
</div>
<div class="mock-stat">
<div class="mock-stat-label">预警 SKU</div>
<div class="mock-stat-value" style="color:var(--warning-500)">7</div>
<div class="mock-stat-delta down">↓ 库存不足</div>
</div>
</div>
<div class="mock-table-card">
<div class="mock-table-head">
<div>SKU</div><div>商品名称</div><div>仓库</div><div>库存</div><div>金额</div><div>状态</div>
</div>
<div class="mock-table-row"><div class="sku">WT-501-006</div><div>茅台飞天 53° · 500ml×6</div><div>A 仓</div><div>148</div><div>¥298,400</div><div><span class="mock-pill ok">充足</span></div></div>
<div class="mock-table-row"><div class="sku">XJ-468-001</div><div>五粮液第八代 52° · 500ml</div><div>A 仓</div><div>92</div><div>¥92,920</div><div><span class="mock-pill ok">充足</span></div></div>
<div class="mock-table-row"><div class="sku">XJ-330-024</div><div>剑南春水晶剑 52° · 500ml×6</div><div>B 仓</div><div style="color:var(--warning-700);font-weight:500">12</div><div>¥4,560</div><div><span class="mock-pill warn">偏低</span></div></div>
<div class="mock-table-row"><div class="sku">PJ-750-012</div><div>拉菲传奇波尔多 · 750ml</div><div>A 仓</div><div>64</div><div>¥18,560</div><div><span class="mock-pill ok">充足</span></div></div>
<div class="mock-table-row"><div class="sku">PJ-700-008</div><div>轩尼诗 VSOP · 700ml</div><div>B 仓</div><div>38</div><div>¥22,420</div><div><span class="mock-pill pending">入库中</span></div></div>
</div>
</main>
</div>
</div>
<div class="hero-toast">
<div class="hero-toast-icon"><i data-lucide="check-circle-2" class="icon"></i></div>
<div>
<div class="fw-6 fs-sm text-gray-9 mb-2">入库单已审批</div>
<div class="fs-sm text-muted" style="line-height:1.45">RK20260523000007 库存 +24 瓶<br/>生成应付 ¥48,400</div>
</div>
</div>
</div>
</div>
</section>
<!-- ====================== TRUST ====================== -->
<section class="trust">
<div class="container">
<div class="trust-grid">
<div class="fs-sm text-muted">服务各类酒水经营场所</div>
<div><div class="trust-stat-num">1,280<sup>+</sup></div><div class="fs-xs text-muted mt-4">酒行 / 酒店门店</div></div>
<div><div class="trust-stat-num">8.4<sup>%</sup></div><div class="fs-xs text-muted mt-4">平均损耗下降</div></div>
<div><div class="trust-stat-num">99.9<sup>%</sup></div><div class="fs-xs text-muted mt-4">系统可用性</div></div>
<div><div class="trust-stat-num">5<sup>端</sup></div><div class="fs-xs text-muted mt-4">Web / iOS / Android / Win / Mac</div></div>
</div>
</div>
</section>
<!-- ====================== MODULES ====================== -->
<section class="section" id="modules">
<div class="container">
<p class="eyebrow">核心模块</p>
<h2 class="section-title">七大模块,覆盖酒水经营全流程</h2>
<p class="section-sub">从商品建档到入库出库、从财务结算到数据导入,岩美一站式承载日常运营。</p>
<div class="grid-3 gap-16 mt-48">
<div class="module-card feature-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="package-plus" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">入库管理</h3>
<p class="fs-sm lh-16 text-muted m-0">审核驱动的入库流程。草稿、提交、审批、库存更新、应付账款生成 — 一气呵成。</p>
<ul>
<li><i data-lucide="check" class="icon"></i>多商品行明细录入,自动算金额</li>
<li><i data-lucide="check" class="icon"></i>审批通过即同步库存与应付账款</li>
<li><i data-lucide="check" class="icon"></i>支持单据打印、商品标签打印</li>
<li><i data-lucide="check" class="icon"></i>批次号追踪,生产日期可追溯</li>
</ul>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="package-minus" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">出库管理</h3>
<p class="fs-sm lh-16 text-muted m-0">出库前自动校验库存,审批通过即扣减库存并生成应收。库存不足,单据无法通过。</p>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="package" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">库存管理</h3>
<p class="fs-sm lh-16 text-muted m-0">实时查询每个 SKU 的库存数量、所在仓库、批次。支持全仓盘点与库存流水。</p>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="wallet" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">财务管理</h3>
<p class="fs-sm lh-16 text-muted m-0">审批同步生成应付应收,月度汇总。结清一键完成,可按往来单位筛选导出。</p>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="truck" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">往来单位</h3>
<p class="fs-sm lh-16 text-muted m-0">供应商与客户统一档案管理。卡号、初始余额、联系信息集中维护。</p>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="database" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">基础数据</h3>
<p class="fs-sm lh-16 text-muted m-0">商品名称、系列、规格三级字典,单品数量配置。先建字典,后录单据。</p>
</div>
<div class="module-card card p-24 transition">
<div class="icon-box-lg bg-brand-50 text-brand mb-16"><i data-lucide="settings" class="icon-md"></i></div>
<h3 class="fs-xl fw-6 text-brand-900 m-0 mb-6 ls-1">系统设置</h3>
<p class="fs-sm lh-16 text-muted m-0">用户与权限、多仓库、编号规则、参数与数据导入 — 自助配置,无需开发。</p>
</div>
</div>
</div>
</section>
<!-- ====================== WORKFLOW ====================== -->
<section class="section bg-25" id="workflow">
<div class="container">
<p class="eyebrow">业务流程</p>
<h2 class="section-title">审核驱动业务流,每一笔交易都可追溯</h2>
<p class="section-sub">从单据录入到库存变动、账款生成,每一步都有清晰状态与经办人记录。</p>
<div class="workflow-grid">
<div>
<h3 class="fs-2xl fw-6 text-brand-900 m-0 mb-12">一张入库单的完整生命周期</h3>
<div class="d-flex flex-col gap-14 mt-24">
<div class="wf-step"><div class="wf-num">1</div><div><h4 class="mt-4 mb-4 fs-md fw-6 text-gray-9">录入草稿</h4><p class="m-0 fs-sm text-muted lh-15">选择仓库、供应商、入库日期,逐行录入商品明细。系统自动算金额,可随时保存草稿。</p></div></div>
<div class="wf-step"><div class="wf-num">2</div><div><h4 class="mt-4 mb-4 fs-md fw-6 text-gray-9">提交审核</h4><p class="m-0 fs-sm text-muted lh-15">确认无误后提交。单据进入「待审核」,此时不可再编辑,保证数据完整。</p></div></div>
<div class="wf-step active"><div class="wf-num">3</div><div><h4 class="mt-4 mb-4 fs-md fw-6 text-gray-9">审批通过</h4><p class="m-0 fs-sm text-muted lh-15">操作员及以上权限审批。通过后库存自动 +N,同时生成一笔应付账款,账款挂在对应供应商名下。</p></div></div>
<div class="wf-step"><div class="wf-num">4</div><div><h4 class="mt-4 mb-4 fs-md fw-6 text-gray-9">结清账款</h4><p class="m-0 fs-sm text-muted lh-15">财务结算时一键「结清」,财务记录由「未结清」变为「已结清」。账目清晰,按月汇总。</p></div></div>
</div>
</div>
<div class="flow-vis">
<div class="flow-doc">
<div class="flow-doc-head">
<div class="flow-doc-id">RK20260523000007</div>
<div class="flow-doc-status approved">已审批</div>
</div>
<div class="flow-row head"><div>商品</div><div>规格</div><div>数量</div><div>金额</div></div>
<div class="flow-row"><div>茅台飞天</div><div>500ml×6</div><div>4</div><div>¥8,000</div></div>
<div class="flow-row"><div>五粮液</div><div>500ml</div><div>20</div><div>¥18,400</div></div>
<div class="flow-row"><div>剑南春</div><div>500ml×6</div><div>2</div><div>¥4,200</div></div>
<div class="flow-row"><div>拉菲传奇</div><div>750ml</div><div>10</div><div>¥17,800</div></div>
<div class="flow-row foot"><div>合计</div><div></div><div>36</div><div>¥48,400</div></div>
</div>
<div class="flow-arrow"><i data-lucide="arrow-down" class="icon"></i></div>
<div class="flow-effects">
<div class="flow-effect"><div class="flow-effect-label"><i data-lucide="check-circle-2" class="icon"></i>库存更新</div><div class="flow-effect-val">+36 瓶</div></div>
<div class="flow-effect"><div class="flow-effect-label"><i data-lucide="check-circle-2" class="icon"></i>应付账款</div><div class="flow-effect-val">¥48,400</div></div>
</div>
</div>
</div>
</div>
</section>
<!-- ====================== PLATFORMS ====================== -->
<section class="section" id="platforms">
<div class="container">
<p class="eyebrow">多端覆盖</p>
<h2 class="section-title">一个账号,五端同步</h2>
<p class="section-sub">办公室开台账,仓库扫码盘点,老板出差查看实时报表。同一份数据,任意终端访问。</p>
<div class="grid-5 gap-12 mt-48">
<div class="platform-card card py-24 px-16 text-center transition"><i data-lucide="globe" class="icon-xl text-brand mx-auto mb-12"></i><h4 class="m-0 mb-4 fs-md fw-6 text-brand-900">Web</h4><p class="m-0 fs-xs text-muted">主流浏览器,无需安装</p></div>
<div class="platform-card card py-24 px-16 text-center transition"><i data-lucide="monitor" class="icon-xl text-brand mx-auto mb-12"></i><h4 class="m-0 mb-4 fs-md fw-6 text-brand-900">Windows</h4><p class="m-0 fs-xs text-muted">桌面客户端</p></div>
<div class="platform-card card py-24 px-16 text-center transition"><i data-lucide="laptop" class="icon-xl text-brand mx-auto mb-12"></i><h4 class="m-0 mb-4 fs-md fw-6 text-brand-900">macOS</h4><p class="m-0 fs-xs text-muted">原生应用</p></div>
<div class="platform-card card py-24 px-16 text-center transition"><i data-lucide="smartphone" class="icon-xl text-brand mx-auto mb-12"></i><h4 class="m-0 mb-4 fs-md fw-6 text-brand-900">iOS</h4><p class="m-0 fs-xs text-muted">iPhone / iPad</p></div>
<div class="platform-card card py-24 px-16 text-center transition"><i data-lucide="tablet-smartphone" class="icon-xl text-brand mx-auto mb-12"></i><h4 class="m-0 mb-4 fs-md fw-6 text-brand-900">Android</h4><p class="m-0 fs-xs text-muted">手机 / 平板</p></div>
</div>
<div class="platforms-visual">
<div class="pv-text">
<h3>仓库里也能用得顺手</h3>
<p>移动端扫码即查库存、入库、出库,断网也能继续工作,恢复网络后自动同步。</p>
<div class="d-flex flex-col gap-10">
<div class="pv-feature"><i data-lucide="scan-line" class="icon"></i>扫码即查商品 · 二维码标签</div>
<div class="pv-feature"><i data-lucide="wifi-off" class="icon"></i>离线缓存,断网继续作业</div>
<div class="pv-feature"><i data-lucide="bell" class="icon"></i>实时推送审批与库存预警</div>
<div class="pv-feature"><i data-lucide="printer" class="icon"></i>蓝牙连接打印商品标签</div>
</div>
</div>
<div class="device-stack">
<div class="device-laptop">
<div class="device-laptop-screen">
<div class="device-laptop-mock-row brand"></div>
<div class="device-laptop-mock-row short"></div>
<div class="device-laptop-mock-row"></div>
<div class="device-laptop-mock-row short"></div>
<div class="device-laptop-mock-row"></div>
<div class="device-laptop-mock-row short"></div>
<div class="device-laptop-mock-row"></div>
<div class="device-laptop-mock-row short"></div>
<div class="d-flex gap-6 mt-10">
<div style="flex:1;height:50px;background:var(--gray-100);border-radius:3px"></div>
<div style="flex:1;height:50px;background:var(--brand-100);border-radius:3px"></div>
<div style="flex:1;height:50px;background:var(--gray-100);border-radius:3px"></div>
</div>
</div>
</div>
<div class="device-phone">
<div class="device-phone-screen">
<div class="top"></div>
<div style="height:8px;background:var(--gray-200);border-radius:2px;margin-bottom:4px;width:70%"></div>
<div style="height:8px;background:var(--gray-200);border-radius:2px;margin-bottom:8px;width:50%"></div>
<div style="background:var(--gray-0);border:1px solid var(--gray-200);border-radius:4px;padding:6px;margin-bottom:4px"><div style="height:6px;background:var(--brand-300);border-radius:1px;width:60%;margin-bottom:3px"></div><div style="height:4px;background:var(--gray-200);border-radius:1px;width:80%"></div></div>
<div style="background:var(--gray-0);border:1px solid var(--gray-200);border-radius:4px;padding:6px;margin-bottom:4px"><div style="height:6px;background:var(--brand-300);border-radius:1px;width:50%;margin-bottom:3px"></div><div style="height:4px;background:var(--gray-200);border-radius:1px;width:70%"></div></div>
<div style="background:var(--gray-0);border:1px solid var(--gray-200);border-radius:4px;padding:6px;margin-bottom:4px"><div style="height:6px;background:var(--brand-300);border-radius:1px;width:55%;margin-bottom:3px"></div><div style="height:4px;background:var(--gray-200);border-radius:1px;width:75%"></div></div>
<div style="position:absolute;bottom:8px;left:8px;right:8px;background:var(--brand-500);height:22px;border-radius:4px;display:grid;place-items:center"><div style="height:6px;background:rgba(255,255,255,0.9);border-radius:1px;width:50%"></div></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ====================== REPORTS ====================== -->
<section class="section bg-25" id="reports">
<div class="container">
<p class="eyebrow">数据洞察</p>
<h2 class="section-title">把每一瓶酒的进出,转成可分析的数据</h2>
<p class="section-sub">报表自动生成,可按日、按月、按往来单位维度切换。导出 Excel 一键完成。</p>
<div class="reports-grid">
<div class="card p-24 shadow-sm">
<div class="report-head">
<div><h4 class="fs-md fw-6 text-gray-9 m-0">本月财务流水</h4><p class="fs-xs text-muted mt-2 m-0">2026 年 5 月 · 应付与应收对比</p></div>
<div class="report-tabs">
<div class="report-tab">日</div>
<div class="report-tab active">月</div>
<div class="report-tab">季</div>
</div>
</div>
<div class="chart">
<svg viewBox="0 0 600 200" preserveAspectRatio="none">
<line x1="0" y1="50" x2="600" y2="50" stroke="#ECEFF4" stroke-width="1"/>
<line x1="0" y1="100" x2="600" y2="100" stroke="#ECEFF4" stroke-width="1"/>
<line x1="0" y1="150" x2="600" y2="150" stroke="#ECEFF4" stroke-width="1"/>
<path d="M 20 140 L 80 110 L 140 130 L 200 90 L 260 100 L 320 70 L 380 85 L 440 50 L 500 65 L 560 40 L 560 190 L 20 190 Z" fill="rgba(37,99,172,0.10)" />
<path d="M 20 140 L 80 110 L 140 130 L 200 90 L 260 100 L 320 70 L 380 85 L 440 50 L 500 65 L 560 40" fill="none" stroke="#2563AC" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 20 160 L 80 140 L 140 145 L 200 120 L 260 130 L 320 105 L 380 115 L 440 90 L 500 95 L 560 70 L 560 190 L 20 190 Z" fill="rgba(139,35,49,0.08)" />
<path d="M 20 160 L 80 140 L 140 145 L 200 120 L 260 130 L 320 105 L 380 115 L 440 90 L 500 95 L 560 70" fill="none" stroke="#8B2331" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="560" cy="40" r="4" fill="#2563AC" />
<circle cx="560" cy="40" r="8" fill="rgba(37,99,172,0.20)" />
<circle cx="560" cy="70" r="4" fill="#8B2331" />
</svg>
<div class="d-flex gap-16 fs-xs text-muted mt-8">
<span class="d-flex items-center gap-4"><span style="width:8px;height:8px;background:var(--brand-500);border-radius:50%"></span>应付账款</span>
<span class="d-flex items-center gap-4"><span style="width:8px;height:8px;background:var(--accent-500);border-radius:50%"></span>应收账款</span>
</div>
</div>
<div class="chart-stats">
<div><div class="fs-xs text-muted mb-4">本月应付</div><div class="fs-lg fw-6 text-brand-900 tabular">¥248,600<small>↑ 12%</small></div></div>
<div><div class="fs-xs text-muted mb-4">本月应收</div><div class="fs-lg fw-6 text-brand-900 tabular">¥182,400<small>↑ 8%</small></div></div>
<div><div class="fs-xs text-muted mb-4">已结清率</div><div class="fs-lg fw-6 text-brand-900 tabular">86.4%<small>↑ 4%</small></div></div>
</div>
</div>
<div class="d-flex flex-col gap-24">
<div class="d-grid gap-16" style="grid-template-columns:36px 1fr">
<div class="icon-box-md bg-brand-50 text-brand"><i data-lucide="bar-chart-3" class="icon-md"></i></div>
<div><h4 class="m-0 mb-4 fs-lg fw-6 text-brand-900">财务汇总自动生成</h4><p class="m-0 fs-sm text-muted lh-16">每月应付应收按往来单位、按时间维度自动汇总。无需手工统计,月底一键导出。</p></div>
</div>
<div class="d-grid gap-16" style="grid-template-columns:36px 1fr">
<div class="icon-box-md bg-brand-50 text-brand"><i data-lucide="trending-down" class="icon-md"></i></div>
<div><h4 class="m-0 mb-4 fs-lg fw-6 text-brand-900">损耗趋势可见</h4><p class="m-0 fs-sm text-muted lh-16">每次盘点的账实差异自动累计为损耗数据,结合周转率帮你发现异常 SKU。</p></div>
</div>
<div class="d-grid gap-16" style="grid-template-columns:36px 1fr">
<div class="icon-box-md bg-brand-50 text-brand"><i data-lucide="file-spreadsheet" class="icon-md"></i></div>
<div><h4 class="m-0 mb-4 fs-lg fw-6 text-brand-900">Excel 进出自由</h4><p class="m-0 fs-sm text-muted lh-16">历史数据可批量导入,月度报表可一键导出。与会计、税务系统无缝衔接。</p></div>
</div>
<div class="d-grid gap-16" style="grid-template-columns:36px 1fr">
<div class="icon-box-md bg-brand-50 text-brand"><i data-lucide="alert-triangle" class="icon-md"></i></div>
<div><h4 class="m-0 mb-4 fs-lg fw-6 text-brand-900">库存预警实时提醒</h4><p class="m-0 fs-sm text-muted lh-16">SKU 库存低于阈值,系统在 Web 与移动端同步推送。永远不会错过补货时机。</p></div>
</div>
</div>
</div>
</div>
</section>
<!-- ====================== SECURITY ====================== -->
<section class="section bg-25">
<div class="container">
<p class="eyebrow">安全与权限</p>
<h2 class="section-title">企业级权限控制,操作可追溯</h2>
<p class="section-sub">四级角色细分权限,每一次单据操作都有经办人记录。数据备份与审批留痕,按合规要求设计。</p>
<div class="grid-4 gap-16 mt-48">
<div class="card p-24"><i data-lucide="users" class="icon-lg text-brand mb-14"></i><h4 class="fs-lg fw-6 text-brand-900 m-0 mb-6">四级角色</h4><p class="m-0 fs-sm text-muted lh-15">超级管理员、管理员、操作员、只读。按岗位分配,最小权限原则。</p></div>
<div class="card p-24"><i data-lucide="file-clock" class="icon-lg text-brand mb-14"></i><h4 class="fs-lg fw-6 text-brand-900 m-0 mb-6">操作审计</h4><p class="m-0 fs-sm text-muted lh-15">谁、什么时候、做了什么 — 每一笔单据都有经办人与时间戳。</p></div>
<div class="card p-24"><i data-lucide="shield-check" class="icon-lg text-brand mb-14"></i><h4 class="fs-lg fw-6 text-brand-900 m-0 mb-6">审批留痕</h4><p class="m-0 fs-sm text-muted lh-15">审批不可撤销,单据从草稿到结清的每一步状态完整保留。</p></div>
<div class="card p-24"><i data-lucide="hard-drive" class="icon-lg text-brand mb-14"></i><h4 class="fs-lg fw-6 text-brand-900 m-0 mb-6">每日备份</h4><p class="m-0 fs-sm text-muted lh-15">云端每日自动备份,支持私有部署。数据始终在你的控制下。</p></div>
</div>
<div class="roles-table">
<div class="roles-row head">
<div>角色</div><div>说明</div>
<div class="text-center">查看</div><div class="text-center">录入</div>
<div class="text-center">审批</div><div class="text-center">设置</div>
</div>
<div class="roles-row"><div class="fw-6 text-brand-900">超级管理员</div><div class="text-muted fs-sm">系统最高权限,含数据清空</div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div></div>
<div class="roles-row"><div class="fw-6 text-brand-900">管理员</div><div class="text-muted fs-sm">门店管理人员,含用户与门店设置</div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div></div>
<div class="roles-row"><div class="fw-6 text-brand-900">操作员</div><div class="text-muted fs-sm">日常录入与审核单据</div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check no"><i data-lucide="minus" class="icon"></i></div></div>
<div class="roles-row"><div class="fw-6 text-brand-900">只读</div><div class="text-muted fs-sm">仅查看,不可修改任何数据</div><div class="role-check"><i data-lucide="check" class="icon"></i></div><div class="role-check no"><i data-lucide="minus" class="icon"></i></div><div class="role-check no"><i data-lucide="minus" class="icon"></i></div><div class="role-check no"><i data-lucide="minus" class="icon"></i></div></div>
</div>
</div>
</section>
<!-- ====================== PRICING ====================== -->
<section class="section" id="pricing">
<div class="container">
<p class="eyebrow">价格</p>
<h2 class="section-title">按门店付费,明码标价</h2>
<p class="section-sub">所有方案均含全功能、五端同步、无限单据、技术支持。仅在用户数、门店数、部署方式上区分。</p>
<div class="grid-3 gap-16 mt-48">
<div class="card d-flex flex-col" style="padding:32px 28px">
<div class="fs-sm text-muted fw-5 mb-4">入门方案</div>
<div class="fs-2xl fw-6 text-brand-900 mb-16">试用版</div>
<div class="price-amount"><span class="currency">¥</span><span class="num">0</span><span class="unit">/ 30 天</span></div>
<div class="fs-sm text-muted mb-24">体验完整功能,无需绑卡</div>
<ul class="price-features d-flex flex-col gap-10 p-0 m-0 mb-32" style="list-style:none">
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>单门店 · 最多 3 用户</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>全部模块开放</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>Web 端 + 移动端</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>邮件技术支持</li>
</ul>
<a href="/app/" class="btn btn-secondary w-full justify-center mt-auto">免费开通</a>
</div>
<div class="price-card featured card d-flex flex-col" style="padding:32px 28px">
<div class="fs-sm text-muted fw-5 mb-4">标准方案</div>
<div class="fs-2xl fw-6 text-brand-900 mb-16">单店版</div>
<div class="price-amount"><span class="currency">¥</span><span class="num">299</span><span class="unit">/ 月</span></div>
<div class="fs-sm text-muted mb-24">年付折扣 ¥2,988 / 年(约省 ¥600</div>
<ul class="price-features d-flex flex-col gap-10 p-0 m-0 mb-32" style="list-style:none">
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>单门店 · 最多 10 用户</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>全部模块 + 五端同步</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>无限单据、无限商品</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>云端每日备份</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>工作日 9-18 点支持</li>
</ul>
<a href="/app/" class="btn btn-primary w-full justify-center mt-auto">购买</a>
</div>
<div class="price-card custom card d-flex flex-col" style="padding:32px 28px">
<div class="fs-sm text-muted fw-5 mb-4">企业方案</div>
<div class="fs-2xl fw-6 text-brand-900 mb-16">连锁版</div>
<div class="price-amount"><span class="num">定制</span></div>
<div class="fs-sm text-muted mb-24">多门店连锁,含私有部署</div>
<ul class="price-features d-flex flex-col gap-10 p-0 m-0 mb-32" style="list-style:none">
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>多门店 · 总部数据汇总</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>不限用户数</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>支持私有部署 / 内网</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>SSO 单点登录</li>
<li class="d-flex items-start gap-8 fs-sm text-gray-7"><i data-lucide="check" class="icon-sm text-brand flex-shrink-0 mt-2"></i>7×24 专属客户经理</li>
</ul>
<a href="/app/" class="btn btn-secondary w-full justify-center mt-auto">联系销售</a>
</div>
</div>
</div>
</section>
<!-- ====================== FAQ ====================== -->
<section class="section bg-25" id="faq">
<div class="container">
<p class="eyebrow">常见问题</p>
<h2 class="section-title">购买前常见的问题</h2>
<div class="mt-48" style="max-width:880px">
<details class="card mb-12 overflow-hidden" open>
<summary class="faq-q">支持哪些操作系统和设备?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">系统支持 Windows、macOS 桌面客户端,iOS 与 Android 移动 App,以及主流浏览器的 Web 版本。同一账号可在五端同步使用,数据实时更新。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">没有网络时还能操作吗?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">网络中断时,系统会自动切换到离线模式,展示上次加载的缓存数据。库存查询与单据录入可继续,恢复网络后自动同步至云端。审批与生成账款类操作需要网络。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">能否从原有 Excel / 旧系统迁移数据?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">可以。「系统设置 → 数据导入」支持往来单位、商品名称/系列/规格、库存等数据的批量 Excel 导入,按提供的模板填写即可。导入过程中会显示成功条数与失败原因。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">审批通过后发现错误,怎么办?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">审批通过后操作不可撤销。如发现错误,可由具备权限的用户新建反向调整单据(红冲入库 / 红冲出库)来修正库存与账款。这样可以保留完整的审计链。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">数据安全如何保障?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">云端版采用每日自动备份策略,数据传输全程 HTTPS 加密。企业版支持私有部署,数据存放在你自己的服务器,岩美不接触任何业务数据。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">可以试用多长时间?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">标准版提供 30 天免费试用,无需绑定支付方式。试用期可使用全部功能、五端访问。30 天后可继续按月或按年付费,已录入的数据完整保留。</div>
</details>
<details class="card mb-12 overflow-hidden">
<summary class="faq-q">只读账号能做什么?<i data-lucide="plus" class="icon"></i></summary>
<div class="fs-md text-muted lh-17" style="padding:0 24px 22px">只读账号可查看全部数据,包括单据、库存、财务、报表,并可导出 Excel。但不能新建、修改、审批、删除任何数据。适合财务、税务、审计岗位的查阅需求。</div>
</details>
</div>
</div>
</section>
<!-- ====================== CTA ====================== -->
<section>
<div class="container">
<div class="cta-banner">
<div>
<h2>用一杯咖啡的时间,<br/>看看你的酒库到底有多少瓶。</h2>
<p>30 天免费试用,无需绑卡。任何时间可取消,已录入数据保留 90 天。</p>
</div>
<div class="d-flex flex-col gap-12 items-start">
<a href="/app/" class="btn btn-primary btn-lg">立即开通试用<i data-lucide="arrow-right" class="icon"></i></a>
<a href="/app/" class="btn btn-secondary btn-lg"><i data-lucide="phone" class="icon"></i>预约 1 对 1 演示</a>
<span class="fs-sm" style="color:#99A3B3">销售热线 {{ site.support.phone }} · 工作日 9:00-18:00</span>
</div>
</div>
</div>
</section>
+1671
View File
File diff suppressed because it is too large Load Diff
+12
View File
@@ -0,0 +1,12 @@
{
"name": "jiu-marketing",
"private": true,
"scripts": {
"build": "eleventy",
"dev": "eleventy --serve --port=3000"
},
"devDependencies": {
"@11ty/eleventy": "^3.0.0",
"markdown-it": "^14.2.0"
}
}