This commit is contained in:
Han
2025-02-12 10:09:30 +08:00
parent 8deb0fe01e
commit d116e8fcd1
912 changed files with 5761 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
// 灯箱JS初始化======
import "../../public/assets/js/view-image.min.js";
declare const ViewImage: any;
// 灯箱JS初始化======
// Pre 滚动条======
import "overlayscrollbars/overlayscrollbars.css";
import { OverlayScrollbars } from "overlayscrollbars";
// Pre 滚动条======
// Pre Code 代码复制功能======
let copyText = null;
// Pre Code 代码复制功能======
const ArticleInit = () => {
// 灯箱JS初始化======
ViewImage && ViewImage.init("main>.vh-container>article.vh-article-main img.vh-article-img");
// 灯箱JS初始化======
// Pre 滚动条======
document.querySelectorAll("section.vh-code-box>pre.astro-code").forEach((i: any) => {
OverlayScrollbars(i, { scrollbars: { autoHide: "leave", autoHideDelay: 500, autoHideSuspend: false } });
});
// Pre 滚动条======
// Pre Code 代码复制功能======
document.querySelectorAll("section.vh-code-box>span.vh-code-copy").forEach((i: any) => {
i.vhTimer = null;
i.addEventListener("click", async () => {
if (i.vhTimer) clearTimeout(i.vhTimer);
copyText = i.parentElement.querySelector("pre.astro-code code")?.innerText;
if (!copyText) return;
await navigator.clipboard.writeText(copyText);
i.classList.add("success");
i.vhTimer = setTimeout(() => {
i.classList.remove("success");
i.vhTimer = null;
}, 1000);
});
});
// Pre Code 代码复制功能======
}
export default ArticleInit;
+42
View File
@@ -0,0 +1,42 @@
// 滚动条高度变化事件======
const scrollChangeFn = () => {
const scrollHeight = document.documentElement.scrollHeight;
const clientHeight = window.innerHeight;
const percentage = (window.scrollY / (scrollHeight - clientHeight)) * 100;
// 显示隐藏
backTop.classList[percentage <= 0 ? "remove" : "add"]("active");
// 进度为 不在范围内
if (percentage < 0 || percentage > 100) return;
// 进度不为 0
circle.style.strokeDashoffset = circumference - (percentage / 100) * circumference;
};
// 返回顶部事件
const backTopFn = () => window.scrollTo({ top: 0, behavior: "smooth" });
// 页面更新,初始化函数======
// 回顶部DOM
let backTop: any = document.querySelector(".vh-back-top");
// 彩虹圈圈 DOM
let circle: any = document.querySelector(".vh-back-top>svg>circle");
const circumference = 2 * Math.PI * 10;
const BackTopInitFn = () => {
// 更新 彩虹圈圈 DOM
circle = document.querySelector(".vh-back-top>svg>circle");
// 更新 回顶部DOM
backTop = document.querySelector(".vh-back-top");
// BackTop 圈圈初始化
circle.style.strokeDasharray = circumference;
circle.style.strokeDashoffset = circumference;
// 移除并添加BackTop 事件======
backTop.removeEventListener("click", backTopFn);
backTop.addEventListener("click", backTopFn);
// 移除并添加BackTop 事件======
// 移除并添加ScrollChange 事件======
window.removeEventListener("scroll", scrollChangeFn);
window.addEventListener("scroll", scrollChangeFn);
// 移除并添加ScrollChange 事件======
// 触发 scrollChangeFn
scrollChangeFn();
};
export default BackTopInitFn;
+22
View File
@@ -0,0 +1,22 @@
import vh from 'vh-plugin'
import { $GET } from '../utils/index'
// 图片懒加载
import vhLzImgInit from "../scripts/vhLazyImg";
const LinksInit = async () => {
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');
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();
} catch {
vh.Toast('获取数据失败')
} finally {
vh.hideLoading();
}
}
export default LinksInit;
+22
View File
@@ -0,0 +1,22 @@
import SITE_CONFIG from "../config";
const { vhMusicApi } = SITE_CONFIG;
import { $GET } from '../utils/index'
import { LoadScript, LoadStyle } from "../utils/index";
declare const APlayer: any;
const musicInit = async (musicList: any[]) => {
const musicDOM: any = document.querySelectorAll(".vh-node.vh-vhMusic");
if (musicDOM.length === 0) return;
// 载入依赖
await LoadStyle("https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css");
await LoadScript("https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js");
musicDOM.forEach(async (container: any) => {
const { type, id, list } = container.dataset;
const audio = await $GET(`${vhMusicApi}?server=${type}&type=${id ? 'song' : 'playlist'}&id=${id ? id : list}&r=${Math.random()}`);
const ap = new APlayer({ container, audio, lrcType: 3 });
musicList.push(ap);
});
};
export default musicInit;
+46
View File
@@ -0,0 +1,46 @@
import vh from 'vh-plugin'
import { $GET } from '../utils/index'
// 更新数据
let searchJson: any[] = [];
const getSearchJson = async () => (searchJson = await $GET('/vh-search.json'))
// 搜索
const searchFn = async (value: string) => {
if (searchJson.length < 1) await getSearchJson();
// 渲染页面
renderSearch(findAndModifyElements(searchJson, value))
}
// 关键词匹配
const findAndModifyElements = (arr: any[], keyword: string) => {
if ((keyword || '') == '') return []
return arr
.filter(item => item.content.includes(keyword))
.map(item => {
const content = item.content;
const keywordIndex = content.indexOf(keyword);
const start = Math.max(0, keywordIndex - 50);
const end = Math.min(content.length, keywordIndex + keyword.length + 50);
let newContent = content.substring(start, end);
newContent = newContent.replace(new RegExp(keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), "g"), `<span>${keyword}</span>`);
return { ...item, content: newContent };
});
}
// 渲染页面
let searchHTML = '';
const renderSearch = (arr: any[]) => {
searchHTML = arr.length < 1 ? '' : arr.map(i => `<a class="vh-search-item" href="${i.url}"><span>${i.title}</span><p>${i.content}</p></a>`).join('');
document.querySelector('.vh-header>.main>.vh-search>main>.vh-search-list')!.innerHTML = searchHTML;
}
// 截流
let fnTimer: any = null;
const searchInputChange = (v: any) => {
const value = v.target.value;
if (fnTimer) clearTimeout(fnTimer);
fnTimer = setTimeout(() => searchFn(value), 266);
}
export { searchFn, searchInputChange };
+29
View File
@@ -0,0 +1,29 @@
import vh from 'vh-plugin'
import { $GET } from '../utils/index'
// 图片懒加载
import vhLzImgInit from "../scripts/vhLazyImg";
// 灯箱JS初始化======
import "../../public/assets/js/view-image.min.js";
declare const ViewImage: any;
// 灯箱JS初始化======
const TalkingInit = async () => {
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('');
// 图片懒加载
vhLzImgInit();
// 灯箱JS初始化======
ViewImage && ViewImage.init(".vh-talking>main>article>.main img");
// 灯箱JS初始化======
} catch {
vh.Toast('获取数据失败')
} finally {
vh.hideLoading();
}
}
export default TalkingInit;
+37
View File
@@ -0,0 +1,37 @@
import { LoadScript } from "../utils/index";
// 初始化视频播放器
declare const DPlayer: any;
declare const Hls: any;
const videoInit = async (videoList: any[]) => {
const videoDOM: any = document.querySelectorAll(".vh-node.vh-vhVideo");
if (videoDOM.length === 0) return;
// 载入依赖
await LoadScript("https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/dplayer/1.26.0/DPlayer.min.js");
await LoadScript("https://registry.npmmirror.com/hls.js/1.5.20/files/dist/hls.min.js");
videoDOM.forEach((i: any) => {
const dp = new DPlayer({
container: i,
logo: "/assets/images/logo.png",
volume: 0.7,
mutex: true,
video: {
url: i.getAttribute("data-url"),
type: "auto",
customType: {
hls: (video: any) => {
if (Hls.isSupported()) {
const hls = new Hls({ enableWorker: true, autoStartLoad: true, capLevelToPlayerSize: true });
hls.loadSource(video.src);
hls.attachMedia(video);
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = i.getAttribute("data-url");
}
}
}
}
});
videoList.push(dp);
});
};
export default videoInit;
+19
View File
@@ -0,0 +1,19 @@
// 图片懒加载
import LazyLoad from "vanilla-lazyload";
const vhLzImgInit = () => {
document.querySelectorAll("main>.vh-container>:not(aside) img:not(.view-image-container)").forEach((i: any) => {
// 是否包含data-vh-lz-src
if (!i.hasAttribute("data-vh-lz-src")) {
i.setAttribute("data-vh-lz-src", i.getAttribute("src"));
i.setAttribute("src", '/assets/images/lazy-loading.webp');
}
});
new LazyLoad({
elements_selector: "img:not(.view-image-container)",
threshold: 0,
data_src: "vh-lz-src"
});
}
export default vhLzImgInit;