197 lines
9.5 KiB
HTML
197 lines
9.5 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>{{.pageTitle}}</title>
|
|
<link rel="stylesheet" href="/css/style.css">
|
|
<link rel="icon" href="/img/favicon.png" type="image/png">
|
|
</head>
|
|
<body class="shad-app">
|
|
<header class="site-header">
|
|
<div class="shad-container header-inner">
|
|
<div>
|
|
<span class="eyebrow">YMhut Release Center</span>
|
|
<h1>YMhut Box 下载与模块分发中心</h1>
|
|
<p>自动识别 <code>public/downloads</code> 下的安装包,生成主程序更新、历史版本和模块化工具分发清单。</p>
|
|
</div>
|
|
<div class="header-actions">
|
|
<a class="shad-button shad-button--secondary" href="/api/update-info">更新清单</a>
|
|
<a class="shad-button shad-button--secondary" href="/api/modules">模块清单</a>
|
|
<a class="shad-button shad-button--primary" href="/admin">管理后台</a>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="shad-main">
|
|
<div class="shad-container">
|
|
<section class="summary-grid">
|
|
<article class="summary-card">
|
|
<span>自动扫描</span>
|
|
<strong>downloads</strong>
|
|
<p>无需手工维护下载卡片,刷新页面即可读取安装包并按产品分组。</p>
|
|
</article>
|
|
<article class="summary-card">
|
|
<span>兼容更新</span>
|
|
<strong>v1 + v2</strong>
|
|
<p>保留旧版 <code>update-info.json</code>,同时提供模块化清单。</p>
|
|
</article>
|
|
<article class="summary-card">
|
|
<span>校验能力</span>
|
|
<strong>SHA256</strong>
|
|
<p>服务端自动为主程序、资源包和未来模块包生成校验字段。</p>
|
|
</article>
|
|
</section>
|
|
|
|
{{if .errorMessage}}
|
|
<section class="shad-card shad-card--state shad-card--danger">
|
|
<h2>读取目录失败</h2>
|
|
<p>{{.errorMessage}}</p>
|
|
</section>
|
|
{{else if not .products}}
|
|
<section class="shad-card shad-card--state">
|
|
<h2>暂无可识别安装包</h2>
|
|
<p>请将 Windows、Android、macOS 或 Linux 安装包放入 <code>public/downloads</code>。</p>
|
|
</section>
|
|
{{else}}
|
|
<section class="section-title">
|
|
<div>
|
|
<span class="eyebrow">Packages</span>
|
|
<h2>安装包列表</h2>
|
|
</div>
|
|
<p>按产品自动分组,默认展示每个产品的最新版本。</p>
|
|
</section>
|
|
|
|
<section class="shad-grid">
|
|
{{range $productName, $versions := .products}}
|
|
{{$latestVersion := index $versions 0}}
|
|
{{$historyVersions := slice $versions 1}}
|
|
{{$meta := index $.productMeta $productName}}
|
|
{{if not $meta}}
|
|
{{$meta = $.defaultMeta}}
|
|
{{end}}
|
|
<article class="shad-card shad-product">
|
|
<div class="shad-product__head">
|
|
<div class="shad-product__icon">{{$meta.Icon | safeHTML}}</div>
|
|
<div class="shad-product__title">
|
|
<h3>{{$productName}}</h3>
|
|
<p>{{$meta.Description}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="shad-stack shad-stack--row shad-stack--wrap">
|
|
{{range $meta.Tags}}
|
|
<span class="shad-badge shad-badge--outline">{{.}}</span>
|
|
{{end}}
|
|
<span class="shad-badge shad-badge--muted">{{len $versions}} 个版本</span>
|
|
</div>
|
|
|
|
<div class="shad-panel">
|
|
<div class="shad-panel__main">
|
|
<div>
|
|
<span class="shad-muted">最新版本</span>
|
|
<strong>{{$latestVersion.Version}}</strong>
|
|
</div>
|
|
<span class="shad-badge shad-badge--subtle">{{$latestVersion.Extension}}</span>
|
|
</div>
|
|
<div class="shad-meta-grid">
|
|
<div class="shad-meta">
|
|
<span class="shad-muted">更新时间</span>
|
|
<span>{{$latestVersion.UpdateDate}}</span>
|
|
</div>
|
|
<div class="shad-meta">
|
|
<span class="shad-muted">文件大小</span>
|
|
<span>{{$latestVersion.Size}}</span>
|
|
</div>
|
|
<div class="shad-meta">
|
|
<span class="shad-muted">文件名</span>
|
|
<span class="shad-truncate">{{$latestVersion.FileName}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="shad-actions">
|
|
<a href="{{$latestVersion.DownloadPath}}" class="shad-button shad-button--primary" download>下载最新版本</a>
|
|
{{if $historyVersions}}
|
|
<button class="shad-button shad-button--secondary history-btn"
|
|
data-product-name="{{$productName}}"
|
|
data-history='{{marshalJSON $historyVersions}}'>历史版本</button>
|
|
{{end}}
|
|
</div>
|
|
</article>
|
|
{{end}}
|
|
</section>
|
|
{{end}}
|
|
</div>
|
|
</main>
|
|
|
|
<div class="shad-dialog" id="history-modal" aria-hidden="true">
|
|
<div class="shad-dialog__overlay"></div>
|
|
<div class="shad-dialog__content">
|
|
<div class="shad-dialog__header">
|
|
<h3 id="modal-title">历史版本</h3>
|
|
<button class="shad-icon-button" id="close-modal" aria-label="关闭">×</button>
|
|
</div>
|
|
<div class="shad-dialog__body">
|
|
<ul class="shad-history" id="history-list"></ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<footer class="shad-footer">
|
|
<div class="shad-container shad-footer__inner">
|
|
<span>YMhut 下载中心</span>
|
|
<span>主程序、资源包与模块包统一分发</span>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const modal = document.getElementById('history-modal');
|
|
const modalTitle = document.getElementById('modal-title');
|
|
const historyList = document.getElementById('history-list');
|
|
const closeModalBtn = document.getElementById('close-modal');
|
|
|
|
function closeHistoryModal() {
|
|
modal.classList.remove('is-open');
|
|
modal.setAttribute('aria-hidden', 'true');
|
|
document.body.style.overflow = '';
|
|
}
|
|
|
|
document.querySelectorAll('.history-btn').forEach(button => {
|
|
button.addEventListener('click', () => {
|
|
const versions = JSON.parse(button.dataset.history || '[]');
|
|
modalTitle.textContent = `${button.dataset.productName} 历史版本`;
|
|
historyList.innerHTML = versions.length ? '' : '<li class="shad-history__item"><strong>暂无历史版本</strong></li>';
|
|
versions.forEach(version => {
|
|
const item = document.createElement('li');
|
|
item.className = 'shad-history__item';
|
|
item.innerHTML = `
|
|
<div>
|
|
<strong>版本 ${version.version}</strong>
|
|
<p>${version.updateDate} · ${version.size} · ${version.extension}</p>
|
|
</div>
|
|
<a href="${version.downloadPath}" class="shad-button shad-button--secondary" download>下载</a>
|
|
`;
|
|
historyList.appendChild(item);
|
|
});
|
|
modal.classList.add('is-open');
|
|
modal.setAttribute('aria-hidden', 'false');
|
|
document.body.style.overflow = 'hidden';
|
|
});
|
|
});
|
|
|
|
closeModalBtn.addEventListener('click', closeHistoryModal);
|
|
modal.addEventListener('click', event => {
|
|
if (event.target === modal || event.target.classList.contains('shad-dialog__overlay')) {
|
|
closeHistoryModal();
|
|
}
|
|
});
|
|
document.addEventListener('keydown', event => {
|
|
if (event.key === 'Escape') closeHistoryModal();
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|