Files
whoami/homepage/swiss/index.html
T
ylhan e49ce2e4a1 feat: 主页多风格改版(终端版加速+矩阵背景,新增 Bento/Brutal/Swiss/HUD 四版本)
- 终端版 /:开机动画时间减半、绿色数据流背景、页脚五版本切换
- Bento /bento/:网格卡片 + 鼠标互动动态光晕,深浅色自适应
- Brutal /brutal/:新粗野主义撞色硬阴影风
- Swiss /swiss/:极简瑞士细分割线排版
- HUD /hud/:赛博朋克霓虹切角面板
- 各版本内容一致:天气/日期/时间、四引擎搜索框、四组 12 链接
2026-08-27 00:14:20 +08:00

322 lines
17 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https: data:; script-src 'self' 'unsafe-inline'; connect-src https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https: *;">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' fill='%23111111'/%3E%3Crect x='18' y='18' width='28' height='28' fill='%23ff3b30'/%3E%3C/svg%3E">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>hyonglin.top</title>
<style>
/* ===== Swiss / Editorial:浅色为主,深色自适应 ===== */
:root {
--bg: #f4f4f2;
--text: #111111;
--muted: #6b6b70;
--line: rgba(17,17,17,.22);
--accent: #ff3b30;
--mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f0f10;
--text: #f4f4f2;
--muted: #8a8a8e;
--line: rgba(255,255,255,.2);
--accent: #ff453a;
}
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Microsoft YaHei", sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
-webkit-font-smoothing: antialiased;
}
::selection { background: var(--accent); color: #fff; }
.page { max-width: 1240px; margin: 0 auto; padding: 0 clamp(20px, 5vw, 64px) 0; }
/* ===== 入场:克制的淡入上移 ===== */
.reveal { animation: fadeup .7s ease both; animation-delay: var(--d, 0s); }
@keyframes fadeup { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
/* ===== 报头 ===== */
.masthead { padding-top: 40px; }
.meta-row { display: flex; justify-content: space-between; gap: 16px; font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--line); padding-bottom: 14px; }
.meta-row .sq { display: inline-block; width: 8px; height: 8px; background: var(--accent); margin-right: 10px; vertical-align: middle; }
h1 { font-size: clamp(3rem, 9vw, 7.5rem); font-weight: 200; letter-spacing: -.03em; line-height: .98; margin-top: clamp(24px, 4vh, 48px); }
p.sub { margin-top: 14px; font-size: .8rem; letter-spacing: .35em; color: var(--muted); text-transform: uppercase; }
/* ===== 数据栏:天气 / 日期 / 时间(杂志数据页) ===== */
.data { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px solid var(--line); margin-top: clamp(28px, 5vh, 56px); }
.cell { padding: 26px 0 30px; min-width: 0; }
.cell + .cell { border-left: 1px solid var(--line); padding-left: clamp(18px, 3vw, 40px); }
.label { display: flex; align-items: center; gap: 9px; font-size: .68rem; letter-spacing: .22em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; }
.label::before { content: ""; width: 6px; height: 6px; background: var(--accent); flex-shrink: 0; }
.big { font-size: clamp(2rem, 5vw, 3.6rem); font-weight: 250; font-variant-numeric: tabular-nums; letter-spacing: -.01em; line-height: 1.05; display: flex; align-items: baseline; gap: .28em; white-space: nowrap; }
.sky .emoji { font-size: .62em; transform: translateY(-.04em); }
.wcity { margin-top: 10px; font-size: .78rem; color: var(--muted); letter-spacing: .06em; min-height: 1.2em; }
/* ===== 搜索行 ===== */
form.search { display: flex; align-items: center; gap: clamp(12px, 2vw, 24px); padding: 18px 0; border-top: 1px solid var(--line); margin-top: -1px; }
.slabel { font-size: .68rem; letter-spacing: .22em; text-transform: uppercase; color: var(--muted); flex-shrink: 0; }
form.search select {
cursor: pointer; flex-shrink: 0;
font-family: inherit; font-size: .85rem; color: var(--text);
background: transparent; border: 1px solid var(--line); border-radius: 0;
padding: 9px 12px; outline: none; max-width: 130px;
}
form.search select:focus-visible { border-color: var(--accent); }
form.search input { flex: 1; min-width: 0; background: none; border: none; outline: none; color: var(--text); font-family: inherit; font-size: 1rem; padding: 8px 0; caret-color: var(--accent); }
form.search input::placeholder { color: var(--muted); }
form.search button {
border: 1px solid var(--line); background: transparent; cursor: pointer; flex-shrink: 0;
width: 44px; height: 38px; font-size: 1.05rem; color: var(--text);
transition: background .15s ease, color .15s ease, border-color .15s ease;
}
form.search button:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
/* ===== 分组:编号索引式列表 ===== */
.group { border-top: 1px solid var(--line); margin-top: -1px; }
.ghead { display: grid; grid-template-columns: clamp(64px, 8vw, 96px) 1fr auto; align-items: baseline; gap: 18px; padding: 20px 0 6px; }
.ghead .num { font-size: clamp(1.5rem, 2.6vw, 2.1rem); font-weight: 300; color: var(--accent); font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.ghead h2 { font-size: .82rem; font-weight: 600; letter-spacing: .24em; text-transform: uppercase; display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.ghead h2 .en { font-family: var(--mono); font-size: .68rem; font-weight: 400; letter-spacing: .18em; color: var(--muted); text-transform: uppercase; }
.ghead .count { font-family: var(--mono); font-size: .72rem; color: var(--muted); letter-spacing: .12em; }
ul.rows { list-style: none; }
ul.rows li + li a, ul.rows li:first-child a { border-top: 1px solid var(--line); }
ul.rows a {
display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
padding: 15px 0; text-decoration: none; color: var(--text);
transition: color .15s ease;
}
ul.rows .name { font-size: clamp(1rem, 1.6vw, 1.18rem); font-weight: 450; letter-spacing: .01em; }
ul.rows .arrow { opacity: 0; transform: translateX(-6px); color: var(--accent); transition: opacity .15s ease, transform .15s ease; }
ul.rows a:hover .name, ul.rows a:focus-visible .name { color: var(--accent); }
ul.rows a:hover .arrow, ul.rows a:focus-visible .arrow { opacity: 1; transform: none; }
ul.rows .dom { margin-left: auto; font-family: var(--mono); font-size: .72rem; color: var(--muted); letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 56%; }
a:focus-visible, button:focus-visible, select:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }
/* ===== 页脚:版本切换行 ===== */
.foot { display: flex; justify-content: space-between; align-items: baseline; gap: 18px; flex-wrap: wrap; border-top: 1px solid var(--line); margin-top: clamp(36px, 7vh, 72px); padding: 22px 0 40px; }
.fbrand { font-size: .9rem; font-weight: 600; letter-spacing: .04em; }
nav.versions { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: .78rem; color: var(--muted); }
nav.versions .sep { opacity: .6; }
nav.versions a { color: var(--muted); text-decoration: none; transition: color .15s ease; }
nav.versions a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; }
nav.versions .path { font-family: var(--mono); font-size: .72rem; margin-left: 3px; }
nav.versions .current { color: var(--text); }
nav.versions .current::after { content: "(当前)"; color: var(--accent); font-size: .72rem; margin-left: 4px; }
/* ===== 响应式:窄屏分区堆叠 ===== */
@media (max-width: 720px) {
.data { grid-template-columns: 1fr; }
.cell + .cell { border-left: none; padding-left: 0; border-top: 1px solid var(--line); }
.ghead { grid-template-columns: auto 1fr; }
.ghead .count { display: none; }
ul.rows a { gap: 8px; }
ul.rows .dom { margin-left: 0; max-width: 100%; width: 100%; order: 3; text-align: left; }
}
@media (prefers-reduced-motion: reduce) {
.reveal { animation: none; }
ul.rows a, ul.rows .arrow, form.search button, nav.versions a { transition: none; }
}
</style>
</head>
<body>
<main class="page">
<!-- 报头 -->
<header class="masthead reveal" style="--d:.02s">
<div class="meta-row">
<span><span class="sq"></span>HYONGLIN.TOP — INDEX</span>
<span>NAVIGATION / 导航索引</span>
</div>
<h1>hyonglin.top</h1>
<p class="sub">个人服务导航 · 随时可达</p>
</header>
<!-- 数据栏:天气 / 日期 / 时间 -->
<section class="data reveal" style="--d:.1s" aria-label="天气与时间">
<div class="cell sky">
<span class="label">天气 Weather</span>
<span class="big"><span class="emoji">☀️</span><span class="wtxt">获取中…</span></span>
<span class="wcity"></span>
</div>
<div class="cell">
<span class="label">日期 Date</span>
<span class="big" id="dateval">----</span>
</div>
<div class="cell">
<span class="label">时间 Time</span>
<span class="big" id="clockval">--:--:--</span>
</div>
</section>
<!-- 搜索 -->
<form class="search reveal" style="--d:.18s" action="https://www.bing.com/search" method="get" target="_blank" rel="noopener">
<span class="slabel">Search</span>
<select name="engine" id="engine" aria-label="搜索引擎">
<option value="bing" selected>Bing</option>
<option value="google">Google</option>
<option value="baidu">百度</option>
<option value="duckduckgo">DuckDuckGo</option>
</select>
<input type="text" name="q" placeholder="输入关键词,回车搜索…" autocomplete="off" aria-label="搜索">
<button type="submit" aria-label="搜索">→</button>
</form>
<!-- 01 自建服务 -->
<section class="group reveal" style="--d:.26s">
<header class="ghead">
<span class="num">01</span>
<h2>自建服务<span class="en">Self-Hosted</span></h2>
<span class="count">4 ITEMS</span>
</header>
<ul class="rows">
<li><a href="https://note.hyonglin.top"><span class="name">笔记</span><span class="arrow">→</span><span class="dom">note.hyonglin.top · SilverBullet</span></a></li>
<li><a href="https://git.hyonglin.top"><span class="name">Git 服务</span><span class="arrow">→</span><span class="dom">git.hyonglin.top · Gitea</span></a></li>
<li><a href="https://ssh.hyonglin.top"><span class="name">网页 SSH 终端</span><span class="arrow">→</span><span class="dom">ssh.hyonglin.top</span></a></li>
<li><a href="https://frp.hyonglin.top"><span class="name">frp 管理面板</span><span class="arrow">→</span><span class="dom">frp.hyonglin.top</span></a></li>
</ul>
</section>
<!-- 02 AI 助手 -->
<section class="group reveal" style="--d:.34s">
<header class="ghead">
<span class="num">02</span>
<h2>AI 助手<span class="en">AI Assistants</span></h2>
<span class="count">2 ITEMS</span>
</header>
<ul class="rows">
<li><a href="https://chat.deepseek.com/" target="_blank" rel="noopener"><span class="name">DeepSeek</span><span class="arrow">→</span><span class="dom">chat.deepseek.com</span></a></li>
<li><a href="https://www.doubao.com/chat/" target="_blank" rel="noopener"><span class="name">豆包</span><span class="arrow">→</span><span class="dom">doubao.com</span></a></li>
</ul>
</section>
<!-- 03 云服务 -->
<section class="group reveal" style="--d:.42s">
<header class="ghead">
<span class="num">03</span>
<h2>云服务<span class="en">Cloud Services</span></h2>
<span class="count">3 ITEMS</span>
</header>
<ul class="rows">
<li><a href="https://dash.cloudflare.com/" target="_blank" rel="noopener"><span class="name">Cloudflare</span><span class="arrow">→</span><span class="dom">dash.cloudflare.com</span></a></li>
<li><a href="https://auth.huaweicloud.com/" target="_blank" rel="noopener"><span class="name">华为云</span><span class="arrow">→</span><span class="dom">auth.huaweicloud.com</span></a></li>
<li><a href="https://console.cloud.tencent.com/" target="_blank" rel="noopener"><span class="name">腾讯云</span><span class="arrow">→</span><span class="dom">console.cloud.tencent.com</span></a></li>
</ul>
</section>
<!-- 04 常用 -->
<section class="group reveal" style="--d:.5s">
<header class="ghead">
<span class="num">04</span>
<h2>常用<span class="en">Utilities</span></h2>
<span class="count">3 ITEMS</span>
</header>
<ul class="rows">
<li><a href="https://wx.mail.qq.com/" target="_blank" rel="noopener"><span class="name">QQ 邮箱</span><span class="arrow">→</span><span class="dom">wx.mail.qq.com</span></a></li>
<li><a href="https://www.bing.com/" target="_blank" rel="noopener"><span class="name">Bing 搜索</span><span class="arrow">→</span><span class="dom">bing.com</span></a></li>
<li><a href="https://www.bilibili.com/" target="_blank" rel="noopener"><span class="name">哔哩哔哩</span><span class="arrow">→</span><span class="dom">bilibili.com</span></a></li>
</ul>
</section>
<!-- 页脚:版本切换 -->
<footer class="foot reveal" style="--d:.58s">
<span class="fbrand">hyonglin.top</span>
<nav class="versions" aria-label="版本切换">
<a href="/">终端版<span class="path">/</span></a><span class="sep">·</span>
<a href="/bento/">Bento 版<span class="path">/bento/</span></a><span class="sep">·</span>
<a href="/brutal/">Brutal 版<span class="path">/brutal/</span></a><span class="sep">·</span>
<span class="current">Swiss 版<span class="path">/swiss/</span></span><span class="sep">·</span>
<a href="/hud/">HUD 版<span class="path">/hud/</span></a>
</nav>
</footer>
</main>
<script>
/* ===== 搜索引擎选择 ===== */
(function(){
var sel = document.getElementById('engine');
if (!sel) return;
var ENGINES = {
bing: 'https://www.bing.com/search?q=',
google: 'https://www.google.com/search?q=',
baidu: 'https://www.baidu.com/s?wd=',
duckduckgo: 'https://duckduckgo.com/?q='
};
var form = sel.closest('form');
function apply() { form.action = ENGINES[sel.value] || ENGINES.bing; }
sel.addEventListener('change', apply);
apply();
})();
/* ===== 日期 + 时钟 ===== */
var week = ['日','一','二','三','四','五','六'];
function pad2(n) { return (n < 10 ? '0' : '') + n; }
function updateClock() {
var now = new Date();
var c = document.getElementById('clockval');
if (c) c.textContent = pad2(now.getHours()) + ':' + pad2(now.getMinutes()) + ':' + pad2(now.getSeconds());
var d = document.getElementById('dateval');
if (d) d.textContent = now.getFullYear() + '-' + pad2(now.getMonth()+1) + '-' + pad2(now.getDate()) + ' 周' + week[now.getDay()];
}
setInterval(updateClock, 1000);
updateClock();
/* ===== 天气:GPS 定位 + Open-Meteo(不依赖 IP) ===== */
var emojiBox = function(){ return document.querySelector('.sky .emoji'); };
var tempBox = function(){ return document.querySelector('.wtxt'); };
var cityBox = function(){ return document.querySelector('.wcity'); };
var WMO = {
0:'☀️',1:'🌤',2:'⛅',3:'☁️',45:'🌫',48:'🌫',
51:'🌦',53:'🌦',55:'🌦',56:'🌨',57:'🌨',
61:'🌧',63:'🌧',65:'🌧',66:'🌨',67:'🌨',
71:'🌨',73:'🌨',75:'🌨',77:'🌨',80:'🌦',81:'🌦',82:'🌧',
85:'🌨',86:'🌨',95:'⛈',96:'⛈',99:'⛈'
};
function wmo(w) { return WMO[w] || '🌡️'; }
function setWeather(temp, wcode, city) {
if (tempBox()) tempBox().textContent = temp + '°C';
if (emojiBox()) emojiBox().textContent = wmo(wcode);
if (city && cityBox()) cityBox().textContent = city;
}
function getWeather(lat, lon, city) {
var url = 'https://api.open-meteo.com/v1/forecast?latitude=' + lat + '&longitude=' + lon +
'&current_weather=true&timezone=auto';
fetch(url).then(function(r){ return r.json(); }).then(function(d){
var cw = d.current_weather || {};
setWeather(Math.round(cw.temperature), cw.weathercode, city);
}).catch(function(){ tempBox() && (tempBox().textContent = '天气获取失败'); });
}
// 优先浏览器 GPS 定位;失败则 ipwho.is 按 IP 定位;再失败显示默认城市(北京)
var DEFAULT_LOC = { lat: 39.9042, lon: 116.4074, city: '北京' };
function byIP() {
fetch('https://ipwho.is/').then(function(r){ return r.json(); }).then(function(d){
if (d && d.latitude && d.longitude) getWeather(d.latitude, d.longitude, d.city || '');
else { getWeather(DEFAULT_LOC.lat, DEFAULT_LOC.lon, DEFAULT_LOC.city); }
}).catch(function(){ getWeather(DEFAULT_LOC.lat, DEFAULT_LOC.lon, DEFAULT_LOC.city); });
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(pos){
getWeather(pos.coords.latitude, pos.coords.longitude, '');
}, byIP, { timeout: 8000 });
} else {
byIP();
}
</script>
</body>
</html>