0e91768da4
- 图标 sprite 新增 i-apple / i-android(simple-icons 品牌图标,填充式)与 i-tablet-smartphone(lucide),先登记原型 icons.js 再同步官网 icons.njk - 下载页 macOS/Android/iOS 卡片及当前平台检测卡换用专属图标(原为 copy/phone-call/funnel 错配) - 检测卡高度加倍:icbox 44→84、标题 16→22、内边距加大,新增引导行与版本徽章, 描述文字由 muted 灰改为正文色;窄屏按钮转全宽 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
291 lines
15 KiB
Plaintext
291 lines
15 KiB
Plaintext
---
|
||
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 88px; 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:720px; margin:-56px auto 0; position:relative; z-index:2;}
|
||
.detect .card{display:flex; align-items:center; gap:26px; box-shadow:var(--sh-2); padding:34px 36px;}
|
||
.detect .icbox{width:84px; height:84px; border-radius:var(--r-lg); flex:none; display:flex; align-items:center; justify-content:center;}
|
||
.detect .icbox .ic{width:42px; height:42px;}
|
||
.detect .detect-info{flex:1; min-width:0;}
|
||
.detect .detect-eyebrow{color:var(--primary); font-size:var(--fs-xs); font-weight:800; letter-spacing:1px; margin-bottom:5px;}
|
||
.detect .detect-title{display:flex; align-items:center; gap:10px; margin-bottom:7px; flex-wrap:wrap;}
|
||
.detect b{color:var(--heading); font-size:22px; font-weight:800; line-height:1.3;}
|
||
.detect .detect-ver{font-family:var(--font-mono); font-size:var(--fs-xs); font-weight:700; color:var(--primary); background:var(--info-soft); padding:3px 10px; border-radius:var(--r-pill);}
|
||
.detect .detect-desc{display:block; color:var(--text); font-size:15px; line-height:1.7;}
|
||
.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; padding:26px 22px; gap:18px;} .detect .btn{margin-left:0; width:100%;} .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 class="detect-info">
|
||
<div class="detect-eyebrow">已识别你的设备 · 为你推荐</div>
|
||
<div class="detect-title">
|
||
<b id="detect-name">Web 版</b>
|
||
<span class="detect-ver version-badge">v{{ changelog[0].version }}</span>
|
||
</div>
|
||
<span class="detect-desc" id="detect-desc">浏览器直接访问,功能完整,无需下载安装。</span>
|
||
</div>
|
||
<a class="btn primary lg" 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 / 11(64 位)</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-apple"/></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-android"/></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-tablet-smartphone"/></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-tablet-smartphone', android:'#i-android', windows:'#i-ic63', macos:'#i-apple' };
|
||
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 { '&': '&', '<': '<', '>': '>', '"': '"' }[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>
|