1.2.2原版

This commit is contained in:
anian
2026-04-27 19:09:03 +08:00
commit 219938eb62
100 changed files with 14320 additions and 0 deletions
@@ -0,0 +1,8 @@
apiVersion: plugin.halo.run/v1alpha1
kind: ReverseProxy
metadata:
name: douban-static-assets
rules:
- path: /static/**
file:
directory: static
@@ -0,0 +1,54 @@
apiVersion: v1alpha1
kind: Role
metadata:
name: role-template-douban-anonymous
labels:
rbac.authorization.halo.run/aggregate-to-anonymous: "true"
halo.run/role-template: "true"
halo.run/hidden: "true"
annotations:
rbac.authorization.halo.run/display-name: "查看朋友圈提交模板"
rules:
- apiGroups: [ "api.douban.moony.la" ]
resources: [ "doubanmovies","doubanmovies/genres","doubanmovies/getDoubanDetail"]
verbs: [ "get", "list" ]
---
apiVersion: v1alpha1
kind: Role
metadata:
name: role-template-douban-view
labels:
halo.run/role-template: "true"
annotations:
rbac.authorization.halo.run/module: "豆瓣"
rbac.authorization.halo.run/display-name: "豆瓣查看"
rbac.authorization.halo.run/ui-permissions: |
["plugin:douban:view"]
rules:
- apiGroups: [ "douban.moony.la" ]
resources: [ "doubanmovies"]
verbs: [ "get", "list" ]
---
apiVersion: v1alpha1
kind: Role
metadata:
name: role-template-douban-manage
labels:
halo.run/role-template: "true"
annotations:
rbac.authorization.halo.run/module: "豆瓣"
rbac.authorization.halo.run/display-name: "豆瓣管理"
rbac.authorization.halo.run/ui-permissions: |
["plugin:douban:manage"]
rbac.authorization.halo.run/dependencies: |
["role-template-douban-view"]
rules:
- apiGroups: [ "douban.moony.la" ]
resources: [ "doubanmovies"]
verbs: [ "create", "patch", "update", "delete", "deletecollection" ]
- nonResourceURLs: [ "/apis/api.plugin.halo.run/v1alpha1/plugins/plugin-douban/douban/*"]
verbs: [ "create" , "delete" ]
@@ -0,0 +1,39 @@
apiVersion: v1alpha1
kind: Setting
metadata:
name: plugin-douban-settings
spec:
forms:
- group: base
label: 基本设置
formSchema:
- $formkit: text
label: 页面标题
name: title
validation: required
value: '豆瓣记录'
- $formkit: text
label: 豆瓣的ID
name: doubanId
help: 我的豆瓣 https://www.douban.com/people/xxxx xxxx 就是你的ID
- $formkit: text
label: TMDB API Key
name: apiKey
help: 设置TMDB API Key在https://www.themoviedb.org/settings/api 自行申请
- $formkit: radio
label: 启用图片代理
name: isProxy
id: isProxy
value: false
help: 如果用豆瓣源的图片很慢可以自己搭建给图片反代站点
options:
- value: true
label: 开启
- value: false
label: 关闭
- $formkit: text
if: "$get(isProxy).value === true"
label: 代理地址
name: proxyHost
value: ""
help: "搭建教程:https://docs.kunkunyu.com/docs/plugin-douban/use#%E9%85%8D%E7%BD%AE%E5%9B%BE%E7%89%87%E4%BB%A3%E7%90%86"
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

+23
View File
@@ -0,0 +1,23 @@
apiVersion: plugin.halo.run/v1alpha1
kind: Plugin
metadata:
name: plugin-douban
annotations:
"store.halo.run/app-id": "app-srBOL"
spec:
enabled: true
requires: ">=2.20.0"
author:
name: 困困鱼
website: https://github.com/chengzhongxue
logo: logo.png
homepage: https://www.halo.run/store/apps/app-srBOL
repo: https://github.com/chengzhongxue/plugin-douban
issues: https://github.com/chengzhongxue/plugin-douban/issues
settingName: plugin-douban-settings
configMapName: plugin-douban-configmap
displayName: "豆瓣"
description: "提供从豆瓣爬取到的数据,提供页面路由"
license:
- name: "GPL-3.0"
url: "https://github.com/halo-dev/plugin-douban/blob/main/LICENSE"
@@ -0,0 +1,62 @@
(function () {
function getDoubanDetail(src, e) {
var url = '/apis/api.douban.moony.la/v1alpha1/doubanmovies/-/getDoubanDetail?url=' + src;
fetch(url)
.then(response => response.json())
.then(data => {
renderer(data, e);
})
.catch(console.error)
}
function renderer(data, e) {
let img = data.spec.dataType == 'db' ? `${data.spec.poster}` : data.spec.poster
let date = new Date(data.faves.createTime);
let dateString = date.toLocaleString(); // 使用默认的日期和时间格式
const r = document.createElement("div");
r.classList.add('doulist-item')
r.innerHTML = `<div class="doulist-subject">
<div class="doulist-post"><img decoding="async" referrerpolicy="no-referrer" class="fade-before fade-after"
src="${img}"></div>
<div class="db--viewTime JiEun">Marked ${dateString}</div>
<div class="doulist-content">
<div class="doulist-title"><a class="cute" target="_blank" rel="external nofollow"
href="${data.spec.link}">${data.spec.name}</a></div>
<div class="rating"><span class="allstardark"><span class="allstarlight" style="width: ${data.spec.score * 10}%;"></span></span><span
class="rating_nums">${data.spec.score}</span></div>
<div class="abstract">${data.faves?.remark != null && data.faves?.remark != '' ? data.faves?.remark : data.spec.cardSubtitle}</div>
</div>
</div>`
e.appendChild(r);
}
const mf = () => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const e = entry.target;
const src = e.getAttribute("src");
if (src != null && src != '') {
getDoubanDetail(src, e);
observer.unobserve(e); // 停止观察已经加载的元素,防止重复加载
}
}
});
});
document.querySelectorAll("douban").forEach((e) => {
observer.observe(e);
});
};
document.addEventListener("DOMContentLoaded", () => {
mf();
}, {
once: true
});
document.addEventListener("pjax:success", () => {
mf();
});
})();
+297
View File
@@ -0,0 +1,297 @@
// @ts-nocheck
class HALO_DOUBAN {
constructor() {
this.ver = "1.2.2";
this.type = "movie";
this.status = "done";
this.finished = false;
this.paged = 1;
this.genre_list = [];
this.genre = [];
this.subjects = [];
this._create();
}
on(t, e, n) {
var a = document.querySelectorAll(e);
a.forEach((item) => {
item.addEventListener(t, n);
});
}
_addSearchParams(url, params = {}) {
url = new URL(url, window.location.origin);
let new_url = new URL(
`${url.origin}${url.pathname}?${new URLSearchParams([
...Array.from(url.searchParams.entries()),
...Object.entries(params),
])}`
);
return new_url.href;
}
_fetchGenres() {
document.querySelector(".db--genres").innerHTML = "";
const url = '/apis/api.douban.moony.la/v1alpha1/doubanmovies/-/genres';
fetch(
this._addSearchParams(url, {
type: this.type,
})
)
.then((response) => response.json())
.then((data) => {
if (data.length) {
this.genre_list = data;
this._renderGenre();
}
});
return true;
}
_statusChange() {
this.on("click", ".db--typeItem", (t) => {
const self = t.currentTarget;
if (self.classList.contains("is-active")) {
// const index = this.genre.indexOf(self.innerText);
return;
}
document.querySelector(".db--list").innerHTML = "";
document.querySelector(".lds-ripple").classList.remove("u-hide");
document
.querySelector(".db--typeItem.is-active")
.classList.remove("is-active");
self.classList.add("is-active");
this.status = self.dataset.status;
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
return;
});
}
_handleGenreClick() {
this.on("click", ".db--genreItem", (t) => {
const self = t.currentTarget;
if (self.classList.contains("is-active")) {
const index = this.genre.indexOf(self.innerText);
self.classList.remove("is-active");
this.genre.splice(index, 1);
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
return;
}
document.querySelector(".db--list").innerHTML = "";
document.querySelector(".lds-ripple").classList.remove("u-hide");
self.classList.add("is-active");
this.genre.push(self.innerText);
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
return;
});
}
_renderGenre() {
document.querySelector(".db--genres").innerHTML = this.genre_list
.map((item) => {
return `<span class="db--genreItem">${item}</span>`;
})
.join("");
this._handleGenreClick();
}
_fetchData() {
var url = `/apis/api.douban.moony.la/v1alpha1/doubanmovies?page=${this.paged}&size=49&type=${this.type}&status=${this.status}`;
const genre = this.genre
if (genre.length > 0) {
for (let i = 0; i < genre.length; i++) {
url = url + `&genre=${genre[i]}`
}
}
fetch(url)
.then((response) => response.json())
.then((data) => {
if (data.items.length) {
if(this.subjects==null){
this.subjects =[]
}
if (
document
.querySelector(".db--list")
.classList.contains("db--list__card")
) {
this.subjects = [...this.subjects, ...data.items];
this._randerDateTemplate();
} else {
this.subjects = [...this.subjects, ...data.items];
this._randerListTemplate();
}
document
.querySelector(".lds-ripple")
.classList.add("u-hide");
} else {
document
.querySelector(".db--list")
.classList.contains("db--list__card")
? this._randerDateTemplate()
: this._randerListTemplate();
this.finished = true;
document
.querySelector(".lds-ripple")
.classList.add("u-hide");
}
});
}
_randerDateTemplate() {
if (!this.subjects.length)
return (document.querySelector(
".db--list"
).innerHTML = `<div class="db--empty"></div>`);
const result = this.subjects.reduce((result, item) => {
const date = new Date(item.faves.createTime);
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 JiEun"><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"><img src="${
movie.spec.dataType == 'halo' ? movie.spec.poster : movie.spec.poster
}" referrerpolicy="unsafe-url" class="db--image"><div class="db--score JiEun">${
movie.spec.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.spec.score
: ""
}${
movie.spec.year > 0 ? " · " + movie.spec.year : ""
}</div><div class="db--title"><a href="${
movie.spec.link
}" target="_blank">${movie.spec.name}</a></div>
</div>`;
})
.join("");
html += `</div></div>`;
}
document.querySelector(".db--list").innerHTML = html;
}
_randerListTemplate() {
if (!this.subjects.length)
return (document.querySelector(
".db--list"
).innerHTML = `<div class="db--empty"></div>`);
document.querySelector(".db--list").innerHTML = this.subjects
.map((item) => {
return `<div class="db--item"><img src="${
item.spec.dataType == 'halo' ? item.spec.poster : item.spec.poster
}" referrerpolicy="unsafe-url" class="db--image"><div class="ipc-signpost JiEun">${
item.faves.createTime
}</div><div class="db--score JiEun">${
item.spec.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>' +
item.spec.score
: ""
}${
item.spec.year > 0 ? " · " + item.spec.year : ""
}</div><div class="db--title"><a href="${
item.spec.link
}" target="_blank">${item.spec.name}</a></div>
</div>
</div>`;
})
.join("");
}
_handleScroll() {
window.addEventListener("scroll", () => {
var t = window.scrollY || window.pageYOffset;
// @ts-ignore
if (
document.querySelector(".block-more").offsetTop +
// @ts-ignore
-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) => {
if (t.target.classList.contains("current")) return;
this.genre = [];
this.type = t.target.dataset.type;
if (this.type != "book") {
this._fetchGenres();
document
.querySelector(".db--genres")
.classList.remove("u-hide");
} else {
document.querySelector(".db--genres").classList.add("u-hide");
}
document.querySelector(".db--list").innerHTML = "";
document.querySelector(".lds-ripple").classList.remove("u-hide");
document
.querySelector(".db--navItem.current")
.classList.remove("current");
const self = t.target;
self.classList.add("current");
this.paged = 1;
//this.status = "done";
this.finished = false;
this.subjects = [];
this._fetchData();
});
}
_create() {
if (document.querySelector(".db--container")) {
if (document.querySelector(".db--navItem.current")) {
this.type = document.querySelector(
".db--navItem.current"
).dataset.type;
}
if (document.querySelector(".db--list").dataset.type)
this.type = document.querySelector(".db--list").dataset.type;
if (this.type == "movie") {
document
.querySelector(".db--genres")
.classList.remove("u-hide");
}
this._fetchGenres();
this._fetchData();
this._handleScroll();
this._handleNavClick();
this._statusChange();
}
}
}
new HALO_DOUBAN();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1574920521513" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7948" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3-12.3 12.7-12.1 32.9 0.6 45.3l183.7 179.1-43.4 252.9c-1.2 6.9-0.1 14.1 3.2 20.3 8.2 15.6 27.6 21.7 43.2 13.4L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3z" p-id="7949" fill="#f99b01"></path></svg>

After

Width:  |  Height:  |  Size: 809 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1574920559231" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8164" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3-12.3 12.7-12.1 32.9 0.6 45.3l183.7 179.1-43.4 252.9c-1.2 6.9-0.1 14.1 3.2 20.3 8.2 15.6 27.6 21.7 43.2 13.4L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3zM664.8 561.6l36.1 210.3L512 672.7 323.1 772l36.1-210.3-152.8-149L417.6 382 512 190.7 606.4 382l211.2 30.7-152.8 148.9z" p-id="8165" fill="#f99b01"></path></svg>

After

Width:  |  Height:  |  Size: 927 B

+1
View File
@@ -0,0 +1 @@
:root{--db--text-color-light:rgba(0, 0, 0, 0.6)}.doulist-item{margin:30px 0;border:1px solid #eee;border-radius:4px}.doulist-item:hover{box-shadow:0 3px 12px rgba(0,0,0,.05)}.doulist-item .doulist-subject{display:flex;align-items:flex-start;line-height:1.6;padding:12px;position:relative}.doulist-item .doulist-subject .db--viewTime{position:absolute;right:0;top:0;background:#f5c518;color:#000;border-radius:4px 4px 0 4px;line-height:1;padding:3px 5px 3px 10px;font-size:12px;display:flex;margin-bottom:2px;font-weight:900}.doulist-item .doulist-subject .db--viewTime:after{content:"";border-top-left-radius:0;border-bottom-left-radius:0;left:0;top:0;margin-left:-.2rem;border-radius:0 4px 4px 4px;background:inherit;height:100%;position:absolute;width:.75rem;transform:skewX(20deg)}.doulist-item .doulist-subject .doulist-content{flex:1 1 auto}.doulist-item .doulist-subject .doulist-post{width:96px;margin-right:15px;display:flex;flex:0 0 auto}.doulist-item .doulist-subject .doulist-title{margin-bottom:5px;font-size:18px}.doulist-item .doulist-subject .doulist-title a{text-decoration:none!important}.doulist-item .doulist-subject .rating{margin:0 0 5px;font-size:14px;line-height:1;display:flex;align-items:center}.doulist-item .doulist-subject .rating .allstardark{position:relative;color:#f99b01;height:16px;width:80px;background-repeat:repeat;background-image:url(/plugins/plugin-douban/assets/static/img/star.svg);background-size:auto 100%;margin-right:5px}.doulist-item .doulist-subject .rating .allstarlight{position:absolute;left:0;color:#f99b01;height:16px;overflow:hidden;background-repeat:repeat;background-image:url(/plugins/plugin-douban/assets/static/img/star-fill.svg);background-size:auto 100%}.doulist-item .doulist-subject .abstract{font-size:14px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.6;max-height:3.2em}.doulist-item .doulist-subject img{width:96px!important;height:96px!important;border-radius:4px;object-fit:cover}
+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="https://www.thymeleaf.org" th:with="version = '1.2.2'">
<head>
<title th:text="${title}"></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" id="wpd-css-css" th:href="@{/plugins/plugin-douban/assets/static/db.min.css?v={version}(version=${version})}" type="text/css"
media="screen">
<style>
h1,
h2,
h3,
h4,
h5 {
margin-top: 0;
margin-bottom: 0;
font-weight: 400;
}
.metabar--block {
pointer-events: auto;
display: flex;
align-items: center;
position: relative;
height: 68px;
font-size: 14px;
justify-content: center;
}
.layoutSingleColumn {
max-width: 720px;
margin-left: auto;
margin-right: auto;
width: 92%;
}
.layoutSingleColumn--wide {
max-width: 1180px;
}
.u-paddingTop50 {
padding-top: 50px
}
.db--title a {
color: rgb(0 0 0 / 80%);
text-decoration: none;
}
</style>
</head>
<body>
<header class="metabar metabar--bordered">
<div class="metabar--block" itemprop="publisher" itemscope="">
<h1 class="metabar--headline" itemprop="logo" itemscope="" th:text="${title}"></h1>
</div>
</header>
<main class="main">
<div class="layoutSingleColumn layoutSingleColumn--wide u-paddingTop50">
<section class="db--container">
<nav class="db--nav">
<div th:each="type : ${types}" class="db--navItem JiEun"
th:classappend="${type.key == 'movie' ? 'current' : ''}" th:data-type="${type.key}"
th:text="${type.key}"></div>
</nav>
<div class="db--genres"></div>
<div class="db--type">
<div class="db--typeItem" data-status="mark">想看</div>
<div class="db--typeItem" data-status="doing">在看</div>
<div class="db--typeItem is-active" data-status="done">看过</div>
</div>
<div class="db--list db--list__card" data-type="movie">
</div>
<div class="block-more block-more__centered">
<div class="lds-ripple u-hide">
</div>
</div>
</section>
</div>
</main>
<footer class="site--footer">
<script th:src="@{/plugins/plugin-douban/assets/static/db.min.js?v={version}(version=${version})}"></script>
</footer>
</body>
</html>