v0.4.1: OSS skill videos, site version footer, and mail contact.
Host ability demos on Aliyun OSS instead of Pages bundles; add patches-page version label and top-right mailto link; improve spirit bear portrait export. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
X-Content-Type-Options: nosniff
|
||||
|
||||
/index.html
|
||||
Cache-Control: public, max-age=0, must-revalidate
|
||||
|
||||
/data.json
|
||||
Cache-Control: public, max-age=0, must-revalidate
|
||||
|
||||
/app.js
|
||||
Cache-Control: public, max-age=60, must-revalidate
|
||||
|
||||
/config.js
|
||||
Cache-Control: public, max-age=0, must-revalidate
|
||||
|
||||
/router.js
|
||||
Cache-Control: public, max-age=60, must-revalidate
|
||||
|
||||
/style.css
|
||||
Cache-Control: public, max-age=300, must-revalidate
|
||||
+34
-3
@@ -1,4 +1,30 @@
|
||||
/* global fetch, document */
|
||||
/* global fetch, document, ABILITY_VIDEO_BASE, SITE_VERSION */
|
||||
|
||||
/** OSS / CDN base for ability demos; empty => same-origin `/ability-video/...`. */
|
||||
function abilityVideoBase() {
|
||||
const raw =
|
||||
typeof ABILITY_VIDEO_BASE === "string" ? ABILITY_VIDEO_BASE.trim() : "";
|
||||
return raw.replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
function abilityVideoUrl(heroKey, abilityKey) {
|
||||
const rel = `/ability-video/${heroKey}/${abilityKey}.webm`;
|
||||
const base = abilityVideoBase();
|
||||
return base ? `${base}${rel}` : rel;
|
||||
}
|
||||
|
||||
function siteVersionLabel() {
|
||||
const v = typeof SITE_VERSION === "string" ? SITE_VERSION.trim() : "";
|
||||
return v ? `v${v}` : "";
|
||||
}
|
||||
|
||||
function renderPatchesSiteVersion() {
|
||||
const el = $("#patches-site-version");
|
||||
if (!el) return;
|
||||
const label = siteVersionLabel();
|
||||
el.textContent = label;
|
||||
el.setAttribute("aria-hidden", label ? "false" : "true");
|
||||
}
|
||||
|
||||
const state = {
|
||||
data: null,
|
||||
@@ -724,15 +750,17 @@ function mountSkillInspect(root, skillEnt, heroKey) {
|
||||
// Official-page layout: demo clip on the left, name/desc column on the right.
|
||||
const body = document.createElement("div");
|
||||
body.className = "skill-info-body";
|
||||
// Official demo clip (assets/ability_videos); hidden when not cached locally.
|
||||
// Official demo clip: local `/ability-video/...` (serve_relations) or OSS base
|
||||
// from config.js (static export / Pages). Hidden when the file is missing.
|
||||
if (heroKey && skillEnt.ability_key) {
|
||||
const video = document.createElement("video");
|
||||
video.className = "skill-info-video";
|
||||
video.src = `/ability-video/${heroKey}/${skillEnt.ability_key}.webm`;
|
||||
video.src = abilityVideoUrl(heroKey, skillEnt.ability_key);
|
||||
video.muted = true;
|
||||
video.loop = true;
|
||||
video.autoplay = true;
|
||||
video.playsInline = true;
|
||||
video.crossOrigin = "anonymous";
|
||||
video.addEventListener("error", () => video.remove());
|
||||
body.appendChild(video);
|
||||
}
|
||||
@@ -1723,6 +1751,7 @@ function renderPatches() {
|
||||
if (select) select.innerHTML = "";
|
||||
if (verEl) verEl.textContent = "";
|
||||
root.innerHTML = '<div class="patches-empty">暂无版本数据,请运行 python fetch_patches.py</div>';
|
||||
renderPatchesSiteVersion();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1753,6 +1782,7 @@ function renderPatches() {
|
||||
const det = details[state.selectedPatch];
|
||||
if (!det) {
|
||||
root.innerHTML = '<div class="patches-empty">该版本详情暂未抓取,请重跑 python fetch_patches.py</div>';
|
||||
renderPatchesSiteVersion();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1785,6 +1815,7 @@ function renderPatches() {
|
||||
.map((h) => renderHeroEntry(h, lookup))
|
||||
.join("");
|
||||
renderPatchSection(root, "英雄改动", heroesHtml);
|
||||
renderPatchesSiteVersion();
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Local defaults; production export overwrites via export_relations_site.py. */
|
||||
var SITE_VERSION = "0.4.1";
|
||||
var ABILITY_VIDEO_BASE = "";
|
||||
@@ -12,6 +12,16 @@
|
||||
<img class="brand-logo" src="ui-icon/dota2_logo.png" alt="Dota 2" />
|
||||
<span class="brand-title">上分帝</span>
|
||||
</div>
|
||||
<a
|
||||
class="contact-mail"
|
||||
href="mailto:c9mhs8vfmuyv@outlook.com"
|
||||
aria-label="邮件联系"
|
||||
title="c9mhs8vfmuyv@outlook.com"
|
||||
>
|
||||
<svg class="contact-mail-icon" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false">
|
||||
<path fill="currentColor" d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4-8 5-8-5V6l8 5 8-5v2z"/>
|
||||
</svg>
|
||||
</a>
|
||||
<nav class="main-tabs" aria-label="主分页">
|
||||
<button type="button" class="main-tab active" data-page="heroes">英雄</button>
|
||||
<button type="button" class="main-tab" data-page="items">物品</button>
|
||||
@@ -55,11 +65,13 @@
|
||||
<select id="patch-select" aria-label="选择版本"></select>
|
||||
</div>
|
||||
<div class="patches-detail" id="patches-detail"></div>
|
||||
<footer class="patches-site-version" id="patches-site-version" aria-hidden="true"></footer>
|
||||
</main>
|
||||
|
||||
<section class="detail" id="detail" aria-live="polite"></section>
|
||||
|
||||
<script src="/router.js"></script>
|
||||
<script src="/app.js"></script>
|
||||
<script src="/config.js?v=0.4.1"></script>
|
||||
<script src="/router.js?v=0.4.1"></script>
|
||||
<script src="/app.js?v=0.4.1"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -75,6 +75,34 @@ body {
|
||||
@media (max-width: 620px) {
|
||||
.brand { display: none; }
|
||||
}
|
||||
.contact-mail {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 12px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s, background 0.15s;
|
||||
}
|
||||
.contact-mail:hover {
|
||||
color: var(--text);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
.contact-mail:focus-visible {
|
||||
outline: 2px solid var(--sel);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.contact-mail-icon {
|
||||
display: block;
|
||||
}
|
||||
.main-tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -1609,6 +1637,17 @@ body:has(#items-view:not(.hidden)) {
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
}
|
||||
.patches-site-version {
|
||||
width: min(820px, 92%);
|
||||
padding: 4px 0 28px;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--muted);
|
||||
letter-spacing: 0.08em;
|
||||
opacity: 0.55;
|
||||
user-select: none;
|
||||
}
|
||||
.patch-section {
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user