Merge branch 'dev' into main

This commit is contained in:
liuzhihang 2022-11-12 16:31:29 +08:00
commit b758179ff0
34 changed files with 6990 additions and 2356 deletions

View File

@ -3,39 +3,47 @@
[![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
![master version](https://img.shields.io/github/package-json/v/liuzhihang/halo-theme-hao/master?color=%231ab1ad&label=master)
![master version](https://img.shields.io/github/package-json/v/liuzhihang/halo-theme-hao/dev?label=dev)
![license](https://img.shields.io/github/license/liuzhihang/halo-theme-hao?color=FF5531)
---
> Halo-Theme-Ha 移植于 Hexo 社区 [Hexo-Theme-Butterfly](https://github.com/jerryc127/hexo-theme-butterfly)
> ,同时参考了 [Heo](https://blog.zhheo.com/) 的魔改
预览:[程序员小航](https://liuzhihang.com)
文档:[语雀](https://www.yuque.com/liuzhihangs/halo-theme-hao)
> Halo-Theme-Ha 是一款 [Halo2.0](https://github.com/halo-dev/halo) 的博客主题
>
> 移植于 Hexo 社区 [Hexo-Theme-Butterfly](https://github.com/liuzhihang/halo-theme-hao) 主题中 [Heo](https://blog.zhheo.com/) 的魔改
## 安裝
### 下载安装
在 [Release](https://github.com/liuzhihang/halo-theme-hao/releases) 页面下载最新版本 zip 后,通过 Halo Console 后台主题安装处上传即可。
## 说明
> 部分功能是使用插件进行支持
本主题是根据 [Heo](https://blog.zhheo.com/) 的博客进行开发,其中部分功能暂未支持
部分功能支持需要安装插件:
- [留言](https://github.com/halo-sigs/plugin-comment-widget)
- [代码高亮](https://github.com/liuzhihang/plugin-prismjs)
- [懒加载](https://github.com/liuzhihang/plugin-lazyload)
- [文章目录](https://github.com/liuzhihang/plugin-tocbot)
图标 icon 来自于 [iconfont](https://www.iconfont.cn/)
- [Awesome常用免费开源图标](https://www.iconfont.cn/collections/detail?spm=a313x.7781069.1998910419.dc64b3430&cid=11790)
- [x] 卡片化设计
- [x] 多栏设置,支持单栏/双栏/三栏/四栏
- [x] 自定义封面图位置,上部/左侧/右侧
- [x] 响应式主题
- [x] 夜间模式
- [x] 文章阅读模式
- [X] [文章目录](https://github.com/liuzhihang/plugin-tocbot)(插件)
- [X] [代码高亮/语言/复制](https://github.com/liuzhihang/plugin-prismjs)(插件)
- [ ] 文章搜索
- [x] 显示字数统计
- [x] 显示相关文章
- [x] 文章过期提醒
- [X] [评论系统](https://github.com/halo-sigs/plugin-comment-widget)
- [x] [懒加载](https://github.com/liuzhihang/plugin-lazyload)
- [x] 其他功能
## 预览
## 支持的功能
- [x] 适配 Halo 最新 2.0 版本
## 更新日志
- 2022-10-20 发布
## 安装
从 tag 处直接下载 zip 包,在 Halo2.0 后台上传即可。
## 许可证

View File

@ -10,20 +10,11 @@ spec:
- $formkit: menuRadio
name: left_menu
label: 导航栏左侧相关链接
- $formkit: radio
name: right_menu
label: 右侧四个按钮
value: true
options:
- label: 显示
value: true
- label: 隐藏
value: false
- $formkit: text
name: site_title
label: 标题
placeholder: 请输入标题
help: 支持 HTML 语法,比如 <span id="site-name-icon">Hao</span>,默认为站点名称
help: '支持 HTML 语法,比如 <i class="iconfont icon-logo-hao-pro" style="font-size: 1rem"></i>,留空为站点名称'
- group: top
label: 顶部
formSchema:
@ -37,8 +28,8 @@ spec:
- label: 隐藏
value: false
- $formkit: radio
name: time_list
label: 日志模块
name: moment
label: 说说模块
value: true
options:
- label: 显示
@ -70,6 +61,30 @@ spec:
label: 必看精选
placeholder: 请输入地址
validation: "url"
- $formkit: radio
name: todayRecommend
label: 今日推荐
value: false
options:
- label: 显示
value: true
- label: 隐藏
value: false
- $formkit: url
name: todayRecommendUrl
label: 今日推荐跳转地址
placeholder: 请输入地址
validation: "url"
- $formkit: text
name: todayRecommendTitle
label: 今日推荐标题
placeholder: 请输入标题
value: "今日推荐"
- $formkit: url
name: todayRecommendCover
label: 今日推荐背景图
placeholder: 请输入地址
validation: "url"
- group: layout
label: 布局
formSchema:
@ -203,13 +218,13 @@ spec:
label: 版权声明
placeholder: '本文是原创文章,采用 <a target="_blank" href="/cc">CC BY-NC-ND 4.0</a> 协议,完整转载请注明来自 <a href="/" target="_blank" >程序员小航</a>'
help: "版权声明内容,支持填入 HTML 标签"
- group: right_menu
- group: rightMenu
label: 右键菜单
formSchema:
- $formkit: radio
name: switch
label: 开关
value: true
value: false
options:
- label: 打开
value: true

View File

@ -1,126 +1,460 @@
"use strict";
var heo_keyboard = !0, heo = {
let heo_cookiesTime = null;
let heo_musicPlaying = false;
let heo_keyboard = false;
let heo_intype = false;
// 私有函数
var heo = {
// 检测显示模式
darkModeStatus: function () {
"light" == ("dark" === document.documentElement.getAttribute("data-theme") ? "dark" : "light") ? $(".menu-darkmode-text").text("深色模式") : $(".menu-darkmode-text").text("浅色模式")
let theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
if (theme == 'light') {
$(".menu-darkmode-text").text("深色模式");
} else {
$(".menu-darkmode-text").text("浅色模式");
}
},
//bb添加时间
changeTimeInEssay: function () {
const relativeDate = function (selector) {
selector.forEach(item => {
const $this = item
const timeVal = $this.getAttribute('datetime')
$this.innerText = btf.diffDate(timeVal, true)
$this.style.display = 'inline'
})
}
if (document.querySelector('#comment')) {
relativeDate(document.querySelectorAll('#comment time'))
}
},
// 首页bb
initIndexEssay: function () {
if (document.querySelector('#comment-list')) {
var swiper = new Swiper('.swiper-container', {
direction: 'vertical', // 垂直切换选项
loop: true,
autoplay: {
delay: 3000,
pauseOnMouseEnter: true
},
});
}
},
// 只在首页显示
onlyHome: function () {
var e = window.location.pathname;
"/" == (e = decodeURIComponent(e)) ? $(".only-home").attr("style", "display: flex") : $(".only-home").attr("style", "display: none")
var urlinfo = window.location.pathname;
urlinfo = decodeURIComponent(urlinfo);
if (urlinfo == '/') {
$('.only-home').attr('style', 'display: flex');
} else {
$('.only-home').attr('style', 'display: none');
}
},
//是否在首页
is_Post: function () {
return 0 <= window.location.href.indexOf("/p/")
var url = window.location.href; //获取url
if (url.indexOf("/p/") >= 0) { //判断url地址中是否包含code字符串
return true;
} else {
return false;
}
},
//监测是否在页面开头
addNavBackgroundInit: function () {
var e, t = 0, o = 0;
document.body && (t = document.body.scrollTop), document.documentElement && (o = document.documentElement.scrollTop), e = 0 < t - o ? t : o, 0 != e && (document.getElementById("page-header").classList.add("nav-fixed"), document.getElementById("page-header").classList.add("nav-visible"), $("#cookies-window").hide(), console.log("已添加class"))
var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0;
if (document.body) {
bodyScrollTop = document.body.scrollTop;
}
if (document.documentElement) {
documentScrollTop = document.documentElement.scrollTop;
}
scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
// console.log("滚动高度"+ scrollTop)
if (scrollTop != 0) {
document.getElementById("page-header").classList.add("nav-fixed");
document.getElementById("page-header").classList.add("nav-visible");
$('#cookies-window').hide()
console.log("已添加class")
}
},
// 标签页面
//分类条
tagPageActive: function () {
var e = window.location.pathname, e = decodeURIComponent(e);
console.log(e);
var t, o, n = /\/tags\/.*?\//.test(e);
console.log(n), n && (t = e.split("/"), console.log(t[2]), o = t[2], document.querySelector("#tag-page-tags") && document.getElementById(o).classList.add("select"))
var urlinfo = window.location.pathname;
urlinfo = decodeURIComponent(urlinfo)
// console.log(urlinfo);
// 验证是否是分类链接
var pattern = /\/tags\/.*?\//;
var patbool = pattern.test(urlinfo);
// console.log(patbool);
// 获取当前的分类
if (patbool) {
var valuegroup = urlinfo.split("/");
// console.log(valuegroup[2]);
// 获取当前分类
var nowCategorie = valuegroup[2];
if (document.querySelector('#tag-page-tags')) {
$('a').removeClass('select')
document.getElementById(nowCategorie).classList.add("select");
}
}
},
//分类条
categoriesBarActive: function () {
document.querySelector("#category-bar") && $(".category-bar-item").removeClass("select");
var e, t = window.location.pathname, t = decodeURIComponent(t);
"/" == t ? document.querySelector("#category-bar") && document.getElementById("category-bar-home").classList.add("select") : /\/categories\/.*?\//.test(t) && (e = t.split("/")[2], document.querySelector("#category-bar") && document.getElementById(e).classList.add("select"))
if (document.querySelector('#category-bar')) {
$(".category-bar-item").removeClass("select")
}
var urlinfo = window.location.pathname;
urlinfo = decodeURIComponent(urlinfo);
// console.log(urlinfo);
//判断是否是首页
if (urlinfo == '/') {
if (document.querySelector('#category-bar')) {
document.getElementById('category-bar-home').classList.add("select");
}
} else {
// 验证是否是分类链接
var pattern = /\/categories\/.*?\//;
var patbool = pattern.test(urlinfo);
// console.log(patbool);
// 获取当前的分类
if (patbool) {
var valuegroup = urlinfo.split("/");
// console.log(valuegroup[2]);
// 获取当前分类
var nowCategorie = valuegroup[2];
if (document.querySelector('#category-bar')) {
document.getElementById(nowCategorie).classList.add("select");
}
}
}
},
// 页脚友链
addFriendLinksInFooter: function () {
var fetchUrl = "https://moments.zhheo.com/randomfriend?num=3"
fetch(fetchUrl)
.then(res => res.json())
.then(json => {
var randomFriendLinks = getArrayItems(json, 3);
var htmlText = '';
for (let i = 0; i < randomFriendLinks.length; ++i) {
var item = randomFriendLinks[i]
htmlText += `<a class='footer-item' href='${item.link}' target="_blank" rel="noopener nofollow">${item.name}</a>`;
}
htmlText += `<a class='footer-item' href='/link/'>更多</a>`
document.getElementById("friend-links-in-footer").innerHTML = htmlText;
})
},
//禁止图片右键单击
stopImgRightDrag: function () {
$("img").on("dragstart", function () {
return !1
})
var img = $("img");
img.on("dragstart", function () {
return false;
});
},
//置顶文章横向滚动
topPostScroll: function () {
var o;
document.getElementById("recent-post-top") && (o = document.getElementById("recent-post-top")).addEventListener("mousewheel", function (e) {
var t = -e.wheelDelta / 2;
o.scrollLeft += t, document.body.clientWidth < 1300 && e.preventDefault()
}, !1)
if (document.getElementById("recent-post-top")) {
let xscroll = document.getElementById("recent-post-top");
xscroll.addEventListener("mousewheel", function (e) {
//计算鼠标滚轮滚动的距离
let v = -e.wheelDelta / 2;
xscroll.scrollLeft += v;
//阻止浏览器默认方法
if (document.body.clientWidth < 1300) {
e.preventDefault();
}
}, false);
}
},
topCategoriesBarScroll: function () {
var o;
document.getElementById("category-bar-items") && (o = document.getElementById("category-bar-items")).addEventListener("mousewheel", function (e) {
var t = -e.wheelDelta / 2;
o.scrollLeft += t, e.preventDefault()
}, !1)
if (document.getElementById("category-bar-items")) {
let xscroll = document.getElementById("category-bar-items");
xscroll.addEventListener("mousewheel", function (e) {
//计算鼠标滚轮滚动的距离
let v = -e.wheelDelta / 2;
xscroll.scrollLeft += v;
//阻止浏览器默认方法
e.preventDefault();
}, false);
}
},
//作者卡片问好
sayhi: function () {
document.querySelector("#author-info__sayhi") && (document.getElementById("author-info__sayhi").innerHTML = getTimeState() + "!我是")
if (document.querySelector('#author-info__sayhi')) {
document.getElementById("author-info__sayhi").innerHTML = getTimeState() + "!我是";
}
},
// 添加标签
addTag: function () {
document.querySelector(".heo-tag-new") && $(".heo-tag-new").append('<sup class="heo-tag heo-tag-new-view">N</sup>'), document.querySelector(".heo-tag-hot") && $(".heo-tag-hot").append('<sup class="heo-tag heo-tag-hot-view">H</sup>')
//添加new标签
if (document.querySelector('.heo-tag-new')) {
$(".heo-tag-new").append(`<sup class="heo-tag heo-tag-new-view">N</sup>`)
}
//添加hot标签
if (document.querySelector('.heo-tag-hot')) {
$(".heo-tag-hot").append(`<sup class="heo-tag heo-tag-hot-view">H</sup>`)
}
},
// 二维码
qrcodeCreate: function () {
document.getElementById("qrcode") && new QRCode(document.getElementById("qrcode"), {
text: window.location.href,
width: 250,
height: 250,
colorDark: "#000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
})
if (document.getElementById('qrcode')) {
document.getElementById("qrcode").innerHTML = "";
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: window.location.href,
width: 250,
height: 250,
colorDark: "#000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
}
},
// 刷新即刻短文瀑布流
reflashEssayWaterFall: function () {
document.querySelector("#waterfall") && setTimeout(function () {
waterfall("#waterfall"), document.getElementById("waterfall").classList.add("show")
}, 500)
if (document.querySelector('#waterfall')) {
setTimeout(function () {
waterfall('#waterfall');
document.getElementById("waterfall").classList.add('show');
}, 500);
}
},
// 即刻短文添加灯箱
addMediumInEssay: function () {
document.querySelector("#waterfall") && mediumZoom(document.querySelectorAll("[data-zoomable]"))
if (document.querySelector('#waterfall')) {
mediumZoom(document.querySelectorAll('[data-zoomable]'))
}
},
downloadImage: function (e, c) {
rm.hideRightMenu(), 0 == rm.downloadimging ? (rm.downloadimging = !0, btf.snackbarShow("正在下载中,请稍后", !1, 1e4), setTimeout(function () {
var a = new Image;
a.setAttribute("crossOrigin", "anonymous"), a.onload = function () {
var e = document.createElement("canvas");
e.width = a.width, e.height = a.height, e.getContext("2d").drawImage(a, 0, 0, a.width, a.height);
var t = e.toDataURL("image/png"), o = document.createElement("a"), n = new MouseEvent("click");
o.download = c || "photo", o.href = t, o.dispatchEvent(n)
}, a.src = e, btf.snackbarShow("图片已添加盲水印,请遵守版权协议"), rm.downloadimging = !1
}, "10000")) : btf.snackbarShow("有正在进行中的下载,请稍后再试")
// 下载图片
downloadImage: function (imgsrc, name) { //下载图片地址和图片名
rm.hideRightMenu();
if (rm.downloadimging == false) {
rm.downloadimging = true;
btf.snackbarShow('正在下载中,请稍后', false, 10000)
setTimeout(function () {
let image = new Image();
// 解决跨域 Canvas 污染问题
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = name || "photo"; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
};
image.src = imgsrc;
btf.snackbarShow('图片已添加盲水印,请遵守版权协议');
rm.downloadimging = false;
}, "10000");
} else {
btf.snackbarShow('有正在进行中的下载,请稍后再试');
}
},
changeThemeColor: function (e) {
null !== document.querySelector('meta[name="theme-color"]') && document.querySelector('meta[name="theme-color"]').setAttribute("content", e)
//控制评论弹幕
switchCommentBarrage: function () {
let commentBarrage = document.querySelector('.comment-barrage');
if (commentBarrage) {
if ($(".comment-barrage").is(":visible")) {
$(".comment-barrage").hide();
$(".menu-commentBarrage-text").text("显示热评");
document.querySelector("#consoleCommentBarrage").classList.remove("on");
localStorage.setItem('commentBarrageSwitch', 'false');
} else if ($(".comment-barrage").is(":hidden")) {
$(".comment-barrage").show();
$(".menu-commentBarrage-text").text("关闭热评");
document.querySelector("#consoleCommentBarrage").classList.add("on");
localStorage.removeItem('commentBarrageSwitch');
}
}
rm.hideRightMenu();
},
//隐藏cookie窗口
hidecookie: function () {
heo_cookiesTime = setTimeout(() => {
document.getElementById("cookies-window").classList.add('cw-hide');
setTimeout(() => {
$('#cookies-window').hide()
}, 1000)
}, 3000)
},
//隐藏今日推荐
hideTodayCard: function () {
if (document.getElementById("todayCard")) {
document.getElementById("todayCard").classList.add('hide');
}
},
//更改主题色
changeThemeColor: function (color) {
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', color)
}
},
//自适应主题色
initThemeColor: function () {
var e, t, o;
heo.is_Post() ? 0 === (window.scrollY || document.documentElement.scrollTop) ? (e = getComputedStyle(document.documentElement).getPropertyValue("--heo-main"), heo.changeThemeColor(e)) : (t = getComputedStyle(document.documentElement).getPropertyValue("--heo-background"), heo.changeThemeColor(t)) : (o = getComputedStyle(document.documentElement).getPropertyValue("--heo-background"), heo.changeThemeColor(o))
if (heo.is_Post()) {
const currentTop = window.scrollY || document.documentElement.scrollTop
if (currentTop === 0) {
let themeColor = getComputedStyle(document.documentElement).getPropertyValue('--heo-main');
heo.changeThemeColor(themeColor);
} else {
let themeColor = getComputedStyle(document.documentElement).getPropertyValue('--heo-background');
heo.changeThemeColor(themeColor);
}
} else {
let themeColor = getComputedStyle(document.documentElement).getPropertyValue('--heo-background');
heo.changeThemeColor(themeColor);
}
},
//跳转到指定位置
jumpTo: function (dom) {
$(document).ready(function () {
$("html,body").animate({
scrollTop: $(dom).eq(i).offset().top
}, 500 /*scroll实现定位滚动*/); /*让整个页面可以滚动*/
});
},
//显示加载动画
showLoading: function () {
document.querySelector("#loading-box").classList.remove("loaded")
document.querySelector("#loading-box").classList.remove("loaded");
let cardColor = getComputedStyle(document.documentElement).getPropertyValue('--heo-card-bg');
heo.changeThemeColor(cardColor);
},
//隐藏加载动画
hideLoading: function () {
document.querySelector("#loading-box").classList.add("loaded")
document.querySelector("#loading-box").classList.add("loaded");
},
//切换音乐播放状态
musicToggle: function () {
let msgPlay = '<i class="fa-solid fa-play"></i><span>播放音乐</span>' // 此處可以更改為你想要顯示的文字
let msgPause = '<i class="fa-solid fa-pause"></i><span>暂停音乐</span>' // 同上,但兩處均不建議更改
if (heo_musicPlaying) {
document.querySelector("#nav-music").classList.remove("playing");
document.getElementById("menu-music-toggle").innerHTML = msgPlay;
document.getElementById("nav-music-hoverTips").innerHTML = "音乐已暂停";
document.querySelector("#consoleMusic").classList.remove("on");
heo_musicPlaying = false;
} else {
document.querySelector("#nav-music").classList.add("playing");
document.getElementById("menu-music-toggle").innerHTML = msgPause;
document.querySelector("#consoleMusic").classList.add("on");
heo_musicPlaying = true;
}
document.querySelector('meting-js').aplayer.toggle();
rm.hideRightMenu();
},
//音乐上一曲
musicSkipBack: function () {
document.querySelector('meting-js').aplayer.skipBack();
rm.hideRightMenu();
},
//音乐下一曲
musicSkipForward: function () {
document.querySelector('meting-js').aplayer.skipForward();
rm.hideRightMenu();
},
//获取音乐中的名称
musicGetName: function () {
var x = $('.aplayer-title')
// var x = document.getElementsByClassName('txt');
// for (var i = x.length - 1; i >= 0; i--) {
// console.log(x[i].innerText)
// }
var arr = []
for (var i = x.length - 1; i >= 0; i--) {
arr[i] = x[i].innerText
// console.log(x[i].innerText)
}
return arr[0]
},
//显示中控台
showConsole: function () {
document.querySelector("#console").classList.add("show")
document.querySelector("#console").classList.add("show");
heo.initConsoleState();
},
//隐藏中控台
hideConsole: function () {
document.querySelector("#console").classList.remove("show")
document.querySelector("#console").classList.remove("show");
},
//快捷键功能开关
keyboardToggle: function () {
heo_keyboard ? (heo_keyboard = !1, document.querySelector("#consoleKeyboard").classList.remove("on"), localStorage.setItem("keyboardToggle", "false")) : (heo_keyboard = !0, document.querySelector("#consoleKeyboard").classList.add("on"), localStorage.setItem("keyboardToggle", "true"))
if (heo_keyboard) {
heo_keyboard = false;
document.querySelector("#consoleKeyboard").classList.remove("on");
localStorage.setItem('keyboardToggle', 'false');
} else {
heo_keyboard = true;
document.querySelector("#consoleKeyboard").classList.add("on");
localStorage.setItem('keyboardToggle', 'true');
}
},
//滚动到指定id
scrollTo: function (id) {
var domTop = document.querySelector(id).offsetTop;
window.scrollTo(0, domTop - 80);
},
//隐藏侧边栏
hideAsideBtn: () => { // Hide aside
const $htmlDom = document.documentElement.classList
$htmlDom.contains('hide-aside')
? saveToLocal.set('aside-status', 'show', 2)
: saveToLocal.set('aside-status', 'hide', 2)
$htmlDom.toggle('hide-aside')
$htmlDom.contains('hide-aside')
? document.querySelector("#consoleHideAside").classList.add("on")
: document.querySelector("#consoleHideAside").classList.remove("on")
},
//初始化console图标
initConsoleState: function () {
//初始化隐藏边栏
const $htmlDom = document.documentElement.classList
$htmlDom.contains('hide-aside')
? document.querySelector("#consoleHideAside").classList.add("on")
: document.querySelector("#consoleHideAside").classList.remove("on")
}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,4 @@
"use strict";
const btf = {
var btf = {
debounce: function (func, wait, immediate) {
let timeout
return function () {
@ -60,40 +58,99 @@ const btf = {
}
},
snackbarShow: (text, showAction = false, duration = 2000) => {
const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar
const bg = document.documentElement.getAttribute('data-theme') === 'light' ? bgLight : bgDark
snackbarShow: (text, showAction, duration) => {
const sa = (typeof showAction !== 'undefined') ? showAction : false
const dur = (typeof duration !== 'undefined') ? duration : 5000
const position = GLOBAL_CONFIG.Snackbar.position
const bg = document.documentElement.getAttribute('data-theme') === 'light' ? GLOBAL_CONFIG.Snackbar.bgLight : GLOBAL_CONFIG.Snackbar.bgDark
document.styleSheets[0].addRule(':root', '--heo-snackbar-time:' + dur + 'ms!important')
Snackbar.show({
text: text,
backgroundColor: bg,
showAction: showAction,
duration: duration,
pos: position,
customClass: 'snackbar-css'
showAction: sa,
duration: dur,
pos: position
})
},
initJustifiedGallery: function (selector) {
if (!(selector instanceof jQuery)) {
selector = $(selector)
}
selector.each(function (i, o) {
if ($(this).is(':visible')) {
$(this).justifiedGallery({
rowHeight: 220,
margins: 4
})
}
})
},
// 图库排版
// initJustifiedGallery: function (selector) {
// selector.forEach(function (i) {
// if (!btf.isHidden(i)) {
// fjGallery(i, {
// itemSelector: '.fj-gallery-item',
// rowHeight: 220,
// gutter: 4,
// onJustify: function () {
// this.$container.style.opacity = '1'
// }
// })
// }
// })
// },
diffDate: (d, more = false) => {
const dateNow = new Date()
const datePost = new Date(d)
const dateDiff = dateNow.getTime() - datePost.getTime()
const minute = 1000 * 60
const hour = minute * 60
const day = hour * 24
const month = day * 30
scrollToDest: (pos, time = 500) => {
const currentPos = window.pageYOffset
if (currentPos > pos) pos = pos - 70
let result
if (more) {
const monthCount = dateDiff / month
const dayCount = dateDiff / day
const hourCount = dateDiff / hour
const minuteCount = dateDiff / minute
if ('scrollBehavior' in document.documentElement.style) {
if (monthCount > 12) {
// result = datePost.toLocaleDateString().replace(/\//g, '-')
result = datePost.toLocaleDateString()
} else if (dayCount >= 7) {
// } else if (monthCount >= 1) {
result = datePost.toLocaleDateString().substr(5)
// result = parseInt(monthCount) + ' ' + GLOBAL_CONFIG.date_suffix.month
} else if (dayCount >= 1) {
result = parseInt(dayCount) + '' + GLOBAL_CONFIG.date_suffix.day
} else if (hourCount >= 1) {
result = '最近'
// result = parseInt(hourCount) + ' ' + GLOBAL_CONFIG.date_suffix.hour
} else if (minuteCount >= 1) {
result = '最近'
// result = parseInt(minuteCount) + ' ' + GLOBAL_CONFIG.date_suffix.min
} else {
result = GLOBAL_CONFIG.date_suffix.just
}
} else {
result = parseInt(dateDiff / day)
}
return result
},
loadComment: (dom, callback) => {
if ('IntersectionObserver' in window) {
const observerItem = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
callback()
observerItem.disconnect()
}
}, {threshold: [0]})
observerItem.observe(dom)
} else {
callback()
}
},
scrollToDest: (pos, time) => {
if (pos < 0 || time < 0) {
return
}
const currentPos = window.scrollY || window.screenTop
pos = pos - 70
if ('CSS' in window && CSS.supports('scroll-behavior', 'smooth')) {
window.scrollTo({
top: pos,
behavior: 'smooth'
@ -102,31 +159,39 @@ const btf = {
}
let start = null
pos = +pos
window.requestAnimationFrame(function step (currentTime) {
time = time || 500
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start
const progress = currentTime - start
if (currentPos < pos) {
const progress = currentTime - start
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos)
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
}
} else {
const progress = currentTime - start
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time))
}
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
}
}
})
},
fadeIn: function (e, t) {
e.style.cssText = "display:block;animation: to_show ".concat(t, "s")
fadeIn: (ele, time) => {
ele.style.cssText = `display:block;animation: to_show ${time}s`
},
fadeOut: function (t, e) {
t.addEventListener("animationend", function e() {
t.style.cssText = "display: none; animation: '' ", t.removeEventListener("animationend", e)
}), t.style.animation = "to_hide ".concat(e, "s")
fadeOut: (ele, time) => {
ele.addEventListener('animationend', function f() {
ele.style.cssText = "display: none; animation: '' "
ele.removeEventListener('animationend', f)
})
ele.style.animation = `to_hide ${time}s`
},
getParents: (elem, selector) => {
@ -146,20 +211,21 @@ const btf = {
},
/**
*
* @param {*} selector
* @param {*} eleType the type of create element
* @param {*} options object key: value
* @param {*} id id
* @param {*} cn class name
*/
wrap: (selector, eleType, options) => {
wrap: function (selector, eleType, id = '', cn = '') {
const creatEle = document.createElement(eleType)
for (const [key, value] of Object.entries(options)) {
creatEle.setAttribute(key, value)
}
if (id) creatEle.id = id
if (cn) creatEle.className = cn
selector.parentNode.insertBefore(creatEle, selector)
creatEle.appendChild(selector)
},
unwrap: el => {
unwrap: function (el) {
const elParentNode = el.parentNode
if (elParentNode !== document.body) {
elParentNode.parentNode.insertBefore(el, elParentNode)
@ -167,9 +233,17 @@ const btf = {
}
},
isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
isJqueryLoad: (fn) => {
if (typeof jQuery === 'undefined') {
getScript(GLOBAL_CONFIG.source.jQuery).then(fn)
} else {
fn()
}
},
getEleTop: ele => {
isHidden: (ele) => ele.offsetHeight === 0 && ele.offsetWidth === 0,
getEleTop: (ele) => {
let actualTop = ele.offsetTop
let current = ele.offsetParent
@ -179,6 +253,6 @@ const btf = {
}
return actualTop
},
}
};
}

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3736806 */
src: url('iconfont.woff2?t=1667571412098') format('woff2'),
url('iconfont.woff?t=1667571412098') format('woff'),
url('iconfont.ttf?t=1667571412098') format('truetype');
src: url('iconfont.woff2?t=1668096101462') format('woff2'),
url('iconfont.woff?t=1668096101462') format('woff'),
url('iconfont.ttf?t=1668096101462') format('truetype');
}
.iconfont {
@ -13,6 +13,26 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-logo-hao-pro:before {
content: "\f290";
}
.icon-logo-hao:before {
content: "\e609";
}
.icon-logo-moment:before {
content: "\e6af";
}
.icon-indent:before {
content: "\f027";
}
.icon-bars:before {
content: "\ef34";
}
.icon-mail-line:before {
content: "\e668";
}
@ -197,10 +217,6 @@
content: "\e767";
}
.icon-bars:before {
content: "\e9ee";
}
.icon-arrowup:before {
content: "\e64c";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,41 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "32796142",
"name": "logo-hao-copy",
"font_class": "logo-hao-pro",
"unicode": "f290",
"unicode_decimal": 62096
},
{
"icon_id": "32787589",
"name": "logo-hao",
"font_class": "logo-hao",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "16440935",
"name": "logo-moment",
"font_class": "logo-moment",
"unicode": "e6af",
"unicode_decimal": 59055
},
{
"icon_id": "5634161",
"name": "indent",
"font_class": "indent",
"unicode": "f027",
"unicode_decimal": 61479
},
{
"icon_id": "5633834",
"name": "bars",
"font_class": "bars",
"unicode": "ef34",
"unicode_decimal": 61236
},
{
"icon_id": "20817029",
"name": "mail-line",
@ -327,13 +362,6 @@
"unicode": "e767",
"unicode_decimal": 59239
},
{
"icon_id": "348268",
"name": "bars",
"font_class": "bars",
"unicode": "e9ee",
"unicode_decimal": 59886
},
{
"icon_id": "433860",
"name": "arrow-up",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
.comment-barrage {
position: fixed;
bottom: 0;
right: 20px;
padding: 0 0 20px 10px;
z-index: 100;
display: flex;
flex-direction: column;
justify-content: end;
align-items: flex-end;
z-index: 999;
transition: 0.3s;
}
@media screen and (max-width: 768px) {
.comment-barrage {
display: none !important;
}
}
.comment-barrage-item {
min-width: 300px;
max-width: 300px;
width: fit-content;
min-height: 80px;
max-height: 150px;
margin: 4px;
padding: 8px 14px;
background: var(--heo-maskbgdeep);
border-radius: 8px;
color: var(--heo-fontcolor);
animation: barrageIn 0.6s cubic-bezier(0.42, 0, 0.3, 1.11);
transition: 0.3s;
display: flex;
flex-direction: column;
border: var(--style-border);
backdrop-filter: saturate(180%) blur(20px);
-webkit-backdrop-filter: blur(20px);
position: fixed;
box-shadow: var(--heo-shadow-border);
overflow: hidden;
}
.comment-barrage-item:hover {
border: var(--style-border-hover);
box-shadow: var(--heo-shadow-main);
}
.comment-barrage-item.out {
opacity: 0;
animation: barrageOut 0.6s cubic-bezier(0.42, 0, 0.3, 1.11);
}
.comment-barrage-item.hovered {
opacity: 0;
}
.comment-barrage-item .comment-barrage-close {
color: var(--heo-secondtext);
cursor: pointer;
line-height: 1;
padding: 4px;
}
.comment-barrage-item .comment-barrage-close:hover {
color: var(--heo-main);
}
.comment-barrage-item pre {
display: none;
}
.comment-barrage-item p img:not(.tk-owo-emotion) {
display: none;
}
.comment-barrage-item p img.tk-owo-emotion {
width: 16px;
padding: 0;
margin: 0;
transform: translateY(2px);
}
.comment-barrage-item blockquote {
display: none;
}
.comment-barrage-item br {
display: none;
}
.comment-barrage-item .barrageHead {
height: 30px;
padding: 0;
line-height: 30px;
font-size: 12px;
border-bottom: var(--style-border);
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
padding-bottom: 6px;
}
.comment-barrage-item .barrageHead .barrageTitle {
color: var(--heo-card-bg);
margin-right: 8px;
background: var(--heo-fontcolor);
line-height: 1;
padding: 4px;
border-radius: 4px;
}
.comment-barrage-item .barrageHead .barrageTitle:hover {
background: var(--heo-main);
color: var(--heo-white);
}
.comment-barrage-item .barrageAvatar {
width: 16px;
height: 16px;
margin: 0;
margin-left: auto;
margin-right: 8px;
border-radius: 50%;
background: var(--heo-secondbg);
}
.comment-barrage-item .barrageContent {
font-size: 14px !important;
font-weight: normal !important;
height: calc(100% - 30px);
overflow: hidden;
width: fit-content;
}
.comment-barrage-item .barrageContent a {
pointer-events: none;
}
.comment-barrage-item .barrageContent::-webkit-scrollbar {
height: 0;
width: 4px;
}
.comment-barrage-item .barrageContent::-webkit-scrollbar-button {
display: none;
}
.comment-barrage-item p {
margin: 8px 0;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
font-size: 14;
}
.comment-barrage-item .barrageContent h1, .comment-barrage-item .barrageContent h2, .comment-barrage-item .barrageContent h3, .comment-barrage-item .barrageContent h4 {
font-size: 14px !important;
font-weight: normal !important;
margin: 8px 0 !important;
}

View File

@ -0,0 +1,150 @@
var commentBarrageConfig = {
//同时最多显示弹幕数
maxBarrage: 1,
//弹幕显示间隔时间ms
barrageTime: 4000,
//twikoo部署地址腾讯云的为环境ID
twikooUrl: "xxxx",
//token获取见上方
accessToken: "xxxx",
pageUrl: window.location.pathname,
barrageTimer: [],
barrageList: [],
barrageIndex: 0,
dom: document.querySelector('.comment-barrage'),
}
var commentInterval = null;
var hoverOnCommentBarrage = false;
$(".comment-barrage").hover(function () {
hoverOnCommentBarrage = true;
console.log("热评悬浮");
}, function () {
hoverOnCommentBarrage = false;
console.log("停止悬浮");
});
function initCommentBarrage() {
// console.log("开始创建热评")
var data = JSON.stringify({
"event": "COMMENT_GET",
"commentBarrageConfig.accessToken": commentBarrageConfig.accessToken,
"url": commentBarrageConfig.pageUrl
});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
commentBarrageConfig.barrageList = commentLinkFilter(JSON.parse(this.responseText).data);
commentBarrageConfig.dom.innerHTML = '';
}
});
xhr.open("POST", commentBarrageConfig.twikooUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
clearInterval(commentInterval);
commentInterval = null;
commentInterval = setInterval(() => {
if (commentBarrageConfig.barrageList.length && !hoverOnCommentBarrage) {
popCommentBarrage(commentBarrageConfig.barrageList[commentBarrageConfig.barrageIndex]);
commentBarrageConfig.barrageIndex += 1;
commentBarrageConfig.barrageIndex %= commentBarrageConfig.barrageList.length;
}
if ((commentBarrageConfig.barrageTimer.length > (commentBarrageConfig.barrageList.length > commentBarrageConfig.maxBarrage ? commentBarrageConfig.maxBarrage : commentBarrageConfig.barrageList.length)) && !hoverOnCommentBarrage) {
removeCommentBarrage(commentBarrageConfig.barrageTimer.shift())
}
}, commentBarrageConfig.barrageTime)
}
function commentLinkFilter(data) {
data.sort((a, b) => {
return a.created - b.created;
})
let newData = [];
data.forEach(item => {
newData.push(...getCommentReplies(item));
});
return newData;
}
function getCommentReplies(item) {
if (item.replies) {
let replies = [item];
item.replies.forEach(item => {
replies.push(...getCommentReplies(item));
})
return replies;
} else {
return [];
}
}
function popCommentBarrage(data) {
let barrage = document.createElement('div');
let width = commentBarrageConfig.dom.clientWidth;
let height = commentBarrageConfig.dom.clientHeight;
barrage.className = 'comment-barrage-item'
barrage.innerHTML = `
<div class="barrageHead">
<a class="barrageTitle" href="javascript:heo.scrollTo('#post-comment')"">热评</a>
<div class="barrageNick">${data.nick}</div>
<img class="barrageAvatar" src="https://cravatar.cn/avatar/${data.mailMd5}"/>
<a class="comment-barrage-close" href="javascript:heo.switchCommentBarrage()"><i class="fa-solid fa-xmark"></i></a>
</div>
<a class="barrageContent" href="#${data.id}">${data.comment}</a>
`
commentBarrageConfig.barrageTimer.push(barrage);
commentBarrageConfig.dom.append(barrage);
}
function removeCommentBarrage(barrage) {
barrage.className = 'comment-barrage-item out';
setTimeout(() => {
commentBarrageConfig.dom.removeChild(barrage);
}, 1000)
}
// 自动隐藏
document.addEventListener('scroll', btf.throttle(function () {
//滚动条高度+视窗高度 = 可见区域底部高度
var visibleBottom = window.scrollY + document.documentElement.clientHeight;
//可见区域顶部高度
var visibleTop = window.scrollY;
// 获取翻页按钮容器
var pagination = document.querySelector('.comment-barrage');
// 获取位置监测容器,此处采用评论区
var eventlistner = document.getElementById('post-tools');
if (eventlistner && pagination) {
var centerY = eventlistner.offsetTop + (eventlistner.offsetHeight / 2);
if (document.body.clientWidth > 768) {
if (centerY > visibleBottom) {
pagination.style.bottom = '0';
} else {
pagination.style.bottom = '-200px';
}
}
}
}, 200))
initCommentBarrage();
if (localStorage.getItem('commentBarrageSwitch') !== 'false') {
$(".comment-barrage").show();
$(".menu-commentBarrage-text").text("关闭热评");
document.querySelector("#consoleCommentBarrage").classList.add("on");
} else {
$(".comment-barrage").hide();
$(".menu-commentBarrage-text").text("显示热评");
document.querySelector("#consoleCommentBarrage").classList.remove("on");
}
document.addEventListener('pjax:send', function () {
clearInterval(commentInterval);
});

View File

@ -1,342 +1,419 @@
"use strict";
// 初始化函数
let rm = {};
function asyncGeneratorStep(e, n, t, o, i, r, c) {
try {
var m = e[r](c),
a = m.value;
} catch (e) {
return void t(e);
//禁止图片拖拽
rm.stopdragimg = $("img");
rm.stopdragimg.on("dragstart", function () {
return false;
});
// 显示菜单
rm.showRightMenu = function (isTrue, x = 0, y = 0) {
let $rightMenu = $('#rightMenu');
$rightMenu.css('top', x + 'px').css('left', y + 'px');
if (isTrue) {
$rightMenu.show();
stopMaskScroll()
} else {
$rightMenu.hide();
}
m.done ? n(a) : Promise.resolve(a).then(o, i);
}
function _asyncToGenerator(m) {
return function () {
var e = this,
c = arguments;
return new Promise(function (n, t) {
var o = m.apply(e, c);
function i(e) {
asyncGeneratorStep(o, n, t, i, r, "next", e);
}
function r(e) {
asyncGeneratorStep(o, n, t, i, r, "throw", e);
}
i(void 0);
});
};
// 隐藏菜单
rm.hideRightMenu = function () {
rm.showRightMenu(false);
$('#rightmenu-mask').attr('style', 'display: none');
}
var rm = {};
(rm.stopdragimg = $("img")),
rm.stopdragimg.on("dragstart", function () {
return !1;
}),
(rm.showRightMenu = function (e) {
var n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : 0,
t = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : 0,
o = $("#rightMenu");
o.css("top", n + "px").css("left", t + "px"),
e ? (o.show(), stopMaskScroll()) : o.hide();
}),
(rm.hideRightMenu = function () {
rm.showRightMenu(!1), $("#rightmenu-mask").attr("style", "display: none");
});
var rmWidth = $("#rightMenu").width(),
rmHeight = $("#rightMenu").height();
// 尺寸
let rmWidth = $('#rightMenu').width();
let rmHeight = $('#rightMenu').height();
// 重新定义尺寸
rm.reloadrmSize = function () {
(rmWidth = $("#rightMenu").width()), (rmHeight = $("#rightMenu").height());
rmWidth = $('#rightMenu').width();
rmHeight = $('#rightMenu').height();
}
// 获取点击的href
let domhref = '';
let domImgSrc = '';
let globalEvent = null;
// 监听右键初始化
window.oncontextmenu = function (event) {
if (document.body.clientWidth > 768) {
let pageX = event.clientX + 10; //加10是为了防止显示时鼠标遮在菜单上
let pageY = event.clientY;
// console.log(event);
//其他额外菜单
let $rightMenuOther = $('.rightMenuOther');
let $rightMenuPlugin = $('.rightMenuPlugin');
let $rightMenuCopyText = $('#menu-copytext');
let $rightMenuPasteText = $('#menu-pastetext');
let $rightMenuCommentText = $('#menu-commenttext');
let $rightMenuNewWindow = $('#menu-newwindow');
let $rightMenuCopyLink = $('#menu-copylink');
let $rightMenuCopyImg = $('#menu-copyimg');
let $rightMenuDownloadImg = $('#menu-downloadimg');
let $rightMenuSearch = $('#menu-search');
let $rightMenuSearchBaidu = $('#menu-searchBaidu');
let $rightMenuMusicToggle = $('#menu-music-toggle');
let $rightMenuMusicBack = $('#menu-music-back');
let $rightMenuMusicForward = $('#menu-music-forward');
let $rightMenuMusicPlaylist = $('#menu-music-playlist');
let $rightMenuMusicCopyMusicName = $('#menu-music-copyMusicName');
let href = event.target.href;
let imgsrc = event.target.currentSrc;
// 判断模式 扩展模式为有事件
let pluginMode = false;
$rightMenuOther.show();
globalEvent = event;
// 检查是否需要复制 是否有选中文本
if (selectTextNow && window.getSelection()) {
pluginMode = true;
$rightMenuCopyText.show();
$rightMenuCommentText.show();
$rightMenuSearch.show();
$rightMenuSearchBaidu.show();
} else {
$rightMenuCopyText.hide();
$rightMenuCommentText.hide();
$rightMenuSearchBaidu.hide();
$rightMenuSearch.hide();
}
//检查是否右键点击了链接a标签
if (href) {
pluginMode = true;
$rightMenuNewWindow.show();
$rightMenuCopyLink.show();
domhref = href;
} else {
$rightMenuNewWindow.hide();
$rightMenuCopyLink.hide();
}
//检查是否需要复制图片
if (imgsrc) {
pluginMode = true;
$rightMenuCopyImg.show();
$rightMenuDownloadImg.show();
domImgSrc = imgsrc;
} else {
$rightMenuCopyImg.hide();
$rightMenuDownloadImg.hide();
}
// 判断是否为输入框
if (event.target.tagName.toLowerCase() === 'input' || event.target.tagName.toLowerCase() === 'textarea') {
console.log('这是一个输入框')
pluginMode = true;
$rightMenuPasteText.show();
} else {
$rightMenuPasteText.hide();
}
//判断是否是音乐
if (event.target.nodeName == "METING-JS") {
console.log('这是一个音乐');
pluginMode = true;
$rightMenuMusicToggle.show();
$rightMenuMusicBack.show();
$rightMenuMusicForward.show();
$rightMenuMusicPlaylist.show();
$rightMenuMusicCopyMusicName.show();
} else {
$rightMenuMusicToggle.hide();
$rightMenuMusicBack.hide();
$rightMenuMusicForward.hide();
$rightMenuMusicPlaylist.hide();
$rightMenuMusicCopyMusicName.hide()
}
// 如果不是扩展模式则隐藏扩展模块
if (pluginMode) {
$rightMenuOther.hide();
$rightMenuPlugin.show();
} else {
$rightMenuPlugin.hide()
}
rm.reloadrmSize()
// 鼠标默认显示在鼠标右下方,当鼠标靠右或考下时,将菜单显示在鼠标左方\上方
if (pageX + rmWidth > window.innerWidth) {
pageX -= rmWidth + 10;
}
if (pageY + rmHeight > window.innerHeight) {
pageY -= pageY + rmHeight - window.innerHeight;
}
rm.showRightMenu(true, pageY, pageX);
$('#rightmenu-mask').attr('style', 'display: flex');
return false;
}
};
var domhref = "",
domImgSrc = "",
globalEvent = null;
function imageToBlob(e) {
var t = new Image(),
o = document.createElement("canvas"),
i = o.getContext("2d");
return (
(t.crossOrigin = ""),
(t.src = e),
new Promise(function (n) {
t.onload = function () {
(o.width = this.naturalWidth),
(o.height = this.naturalHeight),
i.drawImage(this, 0, 0),
o.toBlob(
function (e) {
n(e);
},
"image/png",
0.75
);
};
})
);
// 下载图片状态
rm.downloadimging = false;
// 复制图片到剪贴板
rm.writeClipImg = function (imgsrc) {
console.log('按下复制');
rm.hideRightMenu();
btf.snackbarShow('正在下载中,请稍后', false, 10000)
if (rm.downloadimging == false) {
rm.downloadimging = true;
setTimeout(function () {
copyImage(imgsrc);
btf.snackbarShow('复制成功!图片已添加盲水印,请遵守版权协议');
rm.downloadimging = false;
}, "10000")
}
}
function copyImage(e) {
return _copyImage.apply(this, arguments);
function imageToBlob(imageURL) {
const img = new Image;
const c = document.createElement("canvas");
const ctx = c.getContext("2d");
img.crossOrigin = "";
img.src = imageURL;
return new Promise(resolve => {
img.onload = function () {
c.width = this.naturalWidth;
c.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
c.toBlob((blob) => {
// here the image is a blob
resolve(blob)
}, "image/png", 0.75);
};
})
}
function _copyImage() {
return (_copyImage = _asyncToGenerator(
regeneratorRuntime.mark(function e(n) {
var t, o;
return regeneratorRuntime.wrap(function (e) {
for (; ;)
switch ((e.prev = e.next)) {
case 0:
return (e.next = 2), imageToBlob(n);
case 2:
(t = e.sent),
(o = new ClipboardItem({"image/png": t})),
navigator.clipboard.write([o]);
case 5:
case "end":
return e.stop();
}
}, e);
})
)).apply(this, arguments);
async function copyImage(imageURL) {
const blob = await imageToBlob(imageURL)
const item = new ClipboardItem({"image/png": blob});
navigator.clipboard.write([item]);
}
rm.switchDarkMode = function () {
navFn.switchDarkMode();
rm.hideRightMenu();
heo.darkModeStatus();
}
rm.copyUrl = function (id) {
$("body").after("<input id='copyVal'></input>");
var text = id;
var input = document.getElementById("copyVal");
input.value = text;
input.select();
input.setSelectionRange(0, input.value.length);
document.execCommand("copy");
$("#copyVal").remove();
}
function stopMaskScroll() {
document.getElementById("rightmenu-mask") &&
document.getElementById("rightmenu-mask").addEventListener(
"mousewheel",
function (e) {
if (document.getElementById("rightmenu-mask")) {
let xscroll = document.getElementById("rightmenu-mask");
xscroll.addEventListener("mousewheel", function (e) {
//阻止浏览器默认方法
rm.hideRightMenu();
},
!1
),
document.getElementById("rightMenu") &&
document.getElementById("rightMenu").addEventListener(
"mousewheel",
function (e) {
// e.preventDefault();
}, false);
}
if (document.getElementById("rightMenu")) {
let xscroll = document.getElementById("rightMenu");
xscroll.addEventListener("mousewheel", function (e) {
//阻止浏览器默认方法
rm.hideRightMenu();
},
!1
);
// e.preventDefault();
}, false);
}
}
(window.oncontextmenu = function (e) {
if (768 < document.body.clientWidth) {
var n = e.clientX + 10,
t = e.clientY,
o = $(".rightMenuOther"),
i = $(".rightMenuPlugin"),
r = $("#menu-copytext"),
c = $("#menu-pastetext"),
m = $("#menu-commenttext"),
a = $("#menu-newwindow"),
u = $("#menu-copylink"),
h = $("#menu-copyimg"),
d = $("#menu-downloadimg"),
s = $("#menu-search"),
l = $("#menu-searchBaidu"),
g = $("#menu-music-toggle"),
w = $("#menu-music-back"),
f = $("#menu-music-forward"),
p = $("#menu-music-playlist"),
k = $("#menu-music-copyMusicName"),
y = e.target.href,
v = e.target.currentSrc,
M = !1;
return (
o.show(),
(globalEvent = e),
selectTextNow && window.getSelection()
? ((M = !0), r.show(), m.show(), s.show(), l.show())
: (r.hide(), m.hide(), l.hide(), s.hide()),
y ? ((M = !0), a.show(), u.show(), (domhref = y)) : (a.hide(), u.hide()),
v
? ((M = !0), h.show(), d.show(), (domImgSrc = v))
: (h.hide(), d.hide()),
"input" === e.target.tagName.toLowerCase() ||
"textarea" === e.target.tagName.toLowerCase()
? (console.log("这是一个输入框"), (M = !0), c.show())
: c.hide(),
"METING-JS" == e.target.nodeName
? (console.log("这是一个音乐"),
(M = !0),
g.show(),
w.show(),
f.show(),
p.show(),
k.show())
: (g.hide(), w.hide(), f.hide(), p.hide(), k.hide()),
M ? (o.hide(), i.show()) : i.hide(),
rm.reloadrmSize(),
n + rmWidth > window.innerWidth && (n -= rmWidth + 10),
t + rmHeight > window.innerHeight &&
(t -= t + rmHeight - window.innerHeight),
rm.showRightMenu(!0, t, n),
$("#rightmenu-mask").attr("style", "display: flex"),
!1
);
rm.rightmenuCopyText = function (txt) {
if (navigator.clipboard) {
navigator.clipboard.writeText(txt);
}
}),
(rm.downloadimging = !1),
(rm.writeClipImg = function (e) {
console.log("按下复制"),
rm.hideRightMenu(),
btf.snackbarShow("正在下载中,请稍后", !1, 1e4),
0 == rm.downloadimging &&
((rm.downloadimging = !0),
setTimeout(function () {
copyImage(e),
btf.snackbarShow("复制成功!图片已添加盲水印,请遵守版权协议"),
(rm.downloadimging = !1);
}, "10000"));
}),
(rm.switchDarkMode = function () {
navFn.switchDarkMode(), rm.hideRightMenu(), heo.darkModeStatus();
}),
(rm.copyUrl = function (e) {
$("body").after("<input id='copyVal'></input>");
var n = e,
t = document.getElementById("copyVal");
(t.value = n),
t.select(),
t.setSelectionRange(0, t.value.length),
document.execCommand("copy"),
$("#copyVal").remove();
}),
(rm.rightmenuCopyText = function (e) {
navigator.clipboard && navigator.clipboard.writeText(e), rm.hideRightMenu();
}),
(rm.copyPageUrl = function () {
var e = window.location.href;
rm.copyUrl(e),
btf.snackbarShow("复制本页链接地址成功", !1, 2e3),
rm.hideRightMenu();
}),
(rm.sharePage = function () {
window.location.href;
rm.copyUrl(url),
btf.snackbarShow("复制本页链接地址成功", !1, 2e3),
rm.hideRightMenu();
});
var selectTextNow = "";
rm.hideRightMenu();
}
rm.copyPageUrl = function () {
var url = window.location.href;
rm.copyUrl(url);
btf.snackbarShow('复制本页链接地址成功', false, 2000);
rm.hideRightMenu();
}
rm.sharePage = function () {
var content = window.location.href;
rm.copyUrl(url);
btf.snackbarShow('复制本页链接地址成功', false, 2000);
rm.hideRightMenu();
}
// 复制当前选中文本
var selectTextNow = '';
document.onmouseup = document.ondbclick = selceText;
function selceText() {
var e = document.selection
? document.selection.createRange().text
: window.getSelection() + "";
selectTextNow = e || "";
var txt;
if (document.selection) {
txt = document.selection.createRange().text;
} else {
txt = window.getSelection() + '';
}
if (txt) {
selectTextNow = txt;
// console.log(selectTextNow);
} else {
selectTextNow = '';
}
}
function replaceAll(e, n, t) {
return e.split(n).join(t);
// 读取剪切板
rm.readClipboard = function () {
if (navigator.clipboard) {
navigator.clipboard.readText().then(clipText => rm.insertAtCaret(globalEvent.target, clipText));
}
}
// 粘贴文本到焦点
rm.insertAtCaret = function (elemt, value) {
const startPos = elemt.selectionStart,
endPos = elemt.selectionEnd;
if (document.selection) {
elemt.focus();
var sel = document.selection.createRange();
sel.text = value;
elemt.focus();
} else {
if (startPos || startPos == '0') {
var scrollTop = elemt.scrollTop;
elemt.value = elemt.value.substring(0, startPos) + value + elemt.value.substring(endPos, elemt.value.length);
elemt.focus();
elemt.selectionStart = startPos + value.length;
elemt.selectionEnd = startPos + value.length;
elemt.scrollTop = scrollTop;
} else {
elemt.value += value;
elemt.focus();
}
}
}
//粘贴文本
rm.pasteText = function () {
const result = rm.readClipboard() || '';
rm.hideRightMenu();
}
//引用到评论
rm.rightMenuCommentText = function (txt) {
rm.hideRightMenu();
var input = document.getElementsByClassName('el-textarea__inner')[0];
let evt = document.createEvent('HTMLEvents');
evt.initEvent('input', true, true);
let inputValue = replaceAll(txt, '\n', '\n> ')
input.value = '> ' + inputValue + '\n\n';
input.dispatchEvent(evt);
var domTop = document.querySelector("#post-comment").offsetTop;
window.scrollTo(0, domTop - 80);
input.focus();
input.setSelectionRange(-1, -1);
if (document.getElementById("comment-tips")) {
document.getElementById("comment-tips").classList.add("show");
}
}
//替换所有内容
function replaceAll(string, search, replace) {
return string.split(search).join(replace);
}
// 百度搜索
rm.searchBaidu = function () {
btf.snackbarShow('即将跳转到百度搜索', false, 2000);
setTimeout(function () {
window.open('https://www.baidu.com/s?wd=' + selectTextNow);
}, "2000");
rm.hideRightMenu();
}
//分享链接
rm.copyLink = function () {
rm.rightmenuCopyText(domhref);
btf.snackbarShow('已复制链接地址');
}
function addRightMenuClickEvent() {
$("#menu-backward").on("click", function () {
window.history.back(), rm.hideRightMenu();
}),
$("#menu-forward").on("click", function () {
window.history.forward(), rm.hideRightMenu();
}),
$("#menu-refresh").on("click", function () {
window.location.reload();
}),
$("#menu-top").on("click", function () {
btf.scrollToDest(0, 500), rm.hideRightMenu();
}),
$(".menu-link").on("click", rm.hideRightMenu),
$("#menu-darkmode").on("click", rm.switchDarkMode),
$("#menu-home").on("click", function () {
window.location.href = window.location.origin;
}),
// $("#menu-randomPost").on("click", function () {
// toRandomPost();
// }),
$("#menu-commentBarrage").on("click", heo.switchCommentBarrage),
$("#rightmenu-mask").on("click", rm.hideRightMenu),
$("#rightmenu-mask").contextmenu(function () {
return rm.hideRightMenu(), !1;
}),
$("#menu-copy").on("click", rm.copyPageUrl),
$("#menu-pastetext").on("click", rm.pasteText),
$("#menu-copytext").on("click", function () {
rm.rightmenuCopyText(selectTextNow),
btf.snackbarShow("复制成功,复制和转载请标注本文地址");
}),
$("#menu-commenttext").on("click", function () {
rm.rightMenuCommentText(selectTextNow);
}),
$("#menu-newwindow").on("click", function () {
window.open(domhref), rm.hideRightMenu();
}),
$("#menu-copylink").on("click", rm.copyLink),
$("#menu-downloadimg").on("click", function () {
heo.downloadImage(domImgSrc, "zhheo");
}),
$("#menu-copyimg").on("click", function () {
rm.writeClipImg(domImgSrc);
}),
$("#menu-searchBaidu").on("click", rm.searchBaidu),
$("#menu-music-toggle").on("click", heo.musicToggle),
$("#menu-music-back").on("click", heo.musicSkipBack),
$("#menu-music-forward").on("click", heo.musicSkipForward),
$("#menu-music-copyMusicName").on("click", function () {
rm.rightmenuCopyText(heo.musicGetName()),
btf.snackbarShow("复制歌曲名称成功", !1, 3e3);
});
}
(document.onmouseup = document.ondbclick = selceText),
(rm.readClipboard = function () {
navigator.clipboard &&
navigator.clipboard.readText().then(function (e) {
return rm.insertAtCaret(globalEvent.target, e);
});
}),
(rm.insertAtCaret = function (e, n) {
var t,
o = e.selectionStart,
i = e.selectionEnd;
document.selection
? (e.focus(), (document.selection.createRange().text = n), e.focus())
: o || "0" == o
? ((t = e.scrollTop),
(e.value =
e.value.substring(0, o) + n + e.value.substring(i, e.value.length)),
e.focus(),
(e.selectionStart = o + n.length),
(e.selectionEnd = o + n.length),
(e.scrollTop = t))
: ((e.value += n), e.focus());
}),
(rm.pasteText = function () {
rm.readClipboard();
// 添加点击事件
$('#menu-backward').on('click', function () {
window.history.back();
rm.hideRightMenu();
}),
(rm.rightMenuCommentText = function (e) {
rm.hideRightMenu();
var n = document.getElementsByClassName("el-textarea__inner")[0],
t = document.createEvent("HTMLEvents");
t.initEvent("input", !0, !0);
var o = replaceAll(e, "\n", "\n> ");
(n.value = "> " + o + "\n\n"), n.dispatchEvent(t);
var i = document.querySelector("#post-comment").offsetTop;
window.scrollTo(0, i - 80),
n.focus(),
n.setSelectionRange(-1, -1),
document.getElementById("comment-tips") &&
document.getElementById("comment-tips").classList.add("show");
}),
(rm.searchBaidu = function () {
btf.snackbarShow("即将跳转到百度搜索", !1, 2e3),
setTimeout(function () {
window.open("https://www.baidu.com/s?wd=" + selectTextNow);
}, "2000"),
rm.hideRightMenu();
}),
(rm.copyLink = function () {
rm.rightmenuCopyText(domhref), btf.snackbarShow("已复制链接地址");
});
$('#menu-forward').on('click', function () {
window.history.forward();
rm.hideRightMenu();
});
$('#menu-refresh').on('click', function () {
window.location.reload();
});
$('#menu-top').on('click', function () {
btf.scrollToDest(0, 500);
rm.hideRightMenu();
});
$('.menu-link').on('click', rm.hideRightMenu);
$('#menu-darkmode').on('click', rm.switchDarkMode);
$('#menu-home').on('click', function () {
window.location.href = window.location.origin;
});
$('#menu-randomPost').on('click', function () {
toRandomPost()
});
$('#menu-commentBarrage').on('click', heo.switchCommentBarrage);
$('#rightmenu-mask').on('click', rm.hideRightMenu);
$('#rightmenu-mask').contextmenu(function () {
rm.hideRightMenu();
return false;
});
$('#menu-translate').on('click', function () {
rm.hideRightMenu();
translateInitialization();
});
$('#menu-copy').on('click', rm.copyPageUrl);
$('#menu-pastetext').on('click', rm.pasteText);
$('#menu-copytext').on('click', function () {
rm.rightmenuCopyText(selectTextNow);
btf.snackbarShow('复制成功,复制和转载请标注本文地址');
});
$('#menu-commenttext').on('click', function () {
rm.rightMenuCommentText(selectTextNow);
});
$('#menu-newwindow').on('click', function () {
window.open(domhref);
rm.hideRightMenu();
});
$('#menu-copylink').on('click', rm.copyLink);
$('#menu-downloadimg').on('click', function () {
heo.downloadImage(domImgSrc, 'zhheo');
});
$('#menu-copyimg').on('click', function () {
rm.writeClipImg(domImgSrc);
});
$('#menu-searchBaidu').on('click', rm.searchBaidu);
//音乐
$('#menu-music-toggle').on('click', heo.musicToggle);
$('#menu-music-back').on('click', heo.musicSkipBack);
$('#menu-music-forward').on('click', heo.musicSkipForward);
$('#menu-music-copyMusicName').on('click', function () {
rm.rightmenuCopyText(heo.musicGetName());
btf.snackbarShow('复制歌曲名称成功', false, 3000);
});
}

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
</header>
<div id="home_top">
<!-- 每日说说 -->
<div th:replace="modules/time-list :: time-list"></div>
<div th:replace="modules/moment :: moment"></div>
<!-- 置顶内容 -->
<div th:replace="modules/recent-top :: recent-top"></div>
</div>

View File

@ -60,15 +60,15 @@
</div>
</div>
<!-- 暂时不需要弹窗 -->
<!--<div id="cookies-window">-->
<!-- <div class="cookies-window-title">协议提醒助手</div>-->
<!-- <div class="cookies-window-content">-->
<!-- <span class="cookies-tip">查看本站为你的个人隐私做出的努力</span>-->
<!-- <a class="cookies-link" href="privacy/index.html" title="本站如何保护你的隐私">-->
<!-- <i class="fas fa-arrow-circle-right"></i>-->
<!-- </a>-->
<!-- </div>-->
<!--</div>-->
<div id="cookies-window">
<div class="cookies-window-title">协议提醒助手</div>
<div class="cookies-window-content">
<span class="cookies-tip">查看本站为你的个人隐私做出的努力</span>
<a class="cookies-link" href="privacy/index.html" title="本站如何保护你的隐私">
<i class="fas fa-arrow-circle-right"></i>
</a>
</div>
</div>
<div id="quit-box" onclick="RemoveRewardMask()"></div>
</footer>
</html>

View File

@ -126,6 +126,10 @@
<!-- 复制 https://github.com/zenorocha/clipboard.js -->
<script th:src="@{/assets/libs/clipboard/clipboard.min.js}"></script>
<!-- swiper 在瞬间滚动时会使用 -->
<link rel="stylesheet" th:href="@{/assets/libs/swiper/swiper-bundle.min.css}"/>
<script th:src="@{/assets/libs/swiper/swiper-bundle.min.js}"></script>
<!-- 补充部分 -->
<th:block th:if="${metas != null}">
<th:block th:replace="${metas}"/>

View File

@ -11,6 +11,12 @@
// 页面类型 index,page,post,tag,category
htmlType: [[${htmlType}]],
postTitle: [[${htmlType == 'post' ? post.spec.title : ''}]],
isanchor: true,
isPost: [[${htmlType == 'post'}]],
isHome: [[${htmlType == 'index'}]],
isHighlightShrink: false,
isToc: [[${htmlType == 'post'}]] && document.getElementById("card-toc"),
postUpdate: '2022-11-04 20:08:15',
Snackbar: {
chs_to_cht: "你已切换为繁体",
cht_to_chs: "你已切换为简体",
@ -37,9 +43,23 @@
<!-- 控制台 -->
<div th:replace="modules/widgets/console :: console"></div>
<div th:replace="modules/sidebar :: sidebar"></div>
<!-- 内容 -->
<th:block th:replace="${content}"></th:block>
<!-- todo 暂时没显示,是右下角悬浮操作按钮 -->
<div id="rightside">
<div id="rightside-config-hide">
<button id="translateLink" title="简繁转换" type="button"></button>
<button id="darkmode" title="浅色和深色模式转换" type="button"><i class="fas fa-adjust"></i></button>
<button id="hide-aside-btn" title="单栏和双栏切换" type="button"><i class="fas fa-arrows-alt-h"></i></button>
</div>
<div id="rightside-config-show">
<button id="rightside_config" title="设置" type="button"><i class="fas fa-cog fa-spin"></i></button>
<button id="go-up" title="回到顶部" type="button"><i class="fas fa-arrow-up"></i></button>
</div>
</div>
<div th:replace="modules/right-menu :: right-menu"></div>
@ -59,14 +79,13 @@
<!-- 应该是文章页分享使用 -->
<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qrcodejs/1.0.0/qrcode.min.js"></script>
<!-- todo 不知道是否可以抽到 right-menu.html 中,做到后台可配置 -->
<script th:src="@{/assets/zhheo/rightmenu.js}"></script>
<!-- https://raphamorim.io/waterfall.js/ 应该是这个 还有相关的 js 代码 是否可以调整-->
<script th:src="@{/assets/libs/waterfall/waterfall.min.js}"></script>
<!-- 获取主色 https://lokeshdhakar.com/projects/color-thief/ -->
<script th:src="@{/assets/libs/color-thief/color-thief.umd.js}"></script>
<!--<script th:src="@{/assets/libs/color-thief/color-thief.umd.js}"></script>-->
<script th:src="@{/assets/libs/fast-average-color/index.browser.min.js}"></script>
</div>
<div>
@ -79,7 +98,6 @@
// 移除加载动画
removeLoading();
}
addRightMenuClickEvent();
navTitle();
heo.topPostScroll();
heo.topCategoriesBarScroll();

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div class="commentList container" id="commentList" th:fragment="moment" th:if="${theme.config.top.moment}">
<!-- 等待日志模块适配日志 -->
<i class="iconfont icon-logo-moment" onclick="" style="font-size: 1.3rem;" title="瞬间"></i>
<div class="swiper-container swiper-no-swiping" id="moment" tabindex="-1">
<div class="swiper-wrapper" id="comment-list" onclick="">
<div class="li-style swiper-slide">这里需要后面适配瞬间的插件</div>
<div class="li-style swiper-slide">后面再适配吧!</div>
</div>
</div>
<i class="comment-goto iconfont icon-arrow-circle-right" onclick="" title="查看全文"></i>
</div>
</html>

View File

@ -2,8 +2,7 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="post-list"
th:with="postItems=${posts.items},
totalPages = ${(posts.total - 1) / posts.size + 1}, pageIndex = ${posts.page}">
th:with="postItems=${posts.items}">
<!-- card需要添加在没有图片时使用随机图片 -->
<div class="recent-post-item"
@ -19,12 +18,14 @@
</div>
<!-- 类别非空时 -->
<th:block th:if="${not #lists.isEmpty(post.categories)}">
<a class="article-meta__categories"
th:each="category : ${post.categories}"
th:href="@{${category.status.permalink}}"
th:text="${category.spec.displayName}"
th:title="${category.spec.displayName}">
</a>
<span class="article-meta__categories">
<a class="article-meta__category"
th:each="category : ${post.categories}"
th:href="@{${category.status.permalink}}"
th:text="${category.spec.displayName}"
th:title="${category.spec.displayName}">
</a>
</span>
</th:block>
<div class="recent-post-info">
<div class="recent-post-info-top">
@ -69,7 +70,7 @@
<nav id="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
<!-- 页面小于 7 -->
<div class="pagination" th:if="${(totalPages le 7) && (totalPages gt 0)}">
<div class="pagination" th:if="${(posts.totalPages le 7) && (posts.totalPages gt 0)}">
<!-- 上一页 -->
<a class="extend prev" rel="prev" th:href="@{${posts.prevUrl}}" th:if="${posts.hasPrevious()}">
@ -80,7 +81,7 @@
<!-- th:href="${PostFinder.list(index, posts.size)}" -->
<a class="page-number"
th:classappend="${index eq pageIndex} ? 'current'"
th:each="index : ${#numbers.sequence(1, totalPages)}"
th:each="index : ${#numbers.sequence(1, posts.totalPages)}"
th:text="${index}">
</a>
@ -95,7 +96,7 @@
<!-- 页面大于 7 -->
<!-- https://blog.csdn.net/lizc_lizc/article/details/80215147 -->
<div class="pagination" th:if="${totalPages gt 7}">
<div class="pagination" th:if="${posts.totalPages gt 7}">
<!-- 上一页 -->
<a class="extend prev" rel="prev" th:href="@{${posts.prevUrl}}" th:if="${posts.hasPrevious()}">
@ -115,39 +116,39 @@
th:if="${pageIndex le 4}"
th:text="${index}">
</a>
<!-- TODO 需要添加 th:href 跳转地址 -->
<a class="page-number" th:if="${pageIndex le 4}">...</a>
<!-- 最后一页与当前页面之差小于等于3 -->
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number" th:if="${totalPages - pageIndex le 3}">...</a>
<a class="page-number" th:if="${posts.totalPages - pageIndex le 3}">...</a>
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number"
th:classappend="${index eq pageIndex} ? 'current'"
th:each="index : ${#numbers.sequence(totalPages - 4, totalPages - 1)}"
th:if="${totalPages - pageIndex le 3}"
th:each="index : ${#numbers.sequence(posts.totalPages - 4, posts.totalPages - 1)}"
th:if="${posts.totalPages - pageIndex le 3}"
th:text="${index}">
</a>
<!-- 最后一页与当前页面之差大于3 且当前页面大于4 -->
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number" th:if="${(pageIndex gt 4) && (totalPages - pageIndex gt 3)}">...</a>
<a class="page-number" th:if="${(pageIndex gt 4) && (posts.totalPages - pageIndex gt 3)}">...</a>
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number"
th:each="index : ${#numbers.sequence(pageIndex - 1,pageIndex + 1)}"
th:if="${(pageIndex gt 4) && (totalPages - pageIndex gt 3)}"
th:if="${(pageIndex gt 4) && (posts.totalPages - pageIndex gt 3)}"
th:text="${index}">
</a>
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number" th:if="${(pageIndex gt 4) && (totalPages - pageIndex gt 3)}">...</a>
<a class="page-number" th:if="${(pageIndex gt 4) && (posts.totalPages - pageIndex gt 3)}">...</a>
<!-- 尾页 -->
<!-- 需要添加 th:href 跳转地址 -->
<a class="page-number"
th:classappend="${index eq pageIndex} ? 'current'"
th:text="${totalPages}">
th:text="${posts.totalPages}">
</a>
<!-- 下一页 -->

View File

@ -1,8 +1,9 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!-- 右键菜单 -->
<div th:fragment="right-menu">
<div id="rightMenu">
<div th:fragment="right-menu" th:if="${theme.config.rightMenu.switch}">
<script th:src="@{/assets/zhheo/rightmenu.js}"></script>
<div id="rightMenu" >
<div class="rightMenu-group rightMenu-small">
<div class="rightMenu-item" id="menu-backward"><i class="iconfont icon-arrow-left"></i></div>
<div class="rightMenu-item" id="menu-forward"><i class="iconfont icon-arrow-right"></i></div>
@ -82,5 +83,8 @@
</div>
</div>
<div id="rightmenu-mask"></div>
<script>
addRightMenuClickEvent();
</script>
</div>
</html>

View File

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!-- 侧栏,主要是手机端时会使用 -->
<div id="sidebar" th:fragment="sidebar">
<div id="menu-mask"></div>
<div id="sidebar-menus">
<span class="sidebar-menu-item-title">功能</span>
<div class="sidebar-menu-item">
<a class="darkmode_switchbutton menu-child" href="javascript:void(0);" onclick="rm.switchDarkMode()"
rel="external nofollow" title="显示模式切换">
<i class="iconfont icon-moon" style="font-size: 1rem;"></i>
<span>显示模式</span>
</a>
</div>
<th:block th:if="${not #strings.isEmpty(theme.config.nav.left_menu)}"
th:with="leftMenu = ${menuFinder.getByName(theme.config.nav.left_menu)}">
<div class="back-menu-list-groups">
<div class="back-menu-list-group" th:each="menuItem : ${leftMenu.menuItems}">
<th:block th:if="${not #lists.isEmpty(menuItem.children)}">
<!-- 菜单必须有子项才会展示 -->
<div class="back-menu-list-title" th:text="${menuItem.status.displayName}"></div>
<div class="back-menu-list">
<th:block th:each="childMenu : ${menuItem.children}">
<a class="back-menu-item" rel="external nofollow"
target="_blank" th:href="@{${childMenu.status.href}}">
<!-- icon 预留 -->
<!--<img class="back-menu-item-icon" th:src="@{图片地址}">-->
<span class="back-menu-item-text" th:text="${childMenu.status.displayName}"></span>
</a>
</th:block>
</div>
</th:block>
</div>
</div>
</th:block>
<div class="menus_items">
<div class="menus_item">
<a class="site-page" href="javascript:void(0);" rel="external nofollow">
<span>文库</span><i class="iconfont icon-chevron-down"></i>
</a>
<ul class="menus_item_child">
<li>
<a class="site-page child" href="/archives">
<i class="iconfont icon-list-ul"></i>
<span>文章列表</span>
</a>
</li>
<li>
<a class="site-page child" href="/categories">
<i class="iconfont icon-folder-open"></i>
<span>全部分类</span>
</a>
</li>
<li>
<a class="site-page child" href="/tags">
<i class="iconfont icon-tags"></i>
<span>全部标签</span>
</a>
</li>
<!--<li>-->
<!-- <a class="site-page child" href="essay/index.html">-->
<!-- <i class="fa-fw fas fa-bars-staggered"></i>-->
<!-- <span> 即刻短文</span></a>-->
<!--</li>-->
</ul>
</div>
<div class="menus_item">
<a class="site-page" href="javascript:void(0);" rel="external nofollow">
<span>专栏</span><i class="fas fa-chevron-down expand"></i>
</a>
<ul class="menus_item_child" th:with="categories = ${categoryFinder.listAll()}">
<li th:each="category : ${categories}">
<a class="site-page child" th:href="@{${category.status.permalink}}">
<!--<i class="fa-fw fas fa-swatchbook"></i>-->
<span th:title="${category.spec.displayName}"></span>
</a>
</li>
</ul>
</div>
<!--<div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow"><span>-->
<!-- 友链</span><i class="fas fa-chevron-down expand"></i></a>-->
<!-- <ul class="menus_item_child">-->
<!-- <li><a class="site-page child" href="moments/index.html"><i-->
<!-- class="fa-fw fas fa-fish-fins"></i><span> 友链鱼塘</span></a></li>-->
<!-- <li><a class="site-page child" href="link/index.html"><i-->
<!-- class="fa-fw fas fa-user-group"></i><span> 友情链接</span></a></li>-->
<!-- <li><a class="site-page child" href="javascript:travelling()" rel="external nofollow"><i-->
<!-- class="fa-fw fas fa-bus"></i><span> 宝藏博主</span></a></li>-->
<!-- </ul>-->
<!--</div>-->
<!--<div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow"><span>-->
<!-- 我的</span><i class="fas fa-chevron-down expand"></i></a>-->
<!-- <ul class="menus_item_child">-->
<!-- <li><a class="site-page child" href="tlink/index.html"><i-->
<!-- class="fa-fw fas fa-screwdriver-wrench"></i><span> 在线工具</span></a></li>-->
<!-- <li><a class="site-page child" href="movies/index.html"><i-->
<!-- class="fa-fw fas fa-clapperboard"></i><span> 电影推荐</span></a></li>-->
<!-- <li><a class="site-page child" href="about/index.html"><i-->
<!-- class="fa-fw fas fa-sailboat"></i><span> 关于本站</span></a></li>-->
<!-- </ul>-->
<!--</div>-->
</div>
<span class="sidebar-menu-item-title">标签</span>
<div class="card-widget card-tags card-archives card-webinfo card-allinfo"
th:with="tags = ${tagFinder.listAll()}">
<div class="item-headline"><i class="fas fa-tags"></i><span>标签</span></div>
<div class="card-tag-cloud">
<a style="font-size:1em;color:#d3d3d3" th:each="tag : ${tags}"
th:href="@{${tag.status.permalink}}"
th:title="${tag.spec.displayName}">
<!-- 角标 -->
[[${tag.spec.displayName}]]<sup th:text="${tag.status.postCount}"></sup>
</a>
</div>
</div>
</div>
</div>
</html>

View File

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div class="container" th:fragment="time-list" th:if="${theme.config.top.time_list}">
<!-- 等待日志模块适配日志 -->
</div>
</html>

View File

@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- 控制台,右上角点击的时候会显示 -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!-- TODO 控制台功能 -->
<div id="console" th:fragment="console">
<div class="close-btn" href="javascript:void(0);" onclick="heo.hideConsole()">
<i class="iconfont icon-times-circle"></i>
@ -50,19 +51,21 @@
</div>
</div>
<div class="button-group">
<div class="console-btn-item"><a class="darkmode_switchbutton" href="javascript:void(0);"
onclick="rm.switchDarkMode()" rel="external nofollow" title="显示模式切换"><i
class="fa-duotone fa-moon" style="font-size:1rem"></i></a>
</div>
<div class="console-btn-item" id="consoleKeyboard" onclick="heo.keyboardToggle()" title="快捷键开关"><a
class="keyboard-switch"><i class="fa-duotone fa-keyboard"></i></a>
</div>
<div class="console-btn-item" id="assist-open" onclick="heo.hideConsole()" title="无障碍工具栏"><a
class="assist-btn"><i class="fa-duotone fa-wheelchair"></i></a>
</div>
<div class="console-btn-item" id="consoleMusic" onclick="heo.musicToggle()" title="音乐开关"><a
class="music-switch"><i class="fa-duotone fa-music"></i></a>
<div class="console-btn-item">
<!-- 用到了 rightmenu.js 的功能,还需要调整 -->
<a class="darkmode_switchbutton" href="javascript:void(0);" onclick="rm.switchDarkMode()" rel="external nofollow" title="显示模式切换"><i
class="iconfont icon-moon" style="font-size:1rem"></i>
</a>
</div>
<!--<div class="console-btn-item" id="consoleKeyboard" onclick="heo.keyboardToggle()" title="快捷键开关"><a-->
<!-- class="keyboard-switch"><i class="fa-duotone fa-keyboard"></i></a>-->
<!--</div>-->
<!--<div class="console-btn-item" id="assist-open" onclick="heo.hideConsole()" title="无障碍工具栏"><a-->
<!-- class="assist-btn"><i class="fa-duotone fa-wheelchair"></i></a>-->
<!--</div>-->
<!--<div class="console-btn-item" id="consoleMusic" onclick="heo.musicToggle()" title="音乐开关"><a-->
<!-- class="music-switch"><i class="fa-duotone fa-music"></i></a>-->
<!--</div>-->
</div>
<div class="console-mask" href="javascript:void(0);" onclick="heo.hideConsole()" rel="external nofollow">
</div>

View File

@ -10,7 +10,7 @@
<div class="back-home-button" tabindex="-1"
th:if="${not #lists.isEmpty(leftMenu)}">
<i class="back-home-button-icon iconfont icon-grip-vertical"></i>
<i class="back-home-button-icon iconfont icon-grip-vertical" style="font-size: 1rem"></i>
<div class="back-menu-list-groups">
<div class="back-menu-list-group" th:each="menuItem : ${leftMenu.menuItems}">
<!-- 菜单必须有子项才会展示 -->
@ -34,9 +34,8 @@
</th:block>
<!-- 返回主页 -->
<!-- 这里可以指定使用什么作为图标,默认使用站点名称 -->
<a href="/" id="site-name"
th:utext="${#strings.isEmpty(theme.config.nav.site_title)} ? ${site.title} : ${theme.config.nav.site_title}"
title="返回博客主页">
<a href="/" id="site-name" title="返回博客主页">
<span th:utext="${#strings.isEmpty(theme.config.nav.site_title)} ? ${site.title} : ${theme.config.nav.site_title}"></span>
</a>
</div>

View File

@ -6,7 +6,7 @@
<div class="menus_items">
<!-- 第一层仅展示使用,不做跳转 -->
<div class="menus_item" th:each="menuItem : ${menuFinder.getDefault().menuItems}">
<div class="menus_item" th:each="menuItem : ${menuFinder.getPrimary().menuItems}">
<!-- javascript:void(0);" -->
<a class="site-page" rel="external nofollow" th:href="@{${menuItem.status.href}}">

View File

@ -2,7 +2,7 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!-- 导航栏菜单栏 -->
<div id="nav-right" th:fragment="nav-right" th:if="${theme.config.nav.right_menu}">
<div id="nav-right" th:fragment="nav-right">
<!-- 功能都需要添加开关 -->
@ -21,8 +21,8 @@
</div>
<!-- 搜索使用搜索插件 -->
<div class="nav-button" id="search-button">
<a class="site-page social-icon search" href="javascript:void(0);" rel="external nofollow" title="站内搜索">
<div class="nav-button" id="search-button" th:if="${pluginFinder.available('PluginSearchWidget')}">
<a class="site-page social-icon search" href="javascript:SearchWidget.open();" rel="external nofollow" title="站内搜索">
<i class="iconfont icon-search" style="font-size:1rem"></i>
</a>
</div>
@ -41,11 +41,11 @@
</a>
</div>
<!--<div id="toggle-menu">-->
<!-- <a class="site-page">-->
<!-- <i class="fas fa-bars fa-fw"></i>-->
<!-- </a>-->
<!--</div>-->
<div id="toggle-menu">
<a class="site-page">
<i class="iconfont icon-bars"></i>
</a>
</div>
</div>

View File

@ -21,18 +21,23 @@
</div>
</div>
<!-- 这块功能依赖后台配置 -->
<!--<div class="todayCard" id="todayCard" onclick='window.open("https://www.bilibili.com/video/BV1A841147Ef/")'>-->
<!-- <div class="todayCard-info">-->
<!-- <div class="todayCard-tips">音乐推荐</div>-->
<!-- <div class="todayCard-title">逐星</div>-->
<!-- </div>-->
<!-- <div class="todayCard-cover"-->
<!-- style="background:url(https://img.zhheo.com/i/2022/09/23/632d1625aa0d7.webp) no-repeat center/cover"></div>-->
<!-- <div class="banner-button-group"><a class="banner-button"-->
<!-- onclick="window.event.cancelBubble=!0,heo.hideTodayCard()"><i-->
<!-- class="fas fa-circle-plus"></i><span class="banner-button-text">更多推荐</span></a>-->
<!-- </div>-->
<!--</div>-->
<!-- 今日推荐 -->
<div class="todayCard" id="todayCard"
th:if="${theme.config.top.todayRecommend}"
th:onclick="'window.open('+ ${theme.config.top.todayRecommendUrl} +')'">
<div class="todayCard-info">
<div class="todayCard-tips">今日推荐</div>
<div class="todayCard-title" th:text="${theme.config.top.todayRecommendTitle}"></div>
</div>
<div class="todayCard-cover"
th:style="'background:url('+ ${theme.config.top.todayRecommendCover} +') no-repeat center/cover'">
</div>
<div class="banner-button-group">
<a class="banner-button" onclick="window.event.cancelBubble=!0;heo.hideTodayCard()">
<i class="fas fa-circle-plus"></i>
<span class="banner-button-text">更多推荐</span>
</a>
</div>
</div>
</div>
</html>

View File

@ -41,6 +41,13 @@
<h1 class="post-title" th:text="${post.spec.title}"></h1>
<div id="post-meta">
<div class="meta-secondline">
<span class="post-meta-date">
<i class="iconfont icon-calendar-alt post-meta-icon"></i>
<time th:attr="datetime=${#dates.format(post.spec.publishTime, 'yyyy-MM-dd')}"
th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}"
th:title="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}">
</time>
</span>
<span class="post-meta-wordcount"
th:with="wordCount = ${#strings.length(post.content.content)}">
@ -49,32 +56,24 @@
<span class="word-count" th:text="${{wordCount}}"></span>
<span class="post-meta-separator"></span>
<i class="iconfont icon-clock post-meta-icon" title="阅读耗时"></i>
<span class="post-meta-label">阅读耗时:</span><span>[[${wordCount / 400}]] 分钟</span>
</span>
<span class="post-meta-date"><i class="iconfont icon-calendar-alt post-meta-icon"></i>
<time th:attr="datetime=${#dates.format(post.spec.publishTime, 'yyyy-MM-dd HH:mm:ss')}"
th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd HH:mm:ss')}"
th:title="${#dates.format(post.spec.publishTime,'yyyy-MM-dd HH:mm:ss')}">
</time>
<span class="post-meta-label">阅读耗时:</span>
<span>[[${wordCount / 400}]] 分钟</span>
</span>
<!--<span class="post-meta-wechat" title="该文章已在公众号中更新"><i-->
<!-- class="fab fa-weixin post-meta-icon"></i>公众号同步</span>-->
<!--<span class="post-meta-position" title="作者IP属地为北京"><i-->
<!-- class="fas fa-location-dot post-meta-icon"></i>北京</span>-->
<span class="post-meta-pv" data-flag-title="热度">
<i class="iconfont icon-hotjar post-meta-icon"></i>
<span class="post-meta-label">热度:</span>
<span id="visit" th:text="${post.stats.visit}"></span>
</span>
<span class="post-meta-commentcount" title="评论数"><i class="fa-solid fa-message">
</i>
<span class="post-meta-commentcount" onclick="heo.scrollTo('#post-comment');" title="评论数">
<i class="iconfont icon-comment-alt"></i>
<span class="post-meta-label">评论:</span>
<a href="#post-comment">
<span id="comment-count" th:text="${post.stats.comment}"></span>
</a>
</span>
<a href="#post-comment"><span id="comment-count" th:text="${post.stats.comment}"></span></a>
</span>
</div>
</div>
</div>
</header>
@ -162,7 +161,8 @@
<div class="post-copyright" th:if="${theme.config.post.copyright}">
<div class="post-copyright__author">
<!-- 版权页 以及版权描述文字 -->
<a class="post-copyright__original" th:href="@{${theme.config.post.copyrightAgreement}}" title="该文章为原创文章,注意版权协议">原创</a>
<a class="post-copyright__original" th:href="@{${theme.config.post.copyrightAgreement}}"
title="该文章为原创文章,注意版权协议">原创</a>
<a class="post-copyright-title" href="#"><span th:text="${post.spec.title}"></span></a>
</div>
<div class="post-copyright__type">
@ -216,8 +216,8 @@
</div>
</div>
<hr>
<!-- 评论模块,使用评论插件 -->
<div id="post-comment">
<!-- 评论模块 -->
<div id="post-comment" th:if="${pluginFinder.available('PluginCommentWidget')}">
<div class="comment-head">
<div class="comment-headline"><i class="iconfont icon-comment-alt"></i> <span>评论</span></div>
<div class="comment-privacy"><a href="#">隐私政策</a></div>