commit
4044ea363a
|
@ -1766,7 +1766,33 @@ spec:
|
|||
- group: envelope_comment
|
||||
label: 留言板
|
||||
formSchema:
|
||||
- $formkit: radio
|
||||
label: 弹幕
|
||||
name: enable_danmu
|
||||
value: true
|
||||
options:
|
||||
- label: 启用
|
||||
value: true
|
||||
- label: 禁用
|
||||
value: false
|
||||
- $formkit: number
|
||||
name: maxBarrage
|
||||
value: 20
|
||||
label: 弹幕数页数
|
||||
placeholder: 请输入弹幕数页数
|
||||
- $formkit: radio
|
||||
label: 信笺
|
||||
name: enable_envelope_comment
|
||||
key: enable_envelope_comment
|
||||
id: enable_envelope_comment
|
||||
value: true
|
||||
options:
|
||||
- label: 启用
|
||||
value: true
|
||||
- label: 禁用
|
||||
value: false
|
||||
- $formkit: textarea
|
||||
if: $get(enable_envelope_comment).value
|
||||
name: title
|
||||
label: 标题
|
||||
placeholder: 请输入内容
|
||||
|
@ -1774,6 +1800,7 @@ spec:
|
|||
help: 支持 HTML 语法
|
||||
- $formkit: group
|
||||
name: custom_pic
|
||||
if: $get(enable_envelope_comment).value
|
||||
label: 信笺图片
|
||||
value:
|
||||
cover:
|
||||
|
@ -1803,6 +1830,7 @@ spec:
|
|||
value: "https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"
|
||||
- $formkit: repeater
|
||||
name: messageList
|
||||
if: $get(enable_envelope_comment).value
|
||||
label: 正文
|
||||
value:
|
||||
- content: "有什么想问的?"
|
||||
|
@ -1817,12 +1845,14 @@ spec:
|
|||
value: "有什么想问的?"
|
||||
- $formkit: text
|
||||
name: bottom
|
||||
if: $get(enable_envelope_comment).value
|
||||
label: 底部文本
|
||||
placeholder: 请输入内容
|
||||
value: 自动书记人偶竭诚为您服务!
|
||||
help: 仅支持单行文本
|
||||
- $formkit: number
|
||||
name: height
|
||||
if: $get(enable_envelope_comment).value
|
||||
label: 高度
|
||||
placeholder: 请输入内容
|
||||
help: 信封划出的高度
|
||||
|
|
|
@ -257,5 +257,89 @@ let halo = {
|
|||
|
||||
};
|
||||
Prism.hooks.add("complete", r)
|
||||
}
|
||||
},
|
||||
|
||||
addScript: (e,t,n)=>{
|
||||
if (document.getElementById(e))
|
||||
return n ? n() : void 0;
|
||||
let a = document.createElement("script");
|
||||
a.src = t,
|
||||
a.id = e,
|
||||
n && (a.onload = n),
|
||||
document.head.appendChild(a)
|
||||
},
|
||||
|
||||
|
||||
danmu: (url,token,maxBarrage)=>{
|
||||
const e = new EasyDanmaku({
|
||||
el: "#danmu",
|
||||
line: 10,
|
||||
speed: 20,
|
||||
hover: !0,
|
||||
loop: !0
|
||||
});
|
||||
let t = saveToLocal.get("danmu");
|
||||
if (t)
|
||||
e.batchSend(t, !0);
|
||||
else {
|
||||
let n = [];
|
||||
function a(e) {
|
||||
return e = (e = (e = (e = (e = e.replace(/<\/*br>|[\s\uFEFF\xA0]+/g, "")).replace(/<img.*?>/g, "[图片]")).replace(/<a.*?>.*?<\/a>/g, "[链接]")).replace(/<pre.*?>.*?<\/pre>/g, "[代码块]")).replace(/<.*?>/g, "")
|
||||
}
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
event: "GET_RECENT_COMMENTS",
|
||||
accessToken: token,
|
||||
includeReply: !1,
|
||||
pageSize: maxBarrage
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}).then((e=>e.json())).then((({data: t})=>{
|
||||
t.forEach((e=>{
|
||||
null == e.avatar && (e.avatar = "https://cravatar.cn/avatar/d615d5793929e8c7d70eab5f00f7f5f1?d=mp"),
|
||||
n.push({
|
||||
avatar: e.avatar,
|
||||
content: e.nick + ":" + a(e.comment),
|
||||
href: e.url + '#' + e.id
|
||||
|
||||
})
|
||||
}
|
||||
)),
|
||||
e.batchSend(n, !0),
|
||||
saveToLocal.set("danmu", n, .02)
|
||||
}
|
||||
))
|
||||
}
|
||||
document.getElementById("danmuBtn").innerHTML = "<button class=\"hideBtn\" onclick=\"document.getElementById('danmu').classList.remove('hidedanmu')\">显示弹幕</button> <button class=\"hideBtn\" onclick=\"document.getElementById('danmu').classList.add('hidedanmu')\">隐藏弹幕</button>"
|
||||
},
|
||||
//关闭留言板评论弹幕
|
||||
closeCommentBarrage: 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');
|
||||
}
|
||||
}
|
||||
},
|
||||
//打开评论弹幕
|
||||
openCommentBarrage: function () {
|
||||
let commentBarrage = document.querySelector('.comment-barrage');
|
||||
if (commentBarrage) {
|
||||
if ($(".comment-barrage").is(":hidden")) {
|
||||
$(".comment-barrage").show();
|
||||
$(".menu-commentBarrage-text").text("关闭热评");
|
||||
document.querySelector("#consoleCommentBarrage").classList.add("on");
|
||||
localStorage.removeItem('commentBarrageSwitch');
|
||||
btf.snackbarShow("✨ 已开启评论弹幕", false, 2000)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
class EasyDanmaku {
|
||||
constructor(t) {
|
||||
this.container = this.checkParams(t), this.wrapperStyle = t.wrapperStyle || null, this.line = t.line || 10, this.speed = t.speed || 5, this.runtime = t.runtime || 10, this.colourful = t.colourful || !1, this.loop = t.loop || !1, this.hover = t.hover || !1, this.coefficient = t.coefficient || 1.38, this.originIndex = 0, this.originList = null, this.offsetValue = this.container.offsetHeight / this.line, this.vipIndex = 0, this.overflowArr = [], this.clearIng = !1, this.cleartimer = null, this.init(), this.handleEvents(t)
|
||||
}
|
||||
handleEvents(t) {
|
||||
this.onComplete = t.onComplete || null, this.onHover = t.onHover || null
|
||||
}
|
||||
init() {
|
||||
this.runstatus = 1, this.aisle = [], this.container.style.overflow = "hidden", this.hover && this.handleMouseHover(), "relative" !== Utils.getStyle(this.container, "position") && "fixed" !== Utils.getStyle(this.container, "position") && (this.container.style.position = "relative");
|
||||
for (let t = 0; t < this.line; t++) this.aisle.push({
|
||||
normalRow: !0,
|
||||
vipRow: !0
|
||||
})
|
||||
}
|
||||
checkParams(t) {
|
||||
if (!document.querySelector(t.el)) throw `Could not find the ${t.el} element`;
|
||||
if (t.wrapperStyle && "string" != typeof t.wrapperStyle) throw "The type accepted by the wrapperStyle parameter is string";
|
||||
if (t.line && "number" != typeof t.line) throw "The type accepted by the line parameter is number";
|
||||
if (t.speed && "number" != typeof t.speed) throw "The type accepted by the speed parameter is number";
|
||||
if (t.colourful && "boolean" != typeof t.colourful) throw "The type accepted by the colourful parameter is boolean";
|
||||
if (t.runtime && "number" != typeof t.runtime) throw "The type accepted by the runtime parameter is number";
|
||||
if (t.loop && "boolean" != typeof t.loop) throw "The type accepted by the loop parameter is boolean";
|
||||
if (t.coefficient && "number" != typeof t.coefficient) throw "The type accepted by the coefficient parameter is number";
|
||||
if (t.hover && "boolean" != typeof t.hover) throw "The type accepted by the hover parameter is boolean";
|
||||
if (t.onComplete && "function" != typeof t.onComplete) throw "The type accepted by the onComplete parameter is function";
|
||||
if (t.onHover && "function" != typeof t.onHover) throw "The type accepted by the onHover parameter is function";
|
||||
return document.querySelector(t.el)
|
||||
}
|
||||
send(t, e = null, i = null) {
|
||||
if (0 == this.runstatus) return void this.overflowArr.push({
|
||||
content: t,
|
||||
normalClass: e
|
||||
});
|
||||
if (t.length < 1) return;
|
||||
let n = document.createElement("div"),
|
||||
r = 0,
|
||||
s = this.speed,
|
||||
o = null,
|
||||
l = 0;
|
||||
n.innerHTML = t, n.style.display = "inline-block", n.classList.add("default-style"), (e || this.wrapperStyle) && n.classList.add(e || this.wrapperStyle),
|
||||
function a() {
|
||||
if (r = Math.round(Math.random() * (this.line - 1)), this.aisle[r].normalRow) {
|
||||
this.aisle[r].normalRow = !1, this.container.appendChild(n), s += n.offsetWidth / n.parentNode.offsetWidth * 2, n.style.cssText = `\n text-align:center;\n min-width:130px;\n will-change: transform;\n position:absolute;\n right: -${n.offsetWidth+130}px;\n transition: transform ${s}s linear;\n transform: translateX(-${n.parentNode.offsetWidth+n.offsetWidth+130}px);\n top: ${r*this.offsetValue}px;\n line-height:${this.offsetValue}px;\n color:${this.colourful?"#"+("00000"+(16777216*Math.random()<<0).toString(16)).substr(-6):void 0}\n `;
|
||||
let t = (n.parentNode.offsetWidth + n.offsetWidth) / s / 60;
|
||||
o = setInterval((() => {
|
||||
l += t, l > n.offsetWidth * this.coefficient && (this.aisle[r].normalRow = !0, clearInterval(o))
|
||||
}), 16.66), setTimeout((() => {
|
||||
1 != n.getAttribute("relieveDel") && (i && i({
|
||||
runtime: s,
|
||||
target: n,
|
||||
width: n.offsetWidth
|
||||
}), n.remove())
|
||||
}), 1e3 * s)
|
||||
} else {
|
||||
this.aisle.some((t => !0 === t.normalRow)) ? a.call(this) : (() => {
|
||||
this.overflowArr.push({
|
||||
content: t,
|
||||
normalClass: e
|
||||
}), this.clearIng || this.clearOverflowDanmakuArray()
|
||||
})()
|
||||
}
|
||||
}.call(this)
|
||||
}
|
||||
batchSend(t, e = !1, i = null) {
|
||||
let n = this.runtime || 1.23 * t.length;
|
||||
this.originList = t, this.hasAvatar = e, this.normalClass = i;
|
||||
let r = setInterval((() => {
|
||||
this.originIndex > t.length - 1 ? (clearInterval(r), this.originIndex = 0, this.onComplete && this.onComplete(), this.loop && this.batchSend(this.originList, e, i)) : (e ? this.send(`<img src=${t[this.originIndex].avatar}>\n <a href=${t[this.originIndex].href} target='_blank'> <p>${t[this.originIndex].content}</p> </a>\n `, i || this.wrapperStyle) : this.send(t[this.originIndex], i || this.wrapperStyle), this.originIndex++)
|
||||
}), n / t.length * 1e3)
|
||||
}
|
||||
centeredSend(t, e, i = 3e3, n = null) {
|
||||
let r = document.createElement("div"),
|
||||
s = 0;
|
||||
r.innerHTML = t, (e || this.wrapperStyle) && r.classList.add(e || this.wrapperStyle),
|
||||
function t() {
|
||||
if (this.aisle[s].vipRow) this.container.appendChild(r), r.style.cssText = `\n position:absolute;\n left:50%;\n transform:translateX(-50%);\n top: ${s*this.offsetValue}px;\n `, this.aisle[s].vipRow = !1, setTimeout((() => {
|
||||
n && n({
|
||||
duration: i,
|
||||
target: r,
|
||||
width: r.offsetWidth
|
||||
}), r.remove(), this.aisle[s].vipRow = !0
|
||||
}), i);
|
||||
else {
|
||||
if (s++, s > this.line - 1) return;
|
||||
t.call(this)
|
||||
}
|
||||
}.call(this)
|
||||
}
|
||||
play() {
|
||||
const t = this.container.children;
|
||||
for (let e = 0; e < t.length; e++) this.controlDanmakurunStatus(t[e], 1);
|
||||
this.runstatus = 1, 0 !== this.overflowArr.length && this.clearOverflowDanmakuArray()
|
||||
}
|
||||
pause() {
|
||||
const t = this.container.children;
|
||||
for (let e = 0; e < t.length; e++) this.controlDanmakurunStatus(t[e], 0);
|
||||
this.runstatus = 0
|
||||
}
|
||||
controlDanmakurunStatus(t, e) {
|
||||
const i = 0,
|
||||
n = /-(\S*),/;
|
||||
if (e === 1) {
|
||||
clearTimeout(t.timer);
|
||||
const e = Utils.getStyle(t, "transform").match(n)[1];
|
||||
t.style.transition = `transform ${this.speed}s linear`, t.style.transform = `translateX(-${t.parentNode.offsetWidth+parseInt(e)+t.offsetWidth+130}px)`, t.timer = setTimeout((() => {
|
||||
t.remove()
|
||||
}), 1e3 * this.speed)
|
||||
} else if (e === i) {
|
||||
clearTimeout(t.timer);
|
||||
const e = Utils.getStyle(t, "transform").match(n)[1];
|
||||
t.style.transition = "transform 0s linear", t.style.transform = `translateX(-${e}px)`, t.setAttribute("relieveDel", 1)
|
||||
}
|
||||
}
|
||||
handleMouseHover() {
|
||||
Utils.eventDelegation(this.container, "default-style", "mouseover", (t => {
|
||||
t.style["z-index"] = 1e3, this.controlDanmakurunStatus(t, 0), this.onHover && this.onHover(t)
|
||||
})), Utils.eventDelegation(this.container, "default-style", "mouseout", (t => {
|
||||
t.style.zIndex = 1, 1 == this.runstatus && this.controlDanmakurunStatus(t, 1)
|
||||
}))
|
||||
}
|
||||
clearOverflowDanmakuArray() {
|
||||
clearInterval(this.cleartimer), this.clearIng = !0;
|
||||
let t = 0;
|
||||
this.cleartimer = setInterval((() => {
|
||||
0 === this.overflowArr.length ? (t++, t > 20 && (clearInterval(this.cleartimer), this.clearIng = !1)) : (this.send(this.overflowArr[0].content, this.overflowArr[0].normalClass || this.wrapperStyle), this.overflowArr.shift())
|
||||
}), 500)
|
||||
}
|
||||
}
|
||||
class Utils {
|
||||
static getStyle(t, e) {
|
||||
return window.getComputedStyle(t, null)[e]
|
||||
}
|
||||
static eventDelegation(t, e, i, n) {
|
||||
t.addEventListener(i, (t => {
|
||||
try {
|
||||
t.target.className.includes(e) && n(t.target)
|
||||
} catch (t) {}
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -7,347 +7,272 @@
|
|||
<div class="page" id="body-wrap">
|
||||
|
||||
<!-- 头部导航栏 -->
|
||||
|
||||
|
||||
<header class="not-top-img" id="page-header">
|
||||
<nav th:replace="~{modules/nav :: nav(title = null)}"></nav>
|
||||
</header>
|
||||
|
||||
<main class="layout hide-aside" id="content-inner">
|
||||
<div id="page">
|
||||
<th:block th:if="${not #strings.isEmpty(theme.config.envelope_comment.title)}">
|
||||
<h1>[[${theme.config.envelope_comment.title}]]</h1>
|
||||
</th:block>
|
||||
<style>
|
||||
@media screen and (max-width: 600px) {
|
||||
|
||||
#afterimg,
|
||||
#beforeimg {
|
||||
display: none !important
|
||||
}
|
||||
}
|
||||
<th:block th:if="${theme.config.envelope_comment.enable_envelope_comment}">
|
||||
<th:block th:if="${not #strings.isEmpty(theme.config.envelope_comment.title)}"
|
||||
th:utext="${theme.config.envelope_comment.title}">
|
||||
</th:block>
|
||||
<style>
|
||||
@media screen and (max-width: 600px) {
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
#article-container img {
|
||||
margin: 0 auto 0
|
||||
#afterimg,
|
||||
#beforeimg {
|
||||
display: none !important
|
||||
}
|
||||
}
|
||||
|
||||
#form-wrap {
|
||||
overflow: hidden;
|
||||
height: 447px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
transition: all 1s ease-in-out .3s;
|
||||
z-index: 0
|
||||
@media screen and (min-width: 600px) {
|
||||
#article-container img {
|
||||
margin: 0 auto 0
|
||||
}
|
||||
|
||||
#form-wrap {
|
||||
overflow: hidden;
|
||||
height: 447px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
transition: all 1s ease-in-out .3s;
|
||||
z-index: 0
|
||||
}
|
||||
|
||||
#form-wrap:hover {
|
||||
height: [[${theme.config.envelope_comment.height}]]px;
|
||||
top: -200px
|
||||
}
|
||||
|
||||
#beforeimg {
|
||||
position: absolute;
|
||||
bottom: 126px;
|
||||
left: 0;
|
||||
background-repeat: no-repeat;
|
||||
width: 530px;
|
||||
height: 317px;
|
||||
z-index: -100;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
#afterimg {
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
background-repeat: no-repeat;
|
||||
width: 530px;
|
||||
height: 259px;
|
||||
z-index: 100;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
#envelope {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
transition: all 1s ease-in-out .3s;
|
||||
padding-top: 200px
|
||||
}
|
||||
|
||||
#maincontent {
|
||||
width: 530px;
|
||||
margin: 20px auto 0
|
||||
}
|
||||
|
||||
.formmain {
|
||||
background: #fff;
|
||||
width: 95%;
|
||||
max-width: 800px;
|
||||
margin: auto auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 0 0 20px 0 #000;
|
||||
box-shadow: 0 0 20px 0 #000
|
||||
}
|
||||
}
|
||||
|
||||
#form-wrap:hover {
|
||||
height: [[${theme.config.envelope_comment.height}]]px;
|
||||
top: -200px
|
||||
[data-theme=dark] .formmain {
|
||||
background: #323232
|
||||
}
|
||||
|
||||
#beforeimg {
|
||||
position: absolute;
|
||||
bottom: 126px;
|
||||
left: 0;
|
||||
background-repeat: no-repeat;
|
||||
width: 530px;
|
||||
height: 317px;
|
||||
z-index: -100;
|
||||
pointer-events: none
|
||||
[data-theme=dark] .comments {
|
||||
background: #5a5a5a !important
|
||||
}
|
||||
</style>
|
||||
|
||||
#afterimg {
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
background-repeat: no-repeat;
|
||||
width: 530px;
|
||||
height: 259px;
|
||||
z-index: 100;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
#envelope {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
transition: all 1s ease-in-out .3s;
|
||||
padding-top: 200px
|
||||
}
|
||||
<div id="article-container">
|
||||
<div id="maincontent">
|
||||
<div id="form-wrap">
|
||||
<img class="no-lightbox entered loaded" id="beforeimg"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.beforeimg}}">
|
||||
<div id="envelope">
|
||||
<form>
|
||||
<div class="formmain" style="pointer-events:none">
|
||||
<img class="headerimg no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.cover}}"
|
||||
style="width:100%;overflow:hidden;pointer-events:none">
|
||||
<div class="comments-main">
|
||||
<h3 class="title3"
|
||||
style="text-decoration:none;color:var(--heo-theme);text-align:center">
|
||||
来自[[${site.title}]]的留言:</h3>
|
||||
<div class="comments"
|
||||
style="text-align:center;border-bottom:#ddd 1px solid;border-left:#ddd 1px solid;padding-bottom:20px;background-color:#eee;margin:15px 0;padding-left:20px;padding-right:20px;border-top:#ddd 1px solid;border-right:#ddd 1px solid;padding-top:20px"
|
||||
th:with="message = ${theme.config.envelope_comment.messageList}">
|
||||
|
||||
#maincontent {
|
||||
width: 530px;
|
||||
margin: 20px auto 0
|
||||
}
|
||||
|
||||
.formmain {
|
||||
background: #fff;
|
||||
width: 95%;
|
||||
max-width: 800px;
|
||||
margin: auto auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 0 0 20px 0 #000;
|
||||
box-shadow: 0 0 20px 0 #000
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme=dark] .formmain {
|
||||
background: #323232
|
||||
}
|
||||
|
||||
[data-theme=dark] .comments {
|
||||
background: #5a5a5a !important
|
||||
}
|
||||
|
||||
#danmu {
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 60px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 评论弹幕 */
|
||||
.barrage {
|
||||
position: fixed;
|
||||
right: -500px;
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
z-index: 999
|
||||
}
|
||||
|
||||
.barrage_box {
|
||||
display: flex;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
padding-right: 8px;
|
||||
height: 40px;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.barrage_box .portrait {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
margin-left: 4px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.barrage_box .portrait img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.barrage_box div.p a {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
max-width: 25rem;
|
||||
margin-right: 2px;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.barrage_box div.p a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.hidedanmu {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.hidedanmu * {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
div#danmuBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
div#danmuBtn button {
|
||||
background: var(--heo-theme);
|
||||
color: white;
|
||||
padding: 8px 20px;
|
||||
margin: 0 20px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
.barrage {
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
border-radius: 100px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 6px 16px 6px 6px;
|
||||
color: #eee;
|
||||
}
|
||||
.barrage:hover {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
transition: .3s
|
||||
}
|
||||
|
||||
.barrage img {
|
||||
pointer-events: none;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
margin: 0 5px 0 0 !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.barrage p {
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
margin: 0 !important;
|
||||
max-width: 300px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/yaseng/jquery.barrager.js/dist/js/jquery.barrager.min.js"></script>
|
||||
<div id="article-container">
|
||||
<div id="maincontent">
|
||||
<div id="form-wrap">
|
||||
<img class="no-lightbox entered loaded" id="beforeimg"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.beforeimg}}">
|
||||
<div id="envelope">
|
||||
<form>
|
||||
<div class="formmain" style="pointer-events:none">
|
||||
<img class="headerimg no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.cover}}"
|
||||
style="width:100%;overflow:hidden;pointer-events:none">
|
||||
<div class="comments-main">
|
||||
<h3 class="title3"
|
||||
style="text-decoration:none;color:var(--heo-theme);text-align:center">
|
||||
来自[[${site.title}]]的留言:</h3>
|
||||
<div class="comments"
|
||||
style="text-align:center;border-bottom:#ddd 1px solid;border-left:#ddd 1px solid;padding-bottom:20px;background-color:#eee;margin:15px 0;padding-left:20px;padding-right:20px;border-top:#ddd 1px solid;border-right:#ddd 1px solid;padding-top:20px"
|
||||
th:with="message = ${theme.config.envelope_comment.messageList}">
|
||||
|
||||
<div th:each="data : ${message}">[[${data.content}]]</div>
|
||||
<div th:each="data : ${message}">[[${data.content}]]</div>
|
||||
|
||||
</div>
|
||||
<div class="bottomcontent" style="text-align:center;margin-top:40px">
|
||||
<img class="bottomimg no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.line}}"
|
||||
style="width:100%;margin:5px auto 5px auto;display:block;pointer-events:none">
|
||||
</div>
|
||||
<p class="bottomhr" style="font-size:12px;text-align:center;color:#999">
|
||||
[[${theme.config.envelope_comment.bottom}]]</p>
|
||||
</div>
|
||||
<div class="bottomcontent" style="text-align:center;margin-top:40px">
|
||||
<img class="bottomimg no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.line}}"
|
||||
style="width:100%;margin:5px auto 5px auto;display:block;pointer-events:none">
|
||||
</div>
|
||||
<p class="bottomhr" style="font-size:12px;text-align:center;color:#999">
|
||||
[[${theme.config.envelope_comment.bottom}]]</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
<img id="afterimg" class="no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.afterimg}}">
|
||||
</div>
|
||||
<img id="afterimg" class="no-lightbox entered loaded"
|
||||
th:src="@{${theme.config.envelope_comment.custom_pic.afterimg}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</th:block>
|
||||
|
||||
<div class="flink" id="article-container">
|
||||
<th:block th:utext="${singlePage.content.content}"></th:block>
|
||||
</div>
|
||||
|
||||
<div id="loading"></div>
|
||||
<div id="danmu"></div>
|
||||
<div id="danmuBtn">
|
||||
<button class="hideBtn"
|
||||
onclick="document.getElementById('danmu').classList.remove('hidedanmu')">显示弹幕
|
||||
</button>
|
||||
<button class="hideBtn"
|
||||
onclick="document.getElementById('danmu').classList.add('hidedanmu')">隐藏弹幕
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
let ls = []
|
||||
let Num = 0;
|
||||
|
||||
// 以下注释为twikoo api的返回格式
|
||||
// 返回 Array,包含最新评论的
|
||||
// * id: 评论 ID
|
||||
// * url: 评论地址
|
||||
// * nick: 昵称
|
||||
// * mailMd5: 邮箱的 MD5 值,可用于展示头像
|
||||
// * link: 网址
|
||||
// * comment: HTML 格式的评论内容
|
||||
// * commentText: 纯文本格式的评论内容
|
||||
// * created: 评论时间,格式为毫秒级时间戳
|
||||
// * avatar: 头像地址(0.2.9 新增)
|
||||
// * relativeTime: 相对评论时间,如 “1 小时前”(0.2.9 新增)
|
||||
// 返回示例: [ // 从新到旧顺序
|
||||
// { id: '', url: '', nick: '', mailMd5: '', link: '', comment: '', commentText: '', created: 0 },
|
||||
// { id: '', url: '', nick: '', mailMd5: '', link: '', comment: '', commentText: '', created: 0 },
|
||||
// { id: '', url: '', nick: '', mailMd5: '', link: '', comment: '', commentText: '', created: 0 }
|
||||
// ]
|
||||
addEventListener("load",
|
||||
() => {
|
||||
// 手机端显示效果不好,所以直接不让其显示
|
||||
if (1 && document.body.clientWidth > 768) {
|
||||
// 加载动画,将 /themes/theme-hao/assets/images/load/rotating-ball-o.svg 换成你的加载图片即可
|
||||
document.getElementById('loading').innerHTML = '<a href="/themes/theme-hao/assets/images/load/rotating-ball-o.svg" data-fancybox="gallery" data-caption="弹幕加载中..." data-thumb="/themes/theme-hao/assets/images/load/rotating-ball-o.svg" style="position: fixed;bottom: 100px;left: 4%;"><img src="/themes/theme-hao/assets/images/load/rotating-ball-o.svg" data-lazy-src="/themes/theme-hao/assets/images/load/rotating-ball-o.svg" alt="弹幕加载中..." data-ll-status="loaded" class="entered loaded"></a>';
|
||||
let barrageTime = ''
|
||||
// 使用twikoo 自带api请求全站数据
|
||||
twikoo.getRecentComments({
|
||||
envId: "[(${theme.config.comments.twikoos.envId})]", // 环境 ID
|
||||
// region: 'ap-guangzhou', // 环境地域,默认为 ap-shanghai,如果您的环境地域不是上海,需传此参数
|
||||
pageSize: 50, // 获取多少条,默认:10,最大:100
|
||||
includeReply: false // 是否包括最新回复,默认:false
|
||||
}).then((data) => {
|
||||
data.forEach(i => {
|
||||
if (i.avatar == undefined) i.avatar = 'https://cravatar.cn/avatar/d615d5793929e8c7d70eab5f00f7f5f1?d=mp'
|
||||
ls.push({
|
||||
img: i.avatar, //图片
|
||||
info: i.nick + ':' + formatDanmaku(i.comment), //文字
|
||||
href: i.url, //链接
|
||||
close: false, //显示关闭按钮
|
||||
speed: 15, //延迟,单位秒,默认6
|
||||
// bottom: 70, //距离底部高度,单位px,默认随机
|
||||
color: '#fff', //颜色,默认白色
|
||||
old_ie_color: '#000000', //ie低版兼容色,不能与网页背景相同,默认黑色
|
||||
})
|
||||
});
|
||||
setTimeout(() => {
|
||||
document.getElementById('loading').innerHTML = '';
|
||||
}, 2000);
|
||||
setInterval(() => {
|
||||
if (Num >= ls.length) Num = 0
|
||||
$('#danmu').barrager(ls[Num]);
|
||||
Num++;
|
||||
}, 1000); // 弹幕间隔时长
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
} else {
|
||||
document.getElementById('loading').innerHTML = '<div class="note danger flat"><p>已关闭弹幕功能,请在电脑上查看。</p></div>' // 如果是手机则提醒
|
||||
document.getElementById('danmuBtn').innerHTML = ''
|
||||
}
|
||||
})
|
||||
<th:block th:if="${theme.config.comments.twikooEnable &&
|
||||
#strings.equals(theme.config.comments.use, 'Twikoo') &&
|
||||
theme.config.envelope_comment.enable_danmu }">
|
||||
<div id="danmuBtn">
|
||||
<button class="hideBtn"
|
||||
onclick="document.getElementById('danmu').classList.remove('hidedanmu')">显示弹幕</button>
|
||||
<button class="hideBtn"
|
||||
onclick="document.getElementById('danmu').classList.add('hidedanmu')">隐藏弹幕</button>
|
||||
</div>
|
||||
|
||||
<div id="danmu">
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
.default-style a {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.default-style a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
:root {
|
||||
--hao-purple: #4976f5;
|
||||
}
|
||||
|
||||
#article-container a:not(.headerlink, .fancybox) {
|
||||
font-weight: 700;
|
||||
color: #4c4948;
|
||||
padding: 0 3px;
|
||||
border-bottom: 2px var(--hao-purple) solid;
|
||||
}
|
||||
|
||||
#article-container a:not(.headerlink, .fancybox):hover {
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
background-color: var(--hao-purple);
|
||||
}
|
||||
|
||||
#danmu {
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 60px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hidedanmu {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.hidedanmu * {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
div#danmuBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
div#danmuBtn button {
|
||||
background: var(--hao-purple);
|
||||
color: white;
|
||||
padding: 8px 20px;
|
||||
margin: 0 20px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.default-style {
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
border-radius: 100px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 6px 16px 6px 6px;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.default-style:hover {
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
transition: .3s
|
||||
}
|
||||
|
||||
.default-style img {
|
||||
pointer-events: none;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
margin: 0 5px 0 0 !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.default-style p {
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
margin: 0 !important;
|
||||
max-width: 300px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
</th:block>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 格式化评论
|
||||
function formatDanmaku(str) {
|
||||
str = str.replace(/<\/*br>|[\s\uFEFF\xA0]+/g, '');
|
||||
str = str.replace(/<img.*?>/g, '[图片]');
|
||||
str = str.replace(/<a.*?>.*?<\/a>/g, '[链接]');
|
||||
str = str.replace(/<pre.*?>.*?<\/pre>/g, '[代码块]');
|
||||
str = str.replace(/<.*?>/g, '');
|
||||
return str
|
||||
}
|
||||
</script>
|
||||
<hr>
|
||||
<!--/* 评论组件 */-->
|
||||
<th:block
|
||||
th:replace="~{modules/comment :: comment(group = 'content.halo.run',
|
||||
<th:block th:replace="~{modules/comment :: comment(group = 'content.halo.run',
|
||||
kind = 'SinglePage',
|
||||
name = ${singlePage.metadata.name},
|
||||
allowComment = ${singlePage.spec.allowComment})}"/>
|
||||
allowComment = ${singlePage.spec.allowComment})}" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<div id="random-post"></div>
|
||||
<script type="text/javascript">
|
||||
var fdataUser = {
|
||||
apiurl: [[${ theme.config.fcircle.apiurl }]],
|
||||
apiurl: [(${ theme.config.fcircle.apiurl })],
|
||||
defaultFish: 500,
|
||||
hungryFish: 500,
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@
|
|||
|
||||
<div id="js-pjax"></div>
|
||||
|
||||
<script th:if="${theme.config.envelope_comment.enable_danmu}" th:src="${assets_link + '/libs/twikoo/easy-Danmaku.js'}" id="Danmaku"></script>
|
||||
|
||||
|
||||
<script>
|
||||
let pjaxSelectors = ['title', '#config-diff', '#body-wrap', '#rightside-config-hide', '#rightside-config-show', '.js-pjax','#site-config']
|
||||
|
@ -244,6 +246,13 @@
|
|||
halo.dataCodeTheme()
|
||||
}
|
||||
|
||||
if(document.querySelector('#danmu') &&
|
||||
document.body.clientWidth > 768 &&
|
||||
[[${theme.config.envelope_comment.enable_danmu}]]){
|
||||
halo.closeCommentBarrage();
|
||||
halo.addScript("Danmaku", "[[${assets_link + '/libs/twikoo/easy-Danmaku.js'}]]", halo.danmu("[(${theme.config.comments.twikoos.envId})]","[(${theme.config.comments.twikoos.accessToken})]",[[${theme.config.envelope_comment.maxBarrage}]]))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue