优化
22
.gitignore
vendored
@ -25,24 +25,4 @@ test/
|
||||
|
||||
/public/hanplayer
|
||||
/public/MineWeb
|
||||
/public/other
|
||||
/src/content/blog/*
|
||||
!/src/content/blog
|
||||
/src/content/blog/2024/*
|
||||
!/src/content/blog/2024
|
||||
/src/content/blog/2024/07/*
|
||||
!/src/content/blog/2024/07
|
||||
/src/content/blog/2024/08/*
|
||||
!/src/content/blog/2024/08
|
||||
/src/content/blog/2024/09/*
|
||||
!/src/content/blog/2024/09
|
||||
/src/content/blog/2024/11/*
|
||||
!/src/content/blog/2024/11
|
||||
/src/content/blog/2024/12/*
|
||||
!/src/content/blog/2024/12
|
||||
!/src/content/blog/2024/07/【开源】骤雨重山无限存储图床托管于(Cloudflare Pages).md
|
||||
!/src/content/blog/2024/08/Cloudflare优选IP➕DnsPod的DDNS自动切换.md
|
||||
!/src/content/blog/2024/09/【开源】HanAnalytics访问分析Web统计托管于(Cloudflare Pages).md
|
||||
!/src/content/blog/2024/09/基于AI的微博动态心情分析【开源】.md
|
||||
!/src/content/blog/2024/11/推荐一个开源项目WebWatermark图片添加水印在线小助手.md
|
||||
!/src/content/blog/2024/12/【开源】Tarot-塔罗牌占卜.md
|
||||
/public/other
|
||||
69
README.md
@ -1,2 +1,71 @@
|
||||
# vhAstro-Theme
|
||||
一款简约的 Astro 主题
|
||||
|
||||
# Astro Starter Kit: Blog
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template blog
|
||||
```
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||

|
||||
|
||||
Features:
|
||||
|
||||
- ✅ Minimal styling (make it your own!)
|
||||
- ✅ 100/100 Lighthouse performance
|
||||
- ✅ SEO-friendly with canonical URLs and OpenGraph data
|
||||
- ✅ Sitemap support
|
||||
- ✅ RSS Feed support
|
||||
- ✅ Markdown & MDX support
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
├── public/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── content/
|
||||
│ ├── layouts/
|
||||
│ └── pages/
|
||||
├── astro.config.mjs
|
||||
├── README.md
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
||||
## Credit
|
||||
|
||||
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).
|
||||
|
||||
@ -12,12 +12,12 @@
|
||||
"@astrojs/mdx": "^4.0.8",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"astro": "^5.2.5",
|
||||
"astro": "^5.3.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dplayer": "^1.27.1",
|
||||
"hls.js": "^1.5.20",
|
||||
"nprogress": "^0.2.0",
|
||||
"overlayscrollbars": "^2.10.1",
|
||||
"overlayscrollbars": "^2.11.0",
|
||||
"remark-directive": "^3.0.1",
|
||||
"twikoo": "1.6.41",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
|
||||
@ -1,4 +1,27 @@
|
||||
/*
|
||||
@import url('./HarmonyOS_Sans_Regular/result.css');
|
||||
@import url('./NotoSans/result.css'); */
|
||||
@import url('./SFMono-Regular/result.css');
|
||||
|
||||
/* @import url('./HarmonyOS_Sans/100/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/100/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/200/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/200/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/300/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/300/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/400/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/400/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/500/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/500/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/600/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/600/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/700/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/700/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/800/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/800/sc/result.css');
|
||||
@import url('./HarmonyOS_Sans/900/global/result.css');
|
||||
@import url('./HarmonyOS_Sans/900/sc/result.css'); */
|
||||
|
||||
@import url('./MiSans/100/result.css');
|
||||
@import url('./MiSans/200/result.css');
|
||||
@import url('./MiSans/300/result.css');
|
||||
|
||||
2
public/assets/images/footer/astro.svg
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="101" height="20" role="img" aria-label="Frame: Astro"><title>Frame: Astro</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="101" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="62" height="20" fill="#555"/><rect x="62" width="39" height="20" fill="#bc52ee"/><rect width="101" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjYmM1MmVlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+QXN0cm88L3RpdGxlPjxwYXRoIGQ9Ik04LjM1OCAyMC4xNjJjLTEuMTg2LTEuMDctMS41MzItMy4zMTYtMS4wMzgtNC45NDQuODU2IDEuMDI2IDIuMDQzIDEuMzUyIDMuMjcyIDEuNTM1IDEuODk3LjI4MyAzLjc2LjE3NyA1LjUyMi0uNjc4LjIwMi0uMDk4LjM4OC0uMjI5LjYwOC0uMzYuMTY2LjQ3My4yMDkuOTUuMTUxIDEuNDM3LS4xNCAxLjE4NS0uNzM4IDIuMS0xLjY4OCAyLjc5NC0uMzguMjc3LS43ODIuNTI1LTEuMTc1Ljc4Ny0xLjIwNS44MDQtMS41MzEgMS43NDctMS4wNzggMy4xMTlsLjA0NC4xNDhhMy4xNTggMy4xNTggMCAwIDEtMS40MDctMS4xODggMy4zMSAzLjMxIDAgMCAxLS41NDQtMS44MTVjLS4wMDQtLjMyLS4wMDQtLjY0Mi0uMDQ4LS45NTgtLjEwNi0uNzY5LS40NzItMS4xMTMtMS4xNjEtMS4xMzMtLjcwNy0uMDItMS4yNjcuNDExLTEuNDE1IDEuMDktLjAxMi4wNTMtLjAyOC4xMDQtLjA0NS4xNjVoLjAwMnptLTUuOTYxLTQuNDQ1czMuMjQtMS41NzUgNi40OS0xLjU3NWwyLjQ1MS03LjU2NWMuMDkyLS4zNjYuMzYtLjYxNC42NjItLjYxNC4zMDIgMCAuNTcuMjQ4LjY2Mi42MTRsMi40NSA3LjU2NWMzLjg1IDAgNi40OTEgMS41NzUgNi40OTEgMS41NzVMMTYuMDg4LjcyN0MxNS45My4yODUgMTUuNjYzIDAgMTUuMzAzIDBIOC42OTdjLS4zNiAwLS42MTUuMjg1LS43ODQuNzI3bC01LjUxNiAxNC45OXoiLz48L3N2Zz4="/><text aria-hidden="true" x="405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">Frame</text><text x="405" y="140" transform="scale(.1)" fill="#fff" textLength="350">Frame</text><text aria-hidden="true" x="805" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="290">Astro</text><text x="805" y="140" transform="scale(.1)" fill="#fff" textLength="290">Astro</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
public/assets/images/footer/copyright.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="167" height="20" aria-label="Copyright: BY-NC-SA 4.0"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="167" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h80v20H0z"/><path fill="#d42328" d="M80 0h87v20H80z"/><path fill="url(#b)" d="M0 0h167v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+Q2xhcmlzPC90aXRsZT48cGF0aCBkPSJNMTEuNTYgMGEzLjM0IDMuMzQgMCAwMC0uNTcuMDQzTDIyLjk0NyAxMiAxMC45OSAyMy45NTdjLjEzMi4wMjIuMzA3LjA0My41Ny4wNDMgNi42MjYgMCAxMi01LjM3NSAxMi0xMnMtNS4zNzQtMTItMTItMTJ6bS0xLjUzNSAyLjQxNEM0LjczOCAyLjQxNC40NCA2LjcxMy40NCAxMnM0LjMgOS41ODggOS41ODYgOS41ODhjLjI2NCAwIC40NC0uMDIzLjU3LS4wNDVMMS4wNTQgMTJsOS41NDMtOS41NDNhMy4zMzcgMy4zMzcgMCAwMC0uNTctLjA0M3ptLjc0NiAyLjQ1N2MtLjI2MyAwLS40MzguMDIxLS41Ny4wNDNMMTcuMjg3IDEybC03LjA4NiA3LjA4NmMuMTMyLjAyMi4zMDcuMDQ1LjU3LjA0NSAzLjkyNyAwIDcuMTMtMy4yMDQgNy4xMy03LjEzMXMtMy4yMDMtNy4xMjktNy4xMy03LjEyOXptLS40MTYgMi40MzRBNC43MDEgNC43MDEgMCAwMDUuNjYgMTJhNC43MDEgNC43MDEgMCAwMDQuNjk1IDQuNjk1Yy4yNjQgMCAuNDQtLjAyMy41Ny0uMDQ1TDYuMjc0IDEybDQuNjUzLTQuNjVhMy4yOTYgMy4yOTYgMCAwMC0uNTctLjA0NVoiLz48L3N2Zz4="/><text aria-hidden="true" x="495" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Copyright</text><text x="495" y="140" transform="scale(.1)" textLength="530">Copyright</text><text aria-hidden="true" x="1225" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="770">BY-NC-SA 4.0</text><text x="1225" y="140" transform="scale(.1)" textLength="770">BY-NC-SA 4.0</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
public/assets/images/footer/hananalytics.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="145" height="20" role="img" aria-label="Access: HanAnalytics"><title>Access: HanAnalytics</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="145" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="64" height="20" fill="#f5f5f5"/><rect x="64" width="81" height="20" fill="#454957"/><rect width="145" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjM2IzZjRmIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+QXBhY2hlIFNwYXJrPC90aXRsZT48cGF0aCBkPSJNMTAuODEyIDBjLS40MjUuMDEzLS44NDUuMjE1LTEuMTk2LjYwNWEzLjU5MyAzLjU5MyAwIDAwLS40OTMuNzIyYy0uMzU1LjY2Ny0uNDI1IDEuNDE1LS41NTYgMi4xNDNhNTUxLjkgNTUxLjkgMCAwMC0uNzI2IDQuMDg3Yy0uMDI3LjE2LS4wOTYuMjI3LS4yNDQuMjczQzUuODMgOC4zODYgNC4wNiA4Ljk0IDIuMyA5LjUxNGMtLjM4Ny4xMjUtLjc3My4yODktMS4xMTQuNTA2LTEuMDQyLjY2NS0xLjE5NiAxLjc1My0uNDE1IDIuNzEuMzQ2LjQyMi43OS43MTUgMS4yODQuOTM2IDEuMS40OSAyLjIwMi45NzYgMy4zIDEuNDcuMDE5LjAxLjAzNi4wMTMuMDUzLjAxOWgtLjAwNGwxLjMwNi41MzVjMCAuMDIzLjAwMi4wNDUgMCAuMDczLS4yIDIuMDMtLjM5IDQuMDYzLS41OCA2LjA5NS0uMDQuNDE5LS4wMTIuODMxLjEzNCAxLjIzLjMxNy44NyAxLjA2NSAxLjE0OCAxLjg4MS43MDEuMzcyLS4yMDQuNjY2LS40OTcuOTM3LS44MTggMS4zNzItMS42MjMgMi43NDYtMy4yNDQgNC4xMTMtNC44NzIuMTExLS4xMzMuMjA1LS4xNS4zNjMtLjA5OC4zNDkuMTE3LjY5Ny4yMzEgMS4wNDUuMzQ3aC4wMDFjLjAyLjAxMi4wNDUuMDIuMDczLjAzbC4xNDIuMDQyYzEuMjQ4LjQxNiAyLjY4Ljc3NSAzLjkyOSAxLjE5LjQuMTMyLjYyMi4xNjQgMS4wNDUuMDk4LjMxMS0uMDQ4LjU5Mi0uMDYyLjgyOC0uMjM2LjYwMi0uMzMuOTk1LS45NTcuOTg4LTEuNjgyLS4wMDUtLjQyNy0uMTU0LS44MTMtLjM1LTEuMTg2LS44Mi0xLjU1Ni0xLjYzNy0zLjExMy0yLjQ2MS00LjY2Ni0uMDc4LS4xNDgtLjA3Ni0uMjQzLjAzNy0uMzc1IDEuMzgxLTEuNjE1IDIuNzU2LTMuMjM2IDQuMTMzLTQuODU1LjI3Mi0uMzIuNTEzLS42NTguNjUzLTEuMDU4LjMwOC0uODc4LS4wOS0xLjU3LTEtMS43NDFhMi43ODMgMi43ODMgMCAwMC0xLjIzNS4wNjljLTEuOTc0LjUyMS0zLjk0NyAxLjA0MS01LjkxOCAxLjU3LS4xNzUuMDQ3LS4yNi4wMTUtLjM1NS0uMTQ0YTM1My4wOCAzNTMuMDggMCAwMC0yLjQyMS00LjAxOCA0LjYxIDQuNjEgMCAwMC0uNjUyLS44NDljLS4zNzEtLjM3LS44MDItLjU0OS0xLjIyNy0uNTM2em0uMTcyIDMuNzAzYS41OTIuNTkyIDAgMDEuMTg5LjIxMWMuODcgMS40NDYgMS43NDIgMi44OSAyLjYwOSA0LjMzOC4wNy4xMTguMTM1LjE2LjI3Ny4xMjEgMS41MjUtLjQxIDMuMDUyLS44MTMgNC41NzktMS4yMTcuMzY3LS4wOTguNzM1LS4xOTMgMS4xMDMtLjI4OWEuMzk5LjM5OSAwIDAxLS4xLjJjLTEuMjU5IDEuNDgtMi41MTYgMi45NjItMy43NzkgNC40MzgtLjExLjEzLS4xMi4yMi0uMDQuMzcuOTM3IDEuODAzIDEuNzY4IDMuMzA5IDIuNDk4IDQuNzZsLTMuNjk2LTEuMDE5Yy0uNTM4LS4xOC0xLjA3Ny0uMzU4LTEuNjE1LS41MzktLjE2My0uMDU1LS4yNS0uMDMtLjM2LjEtMS4yNDggMS40ODgtMi41MDQgMi45Ny0zLjc1OSA0LjQ1NGEuMzk4LjM5OCAwIDAxLS4xOC4xMzJjLjAzNS0uMzc4LjA2OC0uNzU3LjEwNC0xLjEzNi4xNDktMS41NzIuMjk3LTMuMTQ0LjQ1MS00LjcxNi0uMDMtLjMxOC4xMTctLjQwNS0uMzIyLS41NDUtMS40OTMtLjU5My0zLjM0Ni0xLjMyMS00LjgxNi0xLjkwNWEuNTk1LjU5NSAwIDAxLjI0LS4xMzRjMS43OTctLjU3IDMuNTk1LTEuMTQgNS4zOTQtMS43MDUuMTI3LS4wNC4xOTktLjA5Mi4yMTEtLjIzMy4wMTMtLjE0OC4wNS0uMjk0LjA3Ni0uNDQxLjI0MS0xLjM2My40ODMtMi43MjYuNzI2LTQuMDg4LjA2OC0uMzg2LjE0LS43NzEuMjEtMS4xNTd6Ii8+PC9zdmc+"/><text aria-hidden="true" x="415" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="370">Access</text><text x="415" y="140" transform="scale(.1)" fill="#333" textLength="370">Access</text><text aria-hidden="true" x="1035" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="710">HanAnalytics</text><text x="1035" y="140" transform="scale(.1)" fill="#fff" textLength="710">HanAnalytics</text></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
1
public/assets/images/footer/icp.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="159" height="20" aria-label="浙ICP备:2022035705号"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="159" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h68v20H0z"/><path fill="#e1d492" d="M68 0h91v20H68z"/><path fill="url(#b)" d="M0 0h159v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/png;base64,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"/><text aria-hidden="true" x="435" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">浙ICP备</text><text x="435" y="140" transform="scale(.1)" textLength="410">浙ICP备</text><text aria-hidden="true" x="1125" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="810">2022035705号</text><text x="1125" y="140" transform="scale(.1)" fill="#333" textLength="810">2022035705号</text></g></svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
1
public/assets/images/footer/ing.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="98" height="20" aria-label="小韩: 营业中"><style></style><linearGradient id="a" x2="0" y2="100%"><stop offset="0" stop-color="#fcfcfc" stop-opacity="0"/><stop offset="1" stop-opacity=".1"/></linearGradient><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#ccc" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><g stroke="#d5d5d5"><rect stroke="none" fill="#fcfcfc" x=".5" y=".5" width="50" height="19" rx="2"/><rect x="56.5" y=".5" width="41" height="19" rx="2" fill="#fafafa"/><path stroke="#fafafa" d="M56 7.5h.5v5H56z"/><path d="m56.5 6.5-3 3v1l3 3" stroke="d5d5d5" fill="#fafafa"/></g><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRDMzQzQzIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+Q2FrZVBIUDwvdGl0bGU+PHBhdGggZD0iTTAgMTMuODc1djMuNzQ1YzAgMi4wNjcgNS4zNyAzLjc0MyAxMiAzLjc0M1YxNy42MmMtNi42MyAwLTEyLTEuNjgtMTItMy43NDN2LS4wMDJ6bTIxLjM4NCAyLjMzM0wxMiAxMy44NzV2My43NDVsOS4zODQgMi4zMzNDMjMuMDIgMTkuMzEzIDI0IDE4LjUwMyAyNCAxNy42MnYtMy43NDVjMCAuODgyLS45OCAxLjY5Mi0yLjYxNiAyLjMzM3pNMTIgMTAuMTMzdjMuNzQyYy02LjYyNyAwLTEyLTEuNjc3LTEyLTMuNzQ0VjYuMzhjMC0yLjA2NCA1LjM3LTMuNzQzIDEyLTMuNzQzIDYuNjI1IDAgMTIgMS42OCAxMiAzLjc0NHYzLjc1YzAgLjg4My0uOTggMS42OS0yLjYxNiAyLjMzNEwxMiAxMC4xM3YuMDAzeiIvPjwvc3ZnPg=="/><g aria-hidden="true" fill="#333" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" text-rendering="geometricPrecision" font-weight="700" font-size="110"><rect id="llink" stroke="#d5d5d5" fill="url(#a)" x=".5" y=".5" width="50" height="19" rx="2"/><text aria-hidden="true" x="335" y="150" fill="#fff" transform="scale(.1)" textLength="230">小韩</text><text x="335" y="140" transform="scale(.1)" textLength="230">小韩</text><text aria-hidden="true" x="765" y="150" fill="#fff" transform="scale(.1)" textLength="330">营业中</text><text id="rlink" x="765" y="140" transform="scale(.1)" textLength="330">营业中</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
public/assets/images/footer/sitemap.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="105" height="20" aria-label="SEO: Sitemap"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="105" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#c5b9a3" d="M0 0h50v20H0z"/><path fill="#738b71" d="M50 0h55v20H50z"/><path fill="url(#b)" d="M0 0h105v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjNTk0ZTM4IiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+UlNTPC90aXRsZT48cGF0aCBkPSJNMTkuMTk5IDI0QzE5LjE5OSAxMy40NjcgMTAuNTMzIDQuOCAwIDQuOFYwYzEzLjE2NSAwIDI0IDEwLjgzNSAyNCAyNGgtNC44MDF6TTMuMjkxIDE3LjQxNWMxLjgxNCAwIDMuMjkzIDEuNDc5IDMuMjkzIDMuMjk1IDAgMS44MTMtMS40ODUgMy4yOS0zLjMwMSAzLjI5QzEuNDcgMjQgMCAyMi41MjYgMCAyMC43MXMxLjQ3NS0zLjI5NCAzLjI5MS0zLjI5NXpNMTUuOTA5IDI0aC00LjY2NWMwLTYuMTY5LTUuMDc1LTExLjI0NS0xMS4yNDQtMTEuMjQ1VjguMDljOC43MjcgMCAxNS45MDkgNy4xODQgMTUuOTA5IDE1LjkxeiIvPjwvc3ZnPg=="/><text aria-hidden="true" x="345" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="230">SEO</text><text x="345" y="140" transform="scale(.1)" fill="#594E38" textLength="230">SEO</text><text aria-hidden="true" x="765" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="450">Sitemap</text><text x="765" y="140" transform="scale(.1)" textLength="450">Sitemap</text></g></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
2
public/assets/images/footer/theme.svg
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="157" height="20" role="img" aria-label="Theme: vhAstro Theme"><title>Theme: vhAstro Theme</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="157" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="64" height="20" fill="#555"/><rect x="64" width="93" height="20" fill="#fff"/><rect width="157" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+QXN0cm88L3RpdGxlPjxwYXRoIGQ9Ik04LjM1OCAyMC4xNjJjLTEuMTg2LTEuMDctMS41MzItMy4zMTYtMS4wMzgtNC45NDQuODU2IDEuMDI2IDIuMDQzIDEuMzUyIDMuMjcyIDEuNTM1IDEuODk3LjI4MyAzLjc2LjE3NyA1LjUyMi0uNjc4LjIwMi0uMDk4LjM4OC0uMjI5LjYwOC0uMzYuMTY2LjQ3My4yMDkuOTUuMTUxIDEuNDM3LS4xNCAxLjE4NS0uNzM4IDIuMS0xLjY4OCAyLjc5NC0uMzguMjc3LS43ODIuNTI1LTEuMTc1Ljc4Ny0xLjIwNS44MDQtMS41MzEgMS43NDctMS4wNzggMy4xMTlsLjA0NC4xNDhhMy4xNTggMy4xNTggMCAwIDEtMS40MDctMS4xODggMy4zMSAzLjMxIDAgMCAxLS41NDQtMS44MTVjLS4wMDQtLjMyLS4wMDQtLjY0Mi0uMDQ4LS45NTgtLjEwNi0uNzY5LS40NzItMS4xMTMtMS4xNjEtMS4xMzMtLjcwNy0uMDItMS4yNjcuNDExLTEuNDE1IDEuMDktLjAxMi4wNTMtLjAyOC4xMDQtLjA0NS4xNjVoLjAwMnptLTUuOTYxLTQuNDQ1czMuMjQtMS41NzUgNi40OS0xLjU3NWwyLjQ1MS03LjU2NWMuMDkyLS4zNjYuMzYtLjYxNC42NjItLjYxNC4zMDIgMCAuNTcuMjQ4LjY2Mi42MTRsMi40NSA3LjU2NWMzLjg1IDAgNi40OTEgMS41NzUgNi40OTEgMS41NzVMMTYuMDg4LjcyN0MxNS45My4yODUgMTUuNjYzIDAgMTUuMzAzIDBIOC42OTdjLS4zNiAwLS42MTUuMjg1LS43ODQuNzI3bC01LjUxNiAxNC45OXoiLz48L3N2Zz4="/><text aria-hidden="true" x="415" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">Theme</text><text x="415" y="140" transform="scale(.1)" fill="#fff" textLength="370">Theme</text><text aria-hidden="true" x="1095" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="830">vhAstro Theme</text><text x="1095" y="140" transform="scale(.1)" fill="#333" textLength="830">vhAstro Theme</text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@ -1,7 +1,7 @@
|
||||
---
|
||||
// 获取用户配置数据
|
||||
import SITE_CONFIG from "../config";
|
||||
import { fmtTime, fmtDate } from "../utils/index";
|
||||
import { fmtDate } from "../utils/index";
|
||||
const { Avatar, Author, Motto, WebSites } = SITE_CONFIG;
|
||||
// 获取文章数据
|
||||
import { getCategories, getTags, getRecommendArticles } from "../utils/getPostInfo";
|
||||
@ -78,7 +78,7 @@ import "../styles/components/Aside.less";
|
||||
</p>
|
||||
<p class="info">
|
||||
<span>{(await i).title}</span>
|
||||
<time>{fmtDate((await i).date)}</time>
|
||||
<time>{fmtDate((await i).date)}前</time>
|
||||
</p>
|
||||
</a>
|
||||
))
|
||||
|
||||
@ -3,20 +3,19 @@ import "../styles/components/Comment.less";
|
||||
---
|
||||
|
||||
<section class="vh-comment"><section></section></section>
|
||||
|
||||
<script>
|
||||
import updateRouter from "../utils/updateRouter";
|
||||
import { LoadScript } from "../utils/index";
|
||||
import SITE_CONFIG from "../config";
|
||||
const { Twikoo } = SITE_CONFIG;
|
||||
import SITE_INFO from "../config";
|
||||
declare const twikoo: any;
|
||||
// 初始化评论插件
|
||||
updateRouter("afterMount", async () => {
|
||||
if (!document.querySelector(".vh-comment>section")) return;
|
||||
await LoadScript("https://registry.npmmirror.com/twikoo/1.6.41/files/dist/twikoo.all.min.js");
|
||||
twikoo.init({
|
||||
envId: Twikoo.envId,
|
||||
el: ".vh-comment>section"
|
||||
SITE_INFO.Twikoo.envId &&
|
||||
updateRouter("afterMount", async () => {
|
||||
if (!document.querySelector(".vh-comment>section")) return;
|
||||
await LoadScript("https://registry.npmmirror.com/twikoo/1.6.41/files/dist/twikoo.all.min.js");
|
||||
twikoo.init({
|
||||
envId: SITE_INFO.Twikoo.envId,
|
||||
el: ".vh-comment>section"
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
17
src/components/Footer.astro
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
import { fmtDate } from "../utils/index";
|
||||
// 页面内容的元数据
|
||||
import SITE_CONFIG from "../config";
|
||||
const { CreateTime } = SITE_CONFIG;
|
||||
// 基础 样式
|
||||
import "../styles/Footer.less";
|
||||
---
|
||||
|
||||
<footer class="vh-footer">
|
||||
<main>
|
||||
<p>
|
||||
<img src="/assets/images/footer/ing.svg" /><span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path fill="#fff" d="M269.4 2.9C265.2 1 260.7 0 256 0s-9.2 1-13.4 2.9L54.3 82.8c-22 9.3-38.4 31-38.3 57.2c.5 99.2 41.3 280.7 213.6 363.2c16.7 8 36.1 8 52.8 0C454.7 420.7 495.5 239.2 496 140c.1-26.2-16.3-47.9-38.3-57.2L269.4 2.9zM144 221.3c0-33.8 27.4-61.3 61.3-61.3c16.2 0 31.8 6.5 43.3 17.9l7.4 7.4 7.4-7.4c11.5-11.5 27.1-17.9 43.3-17.9c33.8 0 61.3 27.4 61.3 61.3c0 16.2-6.5 31.8-17.9 43.3l-82.7 82.7c-6.2 6.2-16.4 6.2-22.6 0l-82.7-82.7c-11.5-11.5-17.9-27.1-17.9-43.3z"></path></svg><cite>稳定运行</cite><em>{fmtDate(CreateTime)}</em></span><a href="https://analytics.vvhan.com" target="_blank" rel="noopener noreferrer"><img src="/assets/images/footer/hananalytics.svg" /></a>
|
||||
</p>
|
||||
<p><a href="https://astro.build/" target="_blank" rel="noopener noreferrer"><img src="/assets/images/footer/astro.svg" /></a><a href="#" target="_blank" rel="noopener noreferrer"><img src="/assets/images/footer/theme.svg" /></a><a href="/sitemap-index.xml"><img src="/assets/images/footer/sitemap.svg" /></a><a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer"><img src="/assets/images/footer/icp.svg" /></a></p>
|
||||
</main>
|
||||
</footer>
|
||||
@ -23,7 +23,7 @@ import "../styles/components/Pagination.less";
|
||||
}
|
||||
<!-- 总页的前一页 -->
|
||||
{
|
||||
(!data.next || !data.last) && (
|
||||
(!data.next || !data.last) && data.prev && (
|
||||
<a class={`vh-pagination-item`} href={data.prev}>
|
||||
{fmtPage(data.prev)}
|
||||
</a>
|
||||
@ -33,7 +33,7 @@ import "../styles/components/Pagination.less";
|
||||
<a class="vh-pagination-item active">{fmtPage(data.current) || "1"}</a>
|
||||
<!-- 第一页的后一页 -->
|
||||
{
|
||||
(!data.prev || !data.first) && (
|
||||
(!data.prev || !data.first) && data.next && (
|
||||
<a class={`vh-pagination-item`} href={data.next}>
|
||||
{fmtPage(data.next)}
|
||||
</a>
|
||||
|
||||
@ -38,7 +38,7 @@ export default {
|
||||
// 博客音乐组件解析接口
|
||||
vhMusicApi: 'https://meting-dd.2333332.xyz/api',
|
||||
// 评论组件 Twikoo
|
||||
Twikoo: {
|
||||
envId: "https://twikoo.vvhan.com/.netlify/functions/twikoo",
|
||||
}
|
||||
Twikoo: { envId: 'https://twikoo.vvhan.com/.netlify/functions/twikoo' },
|
||||
// Han Analytics 统计(https://github.com/uxiaohan/HanAnalytics)
|
||||
HanAnalytics: { enable: true, server: 'https://analytics.vvhan.com', siteId: 'Hello-HanHexoBlog' }
|
||||
}
|
||||
@ -5,6 +5,8 @@ const { title, keywords, description, activeNav } = Astro.props;
|
||||
import Head from "../components/Head.astro";
|
||||
// 顶部 Header
|
||||
import Header from "../components/Header.astro";
|
||||
// 底部 Footer
|
||||
import Footer from "../components/Footer.astro";
|
||||
// 返回顶部
|
||||
import BackTop from "../components/BackTop.astro";
|
||||
// 手机端侧边栏
|
||||
@ -24,6 +26,7 @@ import "../styles/Layout.less";
|
||||
<main class="vh-main">
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
<BackTop />
|
||||
<script>
|
||||
import updateRouter from "../utils/updateRouter";
|
||||
@ -35,6 +38,10 @@ import "../styles/Layout.less";
|
||||
import NProgress from "nprogress";
|
||||
import "nprogress/nprogress.css";
|
||||
NProgress.configure({ easing: "ease", speed: 500, showSpinner: false, trickleSpeed: 200, minimum: 0.3 });
|
||||
// Han Analytics 统计
|
||||
import SITE_INFO from "../config";
|
||||
const { HanAnalytics } = SITE_INFO;
|
||||
import { LoadScript } from "../utils/index";
|
||||
// 初始化 图片懒加载初
|
||||
updateRouter("afterMount", () => {
|
||||
// 预加载搜索数据
|
||||
@ -43,6 +50,8 @@ import "../styles/Layout.less";
|
||||
vhLzImgInit();
|
||||
// 进入页面,进度条结束
|
||||
NProgress.done();
|
||||
// Han Analytics 统计
|
||||
HanAnalytics.enable && LoadScript(`${HanAnalytics.server}/tracker.min.js`, [{ k: "data-website-id", v: HanAnalytics.siteId }]);
|
||||
});
|
||||
// 离开页面,进度条开始
|
||||
updateRouter("beforeCreate", NProgress.start);
|
||||
|
||||
19
src/page_data/Link.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export default {
|
||||
// API 接口请求优先,数据格式保持和 data 一致
|
||||
api: '',
|
||||
// api 为空则使用 data 静态数据
|
||||
data: [
|
||||
{
|
||||
"name": "韩小韩博客",
|
||||
"link": "https://www.vvhan.com",
|
||||
"avatar": "https://q1.qlogo.cn/g?b=qq&nk=1655466387&s=640",
|
||||
"descr": "运气是计划之外的东西."
|
||||
},
|
||||
{
|
||||
"name": "韩小韩API",
|
||||
"link": "https://api.vvhan.com",
|
||||
"avatar": "https://api.vvhan.com/static/images/logo.webp",
|
||||
"descr": "免费Web API数据接口调用服务平台."
|
||||
}
|
||||
]
|
||||
}
|
||||
31
src/page_data/Talking.ts
Normal file
@ -0,0 +1,31 @@
|
||||
export default {
|
||||
// API 接口请求优先,数据格式保持和 data 一致
|
||||
api: '',
|
||||
// api 为空则使用 data 静态数据
|
||||
// 注意:图片请用 vh-img-flex 类包裹
|
||||
data: [
|
||||
{
|
||||
"date": "2025-02-12 19:36:16",
|
||||
"tags": [
|
||||
"树",
|
||||
"夕阳"
|
||||
],
|
||||
"content": "好美🌲<p class=\"vh-img-flex\"><img src=\"https://i0.wp.com/shp.qpic.cn/collector/1655466387/937ec070-8448-4c7b-9c8b-abd41ce892cb/0\"></p>"
|
||||
},
|
||||
{
|
||||
"date": "2024-10-08 18:18:18",
|
||||
"tags": [
|
||||
"日常",
|
||||
"工作"
|
||||
],
|
||||
"content": "下班!"
|
||||
},
|
||||
{
|
||||
"date": "2024-10-05 16:16:06",
|
||||
"tags": [
|
||||
"日常"
|
||||
],
|
||||
"content": "记录第一条说说"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
// 页面 Info
|
||||
import SITE_CONFIG from "../../config";
|
||||
const { Description } = SITE_CONFIG;
|
||||
const { Description, Twikoo } = SITE_CONFIG;
|
||||
// Aside组件
|
||||
import Aside from "../../components/Aside.astro";
|
||||
// 公共 Layout
|
||||
@ -42,7 +42,7 @@ import "../../styles/About.less";
|
||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener nofollow"><img data-vh-lz-src="https://img.shields.io/badge/VS_Code-007ACC?style=for-the-badge&logo=visual-studio-code&logoColor=white" alt="VS Code" /></a>
|
||||
</div>
|
||||
</main>
|
||||
<Comment />
|
||||
{Twikoo.envId && <Comment envId={Twikoo.envId} />}
|
||||
</section>
|
||||
<Aside />
|
||||
</section>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
---
|
||||
import { fmtDate } from "../../utils/index";
|
||||
import { getDescription, fmtTime } from "../../utils/index";
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import { render } from "astro:content";
|
||||
@ -11,6 +12,7 @@ type Props = CollectionEntry<"blog">;
|
||||
const post: any = Astro.props;
|
||||
// 页面 Info
|
||||
import SITE_CONFIG from "../../config";
|
||||
const { Site, Title, Author, Twikoo } = SITE_CONFIG;
|
||||
// 处理文章内容
|
||||
const description = getDescription(post);
|
||||
const { Content } = await render(post);
|
||||
@ -34,11 +36,11 @@ import "../../styles/Article.less";
|
||||
<div class="article-meta">
|
||||
<span class="article-meta-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> <path d="M152 24c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 40L64 64C28.7 64 0 92.7 0 128l0 16 0 48L0 448c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-256 0-48 0-16c0-35.3-28.7-64-64-64l-40 0 0-40c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 40L152 64l0-40zM48 192l80 0 0 56-80 0 0-56zm0 104l80 0 0 64-80 0 0-64zm128 0l96 0 0 64-96 0 0-64zm144 0l80 0 0 64-80 0 0-64zm80-48l-80 0 0-56 80 0 0 56zm0 160l0 40c0 8.8-7.2 16-16 16l-64 0 0-56 80 0zm-128 0l0 56-96 0 0-56 96 0zm-144 0l0 56-64 0c-8.8 0-16-7.2-16-16l0-40 80 0zM272 248l-96 0 0-56 96 0 0 56z"></path></svg>
|
||||
<time>{fmtTime(post.data.date, "YYYY-MM-DD")}</time>
|
||||
<time>{fmtDate(post.data.date)}前</time>
|
||||
</span>
|
||||
<span class="article-meta-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9L0 168c0 13.3 10.7 24 24 24l110.1 0c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24l0 104c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65 0-94.1c0-13.3-10.7-24-24-24z"></path></svg>
|
||||
<time>{fmtTime(post.data.updated, "YYYY-MM-DD")}</time>
|
||||
<time>{fmtDate(post.data.updated || post.data.date)}前</time>
|
||||
</span>
|
||||
<a class="article-meta-item" href={`/categories/${post.data.categories}`}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M40 48C26.7 48 16 58.7 16 72l0 48c0 13.3 10.7 24 24 24l48 0c13.3 0 24-10.7 24-24l0-48c0-13.3-10.7-24-24-24L40 48zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L192 64zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zM16 232l0 48c0 13.3 10.7 24 24 24l48 0c13.3 0 24-10.7 24-24l0-48c0-13.3-10.7-24-24-24l-48 0c-13.3 0-24 10.7-24 24zM40 368c-13.3 0-24 10.7-24 24l0 48c0 13.3 10.7 24 24 24l48 0c13.3 0 24-10.7 24-24l0-48c0-13.3-10.7-24-24-24l-48 0z"></path></svg>
|
||||
@ -47,8 +49,8 @@ import "../../styles/Article.less";
|
||||
</div>
|
||||
</header>
|
||||
<Content />
|
||||
<Copyright site={SITE_CONFIG.Site} id={post.data.id} title={post.data.title} sitename={SITE_CONFIG.Title} time={fmtTime(post.data.date, "YYYY-MM-DD")} auther={SITE_CONFIG.Author} />
|
||||
<Comment />
|
||||
<Copyright site={Site} id={post.data.id} title={post.data.title} sitename={Title} time={fmtTime(post.data.date, "YYYY-MM-DD")} auther={Author} />
|
||||
{Twikoo.envId && <Comment envId={Twikoo.envId} />}
|
||||
</article>
|
||||
<Aside />
|
||||
</section>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
// 页面 Info
|
||||
import SITE_CONFIG from "../../config";
|
||||
const { Description } = SITE_CONFIG;
|
||||
const { Description, Twikoo } = SITE_CONFIG;
|
||||
// Aside组件
|
||||
import Aside from "../../components/Aside.astro";
|
||||
// 公共 Layout
|
||||
@ -20,7 +20,7 @@ import "../../styles/Links.less";
|
||||
<p>天下快意之事莫若友。</p>
|
||||
</header>
|
||||
<main></main>
|
||||
<Comment />
|
||||
{Twikoo.envId && <Comment envId={Twikoo.envId} />}
|
||||
</section>
|
||||
<Aside />
|
||||
</section>
|
||||
@ -29,6 +29,9 @@ import "../../styles/Links.less";
|
||||
import updateRouter from "../../utils/updateRouter";
|
||||
import LinksInit from "../../scripts/Links";
|
||||
// 进入页面时初始化
|
||||
updateRouter("afterMount", LinksInit);
|
||||
// 数据源
|
||||
import LINKS_DATA from "../../page_data/Link";
|
||||
const { api, data } = LINKS_DATA;
|
||||
updateRouter("afterMount", () => LinksInit(api || data));
|
||||
</script>
|
||||
</Layout>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
// 页面 Info
|
||||
import SITE_CONFIG from "../../config";
|
||||
const { Description } = SITE_CONFIG;
|
||||
const { Description, Twikoo } = SITE_CONFIG;
|
||||
// Aside组件
|
||||
import Aside from "../../components/Aside.astro";
|
||||
// 公共 Layout
|
||||
@ -17,7 +17,7 @@ import Comment from "../../components/Comment.astro";
|
||||
<h1>留言板 🌸</h1>
|
||||
<p>快友之事莫若谈。</p>
|
||||
</header>
|
||||
<Comment />
|
||||
{Twikoo.envId && <Comment envId={Twikoo.envId} />}
|
||||
</section>
|
||||
<Aside />
|
||||
</section>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
// 页面 Info
|
||||
import SITE_CONFIG from "../../config";
|
||||
const { Description } = SITE_CONFIG;
|
||||
const { Description, Twikoo } = SITE_CONFIG;
|
||||
// Aside组件
|
||||
import Aside from "../../components/Aside.astro";
|
||||
// 公共 Layout
|
||||
@ -20,7 +20,7 @@ import "../../styles/Talking.less";
|
||||
<p>记录美好生活.</p>
|
||||
</header>
|
||||
<main></main>
|
||||
<Comment />
|
||||
{Twikoo.envId && <Comment envId={Twikoo.envId} />}
|
||||
</section>
|
||||
<Aside />
|
||||
</section>
|
||||
@ -29,6 +29,9 @@ import "../../styles/Talking.less";
|
||||
import updateRouter from "../../utils/updateRouter";
|
||||
import TalkingInit from "../../scripts/Talking";
|
||||
// 进入页面时初始化
|
||||
updateRouter("afterMount", TalkingInit);
|
||||
// 数据源
|
||||
import TALKING_DATA from "../../page_data/Talking";
|
||||
const { api, data } = TALKING_DATA;
|
||||
updateRouter("afterMount", () => TalkingInit(api || data));
|
||||
</script>
|
||||
</Layout>
|
||||
|
||||
@ -4,12 +4,15 @@ import { $GET } from '../utils/index'
|
||||
// 图片懒加载
|
||||
import vhLzImgInit from "../scripts/vhLazyImg";
|
||||
|
||||
const LinksInit = async () => {
|
||||
const LinksInit = async (data: any) => {
|
||||
const linksDOM = document.querySelector('.vh-container>.vh-links>main')
|
||||
if (!linksDOM) return;
|
||||
vh.showLoading();
|
||||
try {
|
||||
const res = await $GET('https://tools-api.vvhan.com/blog/link');
|
||||
let res = data;
|
||||
if (typeof data === 'string') {
|
||||
res = await $GET(data);
|
||||
}
|
||||
linksDOM.innerHTML = res.map((i: any) => `<a href="${i.link}" target="_blank"><img class="avatar" src="${i.avatar}" /><section class="link-info"><span>${i.name}</span><p>${i.descr}</p></section></a>`).join('');
|
||||
// 图片懒加载
|
||||
vhLzImgInit();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
|
||||
import vh from 'vh-plugin'
|
||||
import { fmtDate } from '../utils/index'
|
||||
import { $GET } from '../utils/index'
|
||||
// 图片懒加载
|
||||
import vhLzImgInit from "../scripts/vhLazyImg";
|
||||
@ -8,13 +9,16 @@ import "../../public/assets/js/view-image.min.js";
|
||||
declare const ViewImage: any;
|
||||
// 灯箱JS初始化======
|
||||
|
||||
const TalkingInit = async () => {
|
||||
const TalkingInit = async (data: any) => {
|
||||
const talkingDOM = document.querySelector('.vh-container>.vh-talking>main')
|
||||
if (!talkingDOM) return;
|
||||
vh.showLoading();
|
||||
try {
|
||||
const res = await $GET('https://tools-api.vvhan.com/blog/feeling');
|
||||
talkingDOM.innerHTML = res.map((i: any) => `<article><header><img data-vh-lz-src="https://q1.qlogo.cn/g?b=qq&nk=1655466387&s=640" /><p class="info"><span>.𝙃𝙖𝙣</span><time>${i.date}</time></p></header><section class="main">${i.content}</section><footer>${i.tags.map((tag: any) => `<span>${tag}</span>`).join('')}</footer></article>`).join('');
|
||||
let res = data;
|
||||
if (typeof data === 'string') {
|
||||
res = await $GET(data);
|
||||
}
|
||||
talkingDOM.innerHTML = res.map((i: any) => `<article><header><img data-vh-lz-src="https://q1.qlogo.cn/g?b=qq&nk=1655466387&s=640" /><p class="info"><span>.𝙃𝙖𝙣</span><time>${fmtDate(i.date)}</time></p></header><section class="main">${i.content}</section><footer>${i.tags.map((tag: any) => `<span>${tag}</span>`).join('')}</footer></article>`).join('');
|
||||
// 图片懒加载
|
||||
vhLzImgInit();
|
||||
// 灯箱JS初始化======
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
:root {
|
||||
--vh-animation-delay: 0ms;
|
||||
--vh-padding-top: calc(66px + 1rem);
|
||||
--vh-back-top: calc((calc(100vw - 2rem) - min((100vw - 2rem), 1388px)) / 2 + 1rem);
|
||||
--vh-main-max-width: 1388px;
|
||||
--vh-back-top: calc((calc(100vw - 2rem) - min((100vw - 2rem), var(--vh-main-max-width))) / 2 + 1rem);
|
||||
}
|
||||
|
||||
h1,
|
||||
|
||||
116
src/styles/Footer.less
Normal file
@ -0,0 +1,116 @@
|
||||
.vh-footer {
|
||||
margin-top: 1.68rem;
|
||||
box-sizing: border-box;
|
||||
padding: 2.6rem 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: saturate(100%) blur(2px);
|
||||
user-select: none;
|
||||
|
||||
&>main {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.618rem;
|
||||
width: 100%;
|
||||
max-width: var(--vh-main-max-width);
|
||||
height: max-content;
|
||||
|
||||
&>p {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.618rem;
|
||||
line-height: 1;
|
||||
|
||||
&>a {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&>span {
|
||||
box-sizing: border-box;
|
||||
padding-left: 0.28rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: max-content;
|
||||
height: 1.25rem;
|
||||
background: #25C2A0;
|
||||
font-size: 0.68rem;
|
||||
border-radius: 0.18rem;
|
||||
overflow: hidden;
|
||||
|
||||
&>cite,
|
||||
&>em {
|
||||
box-sizing: border-box;
|
||||
padding: 0 0.618rem;
|
||||
width: max-content;
|
||||
height: 100%;
|
||||
line-height: 1.25rem;
|
||||
color: #fff;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
&>cite {
|
||||
padding-left: 0.28rem;
|
||||
}
|
||||
|
||||
&>em {
|
||||
background: #5D5D5D;
|
||||
}
|
||||
|
||||
&>svg {
|
||||
width: 0.88rem;
|
||||
height: 0.88rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&>section {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.88rem;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
p {
|
||||
line-height: 1;
|
||||
|
||||
a {
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.text {
|
||||
&>p {
|
||||
|
||||
font-size: 0.88rem;
|
||||
|
||||
&>a {
|
||||
color: #94A3B8;
|
||||
transition: opacity 0.16s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.88;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.icon {
|
||||
&>p {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,13 +16,12 @@ body {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
max-width: 1388px;
|
||||
max-width: var(--vh-main-max-width);
|
||||
height: max-content;
|
||||
|
||||
&>section.vh-container {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 5.66rem;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
gap: 1.8rem;
|
||||
|
||||
@ -6,6 +6,7 @@ section.article-list {
|
||||
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
||||
gap: 1.6rem;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
overflow: hidden;
|
||||
|
||||
&>.vh-article-item {
|
||||
|
||||
@ -24,7 +24,7 @@ header.vh-header {
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
max-width: 1388px;
|
||||
max-width: var(--vh-main-max-width);
|
||||
|
||||
a,
|
||||
span.nav-btn-item {
|
||||
|
||||
@ -4,41 +4,55 @@ const getDescription = (post: any, num: number = 150) => (post.rendered ? post.r
|
||||
//处理时间
|
||||
const fmtTime = (time: any, fmt: string = 'MMMM D, YYYY') => dayjs(time).format(fmt)
|
||||
// 处理日期
|
||||
const fmtDate = (time: any) => {
|
||||
const past = dayjs(time);
|
||||
const now = dayjs();
|
||||
const duration = now.diff(past, 'seconds');
|
||||
if (duration < 60) {
|
||||
return `${duration} 秒前`;
|
||||
} else if (duration < 60 * 60) {
|
||||
const minutes = Math.floor(duration / 60);
|
||||
return `${minutes} 分钟前`;
|
||||
} else if (duration < 60 * 60 * 24) {
|
||||
const hours = Math.floor(duration / (60 * 60));
|
||||
return `${hours} 小时前`;
|
||||
} else if (duration < 60 * 60 * 24 * 30) {
|
||||
const days = Math.floor(duration / (60 * 60 * 24));
|
||||
return `${days} 天前`;
|
||||
} else if (duration < 60 * 60 * 24 * 30 * 12) {
|
||||
const months = Math.floor(duration / (60 * 60 * 24 * 30));
|
||||
return `${months} 个月前`;
|
||||
} else {
|
||||
const years = Math.floor(duration / (60 * 60 * 24 * 30 * 12));
|
||||
return `${years} 年前`;
|
||||
}
|
||||
const fmtDate = (time: string | Date) => {
|
||||
const now = dayjs()
|
||||
const past = dayjs(time)
|
||||
// 计算时间差组件
|
||||
const years = now.diff(past, 'year')
|
||||
const months = now.diff(past.add(years, 'year'), 'month')
|
||||
const days = now.diff(past.add(years, 'year').add(months, 'month'), 'day')
|
||||
const hours = now.diff(past, 'hour')
|
||||
const minutes = now.diff(past, 'minute')
|
||||
const seconds = now.diff(past, 'second')
|
||||
// 构建时间差描述
|
||||
return [
|
||||
years && `${years}年`,
|
||||
months && `${months}月`,
|
||||
days && `${days}天`,
|
||||
!years && !months && hours && `${hours}小时`,
|
||||
!years && !months && !days && minutes && `${minutes}分钟`,
|
||||
!years && !months && !days && !hours && `${seconds}秒`
|
||||
].filter(Boolean).join('')
|
||||
}
|
||||
|
||||
// 处理页码展示
|
||||
const fmtPage = (page: string | undefined) => page ? page.replace(/\//g, '') : null
|
||||
// 加载外部脚本
|
||||
const LoadScript = (src: string): Promise<HTMLScriptElement> => {
|
||||
const LoadScript = (
|
||||
src: string,
|
||||
attrs?: Array<{ k: string; v: string | boolean }>
|
||||
): Promise<HTMLScriptElement> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = src;
|
||||
// 添加自定义属性
|
||||
if (attrs?.length) {
|
||||
attrs.forEach(({ k, v }) => {
|
||||
// 处理不同值类型
|
||||
const value = typeof v === "boolean"
|
||||
? (v ? "" : null) // 布尔值处理为 HTML 标准属性格式
|
||||
: String(v); // 其他类型转为字符串
|
||||
|
||||
if (value !== null) {
|
||||
script.setAttribute(k, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
script.onload = () => resolve(script);
|
||||
script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
};
|
||||
// 加载外部CSS
|
||||
const LoadStyle = (href: string): Promise<HTMLLinkElement> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||