feat: sync security & SEO hardening from 2910 (keep placeholders)

This commit is contained in:
hanyixuanten committed 2026-10-26 14:43:18 +08:00
1 parent 2c1f508b14
commit 339e5b5639
15 files changed
+262 -137

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="14" fill="#0d1020"/>
<path d="M32 11l6.2 12.6 13.8 2-10 9.7 2.4 13.7L32 42.5l-12.4 6.5 2.4-13.7-10-9.7 13.8-2z" fill="#e6c068"/>
</svg>

After

Width:  |  Height:  |  Size: 234 B

+33 -7
View File
@@ -1,5 +1,10 @@
/* ================= 星空背景 ================= */
(function () {
// 用户偏好减少动态效果时不播星空,保留静态渐变背景
const reducedMotion = window.matchMedia &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reducedMotion) return;
const canvas = document.getElementById('stars');
const ctx = canvas.getContext('2d');
let w, h, stars = [], dpr = Math.min(window.devicePixelRatio || 1, 2);
@@ -44,11 +49,31 @@
/* ================= 打字机 ================= */
(function () {
const el = document.getElementById('typed');
const lines = [
'我们的故事,从那年秋天开始',
'三年同窗,一生朋友',
'愿此去前程似锦,再相逢依然少年'
];
// 句子由 src/site.config.ts 的 HOME.typedLines 注入(首页内联 JSON),保持单一定制入口
let lines = null;
try {
const src = document.getElementById('typed-lines');
if (src) {
const parsed = JSON.parse(src.textContent);
if (Array.isArray(parsed) && parsed.length && parsed.every(l => typeof l === 'string')) {
lines = parsed;
}
}
} catch (e) { /* 配置缺失时回退到内置句子 */ }
if (!lines) {
lines = [
'我们的故事,从那年秋天开始',
'三年同窗,一生朋友',
'愿此去前程似锦,再相逢依然少年'
];
}
// 减少动态效果偏好:直接完整展示第一句,不做打字动画
const reducedMotion = window.matchMedia &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reducedMotion) {
el.textContent = lines[0];
return;
}
let li = 0, ci = 0, deleting = false;
function tick() {
@@ -262,11 +287,12 @@
}
return;
} catch (err) {
btn.textContent = err.message && err.message.length <= 10 ? err.message : '发送失败';
// 接口返回的中文提示(如「发得太快啦,请等 X 秒」)直接展示,超长才降级
btn.textContent = err.message && err.message.length <= 30 ? err.message : '发送失败';
setTimeout(() => {
btn.textContent = BTN_TEXT;
btn.disabled = false;
}, 1600);
}, 2400);
sending = false;
return;
}
+3
View File
@@ -0,0 +1,3 @@
User-agent: *
Allow: /
Disallow: /api/