This commit is contained in:
2026-01-19 10:49:05 +08:00
parent e575ccd71a
commit 5308047b2d
3 changed files with 31 additions and 56 deletions

28
app.js
View File

@@ -28,7 +28,6 @@ export function initApp() {
const languageButton = document.getElementById("languageButton") const languageButton = document.getElementById("languageButton")
const languageList = document.getElementById("languageList") const languageList = document.getElementById("languageList")
const titleEl = document.querySelector(".title") const titleEl = document.querySelector(".title")
const subtitleEl = document.querySelector(".subtitle")
const designThemeLabelEl = document.querySelector( const designThemeLabelEl = document.querySelector(
'[data-i18n="designThemeLabel"]', '[data-i18n="designThemeLabel"]',
) )
@@ -68,13 +67,23 @@ export function initApp() {
} }
} }
function updateSubtitle(language = currentLanguage) { function setTitleText(titleText) {
if (!subtitleEl) return if (!titleEl) return
if (pins.length) { const cursorEl = titleEl.querySelector(".title-cursor")
subtitleEl.textContent = t("pinnedSubtitle", language) if (cursorEl) {
let textNode = [...titleEl.childNodes].find(
(node) => node.nodeType === Node.TEXT_NODE && node.nodeValue?.trim(),
)
if (!textNode) {
textNode = document.createTextNode(titleText)
titleEl.insertBefore(textNode, cursorEl)
} else { } else {
subtitleEl.textContent = subtitleEl.dataset.text || "" textNode.nodeValue = titleText
} }
} else {
titleEl.textContent = titleText
}
titleEl.dataset.text = titleText
} }
function getDocumentLang(language) { function getDocumentLang(language) {
@@ -115,8 +124,7 @@ export function initApp() {
document.title = t("appTitle", language) document.title = t("appTitle", language)
if (titleEl) { if (titleEl) {
const titleText = t("appTitle", language) const titleText = t("appTitle", language)
titleEl.textContent = titleText setTitleText(titleText)
titleEl.dataset.text = titleText
} }
if (designThemeLabelEl) { if (designThemeLabelEl) {
designThemeLabelEl.textContent = t("designThemeLabel", language) designThemeLabelEl.textContent = t("designThemeLabel", language)
@@ -164,7 +172,6 @@ export function initApp() {
getLabel: getThemeLabel, getLabel: getThemeLabel,
}) })
setSelectedLanguageUI(language) setSelectedLanguageUI(language)
updateSubtitle(language)
renderSites({ container: sitesContainer, sites, pins, language }) renderSites({ container: sitesContainer, sites, pins, language })
} }
@@ -181,9 +188,6 @@ export function initApp() {
titleEl.dataset.text = titleEl.textContent?.trim() || "" titleEl.dataset.text = titleEl.textContent?.trim() || ""
} }
if (subtitleEl && !subtitleEl.dataset.text) {
subtitleEl.dataset.text = subtitleEl.textContent?.trim() || ""
}
const initialTheme = getInitialTheme() const initialTheme = getInitialTheme()
setTheme(initialTheme) setTheme(initialTheme)

View File

@@ -11,9 +11,9 @@
<body> <body>
<div class="theme-controls"> <div class="theme-controls">
<label class="design-theme"> <label class="design-theme">
<span class="visually-hidden" data-i18n="designThemeLabel" <span class="visually-hidden" data-i18n="designThemeLabel">
>设计主题</span 设计主题
> </span>
<button <button
class="design-theme-button" class="design-theme-button"
id="designThemeButton" id="designThemeButton"
@@ -106,8 +106,9 @@
<div id="app"> <div id="app">
<div class="container"> <div class="container">
<main class="main"> <main class="main">
<h1 class="title" data-i18n="appTitle">物联网专业の在线学习平台</h1> <h1 class="title" data-i18n="appTitle">
<h2 class="subtitle"></h2> 物联网专业の在线学习平台<span class="title-cursor" aria-hidden="true"></span>
</h1>
<div class="grid" id="sites"></div> <div class="grid" id="sites"></div>
</main> </main>
<div class="beian"> <div class="beian">

View File

@@ -397,7 +397,7 @@ html[data-theme="dark"]:not([data-design-theme="terminal"])
} }
.main { .main {
padding: 3rem 0; padding: 4rem 3rem 0 3rem;
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -412,11 +412,15 @@ html[data-theme="dark"]:not([data-design-theme="terminal"])
font-size: 2.5rem; font-size: 2.5rem;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
margin-bottom: 0.5rem; margin: 1rem 0;
color: #1a1a1a; color: #1a1a1a;
letter-spacing: -0.02em; letter-spacing: -0.02em;
} }
.title-cursor {
display: none;
}
/* Fluent 2 风格的标题渐变 - 使用 Fluent 蓝系 */ /* Fluent 2 风格的标题渐变 - 使用 Fluent 蓝系 */
.title { .title {
background: var(--title-gradient); background: var(--title-gradient);
@@ -583,8 +587,7 @@ html[data-theme="dark"]:not([data-design-theme="terminal"])
} }
.beian { .beian {
margin-bottom: 24px; margin: 24px 0;
margin-top: 32px;
text-align: center; text-align: center;
} }
@@ -918,41 +921,9 @@ html[data-design-theme="cyberpunk"] .title {
animation: cyberpunk-rgbShift 4.5s ease-in-out infinite; animation: cyberpunk-rgbShift 4.5s ease-in-out infinite;
} }
html[data-design-theme="cyberpunk"] .title::before,
html[data-design-theme="cyberpunk"] .title::after {
content: attr(data-text);
position: absolute;
left: 0;
top: 0;
width: 100%;
pointer-events: none;
opacity: 0.65;
mix-blend-mode: screen;
}
html[data-design-theme="cyberpunk"] .title::before { html[data-design-theme="cyberpunk"] .title-cursor {
transform: translate3d(-2px, 0, 0); display: none;
color: rgba(255, 0, 255, 0.85);
animation: cyberpunk-glitch 6.2s steps(2, end) infinite;
}
html[data-design-theme="cyberpunk"] .title::after {
transform: translate3d(2px, 0, 0);
color: rgba(0, 212, 255, 0.85);
animation: cyberpunk-glitch 5.3s steps(2, end) infinite reverse;
}
html[data-design-theme="cyberpunk"] .subtitle {
color: var(--cyber-muted-fg);
letter-spacing: 0.14em;
text-transform: uppercase;
}
html[data-design-theme="cyberpunk"] .subtitle::after {
content: "\2588";
margin-left: 8px;
color: rgba(var(--accent-rgb), 0.85);
animation: cyberpunk-blink 1s step-end infinite;
} }
html[data-design-theme="cyberpunk"] .card { html[data-design-theme="cyberpunk"] .card {
@@ -1036,7 +1007,6 @@ html[data-design-theme="cyberpunk"] .beian a:hover {
html[data-design-theme="cyberpunk"] .title, html[data-design-theme="cyberpunk"] .title,
html[data-design-theme="cyberpunk"] .title::before, html[data-design-theme="cyberpunk"] .title::before,
html[data-design-theme="cyberpunk"] .title::after, html[data-design-theme="cyberpunk"] .title::after,
html[data-design-theme="cyberpunk"] .subtitle::after,
html[data-design-theme="cyberpunk"] .card { html[data-design-theme="cyberpunk"] .card {
animation: none !important; animation: none !important;
transition-duration: 0.01ms !important; transition-duration: 0.01ms !important;