diff --git a/Client/src/api/auth.ts b/Client/src/api/auth.ts index 783cdd5..210fe6a 100644 --- a/Client/src/api/auth.ts +++ b/Client/src/api/auth.ts @@ -24,14 +24,14 @@ export async function login(username: string, password: string): Promise `jpg` > `png`;插画/需透明用 `png` + +缺图时该区域会自动透出页面的 Lunada 渐变背景,不会显示裂图占位符。 + +## 当前文件 + +- `side-01.jpg` —— 左栏 +- `side-02.jpg` —— 右栏 diff --git a/Client/src/assets/sides/side-01.jpg b/Client/src/assets/sides/side-01.jpg new file mode 100644 index 0000000..4392701 Binary files /dev/null and b/Client/src/assets/sides/side-01.jpg differ diff --git a/Client/src/assets/sides/side-02.jpg b/Client/src/assets/sides/side-02.jpg new file mode 100644 index 0000000..6723e8e Binary files /dev/null and b/Client/src/assets/sides/side-02.jpg differ diff --git a/Client/src/components/BlogPage.tsx b/Client/src/components/BlogPage.tsx index 124e8dd..22f840f 100644 --- a/Client/src/components/BlogPage.tsx +++ b/Client/src/components/BlogPage.tsx @@ -53,17 +53,36 @@ const POSTS: Post[] = [ }, ] +// 两侧图片区的图片:用 Vite 的 import.meta.glob 自动索引 src/assets/sides/ 下的所有图。 +// 走 bundler import —— 自带内容哈希、构建期校验、可优化;丢新图进该文件夹即生效,无需改代码。 +// 按文件名升序取用:第 1 张 → 左栏,第 2 张 → 右栏。详见 src/assets/sides/README.md。 +const sideImages = Object.entries( + import.meta.glob('../assets/sides/*.{jpg,jpeg,png,webp}', { + eager: true, + query: '?url', + import: 'default', + }), +) + .sort(([pathA], [pathB]) => pathA.localeCompare(pathB)) + .map(([, url]) => url) + +const SIDE_IMAGE_LEFT = sideImages[0] +const SIDE_IMAGE_RIGHT = sideImages[1] ?? sideImages[0] + export function BlogPage({ username, onSignOut }: BlogPageProps) { // 顶部栏沿用系统状态彩蛋,保持与登录页同一风格。 const stats = useSystemStats() return ( -
+
+ {/* 整页 Lunada 渐变极光背景,固定铺满视口、置于所有内容之下 */} +
+ - {/* 顶部导航 */} -
-
+ {/* 顶部彩虹栏:通栏,横跨左右图片区之上;底部一条流动彩虹线 */} +
+
cc.dev @@ -79,55 +98,72 @@ export function BlogPage({ username, onSignOut }: BlogPageProps) {
+
-
- {/* Hero:整段全宽,彩虹光斑横跨整个页面;文字内容仍居中限宽 */} -
- + {/* Hero 通栏:彩虹光标动效 + 大字标题 + 灵感来源,占满一整行(在三栏之上) */} +
+ - + - - Personal blog - + Personal blog + - - Hello, I'm cc - _ - + + Hello, I'm cc + _ + - + 我在这里写关于前端动效、Rust 后端和把事情做简单的笔记。把鼠标移到这片区域, + 会有一道彩虹跟着你——灵感来自{' '} + - 我在这里写关于前端动效、Rust 后端和把事情做简单的笔记。把鼠标移到这片区域, - 会有一道彩虹跟着你——灵感来自{' '} - - Josh W. Comeau - - 。 - - -
+ Josh W. Comeau + + 。 + + +
- {/* 文章列表 */} -
+ {/* 三栏:左侧图片 · 中间内容(文章列表) · 右侧图片。 + 中间内容保持原比例(max-w-3xl),两侧 flex-1 图片区吃掉剩余留白(窄屏隐藏)。 */} +
+ {/* 左侧图片区:高度适配展示框、宽度按比例(不拉伸变形)、居中(水平溢出裁切); + 上覆液态玻璃。缺图时透出 Lunada 背景。 */} + + + {/* 中间内容纸(玻璃纸张) */} +
+
+ {/* 文章列表 */} +

Latest writing

@@ -171,14 +207,26 @@ export function BlogPage({ username, onSignOut }: BlogPageProps) {
- {/* 页脚:一条流动彩虹装饰线 */} -
-
-
- © {new Date().getFullYear()} cc - built with React · Rust · 🌈 + {/* 页脚:一条流动彩虹装饰线 */} +
+
+
+ © {new Date().getFullYear()} cc + built with React · Rust · 🌈 +
+
-
+ + {/* 右侧图片区(与左侧同样的高度适配 + 居中 + 液态玻璃覆层) */} + +
) } diff --git a/Client/src/components/LoginForm.tsx b/Client/src/components/LoginForm.tsx index c55f634..42a90f5 100644 --- a/Client/src/components/LoginForm.tsx +++ b/Client/src/components/LoginForm.tsx @@ -27,7 +27,7 @@ export function LoginForm({ onSignIn }: LoginFormProps) { await onSignIn(username.trim(), password, remember) // 成功后由上层切换到博客页,本组件随之卸载,无需额外处理。 } catch (err) { - setError(err instanceof Error ? err.message : '登录失败') + setError(err instanceof Error ? err.message : 'Sign-in failed') setSubmitting(false) } } diff --git a/Client/src/index.css b/Client/src/index.css index e3a12cd..26cc43c 100644 --- a/Client/src/index.css +++ b/Client/src/index.css @@ -164,15 +164,17 @@ body { animation: rainbow-pan 6s linear infinite; } -/* ── 整页彩虹极光背景(玻璃栏透出的就是它)────────────────────── - 固定铺满视口、置于所有内容之下。多个彩色径向光斑缓慢漂移, - 再大幅模糊成柔和极光。底色为暗色,避免内容区透出时发灰。 */ +/* ── 整页渐变极光背景(玻璃栏透出的就是它)────────────────────── + 固定铺满视口、置于所有内容之下。底色为 Lunada 渐变 + (uigradients「Lunada」:#A7BFE8 → #6190E8),上面叠几团同色系 + 蓝光斑缓慢漂移并大幅模糊,让平面渐变产生液态流动感。 */ .aurora { position: fixed; inset: 0; z-index: -10; overflow: hidden; - background-color: var(--color-bg); + /* Lunada 渐变打底 */ + background: linear-gradient(135deg, #6190e8 0%, #89a8e6 48%, #a7bfe8 100%); } .aurora::before { @@ -180,30 +182,65 @@ body { position: absolute; inset: -25%; background: - radial-gradient(28% 30% at 18% 28%, rgba(255, 95, 109, 0.55), transparent 70%), - radial-gradient(26% 30% at 82% 26%, rgba(56, 189, 248, 0.50), transparent 70%), - radial-gradient(30% 34% at 72% 76%, rgba(167, 139, 250, 0.50), transparent 70%), - radial-gradient(28% 32% at 26% 80%, rgba(74, 222, 128, 0.45), transparent 70%), - radial-gradient(24% 28% at 50% 50%, rgba(255, 177, 61, 0.40), transparent 70%); - filter: blur(70px); - animation: drift 28s ease-in-out infinite; - will-change: transform; + radial-gradient(30% 34% at 18% 28%, rgba(97, 144, 232, 0.65), transparent 70%), + radial-gradient(28% 32% at 82% 24%, rgba(167, 191, 232, 0.70), transparent 70%), + radial-gradient(34% 38% at 72% 78%, rgba(120, 162, 236, 0.60), transparent 70%), + radial-gradient(26% 30% at 26% 82%, rgba(192, 211, 245, 0.55), transparent 70%), + radial-gradient(24% 28% at 50% 50%, rgba(140, 175, 240, 0.45), transparent 70%); + filter: blur(60px); + /* 静止:持续漂移会让上层多个 backdrop-filter 每帧重算模糊,是卡顿主因 */ } /* ── 两侧液态玻璃竖栏 ───────────────────────────────────────── - backdrop-filter 把背后的极光磨成柔光;内侧一道高光边模拟玻璃厚度。 */ + backdrop-filter 把背后的极光磨成柔光;上下渐变的白色叠层 + 内侧两道 + 高光边模拟玻璃厚度,做出「液态玻璃」的体积感。 */ .glass-rail { - background: rgba(255, 255, 255, 0.04); - backdrop-filter: blur(16px) saturate(140%); - -webkit-backdrop-filter: blur(16px) saturate(140%); - box-shadow: inset 0 0 60px rgba(255, 255, 255, 0.03); + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0.12), + rgba(255, 255, 255, 0.03) 55%, + rgba(255, 255, 255, 0.08) + ); + backdrop-filter: blur(18px) saturate(150%); + -webkit-backdrop-filter: blur(18px) saturate(150%); + box-shadow: + inset 0 0 60px rgba(255, 255, 255, 0.06), + inset 1px 0 0 rgba(255, 255, 255, 0.20), + inset -1px 0 0 rgba(255, 255, 255, 0.20); } -/* 中间内容纸张:也带轻微玻璃感(压暗 + 模糊背后极光保证可读) */ +/* 中间内容纸张:压暗的暖色玻璃(模糊背后极光保证可读), + 两侧各一道高光描边,与左右玻璃竖栏拼出连续的玻璃接缝。 */ .glass-sheet { - background: rgba(23, 19, 15, 0.82); - backdrop-filter: blur(22px) saturate(120%); - -webkit-backdrop-filter: blur(22px) saturate(120%); + /* 底色 84% 不透明,背后极光本就几乎透不过来;省掉昂贵的 backdrop-filter, + 观感基本无差,却避免这条又高又大的区域每帧重算模糊。 */ + background: rgba(23, 19, 15, 0.84); + box-shadow: + inset 1px 0 0 rgba(255, 255, 255, 0.12), + inset -1px 0 0 rgba(255, 255, 255, 0.12), + 0 30px 80px rgba(20, 30, 60, 0.30); +} + +/* 两侧图片上的「液态玻璃」覆层:backdrop-filter 把图片磨成柔光, + 叠一道斜向高光 + 内侧四边亮边,做出通透的玻璃质感。 + 盖在