mirror of
https://github.com/jkjoy/typecho-theme-farallon.git
synced 2026-06-27 20:34:30 +00:00
0.7.0
重新整理了一下目录,更改了部分内容的实现方式
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
.donate-panel {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.button--like {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.button--like:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.icon--default {
|
||||
fill: #666;
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
.button--like:hover .icon--default {
|
||||
fill: #ff4081;
|
||||
}
|
||||
|
||||
#qrcode-panel {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
display: none;
|
||||
animation: fadeIn 0.3s ease;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, 10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.qrcode-body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.donate-memo {
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#donate-close {
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
top: -5px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#donate-close:hover {
|
||||
color: #ff4081;
|
||||
}
|
||||
|
||||
.donate-qrpay img {
|
||||
max-width: 240px;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
/* 支付方式切换按钮样式 */
|
||||
.donate-methods {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 15px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.donate-method-btn {
|
||||
padding: 5px 15px;
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
background: #f5f5f5;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.donate-method-btn.active {
|
||||
background: #ff4081;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.donate-method-btn:hover {
|
||||
background: #ff4081;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* QR码容器样式 */
|
||||
.qr-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.qr-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
}
|
||||
|
||||
.qr-image.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* 小三角形 */
|
||||
#qrcode-panel:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid white;
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
.lb-loader,.lightbox{text-align:center;line-height:0;position:absolute;left:0}body.lb-disable-scrolling{overflow:hidden}.lightboxOverlay{position:absolute;top:0;left:0;z-index:9999;background-color:#000;filter:alpha(Opacity=80);opacity:.8;display:none}.lightbox{width:100%;z-index:10000;font-weight:400;outline:0}.lightbox .lb-image{display:block;height:auto;max-width:inherit;max-height:none;border-radius:3px;border:4px solid #fff}.lightbox a img{border:none}.lb-outerContainer{position:relative;width:250px;height:250px;margin:0 auto;border-radius:4px;background-color:#fff}.lb-outerContainer:after{content:"";display:table;clear:both}.lb-loader{top:43%;height:25%;width:100%}.lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background:url(../images/loading.gif) no-repeat}.lb-nav{position:absolute;top:0;left:0;height:100%;width:100%;z-index:10}.lb-container>.nav{left:0}.lb-nav a{outline:0;background-image:url(data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.lb-next,.lb-prev{height:100%;cursor:pointer;display:block}.lb-nav a.lb-prev{width:34%;left:0;float:left;background:url(../images/prev.png) left 48% no-repeat;filter:alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-prev:hover{filter:alpha(Opacity=100);opacity:1}.lb-nav a.lb-next{width:64%;right:0;float:right;background:url(../images/next.png) right 48% no-repeat;filter:alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-next:hover{filter:alpha(Opacity=100);opacity:1}.lb-dataContainer{margin:0 auto;padding-top:5px;width:100%;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.lb-dataContainer:after{content:"";display:table;clear:both}.lb-data{padding:0 4px;color:#ccc}.lb-data .lb-details{width:85%;float:left;text-align:left;line-height:1.1em}.lb-data .lb-caption{font-size:13px;font-weight:700;line-height:1em}.lb-data .lb-caption a{color:#4ae}.lb-data .lb-number{display:block;clear:left;padding-bottom:1em;font-size:12px;color:#999}.lb-data .lb-close{display:block;float:right;width:30px;height:30px;background:url(../images/close.png) top right no-repeat;text-align:right;outline:0;filter:alpha(Opacity=70);opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.lb-data .lb-close:hover{cursor:pointer;filter:alpha(Opacity=100);opacity:1}
|
||||
@@ -0,0 +1 @@
|
||||
.neodb-container{--db-item-width:150px;--db-item-height:180px;--db-music-width:150px;--db-music-height:150px;--db-primary-color:var(--farallon-hover-color);--db-background-white:var(--farallon-background-white);--db-background-gray:var(--farallon-background-gray);--db-border-color:var(--farallon-border-color);--db-text-light:var(--farallon-text-light);}.neodb-nav{padding:30px 0 20px;display:flex;align-items:center;flex-wrap:wrap;}.neodb-navItem{font-size:20px;cursor:pointer;border-bottom:1px solid rgba(0,0,0,0);transition:0.5s border-color;display:flex;align-items:center;text-transform:capitalize;}.neodb-navItem.current,.neodb-navItem:hover{border-color:inherit;}.neodb-navItem{margin-right:20px;}.neodb-score svg{fill:#f5c518;margin-right:5px;}.neodb-list{display:flex;align-items:flex-start;flex-wrap:wrap;}.neodb-image{width:var(--db-item-width);height:var(--db-item-height);object-fit:cover;border-radius:4px;}.neodb-image:hover{box-shadow:0 0 10px var(--db-border-color);}.neodb-title{margin-top:2px;font-size:14px;line-height:1.4;}.neodb-title a:hover{color:var(--db-primary-color);text-decoration:underline;}.neodb-genreItem{background:var(--db-background-gray);font-size:12px;padding:5px 12px;border-radius:4px;margin-right:6px;margin-bottom:10px;line-height:1.4;cursor:pointer;}.neodb-genreItem.is-active,.neodb-genreItem:hover{background-color:var(--db-primary-color);color:var(--db-background-white);}.neodb-genres{padding-bottom:15px;display:flex;flex-wrap:wrap;}.neodb-genres.u-hide + .neodb-list{padding-top:10px;}.neodb-score{display:flex;align-items:center;font-size:14px;color:var(--db-text-light);}.neodb-item{width:var(--db-item-width);margin-right:20px;margin-bottom:20px;position:relative;}.neodb-item__music img{width:var(--db-music-width);height:var(--db-music-height);object-fit:cover;}.neodb-date{position:relative;font-size:20px;color:var(--farallon-text-light);font-weight:900;line-height:1;}.neodb-date::before{content:"";position:absolute;top:0.5em;bottom:-2px;left:-10px;width:3.4em;z-index:-1;background:var(--farallon-hover-color);opacity:0.3;transform:skew(-35deg);transition:opacity 0.2s ease;border-radius:3px 8px 10px 6px;}.neodb-date{margin-top:30px;margin-bottom:10px;}.neodb-dateList{padding-left:15px;padding-top:5px;padding-right:15px;}.neodb-card__list{display:flex;align-items:center;padding:15px 0;border-bottom:1px dotted var(--farallon-border-color);font-size:14px;color:rgba(0,0,0,0.55);}.neodb-card__list:last-child{border-bottom:0;}.neodb-card__list .title{font-size:18px;margin-bottom:5px;}.neodb-card__list .rating{margin:0 0 0px;font-size:14px;line-height:1;display:flex;align-items:center;}.neodb-card__list .rating .allstardark{position:relative;color:#f99b01;height:16px;width:80px;background-repeat:repeat;background-image:url("../images/star.svg");background-size:auto 100%;margin-right:5px;}.neodb-card__list .rating .allstarlight{position:absolute;left:0;color:#f99b01;height:16px;overflow:hidden;background-repeat:repeat;background-image:url("../images/star-fill.svg");background-size:auto 100%;}.neodb-card__list img{width:80px;border-radius:4px;height:80px;object-fit:cover;flex:0 0 auto;margin-right:15px;}.neodb-titleDate{display:flex;flex-direction:column;line-height:1.1;margin-bottom:10px;flex:0 0 auto;margin-right:15px;align-items:center;}.neodb-titleDate__day{font-weight:900;font-size:44px;}.neodb-titleDate__month{font-size:14px;color:var(--farallon-text-light);font-weight:900;}.neodb-list__card{display:block;}.neodb-dateList__card{display:flex;flex-wrap:wrap;align-items:flex-start;}.neodb-listBydate{display:flex;align-items:flex-start;margin-top:15px;}@media (max-width:600px){.neodb-listBydate{flex-direction:column;}}
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 280 B |
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,120 @@
|
||||
;
|
||||
(() => {
|
||||
var farallonHelper = class {
|
||||
getCookie(t) {
|
||||
if (0 < document.cookie.length) {
|
||||
var e = document.cookie.indexOf(t + "=");
|
||||
if (-1 != e) {
|
||||
e = e + t.length + 1;
|
||||
var n = document.cookie.indexOf(";", e);
|
||||
return -1 == n && (n = document.cookie.length), document.cookie.substring(e, n);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
var farallonBase = class extends farallonHelper {
|
||||
is_single = false;
|
||||
post_id = 0;
|
||||
is_archive = false;
|
||||
VERSION = "0.7.0";
|
||||
constructor() {
|
||||
super();
|
||||
this.initCopyright();
|
||||
this.initThemeSwitch();
|
||||
this.initBack2Top();
|
||||
this.initSearch();
|
||||
}
|
||||
initSearch() {
|
||||
document.querySelector('[data-action="show-search"]').addEventListener("click", () => {
|
||||
document.querySelector(".site--header__center .inner").classList.toggle("search--active");
|
||||
});
|
||||
}
|
||||
initBack2Top() {
|
||||
if (document.querySelector(".backToTop")) {
|
||||
const backToTop = document.querySelector(
|
||||
".backToTop"
|
||||
);
|
||||
window.addEventListener("scroll", () => {
|
||||
const t = window.scrollY || window.pageYOffset;
|
||||
t > 200 ? backToTop.classList.add("is-active") : backToTop.classList.remove("is-active");
|
||||
});
|
||||
backToTop.addEventListener("click", () => {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
});
|
||||
}
|
||||
}
|
||||
initCopyright() {
|
||||
const copyright = `<div class="site--footer__info">由<a href="https://www.typecho.org" target="_blank">Typecho</a> 驱动 <br>
|
||||
Theme <a href="https://fatesinger.com/101971" target="_blank">farallon</a> by bigfa <br>Made with<a href="https://www.imsun.org" target="_blank"> Sun</a> / version ${this.VERSION}
|
||||
</div>`;
|
||||
document.querySelector(".site--footer__content").insertAdjacentHTML("afterend", copyright);
|
||||
document.querySelector(".icon--copryrights").addEventListener("click", () => {
|
||||
document.querySelector(".site--footer__info").classList.toggle("active");
|
||||
});
|
||||
}
|
||||
initThemeSwitch() {
|
||||
const theme = localStorage.getItem("theme") ? localStorage.getItem("theme") : "auto";
|
||||
const html = `<div class="fixed--theme">
|
||||
<span class="${theme == "dark" ? "is-active" : ""}" data-action-value="dark">
|
||||
<svg fill="none" height="24" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" width="24"
|
||||
style="color: currentcolor; width: 16px; height: 16px;">
|
||||
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="${theme == "light" ? "is-active" : ""}" data-action-value="light">
|
||||
<svg fill="none" height="24" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" width="24"
|
||||
style="color: currentcolor; width: 16px; height: 16px;">
|
||||
<circle cx="12" cy="12" r="5"></circle>
|
||||
<path d="M12 1v2"></path>
|
||||
<path d="M12 21v2"></path>
|
||||
<path d="M4.22 4.22l1.42 1.42"></path>
|
||||
<path d="M18.36 18.36l1.42 1.42"></path>
|
||||
<path d="M1 12h2"></path>
|
||||
<path d="M21 12h2"></path>
|
||||
<path d="M4.22 19.78l1.42-1.42"></path>
|
||||
<path d="M18.36 5.64l1.42-1.42"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="${theme == "auto" ? "is-active" : ""}" data-action-value="auto">
|
||||
<svg fill="none" height="24" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="1.5" viewBox="0 0 24 24" width="24"
|
||||
style="color: currentcolor; width: 16px; height: 16px;">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
||||
<path d="M8 21h8"></path>
|
||||
<path d="M12 17v4"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>`;
|
||||
document.querySelector("body").insertAdjacentHTML("beforeend", html);
|
||||
document.querySelectorAll(".fixed--theme span").forEach((item) => {
|
||||
item.addEventListener("click", () => {
|
||||
if (item.classList.contains("is-active"))
|
||||
return;
|
||||
document.querySelectorAll(".fixed--theme span").forEach((item2) => {
|
||||
item2.classList.remove("is-active");
|
||||
});
|
||||
if (item.dataset.actionValue == "dark") {
|
||||
localStorage.setItem("theme", "dark");
|
||||
document.querySelector("body").classList.remove("auto");
|
||||
document.querySelector("body").classList.add("dark");
|
||||
item.classList.add("is-active");
|
||||
} else if (item.dataset.actionValue == "light") {
|
||||
localStorage.setItem("theme", "light");
|
||||
document.querySelector("body").classList.remove("auto");
|
||||
document.querySelector("body").classList.remove("dark");
|
||||
item.classList.add("is-active");
|
||||
} else if (item.dataset.actionValue == "auto") {
|
||||
localStorage.setItem("theme", "auto");
|
||||
document.querySelector("body").classList.remove("dark");
|
||||
document.querySelector("body").classList.add("auto");
|
||||
item.classList.add("is-active");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
new farallonBase();
|
||||
})();
|
||||
+350
@@ -0,0 +1,350 @@
|
||||
class Douban {
|
||||
constructor(config) {
|
||||
this.container = config.container;
|
||||
this.types = config.types ?? [
|
||||
"movie",
|
||||
"book",
|
||||
"music",
|
||||
"game",
|
||||
"drama",
|
||||
];
|
||||
this.baseAPI = config.baseAPI;
|
||||
this.ver = "1.0.6";
|
||||
this.type = "movie";
|
||||
this.status = "done";
|
||||
this.finished = false;
|
||||
this.paged = 1;
|
||||
this.genre_list = [
|
||||
{
|
||||
name: "已看",
|
||||
value: "done",
|
||||
},
|
||||
{
|
||||
name: "在看",
|
||||
value: "doing",
|
||||
},
|
||||
{
|
||||
name: "想看",
|
||||
value: "mark",
|
||||
},
|
||||
];
|
||||
this.subjects = [];
|
||||
this._create();
|
||||
}
|
||||
|
||||
on(event, element, callback) {
|
||||
const nodeList = document.querySelectorAll(element);
|
||||
nodeList.forEach((item) => {
|
||||
item.addEventListener(event, callback);
|
||||
});
|
||||
}
|
||||
|
||||
_handleGenreClick() {
|
||||
this.on("click", ".db--genreItem", (t) => {
|
||||
const self = t.currentTarget;
|
||||
if (self.classList.contains("is-active")) {
|
||||
return;
|
||||
}
|
||||
document.querySelector(".db--list").innerHTML = "";
|
||||
document.querySelector(".lds-ripple").classList.remove("u-hide");
|
||||
|
||||
this.status = self.dataset.status || ""; // Provide a default value of an empty string if self.dataset.status is undefined
|
||||
this._renderGenre();
|
||||
this.paged = 1;
|
||||
this.finished = false;
|
||||
this.subjects = [];
|
||||
this._fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
_reanderTypes() {
|
||||
document.querySelector(".db--nav").innerHTML = this.types
|
||||
.map((item) => {
|
||||
return `<span class="db--navItem JiEun${
|
||||
this.type == item ? " current" : ""
|
||||
}" data-type="${item}">${item}</span>`;
|
||||
})
|
||||
.join("");
|
||||
this._handleNavClick();
|
||||
}
|
||||
|
||||
_renderGenre() {
|
||||
document.querySelector(".db--genres").innerHTML = this.genre_list
|
||||
.map((item) => {
|
||||
return `<span class="db--genreItem${
|
||||
this.status == item.value ? " is-active" : ""
|
||||
}" data-status="${item.value}">${item.name}</span>`;
|
||||
})
|
||||
.join("");
|
||||
this._handleGenreClick();
|
||||
}
|
||||
|
||||
_fetchData() {
|
||||
const params = new URLSearchParams({
|
||||
paged: this.paged.toString(),
|
||||
type: this.type,
|
||||
status: this.status,
|
||||
});
|
||||
fetch(this.baseAPI + "list?" + params.toString())
|
||||
.then((response) => response.json())
|
||||
.then((t) => {
|
||||
console.log(t.results);
|
||||
if (t.results.length) {
|
||||
if (
|
||||
document
|
||||
.querySelector(".db--list")
|
||||
.classList.contains("db--list__card")
|
||||
) {
|
||||
this.subjects = [...this.subjects, ...t.results];
|
||||
this._randerDateTemplate();
|
||||
} else {
|
||||
this.subjects = [...this.subjects, ...t.results];
|
||||
this._randerListTemplate();
|
||||
}
|
||||
document
|
||||
.querySelector(".lds-ripple")
|
||||
.classList.add("u-hide");
|
||||
} else {
|
||||
this.finished = true;
|
||||
document
|
||||
.querySelector(".lds-ripple")
|
||||
.classList.add("u-hide");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_randerDateTemplate() {
|
||||
const result = this.subjects.reduce((result, item) => {
|
||||
const date = new Date(item.create_time);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const key = `${year}-${month.toString().padStart(2, "0")}`;
|
||||
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
||||
result[key].push(item);
|
||||
} else {
|
||||
result[key] = [item];
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
let html = ``;
|
||||
for (let key in result) {
|
||||
const date = key.split("-");
|
||||
html += `<div class="db--listBydate"><div class="db--titleDate"><div class="db--titleDate__day">${date[1]}</div><div class="db--titleDate__month">${date[0]}</div></div><div class="db--dateList__card">`;
|
||||
html += result[key]
|
||||
.map((movie) => {
|
||||
return `<div class="db--item${
|
||||
this.type == "music" ? " db--item__music" : ""
|
||||
}"><img src="${
|
||||
movie.poster
|
||||
}" referrerpolicy="no-referrer" class="db--image"><div class="db--score ">${
|
||||
movie.douban_score > 0
|
||||
? '<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" ><path d="M12 20.1l5.82 3.682c1.066.675 2.37-.322 2.09-1.584l-1.543-6.926 5.146-4.667c.94-.85.435-2.465-.799-2.567l-6.773-.602L13.29.89a1.38 1.38 0 0 0-2.581 0l-2.65 6.53-6.774.602C.052 8.126-.453 9.74.486 10.59l5.147 4.666-1.542 6.926c-.28 1.262 1.023 2.26 2.09 1.585L12 20.099z"></path></svg>' +
|
||||
movie.douban_score
|
||||
: ""
|
||||
}${
|
||||
movie.year > 0 ? " · " + movie.year : ""
|
||||
}</div><div class="db--title"><a href="${
|
||||
movie.link
|
||||
}" target="_blank">${movie.name}</a></div></div>`;
|
||||
})
|
||||
.join("");
|
||||
html += `</div></div>`;
|
||||
}
|
||||
document.querySelector(".db--list").innerHTML = html;
|
||||
}
|
||||
|
||||
_randerListTemplate() {
|
||||
document.querySelector(".db--list").innerHTML = this.subjects
|
||||
.map((item) => {
|
||||
return `<div class="db--item"><img src="${
|
||||
item.poster
|
||||
}" referrerpolicy="no-referrer" class="db--image"><div class="ipc-signpost ">${
|
||||
item.create_time
|
||||
}</div><div class="db--score ">${
|
||||
item.douban_score
|
||||
? '<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" ><path d="M12 20.1l5.82 3.682c1.066.675 2.37-.322 2.09-1.584l-1.543-6.926 5.146-4.667c.94-.85.435-2.465-.799-2.567l-6.773-.602L13.29.89a1.38 1.38 0 0 0-2.581 0l-2.65 6.53-6.774.602C.052 8.126-.453 9.74.486 10.59l5.147 4.666-1.542 6.926c-.28 1.262 1.023 2.26 2.09 1.585L12 20.099z"></path></svg>' +
|
||||
item.douban_score
|
||||
: ""
|
||||
}${
|
||||
item.year ? " · " + item.year : ""
|
||||
}</div><div class="db--title"><a href="${
|
||||
item.link
|
||||
}" target="_blank">${item.name}</a></div>
|
||||
</div>
|
||||
</div>`;
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
_handleScroll() {
|
||||
window.addEventListener("scroll", () => {
|
||||
var t = window.scrollY || window.pageYOffset;
|
||||
const moreElement = document.querySelector(
|
||||
".block-more"
|
||||
);
|
||||
if (
|
||||
moreElement.offsetTop + -window.innerHeight < t &&
|
||||
document
|
||||
.querySelector(".lds-ripple")
|
||||
.classList.contains("u-hide") &&
|
||||
!this.finished
|
||||
) {
|
||||
document
|
||||
.querySelector(".lds-ripple")
|
||||
.classList.remove("u-hide");
|
||||
this.paged++;
|
||||
this._fetchData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_handleNavClick() {
|
||||
this.on("click", ".db--navItem", (t) => {
|
||||
const self = t.currentTarget;
|
||||
if (self.classList.contains("current")) return;
|
||||
this.status = "done";
|
||||
this.type = self.dataset.type;
|
||||
this._renderGenre();
|
||||
document.querySelector(".db--list").innerHTML = "";
|
||||
document.querySelector(".lds-ripple").classList.remove("u-hide");
|
||||
document
|
||||
.querySelector(".db--navItem.current")
|
||||
.classList .remove("current");
|
||||
self.classList.add("current");
|
||||
this.paged = 1;
|
||||
this.finished = false;
|
||||
this.subjects = [];
|
||||
this._fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
_create() {
|
||||
if (document.querySelector(".db--container")) {
|
||||
const container = document.querySelector(
|
||||
this.container
|
||||
);
|
||||
if (!container) return;
|
||||
container.innerHTML = `<nav class="db--nav">
|
||||
</nav>
|
||||
<div class="db--genres">
|
||||
</div>
|
||||
<div class="db--list db--list__card">
|
||||
</div>
|
||||
<div class="block-more block-more__centered">
|
||||
<div class="lds-ripple">
|
||||
</div>
|
||||
</div>`;
|
||||
this._renderGenre();
|
||||
this._reanderTypes();
|
||||
this._fetchData();
|
||||
this._handleScroll();
|
||||
}
|
||||
|
||||
if (document.querySelector(".js-db")) {
|
||||
document.querySelectorAll(".js-db").forEach((item) => {
|
||||
const db = item;
|
||||
const id = db.dataset.id;
|
||||
const type = db.dataset.type;
|
||||
const nodeParent = db.parentNode;
|
||||
fetch(this.baseAPI + `${type}/${id}`).then((response) => {
|
||||
response.json().then((t) => {
|
||||
if (t.data) {
|
||||
const data = t.data;
|
||||
const node = document.createElement("div");
|
||||
node.classList.add("doulist-item");
|
||||
node.innerHTML = `<div class="doulist-subject">
|
||||
<div class="doulist-post"><img decoding="async" referrerpolicy="no-referrer" src="${data.poster}"></div>
|
||||
<div class="doulist-content">
|
||||
<div class="doulist-title"><a href="${data.link}" class="cute" target="_blank" rel="external nofollow">${data.name}</a></div>
|
||||
<div class="rating"><span class="allstardark"><span class="allstarlight" style="width:55%"></span></span><span class="rating_nums"> ${data.douban_score} </span></div>
|
||||
<div class="abstract">${data.card_subtitle}</div>
|
||||
</div>
|
||||
</div>`;
|
||||
nodeParent.replaceWith(node);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.querySelector(".db--collection")) {
|
||||
document
|
||||
.querySelectorAll(".db--collection")
|
||||
.forEach((item) => {
|
||||
this._fetchCollection(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_fetchCollection(item) {
|
||||
const type = item.dataset.style ? item.dataset.style : "card";
|
||||
fetch(
|
||||
this.baseAPI +
|
||||
"/list?type=" +
|
||||
item.dataset.type +
|
||||
"&paged=1&start_time=" +
|
||||
item.dataset.start +
|
||||
"&end_time=" +
|
||||
item.dataset.end
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((t) => {
|
||||
if (t.length) {
|
||||
if (type == "card") {
|
||||
item.innerHTML += t
|
||||
.map((movie) => {
|
||||
return `<div class="doulist-item">
|
||||
<div class="doulist-subject">
|
||||
<div class="db--viewTime ">Marked ${movie.create_time}</div>
|
||||
<div class="doulist-post"><img referrerpolicy="no-referrer" src="${movie.poster}"></div><div class="doulist-content"><div class="doulist-title"><a href="${movie.link}" class="cute" target="_blank" rel="external nofollow">${movie.name}</a></div><div class="rating"><span class="allstardark"><span class="allstarlight" style="width:75%"></span></span><span class="rating_nums">${movie.douban_score}</span></div><div class="abstract">${movie.card_subtitle}</div></div></div></div>`;
|
||||
})
|
||||
.join("");
|
||||
} else {
|
||||
const result = t.reduce(
|
||||
(result, item) => {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
result,
|
||||
item.create_time
|
||||
)
|
||||
) {
|
||||
result[item.create_time].push(item);
|
||||
} else {
|
||||
result[item.create_time] = [item];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
{}
|
||||
);
|
||||
let html = ``;
|
||||
for (let key in result) {
|
||||
html += `<div class="db--date">${key}</div><div class="db--dateList">`;
|
||||
html += result[key]
|
||||
.map((movie) => {
|
||||
return `<div class="db--card__list">
|
||||
<img referrerpolicy="no-referrer" src="${
|
||||
movie.poster
|
||||
}">
|
||||
<div>
|
||||
<div class="title"><a href="${
|
||||
movie.link
|
||||
}" class="cute" target="_blank" rel="external nofollow">${
|
||||
movie.name
|
||||
}</a></div>
|
||||
<div class="rating"><span class="allstardark"><span class="allstarlight" style="width:75%"></span></span><span class="rating_nums">${
|
||||
movie.douban_score
|
||||
}</span></div>
|
||||
${movie.remark || movie.card_subtitle}
|
||||
</div>
|
||||
</div>`;
|
||||
})
|
||||
.join("");
|
||||
html += `</div>`;
|
||||
}
|
||||
item.innerHTML = html;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const donateBtn = document.getElementById('donate-btn');
|
||||
const qrcodePanel = document.getElementById('qrcode-panel');
|
||||
const donateClose = document.getElementById('donate-close');
|
||||
const methodBtns = document.querySelectorAll('.donate-method-btn');
|
||||
const qrImages = document.querySelectorAll('.qr-image');
|
||||
let isVisible = false;
|
||||
|
||||
// 切换支付方式
|
||||
function switchPayMethod(method) {
|
||||
// 更新按钮状态
|
||||
methodBtns.forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
if (btn.dataset.method === method) {
|
||||
btn.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// 更新二维码显示
|
||||
qrImages.forEach(img => {
|
||||
img.classList.remove('active');
|
||||
if (img.dataset.method === method) {
|
||||
img.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 点击打赏按钮切换二维码显示状态
|
||||
function toggleQRCode(event) {
|
||||
event.stopPropagation();
|
||||
isVisible = !isVisible;
|
||||
qrcodePanel.style.display = isVisible ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// 点击关闭按钮隐藏二维码
|
||||
function hideQRCode(event) {
|
||||
event.stopPropagation();
|
||||
isVisible = false;
|
||||
qrcodePanel.style.display = 'none';
|
||||
}
|
||||
|
||||
// 点击二维码面板之外的地方隐藏二维码
|
||||
function handleDocumentClick(event) {
|
||||
if (isVisible && !qrcodePanel.contains(event.target) && !donateBtn.contains(event.target)) {
|
||||
isVisible = false;
|
||||
qrcodePanel.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定事件监听器
|
||||
donateBtn.addEventListener('click', toggleQRCode);
|
||||
donateClose.addEventListener('click', hideQRCode);
|
||||
document.addEventListener('click', handleDocumentClick);
|
||||
|
||||
// 绑定支付方式切换按钮事件
|
||||
methodBtns.forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const method = e.target.dataset.method;
|
||||
switchPayMethod(method);
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化显示第一个支付方式
|
||||
switchPayMethod('wechat');
|
||||
});
|
||||
+38
File diff suppressed because one or more lines are too long
Vendored
+6
File diff suppressed because one or more lines are too long
@@ -0,0 +1,142 @@
|
||||
class NeoDB {
|
||||
constructor(config) {
|
||||
this.container = config.container;
|
||||
this.types = config.types ?? ["book", "movie", "tv", "music", "game", "podcast"];
|
||||
this.baseAPI = config.baseAPI;
|
||||
this.type = "movie";
|
||||
this.status = "complete";
|
||||
this.finished = false;
|
||||
this.paged = 1;
|
||||
this.subjects = [];
|
||||
this._create();
|
||||
}
|
||||
|
||||
on(event, element, callback) {
|
||||
const nodeList = document.querySelectorAll(element);
|
||||
nodeList.forEach((item) => {
|
||||
item.addEventListener(event, callback);
|
||||
});
|
||||
}
|
||||
|
||||
_handleTypeClick() {
|
||||
this.on("click", ".neodb-navItem", (t) => {
|
||||
const self = t.currentTarget;
|
||||
if (self.classList.contains("current")) return;
|
||||
this.type = self.dataset.type;
|
||||
document.querySelector(".neodb-list").innerHTML = "";
|
||||
document.querySelector(".lds-ripple").classList.remove("u-hide");
|
||||
document.querySelector(".neodb-navItem.current").classList.remove("current");
|
||||
self.classList.add("current");
|
||||
this.paged = 1;
|
||||
this.finished = false;
|
||||
this.subjects = [];
|
||||
this._fetchData();
|
||||
});
|
||||
}
|
||||
|
||||
_renderTypes() {
|
||||
document.querySelector(".neodb-nav").innerHTML = this.types
|
||||
.map((item) => {
|
||||
return `<span class="neodb-navItem${
|
||||
this.type == item ? " current" : ""
|
||||
}" data-type="${item}">${item}</span>`;
|
||||
})
|
||||
.join("");
|
||||
this._handleTypeClick();
|
||||
}
|
||||
|
||||
_fetchData() {
|
||||
const params = new URLSearchParams({
|
||||
type: "complete",
|
||||
category: this.type,
|
||||
page: this.paged.toString(),
|
||||
});
|
||||
|
||||
return fetch(this.baseAPI + "?" + params.toString())
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.length) {
|
||||
// 过滤重复项
|
||||
data = data.filter(item => !this.subjects.some(existing => existing.item.id === item.item.id));
|
||||
|
||||
if (data.length) {
|
||||
this.subjects = [...this.subjects, ...data];
|
||||
this._renderListTemplate();
|
||||
}
|
||||
|
||||
document.querySelector(".lds-ripple").classList.add("u-hide");
|
||||
} else {
|
||||
this.finished = true; // 没有更多数据
|
||||
document.querySelector(".lds-ripple").classList.add("u-hide");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_renderListTemplate() {
|
||||
document.querySelector(".neodb-list").innerHTML = this.subjects
|
||||
.map((item) => {
|
||||
const coverImage = item.item.cover_image_url;
|
||||
const title = item.item.title;
|
||||
const rating = item.item.rating;
|
||||
const link = item.item.id;
|
||||
|
||||
return `<div class="neodb-item">
|
||||
<img src="${coverImage}" referrerpolicy="no-referrer" class="neodb-image">
|
||||
<div class="neodb-score">
|
||||
${rating ? `<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M12 20.1l5.82 3.682c1.066.675 2.37-.322 2.09-1.584l-1.543-6.926 5.146-4.667c.94-.85.435-2.465-.799-2.567l-6.773-.602L13.29.89a1.38 1.38 0 0 0-2.581 0l-2.65 6.53-6.774.602C.052 8.126-.453 9.74.486 10.59l5.147 4.666-1.542 6.926c-.28 1.262 1.023 2.26 2.09 1.585L12 20.099z"></path></svg>${rating}` : ""}
|
||||
</div>
|
||||
<div class="neodb-title">
|
||||
<a href="${link}" target="_blank">${title}</a>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
_handleScroll() {
|
||||
let isLoading = false; // 标志位,表示是否正在加载数据
|
||||
let lastScrollTop = 0; // 上一次的滚动位置
|
||||
|
||||
window.addEventListener("scroll", () => {
|
||||
const scrollY = window.scrollY || window.pageYOffset;
|
||||
const moreElement = document.querySelector(".block-more");
|
||||
|
||||
// 检查滚动到底部的条件
|
||||
if (
|
||||
moreElement.offsetTop + moreElement.clientHeight <= scrollY + window.innerHeight &&
|
||||
document.querySelector(".lds-ripple").classList.contains("u-hide") &&
|
||||
!this.finished &&
|
||||
!isLoading // 确保没有正在加载数据
|
||||
) {
|
||||
isLoading = true; // 设置标志位为 true,表示正在加载数据
|
||||
document.querySelector(".lds-ripple").classList.remove("u-hide");
|
||||
this.paged++;
|
||||
this._fetchData().finally(() => {
|
||||
isLoading = false; // 数据加载完成后,重置标志位
|
||||
});
|
||||
}
|
||||
|
||||
// 更新上一次的滚动位置
|
||||
lastScrollTop = scrollY;
|
||||
});
|
||||
}
|
||||
|
||||
_create() {
|
||||
if (document.querySelector(".neodb-container")) {
|
||||
const container = document.querySelector(this.container);
|
||||
if (!container) return;
|
||||
container.innerHTML = `
|
||||
<nav class="neodb-nav"></nav>
|
||||
<div class="neodb-list"></div>
|
||||
<div class="block-more block-more__centered">
|
||||
<div class="lds-ripple"></div>
|
||||
</div>
|
||||
`;
|
||||
this._renderTypes();
|
||||
this._fetchData();
|
||||
this._handleScroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const tooltip = document.getElementById('copyTooltip');
|
||||
let timeoutId = null;
|
||||
// 确保初始状态下提示框是隐藏的
|
||||
tooltip.style.display = 'none';
|
||||
// 复制函数
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
// 显示提示
|
||||
tooltip.style.display = 'block';
|
||||
tooltip.style.opacity = '1';
|
||||
// 清除之前的定时器(如果存在)
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
// 设置新的定时器
|
||||
timeoutId = setTimeout(() => {
|
||||
tooltip.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
tooltip.style.display = 'none';
|
||||
}, 300); // 等待淡出动画完成后再隐藏
|
||||
}, 1500);
|
||||
}).catch(err => {
|
||||
tooltip.textContent = '复制失败,请重试';
|
||||
tooltip.style.display = 'block';
|
||||
tooltip.style.opacity = '1';
|
||||
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
tooltip.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
tooltip.style.display = 'none';
|
||||
tooltip.textContent = '复制成功!'; // 重置文本
|
||||
}, 300);
|
||||
}, 1500);
|
||||
console.error('复制失败:', err);
|
||||
});
|
||||
}
|
||||
// 给所有复制链接添加点击事件
|
||||
document.querySelectorAll('.text').forEach(link => {
|
||||
link.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const textToCopy = this.getAttribute('data-copy') || this.textContent;
|
||||
copyToClipboard(textToCopy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
const targetClassElement = document.querySelector('.post--single__title');
|
||||
const postContent = document.querySelector('.post--single__content');
|
||||
if (!postContent) return;
|
||||
let found = false;
|
||||
for (let i = 1; i <= 6 &&!found; i++) {
|
||||
if (postContent.querySelector(`h${i}`)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) return;
|
||||
const heads = postContent.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
||||
const toc = document.createElement('div');
|
||||
toc.id = 'toc';
|
||||
toc.innerHTML = '<details class="toc" open><summary class="toc-title">目录</summary><nav id="TableOfContents"><ul></ul></nav></details>';
|
||||
// 插入到指定 class 元素之后
|
||||
if (targetClassElement) {
|
||||
targetClassElement.parentNode.insertBefore(toc, targetClassElement.nextSibling);
|
||||
}
|
||||
let currentLevel = 0;
|
||||
let currentList = toc.querySelector('ul');
|
||||
let levelCounts = [0];
|
||||
heads.forEach((head, index) => {
|
||||
const level = parseInt(head.tagName.substring(1));
|
||||
if (levelCounts[level] === undefined) {
|
||||
levelCounts[level] = 1;
|
||||
} else {
|
||||
levelCounts[level]++;
|
||||
}
|
||||
// 重置下级标题的计数器
|
||||
levelCounts = levelCounts.slice(0, level + 1);
|
||||
if (currentLevel === 0) {
|
||||
currentLevel = level;
|
||||
}
|
||||
while (level > currentLevel) {
|
||||
let newList = document.createElement('ul');
|
||||
if (!currentList.lastElementChild) {
|
||||
currentList.appendChild(newList);
|
||||
} else {
|
||||
currentList.lastElementChild.appendChild(newList);
|
||||
}
|
||||
currentList = newList;
|
||||
currentLevel++;
|
||||
levelCounts[currentLevel] = 1;
|
||||
}
|
||||
while (level < currentLevel) {
|
||||
currentList = currentList.parentElement;
|
||||
if (currentList.tagName.toLowerCase() === 'li') {
|
||||
currentList = currentList.parentElement;
|
||||
}
|
||||
currentLevel--;
|
||||
}
|
||||
const anchor = head.textContent.trim().replace(/\s+/g, '-');
|
||||
head.id = anchor;
|
||||
const item = document.createElement('li');
|
||||
const link = document.createElement('a');
|
||||
link.href = `#${anchor}`;
|
||||
link.textContent = `${head.textContent}`;
|
||||
link.style.textDecoration = 'none';
|
||||
item.appendChild(link);
|
||||
currentList.appendChild(item);
|
||||
});
|
||||
});
|
||||
|
||||
function fetchWithRetry(url, retries = 3) {
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.text(); // 首先获取文本响应
|
||||
})
|
||||
.then(text => {
|
||||
try {
|
||||
return JSON.parse(text); // 尝试解析 JSON
|
||||
} catch (e) {
|
||||
console.error('Invalid JSON:', text);
|
||||
throw new Error('Invalid JSON response');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (retries > 0) {
|
||||
console.log(`Retrying... (${retries} attempts left)`);
|
||||
return new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒
|
||||
.then(() => fetchWithRetry(url, retries - 1));
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const doubanLinks = document.querySelectorAll('a[href^="https://movie.douban.com/subject/"]');
|
||||
doubanLinks.forEach(link => {
|
||||
const url = link.href;
|
||||
const movieId = url.match(/subject\/(\d+)/)[1];
|
||||
link.innerHTML += ' <span class="loading">(加载中...)</span>';
|
||||
fetchWithRetry(`https://api.loliko.cn/movies/${movieId}`)
|
||||
.then(data => {
|
||||
const movieInfo = createMovieInfoHTML(data, url);
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = movieInfo;
|
||||
link.parentNode.replaceChild(wrapper, link);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching movie data:', error);
|
||||
// 显示错误消息给用户
|
||||
link.innerHTML = `<span style="color: red;">加载失败</span> <a href="${url}" target="_blank">查看豆瓣电影详情</a>`;
|
||||
})
|
||||
.finally(() => {
|
||||
const loadingSpan = link.querySelector('.loading');
|
||||
if (loadingSpan) {
|
||||
loadingSpan.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
function createMovieInfoHTML(data, originalUrl) {
|
||||
if (!data || data.error || Object.keys(data).length === 0) {
|
||||
return `<a href="${originalUrl}" target="_blank">查看豆瓣电影详情</a>`;
|
||||
}
|
||||
return `
|
||||
<div class=doulist-item>
|
||||
<div class=doulist-subject>
|
||||
<div class=doulist-post>
|
||||
<img decoding=async referrerpolicy=no-referrer src=${data.img}>
|
||||
</div>
|
||||
<div class=doulist-content>
|
||||
<div class=doulist-title>
|
||||
<a href="${originalUrl}" class=cute target="_blank" rel="external nofollow"> ${data.name} </a>
|
||||
</div>
|
||||
<div class=rating>
|
||||
<span class=rating_nums>豆瓣评分 : ${data.rating}</span>
|
||||
</div>
|
||||
<div class=abstract>
|
||||
${data.year}年 · ${data.country} · ${data.genre} · 导演: ${data.director} · 演员 : ${data.actor}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user