From 471b980179132060ce437703fb4d17c36888238f Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Tue, 26 May 2026 12:24:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor(web):=20=E8=90=A5=E9=94=80=E7=AB=99?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=B8=BA=20Eleventy=20SSG=EF=BC=8C=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E8=BF=81=E7=A7=BB=E8=87=B3=20Markdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 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 --- .gitignore | 4 + web/.eleventy.js | 22 + web/.eleventyignore | 6 + web/_data/changelog.js | 44 + web/_data/docs.js | 51 + web/_data/site.json | 12 + web/_data/sysreq.js | 8 + web/_includes/base.njk | 28 + web/_includes/footer.njk | 55 + web/_includes/nav.njk | 15 + web/assets/color.css | 261 ++++ web/assets/docs.css | 347 ++++++ web/assets/nav.js | 90 ++ web/assets/shared.css | 183 +++ web/assets/style.css | 459 +++++++ web/content/docs.md | 487 ++++++++ web/content/system-requirements.md | 36 + web/docs.html | 1167 ----------------- web/docs.njk | 194 +++ web/download.html | 1218 ------------------ web/download.njk | 506 ++++++++ web/index.html | 1860 ---------------------------- web/index.njk | 627 ++++++++++ web/package-lock.json | 1671 +++++++++++++++++++++++++ web/package.json | 12 + 25 files changed, 5118 insertions(+), 4245 deletions(-) create mode 100644 web/.eleventy.js create mode 100644 web/.eleventyignore create mode 100644 web/_data/changelog.js create mode 100644 web/_data/docs.js create mode 100644 web/_data/site.json create mode 100644 web/_data/sysreq.js create mode 100644 web/_includes/base.njk create mode 100644 web/_includes/footer.njk create mode 100644 web/_includes/nav.njk create mode 100644 web/assets/color.css create mode 100644 web/assets/docs.css create mode 100644 web/assets/nav.js create mode 100644 web/assets/shared.css create mode 100644 web/assets/style.css create mode 100644 web/content/docs.md create mode 100644 web/content/system-requirements.md delete mode 100644 web/docs.html create mode 100644 web/docs.njk delete mode 100644 web/download.html create mode 100644 web/download.njk delete mode 100644 web/index.html create mode 100644 web/index.njk create mode 100644 web/package-lock.json create mode 100644 web/package.json diff --git a/.gitignore b/.gitignore index d9f248e..2a8dc06 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,10 @@ client/devtools_options.yaml # Flutter 构建产物 client/build/ + +# 营销站构建产物 +web/dist/ +web/node_modules/ client/.dart_tool/ client/.flutter-plugins client/.flutter-plugins-dependencies diff --git a/web/.eleventy.js b/web/.eleventy.js new file mode 100644 index 0000000..9e7f194 --- /dev/null +++ b/web/.eleventy.js @@ -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", + }; +}; diff --git a/web/.eleventyignore b/web/.eleventyignore new file mode 100644 index 0000000..9b0e65c --- /dev/null +++ b/web/.eleventyignore @@ -0,0 +1,6 @@ +scan.html +content/ +features/approval.html +features/inventory.html +node_modules +dist diff --git a/web/_data/changelog.js b/web/_data/changelog.js new file mode 100644 index 0000000..8730072 --- /dev/null +++ b/web/_data/changelog.js @@ -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; +}; diff --git a/web/_data/docs.js b/web/_data/docs.js new file mode 100644 index 0000000..7205c58 --- /dev/null +++ b/web/_data/docs.js @@ -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 }; +}; diff --git a/web/_data/site.json b/web/_data/site.json new file mode 100644 index 0000000..9da0c12 --- /dev/null +++ b/web/_data/site.json @@ -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" +} diff --git a/web/_data/sysreq.js b/web/_data/sysreq.js new file mode 100644 index 0000000..585d869 --- /dev/null +++ b/web/_data/sysreq.js @@ -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); +}; diff --git a/web/_includes/base.njk b/web/_includes/base.njk new file mode 100644 index 0000000..dcb9b47 --- /dev/null +++ b/web/_includes/base.njk @@ -0,0 +1,28 @@ + + + + + + +{% if title %}{{ title }} · {% endif %}{{ site.name }} +{% if description %}{% endif %} + + +{% if pageExtraCss %}{% endif %} + + + + +{% if pageStyle %}{% endif %} + + + +{% include "nav.njk" %} + +{{ content | safe }} + +{% include "footer.njk" %} + + + + diff --git a/web/_includes/footer.njk b/web/_includes/footer.njk new file mode 100644 index 0000000..7edf189 --- /dev/null +++ b/web/_includes/footer.njk @@ -0,0 +1,55 @@ + diff --git a/web/_includes/nav.njk b/web/_includes/nav.njk new file mode 100644 index 0000000..5102063 --- /dev/null +++ b/web/_includes/nav.njk @@ -0,0 +1,15 @@ + diff --git a/web/assets/color.css b/web/assets/color.css new file mode 100644 index 0000000..9574df8 --- /dev/null +++ b/web/assets/color.css @@ -0,0 +1,261 @@ +/* ========================================================================= + 岩美 Design System — Foundations + Tokens for color, type, spacing, radius, shadow. + Import once at root: + ========================================================================= */ + +: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); +} diff --git a/web/assets/docs.css b/web/assets/docs.css new file mode 100644 index 0000000..3d41bca --- /dev/null +++ b/web/assets/docs.css @@ -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; } +} diff --git a/web/assets/nav.js b/web/assets/nav.js new file mode 100644 index 0000000..e68d26e --- /dev/null +++ b/web/assets/nav.js @@ -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 = + ''; + } else { + cta.innerHTML = + '登录' + + '免费试用'; + } + 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' }); + } + }); + }); + }); +})(); diff --git a/web/assets/shared.css b/web/assets/shared.css new file mode 100644 index 0000000..20e8f9f --- /dev/null +++ b/web/assets/shared.css @@ -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; } +} diff --git a/web/assets/style.css b/web/assets/style.css new file mode 100644 index 0000000..d527ed7 --- /dev/null +++ b/web/assets/style.css @@ -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:8px,gap-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 高频组合 + ---------------------------------------------------------------- */ + +/* card:bg-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); } +} diff --git a/web/content/docs.md b/web/content/docs.md new file mode 100644 index 0000000..685bc84 --- /dev/null +++ b/web/content/docs.md @@ -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 可获得响应。 diff --git a/web/content/system-requirements.md b/web/content/system-requirements.md new file mode 100644 index 0000000..bf375df --- /dev/null +++ b/web/content/system-requirements.md @@ -0,0 +1,36 @@ +## Web 版(已上线) + +| 要求 | 最低 | 推荐 | +|---|---|---| +| 浏览器 | Chrome 90 / Firefox 90 / Safari 15 / Edge 90 | 最新稳定版 | +| 网络 | 任意宽带 | 10 Mbps+ | + +## Windows(敬请期待) + +| 要求 | 版本 | +|---|---| +| 系统 | Windows 10(64 位)及以上 | +| 内存 | 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 | diff --git a/web/docs.html b/web/docs.html deleted file mode 100644 index bff373e..0000000 --- a/web/docs.html +++ /dev/null @@ -1,1167 +0,0 @@ - - - - - -文档 · 岩美酒库管理系统 - - - - - - - - - - - - - -
-
- - -
- - 手册版本 - v1.6.2 - -
-
-
- - -
- - - - - -
-
第 5 章
-

入库管理

-

- 入库管理是货物进入门店的起点。本章介绍如何录入入库单、提交审核、审批通过自动更新库存与应付账款的完整流程。所有入库操作均需审核驱动,单据状态不可跳过、不可撤销。 -

- -

5.1 入库单状态说明

-

每张入库单都在一个固定的状态流中流转。状态变化由系统记录,不可手动跳过。

- -
-
-
-
草稿
- 可编辑 -
-
-
-
待审核
- 已锁定 -
-
-
-
-
已审批
- 库存 +N · 应付生成 -
-
-
已拒绝
- 库存不变 -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
状态含义可执行操作
草稿已保存但未提交编辑、删除、提交审核
待审核已提交等待审批,不可再编辑审批通过、审批拒绝
已审批库存已增加,并生成应付账款查看详情、打印、打标签、结清
已拒绝审批不通过,库存与账款不变查看详情
- -
- -
-
审批通过不可撤销
-

「已审批」状态的单据无法回退到「草稿」或「待审核」。如发现错误,请由具备权限的用户新建反向调整单据(红冲入库)进行修正,以保留完整审计链。

-
-
- -

5.2 新建入库单

-

新建入库单的入口在「入库管理 → 入库审核」标签页,点击右上角新建入库审核单按钮即可打开录入面板。

- -
    -
  1. 点击左侧「入库管理」,切换到 入库审核 标签页。
  2. -
  3. 点击右上角 新建入库审核单 按钮,弹出录入面板。
  4. -
  5. 填写表头信息(见下方字段说明)。
  6. -
  7. 在商品明细区逐行录入商品。点击 添加商品 增加新行,行末 删除 移除。
  8. -
  9. 完成后可保存草稿(继续修改)或保存并提交审核(进入待审核)。
  10. -
- -

表头字段

-
-
- 仓库 - 必填 - 货物入库的目标仓库。系统默认选中设置中的「默认仓库」。 -
-
- 供应商 - 必填 - 供货的往来单位。需提前在「往来单位 → 供应商」中维护。 -
-
- 入库日期 - 必填 - 默认为当天,可修改为历史日期(不能晚于今天)。 -
-
- 备注 - 选填 - 本批次入库的说明,最多 200 字符。 -
-
- -

商品明细字段

-
-
- 商品名称 - 必填 - 从「基础数据 → 商品名称」字典中选择,支持模糊搜索。 -
-
- 系列 - 必填 - 商品所属的系列或品牌线,如「飞天系列」。 -
-
- 规格 - 必填 - 包装规格,如 500ml×6 -
-
- 生产日期 - 必填 - 点击日历图标选择,用于批次追溯与过期预警。 -
-
- 批次号 - 选填 - 用于后续追踪、出库时按批次先进先出。 -
-
- 数量 · 单价 - 必填 - 入库数量与进货单价,系统自动计算金额 = 数量 × 单价。 -
-
- -
- -
-
小技巧:复制上一行
-

从 v1.6.2 起,明细行右侧出现 复制 按钮,可快速复制上一行的商品 / 规格 / 单价,连续录入同系列商品更快。

-
-
- -

5.4 审批入库单

-

具有操作员及以上权限的用户均可审批。审批通过后,系统会自动完成两件事:

-
    -
  1. 将所有商品按数量加入对应仓库的库存;
  2. -
  3. 按供应商生成一笔应付账款,金额等于入库单合计。
  4. -
- -

审批接口示例

-

若需通过 API 触发审批,使用如下请求:

-
POST /api/v1/stockin/{id}/approve -Content-Type: application/json -Authorization: Bearer {token} - -{ - "decision": "approve", // approve | reject - "operator": "李建国", - "remark": "已核对数量与单价" -}
- -

审批成功后返回:

-
{ - "ok": true, - "stockin_no": "RK20260523000007", - "status": "approved", - "effects": { - "inventory_delta": 36, - "payable_id": "AP20260523000012", - "payable_amount": 48400.00 - } -}
- -
- -
-
审批前请核对数量与单价
-

审批一旦通过即不可撤销,库存与应付账款将立即变动。如确实需要修正,唯一的合法路径是新建反向调整单(红冲入库),原始单据将完整保留以供审计。

-
-
- -

5.7 打印商品标签

-

审批通过的入库单,可批量打印商品标签。标签内容包括:

-
    -
  • 商品名称、编码、系列、规格
  • -
  • 批次号、生产日期
  • -
  • 酒行名称、地址、联系电话
  • -
  • 商品二维码(扫码可访问公开信息页)
  • -
- -

操作步骤:

-
    -
  1. 在入库单列表中找到对应行,点击 打标签 按钮。
  2. -
  3. 弹出对话框列出本次入库的所有商品,默认全部勾选。
  4. -
  5. 勾选需打印的商品(可批量取消),点击 打印选中
  6. -
  7. 系统依次将每张标签发送给已连接的标签打印机。
  8. -
- -
- -
-
支持的标签打印机
-

已验证支持佳博 GP-1124T、芯烨 XP-365B、汉印 N31。蓝牙打印机需先在系统设置 → 外设管理中配对。完整型号见 硬件支持文档

-
-
- - - - - -
- - -
-
- - - -
- - - - - - - - diff --git a/web/docs.njk b/web/docs.njk new file mode 100644 index 0000000..8a481f0 --- /dev/null +++ b/web/docs.njk @@ -0,0 +1,194 @@ +--- +layout: base.njk +title: 使用手册 +description: 岩美酒库管理系统使用手册,覆盖入库、出库、库存、财务等全功能操作说明。 +pageExtraCss: /assets/docs.css +--- + + +
+
+ + + + +
+ + 版本 + v{{ changelog[0].version }} +
+
+
+ + +
+ + + + + +
+ {% for chapter in docs.chapters %} +
+

{{ chapter.num }}. {{ chapter.title }}

+ {{ chapter.html | safe }} +
+ {% endfor %} + +
+ + +
+
+ + + + +
+ + diff --git a/web/download.html b/web/download.html deleted file mode 100644 index 7c2d996..0000000 --- a/web/download.html +++ /dev/null @@ -1,1218 +0,0 @@ - - - - - -下载 · 岩美酒库管理系统 - - - - - - - - - - - - - - - - -
-
-

支持的平台

-

所有版本功能一致,数据云端实时同步。

- - -
- -
-
-
- v1.6.2 · x64 -
-

Windows

-

适合办公室、收银台日常使用。支持小票机、标签机直连打印。

-
-
-
系统要求
-
Windows 10+
-
-
-
安装包大小
-
86.4 MB
-
-
- - -
- - -
-
-
- v1.6.2 · Universal -
-

macOS

-

通用版本,原生支持 Apple Silicon 与 Intel 芯片,无需切换。

-
-
-
系统要求
-
macOS 12+
-
-
-
安装包大小
-
92.1 MB
-
-
- - -
- - -
-
-
- 无需安装 -
-

Web 版

-

浏览器直接访问,无需下载。功能与桌面端一致,适合临时使用。

-
-
-
支持浏览器
-
Chrome 110+
-
-
-
同步
-
实时云端
-
-
- -
- 推荐 Chrome · Edge · Safari 15+ -
-
-
- - -
- -
-
-
- v1.6.2 -
-

iOS

-

iPhone 与 iPad 通用版本。支持扫码盘点、离线缓存、推送通知。

-
-
-
系统要求
-
iOS 15+
-
-
-
App 大小
-
48.2 MB
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- 扫码或选择应用商店 - - App Store - - - - 下载 .ipa (企业证书) - - -
-
-
- - -
-
-
- v1.6.2 -
-

Android

-

支持手机与平板,可通过四大应用商店或官网直接安装 APK。

-
-
-
系统要求
-
Android 9+
-
-
-
App 大小
-
42.8 MB
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-
-
- - -
-
-

系统要求

-

- 在以下环境中均经过测试与验证。低于最低要求的环境可能影响功能可用性。 -

- -
-
-
平台
-
最低要求
-
推荐配置
-
状态
-
-
-
Windows
-
Win 10 · 4GB RAM · 1GB 存储
-
Win 11 · 8GB RAM · SSD
-
已验证
-
-
-
macOS
-
macOS 12 · 4GB RAM
-
macOS 14+ · M1/M2 芯片
-
已验证
-
-
-
iOS
-
iOS 15 · iPhone 8 及以上
-
iOS 17+ · iPhone 12+
-
已验证
-
-
-
Android
-
Android 9 · 3GB RAM
-
Android 13+ · 6GB RAM
-
已验证
-
-
-
Web
-
Chrome 110 · Edge 110 · Safari 15
-
最新版 Chrome / Edge
-
已验证
-
-
- -
- -
- 硬件外设支持 · 打印机:USB / 网络 ESC/POS · 标签机:佳博、芯烨、汉印 · 扫码枪:USB / 蓝牙 HID 模式。完整外设兼容列表参见文档 · 硬件支持。 -
-
-
-
- - -
-
-

版本更新日志

-

- 每月一次小版本,每季度一次大更新。完整变更见 GitHub Releases。 -

- -
- -
-
-
...
-
-
- 当前版本 -
-
-

加载中...

-
-
新功能
-
    -
  • 「库存盘点」支持跨仓库联动盘点,一次盘完多仓数据
  • -
  • 新增「只读账号」可独立配置导出权限
  • -
  • 商品标签支持自定义二维码内容与门店 logo 水印
  • -
-
-
-
体验改进
-
    -
  • 入库单明细行支持复制上一行,连续录入更快
  • -
  • 财务列表新增「往来单位余额」一列
  • -
  • 移动端扫码识别速度提升约 30%
  • -
-
-
-
问题修复
-
    -
  • 修复 macOS 14.4 下打印对话框偶发卡死
  • -
  • 修复数据导入时空行被计入失败计数
  • -
-
-
-
- - -
-
-
v1.6.0
-
2026-04-02
-
-
-

财务模块大幅升级

-
-
新功能
-
    -
  • 财务管理新增「应付应收对账单」模块,按月按往来单位汇总
  • -
  • 支持「部分结清」与「批量结清」操作
  • -
  • 报表新增损耗趋势分析
  • -
-
-
-
体验改进
-
    -
  • 侧边栏支持收起与图标导航模式
  • -
  • 商品字典三级联动(名称/系列/规格)下拉响应更顺滑
  • -
-
-
-
- - -
-
-
v1.5.4
-
2026-03-12
-
-
-

稳定性更新

-
-
问题修复
-
    -
  • 修复连续高频提交单据时的偶发重复编号问题
  • -
  • 修复 Windows 7 系统下中文输入法弹出的兼容问题
  • -
  • 提升弱网环境下数据同步的可靠性
  • -
-
-
-
- - -
-
-
v1.5.0
-
2026-02-08
-
-
-

引入移动端 App

-
-
新功能
-
    -
  • 正式发布 iOS 与 Android 移动端 App
  • -
  • 支持蓝牙扫码枪与蓝牙标签打印
  • -
  • 离线缓存机制:断网时仍可查询库存与录入单据
  • -
-
-
-
-
- -
- 查看完整变更历史 -
-
-
- - -
-
-
-
- BETA · 内测通道 -
-

抢先体验下一个版本

-

v1.7 内测包含智能补货建议、AI 单据识别、批次过期预警等新特性。Beta 渠道独立部署,不影响正式环境数据。

-
-
- - 申请加入 Beta - - 名额限定,需企业账号审批通过 -
-
-
- - - - - - - - diff --git a/web/download.njk b/web/download.njk new file mode 100644 index 0000000..782e1d9 --- /dev/null +++ b/web/download.njk @@ -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; } + } +--- + + + + + +
+
+

支持的平台

+

Web 版现已可用,其余平台正在开发中。

+ +
+ +
+
+

Web 版

+

浏览器直接访问,功能完整,无需安装,支持 PC 与平板。

+ ✓ 已上线 + + 立即使用 + +
+ + +
+
+

Windows

+

原生桌面客户端,支持离线模式与本地打印。

+ 敬请期待 + + 即将推出 + +
+ + +
+
+

macOS

+

支持 Apple Silicon 与 Intel 芯片,通用版本。

+ 敬请期待 + + 即将推出 + +
+ + +
+
+

iOS

+

iPhone 与 iPad 通用,支持扫码与推送通知。

+ 敬请期待 + + 即将推出 + +
+ + +
+
+

Android

+

手机与平板通用,支持主流应用商店及 APK 安装。

+ 敬请期待 + + 即将推出 + +
+
+
+
+ + +
+
+

系统要求

+

在以下环境中均经过测试与验证。

+
+ {{ sysreq | safe }} +
+
+
+ + +
+
+

版本更新日志

+

最近 {{ changelog | length }} 个版本。

+ +
+ {% for entry in changelog %} +
+
+
v{{ entry.version }}
+
{{ entry.date }}
+ {% if loop.first %}当前版本{% endif %} +
+
+ {% if entry.intro %} +

{{ entry.intro }}

+ {% endif %} + {% for section in entry.sections %} +
+
+ {% if section.type == "新功能" %} + 新功能 + {% elif section.type == "改进" %} + 改进 + {% elif section.type == "修复" %} + 问题修复 + {% else %} + {{ section.type }} + {% endif %} +
+
    + {% for item in section.items %} +
  • {{ item }}
  • + {% endfor %} +
+
+ {% endfor %} +
+
+ {% endfor %} +
+
+
+ + diff --git a/web/index.html b/web/index.html deleted file mode 100644 index d6e9b51..0000000 --- a/web/index.html +++ /dev/null @@ -1,1860 +0,0 @@ - - - - - - -岩美酒库管理系统 — 为酒行与酒店设计的库存管理平台 - - - - - - - - - - - - - -
-
-
-
- v1.6 - 新增多仓库联动盘点 · - 查看更新 -
-

从入库到出库,
一套系统管到底。

-

- 岩美酒库管理系统,为酒行与酒店设计的库存、审核、财务一体化平台。审核驱动业务流,库存与账款自动同步,五端无缝接入。 -

- -
-
无需安装
-
30 天免费
-
支持私有部署
-
-
- -
-
-
-
-
yanmei.app/inventory
-
-
- -
-
-
-
库存列表
-
库存盘点
-
库存流水
-
-
-
导出
-
新建盘点
-
-
- -
-
-
库存总量
-
2,816
-
↑ 4.2% 较上月
-
-
-
库存金额
-
¥486,290
-
↑ 2.8% 较上月
-
-
-
本月入库
-
128
-
↑ 12 单
-
-
-
预警 SKU
-
7
-
↓ 库存不足
-
-
- -
-
-
SKU
商品名称
仓库
库存
金额
状态
-
-
-
WT-501-006
-
茅台飞天 53° · 500ml×6
-
A 仓
-
148
-
¥298,400
-
充足
-
-
-
XJ-468-001
-
五粮液第八代 52° · 500ml
-
A 仓
-
92
-
¥92,920
-
充足
-
-
-
XJ-330-024
-
剑南春水晶剑 52° · 500ml×6
-
B 仓
-
12
-
¥4,560
-
偏低
-
-
-
PJ-750-012
-
拉菲传奇波尔多 · 750ml
-
A 仓
-
64
-
¥18,560
-
充足
-
-
-
PJ-700-008
-
轩尼诗 VSOP · 700ml
-
B 仓
-
38
-
¥22,420
-
入库中
-
-
-
-
-
- -
-
- -
-
-
入库单已审批
-
RK20260523000007 库存 +24 瓶
生成应付 ¥48,400
-
-
-
-
-
- - -
-
-
-
服务各类酒水经营场所
-
-
1,280+
-
酒行 / 酒店门店
-
-
-
8.4%
-
平均损耗下降
-
-
-
99.9%
-
系统可用性
-
-
-
5
-
Web / iOS / Android / Win / Mac
-
-
-
-
- - -
-
-

核心模块

-

七大模块,覆盖酒水经营全流程

-

- 从商品建档到入库出库、从财务结算到数据导入,岩美一站式承载日常运营。 -

- -
-
-
-

入库管理

-

审核驱动的入库流程。草稿、提交、审批、库存更新、应付账款生成 — 一气呵成。

-
    -
  • 多商品行明细录入,自动算金额
  • -
  • 审批通过即同步库存与应付账款
  • -
  • 支持单据打印、商品标签打印
  • -
  • 批次号追踪,生产日期可追溯
  • -
-
- -
-
-

出库管理

-

出库前自动校验库存,审批通过即扣减库存并生成应收。库存不足,单据无法通过。

-
- -
-
-

库存管理

-

实时查询每个 SKU 的库存数量、所在仓库、批次。支持全仓盘点与库存流水。

-
- -
-
-

财务管理

-

审批同步生成应付应收,月度汇总。结清一键完成,可按往来单位筛选导出。

-
- -
-
-

往来单位

-

供应商与客户统一档案管理。卡号、初始余额、联系信息集中维护。

-
- -
-
-

基础数据

-

商品名称、系列、规格三级字典,单品数量配置。先建字典,后录单据。

-
- -
-
-

系统设置

-

用户与权限、多仓库、编号规则、参数与数据导入 — 自助配置,无需开发。

-
-
-
-
- - -
-
-

业务流程

-

审核驱动业务流,每一笔交易都可追溯

-

- 从单据录入到库存变动、账款生成,每一步都有清晰状态与经办人记录。 -

- -
-
-

一张入库单的完整生命周期

-
-
-
1
-
-

录入草稿

-

选择仓库、供应商、入库日期,逐行录入商品明细。系统自动算金额,可随时保存草稿。

-
-
-
-
2
-
-

提交审核

-

确认无误后提交。单据进入「待审核」,此时不可再编辑,保证数据完整。

-
-
-
-
3
-
-

审批通过

-

操作员及以上权限审批。通过后库存自动 +N,同时生成一笔应付账款,账款挂在对应供应商名下。

-
-
-
-
4
-
-

结清账款

-

财务结算时一键「结清」,财务记录由「未结清」变为「已结清」。账目清晰,按月汇总。

-
-
-
-
- -
-
-
-
RK20260523000007
-
已审批
-
-
-
商品
规格
数量
金额
-
-
-
茅台飞天
500ml×6
4
¥8,000
-
-
-
五粮液
500ml
20
¥18,400
-
-
-
剑南春
500ml×6
2
¥4,200
-
-
-
拉菲传奇
750ml
10
¥17,800
-
-
-
合计
36
¥48,400
-
-
- -
- -
-
-
- 库存更新 -
-
+36 瓶
-
-
-
- 应付账款 -
-
¥48,400
-
-
-
-
-
-
- - -
-
-

多端覆盖

-

一个账号,五端同步

-

- 办公室开台账,仓库扫码盘点,老板出差查看实时报表。同一份数据,任意终端访问。 -

- -
-
- -

Web

-

主流浏览器,无需安装

-
-
- -

Windows

-

桌面客户端

-
-
- -

macOS

-

原生应用

-
-
- -

iOS

-

iPhone / iPad

-
-
- -

Android

-

手机 / 平板

-
-
- -
-
-

仓库里也能用得顺手

-

移动端扫码即查库存、入库、出库,断网也能继续工作,恢复网络后自动同步。

-
-
扫码即查商品 · 二维码标签
-
离线缓存,断网继续作业
-
实时推送审批与库存预警
-
蓝牙连接打印商品标签
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-

数据洞察

-

把每一瓶酒的进出,转成可分析的数据

-

- 报表自动生成,可按日、按月、按往来单位维度切换。导出 Excel 一键完成。 -

- -
-
-
-
-

本月财务流水

-

2026 年 5 月 · 应付与应收对比

-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - -
- 应付账款 - 应收账款 -
-
- -
-
-
本月应付
-
¥248,600↑ 12%
-
-
-
本月应收
-
¥182,400↑ 8%
-
-
-
已结清率
-
86.4%↑ 4%
-
-
-
- -
-
-
-
-

财务汇总自动生成

-

每月应付应收按往来单位、按时间维度自动汇总。无需手工统计,月底一键导出。

-
-
-
-
-
-

损耗趋势可见

-

每次盘点的账实差异自动累计为损耗数据,结合周转率帮你发现异常 SKU。

-
-
-
-
-
-

Excel 进出自由

-

历史数据可批量导入,月度报表可一键导出。与会计、税务系统无缝衔接。

-
-
-
-
-
-

库存预警实时提醒

-

SKU 库存低于阈值,系统在 Web 与移动端同步推送。永远不会错过补货时机。

-
-
-
-
-
-
- - -
-
-

安全与权限

-

企业级权限控制,操作可追溯

-

- 四级角色细分权限,每一次单据操作都有经办人记录。数据备份与审批留痕,按合规要求设计。 -

- -
-
- -

四级角色

-

超级管理员、管理员、操作员、只读。按岗位分配,最小权限原则。

-
-
- -

操作审计

-

谁、什么时候、做了什么 — 每一笔单据都有经办人与时间戳。

-
-
- -

审批留痕

-

审批不可撤销,单据从草稿到结清的每一步状态完整保留。

-
-
- -

每日备份

-

云端每日自动备份,支持私有部署。数据始终在你的控制下。

-
-
- -
-
-
角色
-
说明
-
查看
-
录入
-
审批
-
设置
-
-
-
超级管理员
-
系统最高权限,含数据清空
-
-
-
-
-
-
-
管理员
-
门店管理人员,含用户与门店设置
-
-
-
-
-
-
-
操作员
-
日常录入与审核单据
-
-
-
-
-
-
-
只读
-
仅查看,不可修改任何数据
-
-
-
-
-
-
-
-
- - -
-
-

价格

-

按门店付费,明码标价

-

- 所有方案均含全功能、五端同步、无限单据、技术支持。仅在用户数、门店数、部署方式上区分。 -

- -
-
-
入门方案
-
试用版
-
- ¥ - 0 - / 30 天 -
-
体验完整功能,无需绑卡
-
    -
  • 单门店 · 最多 3 用户
  • -
  • 全部模块开放
  • -
  • Web 端 + 移动端
  • -
  • 邮件技术支持
  • -
- 免费开通 -
- - - -
-
企业方案
-
连锁版
-
- 定制 -
-
多门店连锁,含私有部署
-
    -
  • 多门店 · 总部数据汇总
  • -
  • 不限用户数
  • -
  • 支持私有部署 / 内网
  • -
  • SSO 单点登录
  • -
  • 7×24 专属客户经理
  • -
- 联系销售 -
-
-
-
- - -
-
-

常见问题

-

购买前常见的问题

- -
-
- - 支持哪些操作系统和设备? - - -
- 系统支持 Windows、macOS 桌面客户端,iOS 与 Android 移动 App,以及主流浏览器的 Web 版本。同一账号可在五端同步使用,数据实时更新。 -
-
- -
- - 没有网络时还能操作吗? - - -
- 网络中断时,系统会自动切换到离线模式,展示上次加载的缓存数据。库存查询与单据录入可继续,恢复网络后自动同步至云端。审批与生成账款类操作需要网络。 -
-
- -
- - 能否从原有 Excel / 旧系统迁移数据? - - -
- 可以。「系统设置 → 数据导入」支持往来单位、商品名称/系列/规格、库存等数据的批量 Excel 导入,按提供的模板填写即可。导入过程中会显示成功条数与失败原因。 -
-
- -
- - 审批通过后发现错误,怎么办? - - -
- 审批通过后操作不可撤销。如发现错误,可由具备权限的用户新建反向调整单据(红冲入库 / 红冲出库)来修正库存与账款。这样可以保留完整的审计链。 -
-
- -
- - 数据安全如何保障? - - -
- 云端版采用每日自动备份策略,数据传输全程 HTTPS 加密。企业版支持私有部署,数据存放在你自己的服务器,岩美不接触任何业务数据。 -
-
- -
- - 可以试用多长时间? - - -
- 标准版提供 30 天免费试用,无需绑定支付方式。试用期可使用全部功能、五端访问。30 天后可继续按月或按年付费,已录入的数据完整保留。 -
-
- -
- - 只读账号能做什么? - - -
- 只读账号可查看全部数据,包括单据、库存、财务、报表,并可导出 Excel。但不能新建、修改、审批、删除任何数据。适合财务、税务、审计岗位的查阅需求。 -
-
-
-
-
- - -
-
-
-
-

用一杯咖啡的时间,
看看你的酒库到底有多少瓶。

-

30 天免费试用,无需绑卡。任何时间可取消,已录入数据保留 90 天。

-
-
- - 立即开通试用 - - - - - 预约 1 对 1 演示 - - 销售热线 400-880-8888 · 工作日 9:00-18:00 -
-
-
-
- - - - - - - - diff --git a/web/index.njk b/web/index.njk new file mode 100644 index 0000000..f3183c7 --- /dev/null +++ b/web/index.njk @@ -0,0 +1,627 @@ +--- +layout: base.njk +title: 为酒行与酒店设计的库存管理平台 +description: 岩美酒库管理系统,审核驱动业务流,库存与账款自动同步,五端无缝接入。 +--- + + + +
+
+
+
+ v1.6 + 新增多仓库联动盘点 · + 查看更新 +
+

从入库到出库,
一套系统管到底。

+

岩美酒库管理系统,为酒行与酒店设计的库存、审核、财务一体化平台。审核驱动业务流,库存与账款自动同步,五端无缝接入。

+ +
+
无需安装
+
30 天免费
+
支持私有部署
+
+
+ +
+
+
+
+
yanmei.app/inventory
+
+
+ +
+
+
+
库存列表
+
库存盘点
+
库存流水
+
+
+
导出
+
新建盘点
+
+
+
+
+
库存总量
+
2,816
+
↑ 4.2% 较上月
+
+
+
库存金额
+
¥486,290
+
↑ 2.8% 较上月
+
+
+
本月入库
+
128
+
↑ 12 单
+
+
+
预警 SKU
+
7
+
↓ 库存不足
+
+
+
+
+
SKU
商品名称
仓库
库存
金额
状态
+
+
WT-501-006
茅台飞天 53° · 500ml×6
A 仓
148
¥298,400
充足
+
XJ-468-001
五粮液第八代 52° · 500ml
A 仓
92
¥92,920
充足
+
XJ-330-024
剑南春水晶剑 52° · 500ml×6
B 仓
12
¥4,560
偏低
+
PJ-750-012
拉菲传奇波尔多 · 750ml
A 仓
64
¥18,560
充足
+
PJ-700-008
轩尼诗 VSOP · 700ml
B 仓
38
¥22,420
入库中
+
+
+
+
+
+
+
+
入库单已审批
+
RK20260523000007 库存 +24 瓶
生成应付 ¥48,400
+
+
+
+
+
+ + +
+
+
+
服务各类酒水经营场所
+
1,280+
酒行 / 酒店门店
+
8.4%
平均损耗下降
+
99.9%
系统可用性
+
5
Web / iOS / Android / Win / Mac
+
+
+
+ + +
+
+

核心模块

+

七大模块,覆盖酒水经营全流程

+

从商品建档到入库出库、从财务结算到数据导入,岩美一站式承载日常运营。

+
+
+
+

入库管理

+

审核驱动的入库流程。草稿、提交、审批、库存更新、应付账款生成 — 一气呵成。

+
    +
  • 多商品行明细录入,自动算金额
  • +
  • 审批通过即同步库存与应付账款
  • +
  • 支持单据打印、商品标签打印
  • +
  • 批次号追踪,生产日期可追溯
  • +
+
+
+
+

出库管理

+

出库前自动校验库存,审批通过即扣减库存并生成应收。库存不足,单据无法通过。

+
+
+
+

库存管理

+

实时查询每个 SKU 的库存数量、所在仓库、批次。支持全仓盘点与库存流水。

+
+
+
+

财务管理

+

审批同步生成应付应收,月度汇总。结清一键完成,可按往来单位筛选导出。

+
+
+
+

往来单位

+

供应商与客户统一档案管理。卡号、初始余额、联系信息集中维护。

+
+
+
+

基础数据

+

商品名称、系列、规格三级字典,单品数量配置。先建字典,后录单据。

+
+
+
+

系统设置

+

用户与权限、多仓库、编号规则、参数与数据导入 — 自助配置,无需开发。

+
+
+
+
+ + +
+
+

业务流程

+

审核驱动业务流,每一笔交易都可追溯

+

从单据录入到库存变动、账款生成,每一步都有清晰状态与经办人记录。

+
+
+

一张入库单的完整生命周期

+
+
1

录入草稿

选择仓库、供应商、入库日期,逐行录入商品明细。系统自动算金额,可随时保存草稿。

+
2

提交审核

确认无误后提交。单据进入「待审核」,此时不可再编辑,保证数据完整。

+
3

审批通过

操作员及以上权限审批。通过后库存自动 +N,同时生成一笔应付账款,账款挂在对应供应商名下。

+
4

结清账款

财务结算时一键「结清」,财务记录由「未结清」变为「已结清」。账目清晰,按月汇总。

+
+
+
+
+
+
RK20260523000007
+
已审批
+
+
商品
规格
数量
金额
+
茅台飞天
500ml×6
4
¥8,000
+
五粮液
500ml
20
¥18,400
+
剑南春
500ml×6
2
¥4,200
+
拉菲传奇
750ml
10
¥17,800
+
合计
36
¥48,400
+
+
+
+
库存更新
+36 瓶
+
应付账款
¥48,400
+
+
+
+
+
+ + +
+
+

多端覆盖

+

一个账号,五端同步

+

办公室开台账,仓库扫码盘点,老板出差查看实时报表。同一份数据,任意终端访问。

+
+

Web

主流浏览器,无需安装

+

Windows

桌面客户端

+

macOS

原生应用

+

iOS

iPhone / iPad

+

Android

手机 / 平板

+
+
+
+

仓库里也能用得顺手

+

移动端扫码即查库存、入库、出库,断网也能继续工作,恢复网络后自动同步。

+
+
扫码即查商品 · 二维码标签
+
离线缓存,断网继续作业
+
实时推送审批与库存预警
+
蓝牙连接打印商品标签
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+

数据洞察

+

把每一瓶酒的进出,转成可分析的数据

+

报表自动生成,可按日、按月、按往来单位维度切换。导出 Excel 一键完成。

+
+
+
+

本月财务流水

2026 年 5 月 · 应付与应收对比

+
+
+
+
+
+
+
+ + + + + + + + + + + + +
+ 应付账款 + 应收账款 +
+
+
+
本月应付
¥248,600↑ 12%
+
本月应收
¥182,400↑ 8%
+
已结清率
86.4%↑ 4%
+
+
+
+
+
+

财务汇总自动生成

每月应付应收按往来单位、按时间维度自动汇总。无需手工统计,月底一键导出。

+
+
+
+

损耗趋势可见

每次盘点的账实差异自动累计为损耗数据,结合周转率帮你发现异常 SKU。

+
+
+
+

Excel 进出自由

历史数据可批量导入,月度报表可一键导出。与会计、税务系统无缝衔接。

+
+
+
+

库存预警实时提醒

SKU 库存低于阈值,系统在 Web 与移动端同步推送。永远不会错过补货时机。

+
+
+
+
+
+ + +
+
+

安全与权限

+

企业级权限控制,操作可追溯

+

四级角色细分权限,每一次单据操作都有经办人记录。数据备份与审批留痕,按合规要求设计。

+
+

四级角色

超级管理员、管理员、操作员、只读。按岗位分配,最小权限原则。

+

操作审计

谁、什么时候、做了什么 — 每一笔单据都有经办人与时间戳。

+

审批留痕

审批不可撤销,单据从草稿到结清的每一步状态完整保留。

+

每日备份

云端每日自动备份,支持私有部署。数据始终在你的控制下。

+
+
+
+
角色
说明
+
查看
录入
+
审批
设置
+
+
超级管理员
系统最高权限,含数据清空
+
管理员
门店管理人员,含用户与门店设置
+
操作员
日常录入与审核单据
+
只读
仅查看,不可修改任何数据
+
+
+
+ + +
+
+

价格

+

按门店付费,明码标价

+

所有方案均含全功能、五端同步、无限单据、技术支持。仅在用户数、门店数、部署方式上区分。

+
+
+
入门方案
+
试用版
+
¥0/ 30 天
+
体验完整功能,无需绑卡
+
    +
  • 单门店 · 最多 3 用户
  • +
  • 全部模块开放
  • +
  • Web 端 + 移动端
  • +
  • 邮件技术支持
  • +
+ 免费开通 +
+ +
+
企业方案
+
连锁版
+
定制
+
多门店连锁,含私有部署
+
    +
  • 多门店 · 总部数据汇总
  • +
  • 不限用户数
  • +
  • 支持私有部署 / 内网
  • +
  • SSO 单点登录
  • +
  • 7×24 专属客户经理
  • +
+ 联系销售 +
+
+
+
+ + +
+
+

常见问题

+

购买前常见的问题

+
+
+ 支持哪些操作系统和设备? +
系统支持 Windows、macOS 桌面客户端,iOS 与 Android 移动 App,以及主流浏览器的 Web 版本。同一账号可在五端同步使用,数据实时更新。
+
+
+ 没有网络时还能操作吗? +
网络中断时,系统会自动切换到离线模式,展示上次加载的缓存数据。库存查询与单据录入可继续,恢复网络后自动同步至云端。审批与生成账款类操作需要网络。
+
+
+ 能否从原有 Excel / 旧系统迁移数据? +
可以。「系统设置 → 数据导入」支持往来单位、商品名称/系列/规格、库存等数据的批量 Excel 导入,按提供的模板填写即可。导入过程中会显示成功条数与失败原因。
+
+
+ 审批通过后发现错误,怎么办? +
审批通过后操作不可撤销。如发现错误,可由具备权限的用户新建反向调整单据(红冲入库 / 红冲出库)来修正库存与账款。这样可以保留完整的审计链。
+
+
+ 数据安全如何保障? +
云端版采用每日自动备份策略,数据传输全程 HTTPS 加密。企业版支持私有部署,数据存放在你自己的服务器,岩美不接触任何业务数据。
+
+
+ 可以试用多长时间? +
标准版提供 30 天免费试用,无需绑定支付方式。试用期可使用全部功能、五端访问。30 天后可继续按月或按年付费,已录入的数据完整保留。
+
+
+ 只读账号能做什么? +
只读账号可查看全部数据,包括单据、库存、财务、报表,并可导出 Excel。但不能新建、修改、审批、删除任何数据。适合财务、税务、审计岗位的查阅需求。
+
+
+
+
+ + +
+
+
+
+

用一杯咖啡的时间,
看看你的酒库到底有多少瓶。

+

30 天免费试用,无需绑卡。任何时间可取消,已录入数据保留 90 天。

+
+
+ 立即开通试用 + 预约 1 对 1 演示 + 销售热线 {{ site.support.phone }} · 工作日 9:00-18:00 +
+
+
+
diff --git a/web/package-lock.json b/web/package-lock.json new file mode 100644 index 0000000..ccb2463 --- /dev/null +++ b/web/package-lock.json @@ -0,0 +1,1671 @@ +{ + "name": "jiu-marketing", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "jiu-marketing", + "devDependencies": { + "@11ty/eleventy": "^3.0.0", + "markdown-it": "^14.2.0" + } + }, + "node_modules/@11ty/dependency-tree": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree/-/dependency-tree-4.0.2.tgz", + "integrity": "sha512-RTF6VTZHatYf7fSZBUN3RKwiUeJh5dhWV61gDPrHhQF2/gzruAkYz8yXuvGLx3w3ZBKreGrR+MfYpSVkdbdbLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1" + } + }, + "node_modules/@11ty/dependency-tree-esm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree-esm/-/dependency-tree-esm-2.0.4.tgz", + "integrity": "sha512-MYKC0Ac77ILr1HnRJalzKDlb9Z8To3kXQCltx299pUXXUFtJ1RIONtULlknknqW8cLe19DLVgmxVCtjEFm7h0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.7", + "acorn": "^8.15.0", + "dependency-graph": "^1.0.0", + "normalize-path": "^3.0.0" + } + }, + "node_modules/@11ty/eleventy": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@11ty/eleventy/-/eleventy-3.1.5.tgz", + "integrity": "sha512-hZ0g6MwZyRxCqXsPm82gIM304LraKbUz3ZmezOSjsqxttZG6cHTib3Qq8QkESJoKwnr+yX1eyfOkPC5/mEgZnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/dependency-tree": "^4.0.2", + "@11ty/dependency-tree-esm": "^2.0.4", + "@11ty/eleventy-dev-server": "^2.0.8", + "@11ty/eleventy-plugin-bundle": "^3.0.7", + "@11ty/eleventy-utils": "^2.0.7", + "@11ty/lodash-custom": "^4.17.21", + "@11ty/posthtml-urls": "^1.0.2", + "@11ty/recursive-copy": "^4.0.4", + "@sindresorhus/slugify": "^2.2.1", + "bcp-47-normalize": "^2.3.0", + "chokidar": "^3.6.0", + "debug": "^4.4.3", + "dependency-graph": "^1.0.0", + "entities": "^6.0.1", + "filesize": "^10.1.6", + "gray-matter": "^4.0.3", + "iso-639-1": "^3.1.5", + "js-yaml": "^4.1.1", + "kleur": "^4.1.5", + "liquidjs": "^10.25.0", + "luxon": "^3.7.2", + "markdown-it": "^14.1.1", + "minimist": "^1.2.8", + "moo": "0.5.2", + "node-retrieve-globals": "^6.0.1", + "nunjucks": "^3.2.4", + "picomatch": "^4.0.3", + "please-upgrade-node": "^3.2.0", + "posthtml": "^0.16.7", + "posthtml-match-helper": "^2.0.3", + "semver": "^7.7.4", + "slugify": "^1.6.8", + "tinyglobby": "^0.2.15" + }, + "bin": { + "eleventy": "cmd.cjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-dev-server": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-dev-server/-/eleventy-dev-server-2.0.8.tgz", + "integrity": "sha512-15oC5M1DQlCaOMUq4limKRYmWiGecDaGwryr7fTE/oM9Ix8siqMvWi+I8VjsfrGr+iViDvWcH/TVI6D12d93mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1", + "chokidar": "^3.6.0", + "debug": "^4.4.0", + "finalhandler": "^1.3.1", + "mime": "^3.0.0", + "minimist": "^1.2.8", + "morphdom": "^2.7.4", + "please-upgrade-node": "^3.2.0", + "send": "^1.1.0", + "ssri": "^11.0.0", + "urlpattern-polyfill": "^10.0.0", + "ws": "^8.18.1" + }, + "bin": { + "eleventy-dev-server": "cmd.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-plugin-bundle": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-bundle/-/eleventy-plugin-bundle-3.0.7.tgz", + "integrity": "sha512-QK1tRFBhQdZASnYU8GMzpTdsMMFLVAkuU0gVVILqNyp09xJJZb81kAS3AFrNrwBCsgLxTdWHJ8N64+OTTsoKkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.2", + "debug": "^4.4.0", + "posthtml-match-helper": "^2.0.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-utils": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-utils/-/eleventy-utils-2.0.7.tgz", + "integrity": "sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/lodash-custom": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@11ty/lodash-custom/-/lodash-custom-4.17.21.tgz", + "integrity": "sha512-Mqt6im1xpb1Ykn3nbcCovWXK3ggywRJa+IXIdoz4wIIK+cvozADH63lexcuPpGS/gJ6/m2JxyyXDyupkMr5DHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/posthtml-urls": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@11ty/posthtml-urls/-/posthtml-urls-1.0.3.tgz", + "integrity": "sha512-1YvhnkaNlFnnJic1rBMWmTC2adbuy+JQiBfl1Hecr1Wjjik1pQZmGyk/eC9zKX/FQv52s2Nht1Gi/UwhYqrBeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "evaluate-value": "^2.0.0", + "http-equiv-refresh": "^2.0.1", + "list-to-array": "^1.1.0", + "parse-srcset": "^1.0.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@11ty/recursive-copy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@11ty/recursive-copy/-/recursive-copy-4.0.4.tgz", + "integrity": "sha512-oI7m8pa7/IAU/3lqRU9vjBbs20iKFo7x+1K9kT3aVira6scc1X9MjBdgLCHzLJeJ7iB6wydioA+kr9/qPnvmlQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "errno": "^1.0.0", + "junk": "^3.1.0", + "minimatch": "^3.1.5", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sindresorhus/slugify": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", + "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^1.0.0", + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/transliterate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-normalize": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", + "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bcp-47": "^2.0.0", + "bcp-47-match": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz", + "integrity": "sha512-3zV5mFS1E8/1bPxt/B0xxzI1snsg3uSCIh6Zo1qKg6iMw93hzPANk9oBFzSFBFrwuVoQuE3rLoouAUfwOAj1wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm-import-transformer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/esm-import-transformer/-/esm-import-transformer-3.0.5.tgz", + "integrity": "sha512-1GKLvfuMnnpI75l8c6sHoz0L3Z872xL5akGuBudgqTDPv4Vy6f2Ec7jEMKTxlqWl/3kSvNbHELeimJtnqgYniw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/evaluate-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/evaluate-value/-/evaluate-value-2.0.0.tgz", + "integrity": "sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-equiv-refresh": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz", + "integrity": "sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/iso-639-1": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-3.1.5.tgz", + "integrity": "sha512-gXkz5+KN7HrG0Q5UGqSMO2qB9AsbEeyLP54kF1YrMsIxmu+g4BdB7rflReZTSTZGpfj8wywu6pfPBCylPIzGQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/liquidjs": { + "version": "10.27.0", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.27.0.tgz", + "integrity": "sha512-tw/OA59K7aIBlMKIrKlumr37fiZUheShVHXY8cVctWisgY1p9mc5hreOvlreoS0wTiwlWk14Ya7305c2a/Cg5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^10.0.0" + }, + "bin": { + "liquid": "bin/liquid.js", + "liquidjs": "bin/liquid.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/liquidjs" + } + }, + "node_modules/list-to-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", + "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/markdown-it": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.1", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/morphdom": { + "version": "2.7.8", + "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.8.tgz", + "integrity": "sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-retrieve-globals": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/node-retrieve-globals/-/node-retrieve-globals-6.0.1.tgz", + "integrity": "sha512-j0DeFuZ/Wg3VlklfbxUgZF/mdHMTEiEipBb3q0SpMMbHaV3AVfoUQF8UGxh1s/yjqO0TgRZd4Pi/x2yRqoQ4Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "acorn-walk": "^8.3.4", + "esm-import-transformer": "^3.0.3" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/posthtml": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.7.tgz", + "integrity": "sha512-7Hc+IvlQ7hlaIfQFZnxlRl0jnpWq2qwibORBhQYIb0QbNtuicc5ZxvKkVT71HJ4Py1wSZ/3VR1r8LfkCtoCzhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-match-helper": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.3.tgz", + "integrity": "sha512-p9oJgTdMF2dyd7WE54QI1LvpBIkNkbSiiECKezNnDVYhGhD1AaOnAkw0Uh0y5TW+OHO8iBdSqnd8Wkpb6iUqmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" + } + }, + "node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slugify": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ssri": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-11.0.0.tgz", + "integrity": "sha512-aZpUoMN/Jj2MqA4vMCeiKGnc/8SuSyHbGSBdgFbZxP8OJGF/lFkIuElzPxsN0q8TQQ+prw3P4EDfB3TBHHgfXw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..b13449d --- /dev/null +++ b/web/package.json @@ -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" + } +}