feat: 样式调整

This commit is contained in:
2026-07-21 18:14:41 +08:00
parent 60d8f66ad0
commit 634824ff44
12 changed files with 161 additions and 133 deletions

View File

@@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1784382428422" class="icon" viewBox="0 0 1035 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5545" xmlns:xlink="http://www.w3.org/1999/xlink" width="202.1484375" height="200"><path d="M513.407379 0C230.713951 0 1.407379 229.306573 1.407379 512c0 282.693427 229.306573 512 512 512 282.693427 0 512-229.293792 512-512C1025.407379 229.306573 796.100806 0 513.407379 0z m26.17579 817.737837c-6.812352 6.799571-16.756085 10.991787-26.17579 10.991787-9.943733 0-19.37622-4.192216-26.175791-10.991787-6.799571-6.812352-10.991787-16.756085-10.991787-26.699818 0-9.943733 4.192216-19.900247 10.991787-26.699818s16.756085-10.991787 26.175791-10.991787c9.943733 0 19.363439 4.192216 26.17579 10.991787s10.991787 16.756085 10.991787 26.699818c0 9.943733-4.192216 19.887466-10.991787 26.699818z m-26.17579-87.435832c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.756085 37.167577 37.691605 0 20.948301-16.756085 37.691605-37.167577 37.691605z m258.089717-237.678225c-7.847625 7.860406-17.804139 11.515814-27.747872 11.515814-9.943733 0-19.900247-3.668189-27.747871-11.515814l-163.343069-163.343069v261.23388c0 21.472328-17.804139 39.263686-39.263686 39.263686s-39.263686-17.791358-39.263687-39.263686V329.293492l-163.330287 163.343069c-15.184004 15.184004-40.31174 15.184004-55.495744 0-15.184004-15.184004-15.184004-40.31174 0-55.495744L485.646726 206.798972c15.184004-15.184004 40.31174-15.184004 55.495743 0l230.354627 230.341845c15.184004 15.171222 15.184004 39.774932 0 55.482963z m0 0" p-id="5546"></path><path d="M771.497096 492.636561c-7.847625 7.860406-17.804139 11.515814-27.747872 11.515814-9.943733 0-19.900247-3.668189-27.747871-11.515814l-163.343069-163.343069v261.23388c0 21.472328-17.804139 39.263686-39.263686 39.263686s-39.263686-17.791358-39.263687-39.263686V329.293492l-163.330287 163.343069c-15.184004 15.184004-40.31174 15.184004-55.495744 0-15.184004-15.184004-15.184004-40.31174 0-55.495744L485.659507 206.798972c15.184004-15.184004 40.31174-15.184004 55.495744 0l230.354626 230.341845c15.171222 15.184004 15.171222 39.787713-0.012781 55.495744zM513.407379 730.302005c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.756085 37.167577 37.691605 0 20.948301-16.756085 37.691605-37.167577 37.691605M513.407379 828.729624c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.743304 37.167577 37.691605 0 20.93552-16.756085 37.691605-37.167577 37.691605" fill="#FFFFFF" p-id="5547"></path></svg> <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1784628432297" class="icon" viewBox="0 0 1035 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9153" xmlns:xlink="http://www.w3.org/1999/xlink" width="202.1484375" height="200"><path d="M513.407379 0C230.713951 0 1.407379 229.306573 1.407379 512c0 282.693427 229.306573 512 512 512 282.693427 0 512-229.293792 512-512C1025.407379 229.306573 796.100806 0 513.407379 0z m26.17579 817.737837c-6.812352 6.799571-16.756085 10.991787-26.17579 10.991787-9.943733 0-19.37622-4.192216-26.175791-10.991787-6.799571-6.812352-10.991787-16.756085-10.991787-26.699818 0-9.943733 4.192216-19.900247 10.991787-26.699818s16.756085-10.991787 26.175791-10.991787c9.943733 0 19.363439 4.192216 26.17579 10.991787s10.991787 16.756085 10.991787 26.699818c0 9.943733-4.192216 19.887466-10.991787 26.699818z m-26.17579-87.435832c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.756085 37.167577 37.691605 0 20.948301-16.756085 37.691605-37.167577 37.691605z m258.089717-237.678225c-7.847625 7.860406-17.804139 11.515814-27.747872 11.515814-9.943733 0-19.900247-3.668189-27.747871-11.515814l-163.343069-163.343069v261.23388c0 21.472328-17.804139 39.263686-39.263686 39.263686s-39.263686-17.791358-39.263687-39.263686V329.293492l-163.330287 163.343069c-15.184004 15.184004-40.31174 15.184004-55.495744 0-15.184004-15.184004-15.184004-40.31174 0-55.495744L485.646726 206.798972c15.184004-15.184004 40.31174-15.184004 55.495743 0l230.354627 230.341845c15.184004 15.171222 15.184004 39.774932 0 55.482963z m0 0" p-id="9154"></path><path d="M771.497096 492.636561c-7.847625 7.860406-17.804139 11.515814-27.747872 11.515814-9.943733 0-19.900247-3.668189-27.747871-11.515814l-163.343069-163.343069v261.23388c0 21.472328-17.804139 39.263686-39.263686 39.263686s-39.263686-17.791358-39.263687-39.263686V329.293492l-163.330287 163.343069c-15.184004 15.184004-40.31174 15.184004-55.495744 0-15.184004-15.184004-15.184004-40.31174 0-55.495744L485.659507 206.798972c15.184004-15.184004 40.31174-15.184004 55.495744 0l230.354626 230.341845c15.171222 15.184004 15.171222 39.787713-0.012781 55.495744zM513.407379 730.302005c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.756085 37.167577 37.691605 0 20.948301-16.756085 37.691605-37.167577 37.691605M513.407379 828.729624c-20.424274 0-37.167578-16.743304-37.167578-37.691605 0-20.424274 16.743304-37.691605 37.167578-37.691605 20.411493 0 37.167578 16.743304 37.167577 37.691605 0 20.93552-16.756085 37.691605-37.167577 37.691605" fill="#FFFFFF" p-id="9155"></path></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -46,12 +46,16 @@ import backTopIcon from "@/assets/icon/back-top.svg?url";
display: none; display: none;
} }
.back-top :global(img) { .back-top img {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
} }
:global(.dark) .back-top img {
filter: invert(1);
}
.back-top:focus-visible { .back-top:focus-visible {
outline: 2px solid currentColor; outline: 2px solid currentColor;
outline-offset: 4px; outline-offset: 4px;

View File

@@ -1,8 +1,12 @@
--- ---
import { metadata } from "../consts";
const year = new Date().getFullYear();
--- ---
<footer> <footer>
<div class="content"> <div class="content">
<span>© 2026 {metadata.siteTitle}</span>
<a target="_blank" href="https://beian.miit.gov.cn/#/Integrated/index"> <a target="_blank" href="https://beian.miit.gov.cn/#/Integrated/index">
备案号鄂ICP备2023000060号-2 备案号鄂ICP备2023000060号-2
</a> </a>
@@ -12,22 +16,23 @@
<style> <style>
footer { footer {
background: #ffffff; background: #22252b;
height: 70px; height: 70px;
overflow: hidden; overflow: hidden;
flex-shrink: 0; flex-shrink: 0;
box-shadow: rgba(0, 0, 0, 0.05) 0px 1px 2px 2px; box-shadow: var(--shadow);
} }
.content { .content {
max-width: var(--layout-width); max-width: var(--layout-width);
margin: 0 auto; margin: 0 auto;
color: #1f2937; color: #fff;
display: flex; display: flex;
align-items: center; align-items: center;
height: 100%; height: 100%;
font-size: 14px; font-size: 14px;
justify-content: center; justify-content: center;
gap: 12px;
} }
:global(.dark) footer { :global(.dark) footer {

View File

@@ -28,7 +28,7 @@ import ThemeIcon from './ThemeIcon.astro'
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 99999; z-index: 99999;
box-shadow: rgba(0, 0, 0, 0.05) 0px 1px 2px 0px; box-shadow: var(--shadow);
flex-shrink: 0; flex-shrink: 0;
background: #fff; background: #fff;
} }

View File

@@ -12,12 +12,13 @@ interface Props {
const {posts, page, totalPage, categories} = Astro.props const {posts, page, totalPage, categories} = Astro.props
--- ---
<div class="page-content">
<div class="container"> <div class="container">
<PostList posts={posts} page={page} totalPage={totalPage}/> <PostList posts={posts} page={page} totalPage={totalPage}/>
<IndexSidebar categories={categories}/> <IndexSidebar categories={categories}/>
</div> </div>
</div>
<style> <style>
.container { .container {

View File

@@ -94,10 +94,12 @@ posts.map((post) => {
gap: 22px; gap: 22px;
} }
@media (hover: hover) and (pointer: fine) {
.post-card:hover { .post-card:hover {
transform: translateY(-3px); transform: translateY(-3px);
box-shadow: var(--shadow-hover); box-shadow: var(--shadow-hover);
} }
}
.post-cover { .post-cover {
flex-shrink: 0; flex-shrink: 0;
@@ -233,8 +235,6 @@ posts.map((post) => {
width: 128px; width: 128px;
height: 88px; height: 88px;
} }
} }
@media (max-width: 560px) { @media (max-width: 560px) {

View File

@@ -13,7 +13,7 @@ const pageTitle = title ? `${title} - ${siteTitle}` : siteTitle;
--- ---
<!doctype html> <!doctype html>
<html lang="en"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta <meta
@@ -28,7 +28,7 @@ const pageTitle = title ? `${title} - ${siteTitle}` : siteTitle;
</head> </head>
<body> <body>
<BaseHeader /> <BaseHeader />
<main> <main class="main">
<slot /> <slot />
</main> </main>
<BaseFooter /> <BaseFooter />

View File

@@ -5,19 +5,25 @@ import type {Post, CategoriesStats} from "@/types/post";
import { createHttp } from "@/lib/request"; import { createHttp } from "@/lib/request";
import { metadata } from "@/consts.ts"; import { metadata } from "@/consts.ts";
const http = createHttp(Astro.request.headers) const http = createHttp(Astro.request.headers);
const { list, total } = await http.get<ApiPageResponse<Post>>("post", { const { list, total } = await http.get<ApiPageResponse<Post>>("post", {
searchParams: { searchParams: {
page: 1, page: 1,
page_size: metadata.postPageSize page_size: metadata.postPageSize,
} },
}); });
const totalPage = Math.ceil(total / metadata.postPageSize) const totalPage = Math.ceil(total / metadata.postPageSize);
const {data: categories} = await http.get<ApiResponse<CategoriesStats[]>>("category/stats"); const { data: categories } =
await http.get<ApiResponse<CategoriesStats[]>>("category/stats");
--- ---
<Layout> <Layout>
<IndexView categories={categories} posts={list} page={1} totalPage={totalPage}/> <IndexView
categories={categories}
posts={list}
page={1}
totalPage={totalPage}
/>
</Layout> </Layout>

View File

@@ -5,30 +5,36 @@ import {createHttp} from "@/lib/request";
import { metadata } from "@/consts.ts"; import { metadata } from "@/consts.ts";
import IndexView from "@/components/IndexView.astro"; import IndexView from "@/components/IndexView.astro";
const {page} = Astro.params const { page } = Astro.params;
if (isNaN(Number(page))) { if (isNaN(Number(page))) {
return Astro.redirect('/') return Astro.redirect("/");
} }
const http = createHttp(Astro.request.headers) const http = createHttp(Astro.request.headers);
const { list, total } = await http.get<ApiPageResponse<Post>>("post", { const { list, total } = await http.get<ApiPageResponse<Post>>("post", {
searchParams: { searchParams: {
page, page,
page_size: metadata.postPageSize page_size: metadata.postPageSize,
} },
}); });
const totalPage = Math.ceil(total / metadata.postPageSize) const totalPage = Math.ceil(total / metadata.postPageSize);
if (totalPage < Number(page)) { if (totalPage < Number(page)) {
return Astro.redirect('/404') return Astro.redirect("/404");
} }
const {data: categories} = await http.get<ApiResponse<CategoriesStats[]>>("category/stats"); const { data: categories } =
await http.get<ApiResponse<CategoriesStats[]>>("category/stats");
--- ---
<Layout> <Layout>
<IndexView categories={categories} posts={list} page={Number(page)} totalPage={totalPage}/> <IndexView
categories={categories}
posts={list}
page={Number(page)}
totalPage={totalPage}
/>
</Layout> </Layout>

View File

@@ -1,6 +1,6 @@
--- ---
import "@/styles/github-markdown.css" import "@/styles/github-markdown.css";
import "@/styles/github-markdown-reset.css" import "@/styles/github-markdown-reset.css";
import "photoswipe/dist/photoswipe.css"; import "photoswipe/dist/photoswipe.css";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
@@ -13,44 +13,58 @@ const {slug} = Astro.params;
let data: Post; let data: Post;
const http = createHttp(Astro.request.headers) const http = createHttp(Astro.request.headers);
try { try {
const res = await http.get<ApiResponse<Post>>(`post/${slug}`); const res = await http.get<ApiResponse<Post>>(`post/${slug}`);
data = res.data data = res.data;
} catch (error) { } catch (error) {
return Astro.redirect("/404") return Astro.redirect("/404");
} }
const content = await highlightHtmlWithJsdom(data.content) const content = await highlightHtmlWithJsdom(data.content);
const published_at = formatDatetime(data.published_at, 'YYYY 年 M 月 D 日') const published_at = formatDatetime(data.published_at, "YYYY 年 M 月 D 日");
--- ---
<Layout title={data.title} description={data.summary}> <Layout title={data.title} description={data.summary}>
<div class="page-content">
<div class="post"> <div class="post">
<h1 class="post-title">{data.title}</h1> <h1 class="post-title">{data.title}</h1>
<div class="post-meta"> <div class="post-meta">
<div class="published-at"> <div class="published-at">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" <svg
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"
class="lucide lucide-calendar-days-icon lucide-calendar-days"> width="24"
<path d="M8 2v4"/> height="24"
<path d="M16 2v4"/> viewBox="0 0 24 24"
<rect width="18" height="18" x="3" y="4" rx="2"/> fill="none"
<path d="M3 10h18"/> stroke="currentColor"
<path d="M8 14h.01"/> stroke-width="2"
<path d="M12 14h.01"/> stroke-linecap="round"
<path d="M16 14h.01"/> stroke-linejoin="round"
<path d="M8 18h.01"/> class="lucide lucide-calendar-days-icon lucide-calendar-days"
<path d="M12 18h.01"/> >
<path d="M16 18h.01"/> <path d="M8 2v4"></path>
<path d="M16 2v4"></path>
<rect width="18" height="18" x="3" y="4" rx="2"></rect>
<path d="M3 10h18"></path>
<path d="M8 14h.01"></path>
<path d="M12 14h.01"></path>
<path d="M16 14h.01"></path>
<path d="M8 18h.01"></path>
<path d="M12 18h.01"></path>
<path d="M16 18h.01"></path>
</svg> </svg>
{published_at} {published_at}
</div> </div>
<div class="post-view"> <div class="post-view">
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" <svg
p-id="5122"> viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="5122"
>
<path <path
d="M509.618 415.795c-42.695 0-77.253 38.372-77.253 85.738 0 47.352 34.558 86.22 77.253 86.22 42.667 0 76.716-38.867 76.716-86.22 0-47.352-34.049-85.738-76.716-85.738z m1.9-177.9c-211.548 0-383.265 159.859-383.265 274.587 0 114.727 171.717 273.624 383.266 273.624 212.484 0 384.227-162.522 384.227-273.624 0-111.088-171.743-274.587-384.227-274.587z m-1.446 452.006c-89.7 0-162.134-81.71-162.134-181.903 0-101.157 72.435-182.397 162.134-182.397 90.183 0 163.1 81.241 163.1 182.397 0 100.206-72.917 181.903-163.1 181.903z" d="M509.618 415.795c-42.695 0-77.253 38.372-77.253 85.738 0 47.352 34.558 86.22 77.253 86.22 42.667 0 76.716-38.867 76.716-86.22 0-47.352-34.049-85.738-76.716-85.738z m1.9-177.9c-211.548 0-383.265 159.859-383.265 274.587 0 114.727 171.717 273.624 383.266 273.624 212.484 0 384.227-162.522 384.227-273.624 0-111.088-171.743-274.587-384.227-274.587z m-1.446 452.006c-89.7 0-162.134-81.71-162.134-181.903 0-101.157 72.435-182.397 162.134-182.397 90.183 0 163.1 81.241 163.1 182.397 0 100.206-72.917 181.903-163.1 181.903z"
p-id="5123"></path> p-id="5123"></path>
@@ -59,11 +73,8 @@ const published_at = formatDatetime(data.published_at, 'YYYY 年 M 月 D 日')
</div> </div>
</div> </div>
<div <div class="markdown-body" data-color-mode="dark" set:html={content} />
class="markdown-body" </div>
data-color-mode="dark"
set:html={content}
></div>
</div> </div>
</Layout> </Layout>
@@ -73,8 +84,7 @@ const published_at = formatDatetime(data.published_at, 'YYYY 年 M 月 D 日')
border-radius: 12px; border-radius: 12px;
overflow: auto; overflow: auto;
padding: 24px; padding: 24px;
box-shadow: rgba(149, 157, 165, 0.2) 0 2px 14px -4px; box-shadow: var(--shadow);
border: 1px solid #e7e8ec;
} }
.post-title { .post-title {
@@ -140,43 +150,44 @@ const published_at = formatDatetime(data.published_at, 'YYYY 年 M 月 D 日')
} }
</style> </style>
<script> <script>
import PhotoSwipeLightbox from "photoswipe/lightbox" import PhotoSwipeLightbox from "photoswipe/lightbox";
const init = async () => { const init = async () => {
const post = document.querySelector('.post')! const post = document.querySelector(".post")!;
const images = Array.from(post.querySelectorAll('img')) const images = Array.from(post.querySelectorAll("img"));
const waitImageLoaded = (img: HTMLImageElement) => { const waitImageLoaded = (img: HTMLImageElement) => {
if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) { if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {
return Promise.resolve() return Promise.resolve();
} }
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
img.addEventListener("load", () => resolve(), {once: true}) img.addEventListener("load", () => resolve(), { once: true });
img.addEventListener("error", () => resolve(), {once: true}) img.addEventListener("error", () => resolve(), { once: true });
}) });
} };
await Promise.all( await Promise.all(
images.map(async (img) => { images.map(async (img) => {
if (img.closest("a")) return if (img.closest("a")) return;
await waitImageLoaded(img) await waitImageLoaded(img);
const link = document.createElement("a") const link = document.createElement("a");
link.href = img.currentSrc || img.src link.href = img.currentSrc || img.src;
link.target = "_blank" link.target = "_blank";
link.rel = "noreferrer" link.rel = "noreferrer";
link.dataset.pswpWidth = String(img.naturalWidth || img.width || 1200) link.dataset.pswpWidth = String(img.naturalWidth || img.width || 1200);
link.dataset.pswpHeight = String(img.naturalHeight || img.height || 800) link.dataset.pswpHeight = String(
img.naturalHeight || img.height || 800,
);
img.parentNode?.insertBefore(link, img) img.parentNode?.insertBefore(link, img);
link.appendChild(img) link.appendChild(img);
}) }),
) );
const lightbox = new PhotoSwipeLightbox({ const lightbox = new PhotoSwipeLightbox({
gallery: ".post", gallery: ".post",
@@ -192,10 +203,10 @@ const published_at = formatDatetime(data.published_at, 'YYYY 年 M 月 D 日')
bgOpacity: 0.5, bgOpacity: 0.5,
tapAction: "close", tapAction: "close",
bgClickAction: "close", bgClickAction: "close",
}) });
lightbox.init() lightbox.init();
} };
init() init();
</script> </script>

View File

@@ -7,7 +7,7 @@
--shadow: 0 2px 8px rgba(0, 0, 0, 0.06); --shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
--shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.10); --shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.10);
--card-bg: #ffffff; --card-bg: #ffffff;
--text: #2b2f36; --text-color: #2b2f36;
--text-secondary: #6b7280; --text-secondary: #6b7280;
--border: #e5e7eb; --border: #e5e7eb;
--primary: #2b2f36; --primary: #2b2f36;
@@ -16,7 +16,7 @@
.dark { .dark {
--background: #0a0a0a; --background: #0a0a0a;
--card-bg: #161b22; --card-bg: #161b22;
--text: #2b2f36; --text-color: #ffffff;
--text-secondary: #e5e7eb; --text-secondary: #e5e7eb;
--border: #e5e7eb; --border: #e5e7eb;
--primary: #3d414a; --primary: #3d414a;
@@ -24,18 +24,10 @@
html, html,
body { body {
width: 100%;
min-height: 100vh; min-height: 100vh;
font-size: 16px; font-size: 16px;
}
html {
background: var(--background); background: var(--background);
} color: var(--text-color);
html.dark {
background: var(--background);
color: #fff;
} }
body { body {
@@ -43,18 +35,21 @@ body {
flex-direction: column; flex-direction: column;
} }
main { .main {
max-width: var(--layout-width);
flex: 1; flex: 1;
width: 100%;
margin: 0 auto;
padding: 32px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.page-content {
width: 100%;
max-width: var(--layout-width);
margin: 0 auto;
padding: 32px;
}
@media (max-width: 768px) { @media (max-width: 768px) {
main { .page-content {
padding: 16px; padding: 16px;
} }
} }