Files
jiu/web/download.njk
T
wangjia d256e7ac85 feat(site): 官网全新重建(App 真相源风格)+ 四档套餐 + 在线购买流
- tokens.css/site.css 逐值对齐原型设计系统,icons 雪碧图,零外链;首页/下载/帮助/法务全站重皮肤,真实截图
- 注册与登录在官网内完成(写 shared_preferences_web 兼容 localStorage,不再跳 App)
- 价格区四档:免费/标准 299/高级 599/定制;登录后标准/高级按钮变「购买 / 续费」
- 新增 /checkout/(套餐+月付年付切换)与 /license/result/(支付回跳轮询到账)
- 登录页支持 ?next= 站内回跳;二维码措辞改「扫码看详情可分享」
- 下载页构建期真实下载链接+运行时 release 刷新;旧 features 页/死 CSS/dist 产物清理

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 20:40:21 +08:00

283 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layout: base.njk
title: 下载
description: 下载岩美酒库管理系统客户端:Windows、macOS、Android、iOS 与免安装 Web 版。
pageStyle: |
.dl-hero{background:var(--mk-hero-grad); color:var(--on-accent); padding:64px 0 72px; text-align:center;}
.dl-hero h1{color:var(--on-accent); font-size:var(--mk-h2); font-weight:800;}
.dl-hero p{color:var(--on-accent-faint); margin:12px auto 0; max-width:36em;}
.detect{max-width:640px; margin:-40px auto 0; position:relative; z-index:2;}
.detect .card{display:flex; align-items:center; gap:18px; box-shadow:var(--sh-2); padding:20px 22px;}
.detect .icbox{width:44px; height:44px; border-radius:var(--r-lg); flex:none; display:flex; align-items:center; justify-content:center;}
.detect .icbox .ic{width:22px; height:22px;}
.detect b{display:block; color:var(--heading); font-size:16px;}
.detect span{color:var(--muted); font-size:var(--fs-sm);}
.detect .btn{margin-left:auto; flex:none;}
.dl-grid{display:grid; grid-template-columns:repeat(5,1fr); gap:14px; margin-top:46px;}
.dl-card{background:var(--surface); border:1px solid var(--border); border-radius:var(--r-lg); padding:20px 18px; display:flex; flex-direction:column; text-align:center;}
.dl-card.detected{border-color:var(--primary); box-shadow:var(--sh-1);}
.dl-card .icbox{width:38px; height:38px; border-radius:var(--r-md); margin:0 auto 12px; display:flex; align-items:center; justify-content:center;}
.dl-card h3{font-size:15px; font-weight:700; margin-bottom:4px;}
.dl-card .req{color:var(--faint); font-size:var(--fs-xs); margin-bottom:14px;}
.dl-card .dl-status{font-size:var(--fs-xs); color:var(--success); margin-bottom:8px;}
.dl-card .dl-status.soon{color:var(--warn);}
.dl-card .btn{margin-top:auto; width:100%;}
.btn.disabled{opacity:.55; pointer-events:none; background:var(--bg); border:1px solid var(--border); color:var(--muted);}
/* 更新日志时间线 */
.changelog{max-width:820px; margin:0 auto;}
.changelog-entry{display:grid; grid-template-columns:150px 1fr; gap:20px; padding:22px 0; border-bottom:1px solid var(--border-subtle);}
.changelog-version{font-family:var(--font-mono); font-weight:700; color:var(--heading); font-size:16px;}
.changelog-date{color:var(--faint); font-size:var(--fs-sm); margin-top:3px;}
.changelog-tag{display:inline-block; margin-top:8px; background:var(--info-soft); color:var(--primary); font-size:var(--fs-xs); font-weight:700; padding:2px 9px; border-radius:var(--r-pill);}
.changelog-cat-label{display:flex; align-items:center; gap:7px; font-size:var(--fs-sm); font-weight:700; color:var(--heading); margin:10px 0 6px;}
.changelog-cat-label .dot{width:7px; height:7px; border-radius:50%;}
.dot-feature{background:var(--primary);} .dot-improve{background:var(--success);} .dot-fix{background:var(--warn);}
.changelog-body ul{margin:0; padding-left:20px; color:var(--muted); font-size:14px; line-height:1.8;}
.changelog-intro{color:var(--muted); font-size:14px; margin:0 0 4px;}
@media (max-width:900px){ .dl-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:600px){ .dl-grid{grid-template-columns:1fr;} .detect .card{flex-wrap:wrap;} .changelog-entry{grid-template-columns:1fr;} }
---
<header class="dl-hero">
<div class="container">
<h1>下载岩美酒库</h1>
<p>当前版本 <b class="version-badge">v{{ changelog[0].version }}</b> · 一个账号五端同步 · 客户端内置自动更新</p>
</div>
</header>
<div class="detect container">
<div class="card">
<div class="icbox ic-info" id="detect-icon"><svg class="ic"><use href="#i-ic01"/></svg></div>
<div>
<b id="detect-name">Web 版</b>
<span id="detect-desc">已自动识别你的设备,推荐以下版本。</span>
</div>
<a class="btn primary" id="detect-btn" href="{{ site.appBaseUrl }}/app/"><span>立即使用</span></a>
</div>
</div>
<section class="section">
<div class="container">
<div class="dl-grid" id="platform-grid">
<div class="dl-card" data-platform="windows">
<div class="icbox ic-info"><svg class="ic"><use href="#i-ic63"/></svg></div>
<h3>Windows</h3>
<div class="req">Win 10 / 1164 位)</div>
<div class="dl-status">✓ 安装包</div>
<a class="btn primary" id="windows-dl-btn" href="{{ site.appBaseUrl }}/downloads/jiu-windows-x64-setup.exe"><svg class="ic" style="width:15px;height:15px"><use href="#i-download"/></svg>下载</a>
</div>
<div class="dl-card" data-platform="macos">
<div class="icbox ic-info"><svg class="ic"><use href="#i-ic25"/></svg></div>
<h3>macOS</h3>
<div class="req">Apple Silicon / Intel</div>
<div class="dl-status">✓ 已签名公证</div>
<a class="btn primary" id="macos-dl-btn" href="{{ site.appBaseUrl }}/downloads/jiu-macos-x64.zip"><svg class="ic" style="width:15px;height:15px"><use href="#i-download"/></svg>下载</a>
</div>
<div class="dl-card" data-platform="web">
<div class="icbox ic-ok"><svg class="ic"><use href="#i-ic01"/></svg></div>
<h3>Web 版</h3>
<div class="req">现代浏览器均可</div>
<div class="dl-status">✓ 免安装</div>
<a class="btn primary" href="{{ site.appBaseUrl }}/app/">立即使用</a>
</div>
<div class="dl-card" data-platform="android">
<div class="icbox ic-warn"><svg class="ic"><use href="#i-ic43"/></svg></div>
<h3>Android</h3>
<div class="req">Android 6.0 及以上</div>
<div class="dl-status">✓ APK 直装</div>
<a class="btn primary" id="android-dl-btn" href="{{ site.appBaseUrl }}/downloads/jiu-android.apk"><svg class="ic" style="width:15px;height:15px"><use href="#i-download"/></svg>下载</a>
</div>
<div class="dl-card" data-platform="ios" id="ios-card">
<div class="icbox ic-wine"><svg class="ic"><use href="#i-ic22"/></svg></div>
<h3>iOS</h3>
<div class="req">iPhone / iPad</div>
<div class="dl-status soon" id="ios-status">TestFlight 内测中</div>
<a class="btn ghost disabled" id="ios-dl-btn" href="#">敬请期待</a>
</div>
</div>
<p style="text-align:center;color:var(--faint);font-size:var(--fs-sm);margin-top:18px">
桌面与移动客户端内置自动更新 · 各端详细配置见<a href="/system-requirements/">系统要求</a>
</p>
</div>
</section>
<section class="section alt" id="changelog">
<div class="container">
<div class="sec-head">
<div class="eyebrow">更新日志</div>
<h2>最近更新</h2>
<p id="changelog-count">最近 {{ changelog | length }} 个版本。</p>
</div>
<div class="changelog" id="changelog-list">
{% for entry in changelog %}
<div class="changelog-entry{% if loop.first %} current{% endif %}">
<div class="changelog-meta">
<div class="changelog-version">v{{ entry.version }}</div>
<div class="changelog-date">{{ entry.date }}</div>
{% if loop.first %}<span class="changelog-tag">当前版本</span>{% endif %}
</div>
<div class="changelog-body">
{% if entry.intro %}<p class="changelog-intro">{{ entry.intro }}</p>{% endif %}
{% for section in entry.sections %}
<div class="changelog-cat">
<div class="changelog-cat-label">
<span class="dot {% if section.type == '新功能' %}dot-feature{% elif section.type == '修复' %}dot-fix{% else %}dot-improve{% endif %}"></span>
{{ section.type }}
</div>
<ul>{% for item in section.items %}<li>{{ item }}</li>{% endfor %}</ul>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<script>
(function() {
var APP_BASE = '{{ site.appBaseUrl }}';
var SPRITE = { web:'#i-ic01', ios:'#i-ic22', android:'#i-ic43', windows:'#i-ic63', macos:'#i-ic25' };
var platforms = {
web: { name: 'Web 版', desc: '浏览器直接访问,功能完整,无需下载安装。', btnText: '立即使用 Web 版', btnHref: APP_BASE + '/app/', available: true },
ios: { name: 'iOS', desc: 'iPhone 与 iPad 通用,通过 TestFlight 安装。', btnText: '敬请期待', available: false },
android: { name: 'Android', desc: '手机与平板通用,APK 直接安装。', btnText: '下载 Android 版', btnHref: APP_BASE + '/downloads/jiu-android.apk', available: true },
windows: { name: 'Windows 桌面', desc: '原生桌面客户端,支持 Win 10/11(64 位)与本地打印。', btnText: '下载 Windows 版', btnHref: APP_BASE + '/downloads/jiu-windows-x64-setup.exe', available: true },
macos: { name: 'macOS 桌面', desc: '支持 Apple Silicon 与 Intel,解压即用。', btnText: '下载 macOS 版', btnHref: APP_BASE + '/downloads/jiu-macos-x64.zip', available: true }
};
function detectPlatform() {
var ua = navigator.userAgent;
if (/iPhone|iPad|iPod/.test(ua)) return 'ios';
if (/Android/.test(ua)) return 'android';
var platform = navigator.platform || '';
if (/Win/.test(platform) || /Win/.test(ua)) return 'windows';
if (/Mac/.test(platform) || /Mac/.test(ua)) return 'macos';
return 'web';
}
function updateDetectCard(p) {
var info = platforms[p];
var nameEl = document.getElementById('detect-name');
var descEl = document.getElementById('detect-desc');
var btnEl = document.getElementById('detect-btn');
var iconEl = document.getElementById('detect-icon');
if (nameEl) nameEl.textContent = info.name;
if (descEl) descEl.textContent = info.desc;
if (btnEl) {
if (info.available && info.btnHref && info.btnHref !== '#') {
btnEl.href = info.btnHref;
btnEl.classList.remove('disabled');
btnEl.innerHTML = '<span>' + info.btnText + '</span>';
} else if (!info.available) {
btnEl.href = '#';
btnEl.classList.add('disabled');
btnEl.innerHTML = '<span>' + info.btnText + '</span>';
}
}
if (iconEl) {
iconEl.innerHTML = '<svg class="ic"><use href="' + (SPRITE[p] || '#i-ic01') + '"/></svg>';
}
}
function highlightPlatformCard(p) {
document.querySelectorAll('#platform-grid .dl-card').forEach(function(el) {
el.classList.remove('detected');
});
var card = document.querySelector('#platform-grid [data-platform="' + p + '"]');
if (card) card.classList.add('detected');
}
function updateVersionBadges(version) {
document.querySelectorAll('.version-badge').forEach(function(el) {
el.textContent = 'v' + version;
});
}
// 用 /api/v1/public/release 的 changelog 重渲染时间线:客户端发版无需重建官网。
// 接口不可达或字段缺失时保留构建时静态时间线作 fallback。
function renderChangelog(entries) {
if (!Array.isArray(entries) || entries.length === 0) return;
var dotClass = { '新功能': 'dot-feature', '改进': 'dot-improve', '修复': 'dot-fix' };
function esc(s) {
return String(s == null ? '' : s).replace(/[&<>"]/g, function(c) {
return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c];
});
}
var html = '';
entries.forEach(function(entry, i) {
html += '<div class="changelog-entry' + (i === 0 ? ' current' : '') + '">';
html += '<div class="changelog-meta"><div class="changelog-version">v' + esc(entry.version) + '</div>';
html += '<div class="changelog-date">' + esc(entry.date) + '</div>';
if (i === 0) html += '<span class="changelog-tag">当前版本</span>';
html += '</div><div class="changelog-body">';
if (entry.intro) html += '<p class="changelog-intro">' + esc(entry.intro) + '</p>';
(entry.sections || []).forEach(function(section) {
var dot = dotClass[section.type] || 'dot-improve';
html += '<div class="changelog-cat"><div class="changelog-cat-label"><span class="dot ' + dot + '"></span>' + esc(section.type) + '</div><ul>';
(section.items || []).forEach(function(item) { html += '<li>' + esc(item) + '</li>'; });
html += '</ul></div>';
});
html += '</div></div>';
});
var list = document.getElementById('changelog-list');
if (list) list.innerHTML = html;
var count = document.getElementById('changelog-count');
if (count) count.textContent = '最近 ' + entries.length + ' 个版本。';
}
document.addEventListener('DOMContentLoaded', function() {
var detected = detectPlatform();
updateDetectCard(detected);
highlightPlatformCard(detected);
fetch(APP_BASE + '/api/v1/public/release')
.then(function(r) { return r.json(); })
.then(function(data) {
if (data && data.version) updateVersionBadges(data.version);
if (data && data.changelog) renderChangelog(data.changelog);
var urls = (data && data.download_urls) || {};
[['macos','macos-dl-btn'],['windows','windows-dl-btn'],['android','android-dl-btn']].forEach(function(pair) {
if (urls[pair[0]]) {
platforms[pair[0]].btnHref = urls[pair[0]];
var btn = document.getElementById(pair[1]);
if (btn) btn.href = urls[pair[0]];
if (detected === pair[0]) updateDetectCard(detected);
}
});
// iOS 走 TestFlight:仅当返回公开链接时激活
if (urls.ios) {
platforms.ios.available = true;
platforms.ios.btnHref = urls.ios;
platforms.ios.btnText = '通过 TestFlight 安装';
var iosStatus = document.getElementById('ios-status');
var iosBtn = document.getElementById('ios-dl-btn');
if (iosStatus) { iosStatus.className = 'dl-status'; iosStatus.textContent = '✓ 已上线'; }
if (iosBtn) {
iosBtn.className = 'btn primary';
iosBtn.href = urls.ios;
iosBtn.target = '_blank';
iosBtn.rel = 'noopener';
iosBtn.textContent = 'TestFlight 安装';
}
if (detected === 'ios') updateDetectCard(detected);
}
})
.catch(function() {
['windows-dl-btn', 'macos-dl-btn', 'android-dl-btn'].forEach(function(id) {
var btn = document.getElementById(id);
if (btn && btn.getAttribute('href') === '#') {
btn.className = 'btn ghost disabled';
btn.textContent = '暂时无法获取下载地址';
}
});
var detectBtn = document.getElementById('detect-btn');
if (detectBtn && detectBtn.getAttribute('href') === '#') {
detectBtn.classList.add('disabled');
detectBtn.innerHTML = '<span>暂时无法连接服务器</span>';
}
});
});
})();
</script>