Files
jiu/web/download.html
T
wangjia 30a8e791a3 feat: 扫码商品详情页重设计 + 宣传主页 + nginx 路由完善
- public_product_screen: 1:1 复刻设计稿,新增商品介绍、批次防伪(自定义圆形印章)、完整商品参数表、门店营业时间、页脚链接
- app_theme: 完整品牌色系(brand/gray/accent/semantic)
- shop model: 新增 business_hours 字段,public 接口同步返回
- nginx: 新增 /product/ → Flutter app 扫码入口,修复 /docs /download html 后缀兼容
- web/: 新增宣传主页、功能页、文档页、扫码 HTML 及设计资源
- app_shell: 界面优化

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 18:58:04 +08:00

191 lines
9.6 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>下载 — 岩美酒库管理系统</title>
<meta name="description" content="下载岩美酒库管理系统客户端,支持 macOS 和 Windows。" />
<link rel="stylesheet" href="assets/colors_and_type.css" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@0.469.0/dist/umd/lucide.min.js"></script>
<style>
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; font-family: var(--font-sans); color: var(--fg-default); background: var(--bg-surface); -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration: none; }
.container { max-width: 1200px; margin: 0 auto; padding: 0 32px; }
.btn { display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 18px; border-radius: var(--radius-md); font-size: 14px; font-weight: 500; border: 1px solid transparent; cursor: pointer; transition: background 120ms; white-space: nowrap; text-decoration: none; }
.btn-primary { background: var(--brand-500); color: #fff; }
.btn-primary:hover { background: var(--brand-600); }
.btn-secondary { background: var(--gray-0); color: var(--brand-900); border-color: var(--border-default); }
.btn-secondary:hover { background: var(--gray-50); }
.btn-lg { height: 48px; padding: 0 24px; font-size: 15px; }
.btn-disabled { opacity: 0.5; pointer-events: none; }
.icon { width: 18px; height: 18px; }
/* NAV */
.nav { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,0.88); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border-subtle); }
.nav-inner { height: 64px; display: flex; align-items: center; justify-content: space-between; max-width: 1200px; margin: 0 auto; padding: 0 32px; }
.nav-brand { display: flex; align-items: center; gap: 10px; font-size: 18px; font-weight: 700; color: var(--brand-900); }
.nav-brand img { height: 30px; }
.nav-links { display: flex; gap: 2px; }
.nav-links a { padding: 7px 14px; border-radius: var(--radius-md); font-size: 14px; color: var(--gray-700); transition: background 120ms; }
.nav-links a:hover { background: var(--gray-100); }
.nav-cta { display: flex; gap: 10px; }
/* PAGE */
.page-hero { padding: 72px 0 56px; text-align: center; border-bottom: 1px solid var(--border-subtle); }
.eyebrow { font-size: 11px; font-weight: 600; letter-spacing: 0.12em; color: var(--brand-500); text-transform: uppercase; margin-bottom: 14px; }
.page-title { font-size: 40px; font-weight: 700; color: var(--brand-900); margin: 0 0 14px; }
.page-sub { font-size: 16px; color: var(--fg-muted); margin: 0; line-height: 1.6; }
/* LOADING / ERROR */
.state-loading { padding: 60px 0; text-align: center; color: var(--fg-muted); font-size: 14px; }
.state-error { padding: 60px 0; text-align: center; color: var(--danger-500); font-size: 14px; }
/* RELEASE */
.release-section { padding: 64px 0; }
.version-badge { display: inline-flex; align-items: center; gap: 8px; background: var(--brand-50); color: var(--brand-700); padding: 5px 14px; border-radius: var(--radius-pill); font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.build-date { font-size: 13px; color: var(--fg-muted); margin-bottom: 40px; }
.platform-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.platform-card { background: var(--gray-0); border: 1px solid var(--border-default); border-radius: 10px; padding: 28px 24px; }
.platform-card h3 { font-size: 18px; font-weight: 600; color: var(--brand-900); margin: 0 0 6px; display: flex; align-items: center; gap: 10px; }
.platform-card h3 i { width: 20px; height: 20px; color: var(--brand-500); }
.platform-card p { font-size: 13px; color: var(--fg-muted); margin: 0 0 24px; line-height: 1.6; }
.web-badge { display: inline-flex; align-items: center; gap: 6px; background: var(--success-50); color: var(--success-700); padding: 3px 10px; border-radius: var(--radius-pill); font-size: 11px; font-weight: 600; margin-bottom: 6px; }
/* CHANGELOG */
.changelog-section { padding: 0 0 64px; }
.changelog-title { font-size: 20px; font-weight: 600; color: var(--brand-900); margin: 0 0 20px; }
.changelog-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.changelog-item { display: flex; gap: 14px; background: var(--gray-0); border: 1px solid var(--border-default); border-radius: 8px; padding: 16px 20px; }
.changelog-ver { font-size: 13px; font-weight: 600; color: var(--brand-700); font-family: var(--font-mono); min-width: 60px; padding-top: 2px; }
.changelog-content { flex: 1; }
.changelog-date { font-size: 11px; color: var(--fg-subtle); margin-bottom: 6px; }
.changelog-notes { font-size: 13px; color: var(--fg-default); margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.changelog-notes li::before { content: '· '; color: var(--brand-400); }
/* FOOTER */
footer { background: var(--gray-50); border-top: 1px solid var(--border-default); padding: 40px 0; }
.footer-inner { display: flex; align-items: center; justify-content: space-between; }
.footer-brand { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--brand-900); }
.footer-brand img { height: 24px; }
.footer-copy { font-size: 12px; color: var(--fg-subtle); }
</style>
</head>
<body>
<nav class="nav">
<div class="nav-inner">
<a href="/" class="nav-brand"><img src="assets/logo-full.svg" alt="岩美" /></a>
<div class="nav-links">
<a href="/features/inventory.html">功能</a>
<a href="/docs.html">文档</a>
<a href="/download.html">下载</a>
</div>
<div class="nav-cta">
<a href="/app/" class="btn btn-primary">进入管理端 <i data-lucide="arrow-right" class="icon"></i></a>
</div>
</div>
</nav>
<div class="page-hero">
<div class="container">
<div class="eyebrow">Download</div>
<h1 class="page-title">下载岩美客户端</h1>
<p class="page-sub">支持 macOS、Windows 桌面端,以及通过浏览器直接使用的 Web 版本。</p>
</div>
</div>
<section class="release-section">
<div class="container" id="release-container">
<div class="state-loading">正在获取版本信息...</div>
</div>
</section>
<footer>
<div class="container">
<div class="footer-inner">
<div class="footer-brand"><img src="assets/logo-mark.svg" alt="岩美" /> 岩美酒库管理系统</div>
<div class="footer-copy">© 2025 岩美。保留所有权利。</div>
</div>
</div>
</footer>
<script>
lucide.createIcons();
const API_BASE = location.hostname === 'localhost' ? 'http://localhost:8080/api/v1' : '/api/v1';
function fmt(d) {
if (!d) return '—';
return d.replace(/(\d{4})-(\d{2})-(\d{2})/, '$1 年 $2 月 $3 日');
}
function renderRelease(r) {
const dl = r.download_urls || {};
const container = document.getElementById('release-container');
container.innerHTML = `
<div class="version-badge">
<i data-lucide="tag" style="width:14px;height:14px"></i>
v${r.version || '—'}
</div>
<div class="build-date">发布日期:${fmt(r.build_date)}</div>
<div class="platform-grid">
<div class="platform-card">
<h3><i data-lucide="monitor"></i> macOS</h3>
<p>适用于 Apple Silicon / Intel Mac。支持本地打印与快捷键操作。</p>
${dl.macos
? `<a href="${dl.macos}" class="btn btn-primary btn-lg"><i data-lucide="download" class="icon"></i> 下载 macOS</a>`
: `<span class="btn btn-secondary btn-lg btn-disabled"><i data-lucide="clock" class="icon"></i> 暂未发布</span>`}
</div>
<div class="platform-card">
<h3><i data-lucide="monitor"></i> Windows</h3>
<p>适用于 Windows 10 及以上版本,支持本地打印机直连。</p>
${dl.windows
? `<a href="${dl.windows}" class="btn btn-primary btn-lg"><i data-lucide="download" class="icon"></i> 下载 Windows</a>`
: `<span class="btn btn-secondary btn-lg btn-disabled"><i data-lucide="clock" class="icon"></i> 暂未发布</span>`}
</div>
<div class="platform-card">
<h3><i data-lucide="globe"></i> Web 版本</h3>
<span class="web-badge"><i data-lucide="zap" style="width:11px;height:11px"></i> 无需安装</span>
<p>直接在浏览器中使用全功能管理端,推荐 Chrome / Edge。</p>
<a href="/app/" class="btn btn-primary btn-lg"><i data-lucide="external-link" class="icon"></i> 打开 Web 版</a>
</div>
</div>
${renderChangelog(r.changelog)}
`;
lucide.createIcons();
}
function renderChangelog(list) {
if (!list || list.length === 0) return '';
const items = list.map(v => `
<li class="changelog-item">
<div class="changelog-ver">v${v.version}</div>
<div class="changelog-content">
<div class="changelog-date">${fmt(v.date)}</div>
<ul class="changelog-notes">${(v.items||[]).map(i=>`<li>${i}</li>`).join('')}</ul>
</div>
</li>
`).join('');
return `
<div class="changelog-section" style="margin-top:48px">
<h2 class="changelog-title">更新日志</h2>
<ul class="changelog-list">${items}</ul>
</div>
`;
}
fetch(`${API_BASE}/public/release`)
.then(r => r.json())
.then(renderRelease)
.catch(err => {
document.getElementById('release-container').innerHTML =
`<div class="state-error">无法获取版本信息,请稍后再试。<br/><small>${err.message}</small></div>`;
});
</script>
</body>
</html>