8 Commits

Author SHA1 Message Date
浪子 b9e3969134 js使用jsdelivr CDN 2024-06-04 18:22:17 +08:00
浪子 65587efb0c 修复 2024-06-04 18:16:19 +08:00
浪子 0508d16c84 Update page-douban.php 2024-06-04 16:52:59 +08:00
浪子 9f547244d3 增加一些关于设置的说明 2024-06-04 16:44:13 +08:00
浪子 cf64160b75 更新 2024-06-04 16:27:04 +08:00
浪子 7f69fd518d 豆瓣页面的获取方式 2024-06-04 16:21:16 +08:00
浪子 f046a282c8 Update header.php 2024-06-01 10:33:40 +08:00
浪子 8f23486863 Update README.md 2024-06-01 10:33:37 +08:00
8 changed files with 394 additions and 48 deletions
+21 -8
View File
@@ -4,15 +4,20 @@
精简部分 JS.
感谢
- 2024.6.3
还是抄了原版的豆瓣获取方式
- 2024.5.26
抄了个网站统计页面
- 2024.5.24
新增了说说页面,基于memos 0.19 以下的版本
在后台设置memos的地址和memoID即可
默认获取最近20条公开的memo
- 2024.5.26
抄了个网站统计页面
## 原项目地址
https://github.com/bigfa/hugo-theme-farallon
@@ -31,13 +36,17 @@ https://github.com/bigfa/hugo-theme-farallon
### 豆瓣观影
* 能力有限原项目功能无法实现
~~* 能力有限原项目功能无法实现~~
目前只能配合`DoubanBoard`插件使用
~~目前只能配合`DoubanBoard`插件使用~~
项目地址
https://github.com/AlanDecode/Typecho-Plugin-DoubanBoard
!!记得重命名文件夹为`DoubanBoard`
~~项目地址~~
~~https://github.com/AlanDecode/Typecho-Plugin-DoubanBoard~~
~~!!记得重命名文件夹为`DoubanBoard`~~
使用原版的获取方式
https://node.wpista.com/
获取`token`之后填入主题设置项中
### 友情链接
@@ -53,3 +62,7 @@ https://github.com/AlanDecode/Typecho-Plugin-DoubanBoard
## 预览地址
https://www.imsun.org
## 感谢
[bigfa](https://github.com/bigfa/hugo-theme-farallon)
-1
View File
File diff suppressed because one or more lines are too long
+29 -29
View File
@@ -5,40 +5,40 @@ function themeConfig($form) {
$form->addInput($logoUrl);
$icoUrl = new Typecho_Widget_Helper_Form_Element_Text('icoUrl', NULL, NULL, _t('站点 Favicon 地址'));
$form->addInput($icoUrl);
$jzyear = new Typecho_Widget_Helper_Form_Element_Text('jzyear', NULL, NULL, _t('建站年份 eg. 2006'));
$jzyear = new Typecho_Widget_Helper_Form_Element_Text('jzyear', NULL, NULL, _t('建站年份'), _t('eg. 2006'));
$form->addInput($jzyear);
$instagramurl = new Typecho_Widget_Helper_Form_Element_Text('instagramurl', NULL, NULL, _t('ins'));
$form->addInput($instagramurl);
$telegramurl = new Typecho_Widget_Helper_Form_Element_Text('telegramurl', NULL, NULL, _t('电报'));
$form->addInput($telegramurl);
$githuburl = new Typecho_Widget_Helper_Form_Element_Text('githuburl', NULL, NULL, _t('github'));
$form->addInput($githuburl);
$twitterurl = new Typecho_Widget_Helper_Form_Element_Text('twitterurl', NULL, NULL, _t('twitter'));
$form->addInput($twitterurl);
$mastodonurl = new Typecho_Widget_Helper_Form_Element_Text('mastodonurl', NULL, NULL, _t('mastodon'));
$form->addInput($mastodonurl);
$sitemapurl = new Typecho_Widget_Helper_Form_Element_Text('sitemapurl', NULL, NULL, _t('sitemap'));
$form->addInput($sitemapurl);
$cnavatar = new Typecho_Widget_Helper_Form_Element_Text('cnavatar', NULL, 'https://cravatar.cn/avatar/', _t('自定义Gravatar镜像服务器,默认https://cravatar.cn/avatar/'));
$form->addInput($cnavatar);
$donate = new Typecho_Widget_Helper_Form_Element_Text('donate', NULL, 'https://blogcdn.loliko.cn/donate/wx.png', _t('赞赏二维码'));
$form->addInput($donate);
$memos = new Typecho_Widget_Helper_Form_Element_Text('memos', NULL, 'https://m.loliko.cn', _t('memos地址结尾不带"/"'));
$form->addInput($memos);
$memosID = new Typecho_Widget_Helper_Form_Element_Text('memosID', NULL, '1', _t('memosID'));
$form->addInput($memosID);
$twikoo = new Typecho_Widget_Helper_Form_Element_Textarea('twikoo', NULL, NULL, _t('引用第三方评论'));
$form->addInput($twikoo);
$addhead = new Typecho_Widget_Helper_Form_Element_Textarea('addhead', NULL, NULL, _t('添加head'));
$form->addInput($addhead);
$tongji = new Typecho_Widget_Helper_Form_Element_Textarea('tongji', NULL, NULL, _t('统计代码'));
$form->addInput($tongji);
$showProfile = new Typecho_Widget_Helper_Form_Element_Radio('showProfile',
array('0'=> _t('否'), '1'=> _t('是')),
'0', _t('是否在文章页面显示显示作者信息'), _t('选择“是”将在文章页面包含显示作者信息。'));
$form->addInput($showProfile);
$instagramurl = new Typecho_Widget_Helper_Form_Element_Text('instagramurl', NULL, NULL, _t('Instagram'), _t('会在个人信息显示'));
$form->addInput($instagramurl);
$telegramurl = new Typecho_Widget_Helper_Form_Element_Text('telegramurl', NULL, NULL, _t('电报'), _t('会在个人信息显示'));
$form->addInput($telegramurl);
$githuburl = new Typecho_Widget_Helper_Form_Element_Text('githuburl', NULL, NULL, _t('github'), _t('会在个人信息显示'));
$form->addInput($githuburl);
$twitterurl = new Typecho_Widget_Helper_Form_Element_Text('twitterurl', NULL, NULL, _t('twitter'), _t('会在个人信息显示'));
$form->addInput($twitterurl);
$mastodonurl = new Typecho_Widget_Helper_Form_Element_Text('mastodonurl', NULL, NULL, _t('mastodon'), _t('会在个人信息显示'));
$form->addInput($mastodonurl);
$sitemapurl = new Typecho_Widget_Helper_Form_Element_Text('sitemapurl', NULL, NULL, _t('sitemap'), _t('会在页脚显示'));
$form->addInput($sitemapurl);
$cnavatar = new Typecho_Widget_Helper_Form_Element_Text('cnavatar', NULL, 'https://cravatar.cn/avatar/', _t('Gravatar镜像'), _t('默认https://cravatar.cn/avatar/,建议保持默认'));
$form->addInput($cnavatar);
$donate = new Typecho_Widget_Helper_Form_Element_Text('donate', NULL, 'https://blogcdn.loliko.cn/donate/wx.png', _t('赞赏二维码'), _t('不填写则不显示'));
$form->addInput($donate);
$memos = new Typecho_Widget_Helper_Form_Element_Text('memos', NULL, 'https://m.loliko.cn', _t('memos地址'), _t('结尾不带"/"'));
$form->addInput($memos);
$memosID = new Typecho_Widget_Helper_Form_Element_Text('memosID', NULL, '1', _t('memosID'), _t('数字ID'));
$form->addInput($memosID);
$doubanID = new Typecho_Widget_Helper_Form_Element_Text('doubanID', NULL, '322dba2a3a27524b97c06d941d9631d153fc', _t('豆瓣页面必需Token'), _t('从<a href="https://node.wpista.com/" target="_blank">https://node.wpista.com/</a>获得token'));
$form->addInput($doubanID);
$twikoo = new Typecho_Widget_Helper_Form_Element_Textarea('twikoo', NULL, NULL, _t('引用第三方评论'), _t('不填写则不显示'));
$form->addInput($twikoo);
$addhead = new Typecho_Widget_Helper_Form_Element_Textarea('addhead', NULL, NULL, _t('添加head'), _t('支持HTML'));
$form->addInput($addhead);
$tongji = new Typecho_Widget_Helper_Form_Element_Textarea('tongji', NULL, NULL, _t('统计代码'), _t('支持HTML'));
$form->addInput($tongji);
$showallwords = new Typecho_Widget_Helper_Form_Element_Radio('showallwords',
array('0'=> _t('否'), '1'=> _t('是')),
'0', _t('是否显示归档字数统计'), _t('选择“是”将在归档页面显示全站总字数。'));
+4 -2
View File
@@ -1,6 +1,8 @@
<?php ini_set('display_errors', 1);
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
error_reporting(E_ALL);
if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<!DOCTYPE HTML>
<html>
<head>
+1 -1
View File
@@ -3,7 +3,7 @@
* 移植自HUGO主题`farallon`原作者`bigfa`
* @package farallon
* @author 老孙
* @version 0.4.1
* @version 0.5.0
* @link https://imsun.org
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
+1 -1
View File
@@ -10,7 +10,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<header class="archive--header">
<h1 class="post--single__title"><?php $this->title() ?></h1>
<?php Typecho_Widget::widget('Widget_Stat')->to($quantity); ?>
<h2 class="archive--title__year">共包含 <?php $quantity->publishedPostsNum(); ?> 篇文章</h2>
<h2 class="post--single__subtitle">共包含 <?php $quantity->publishedPostsNum(); ?> 篇文章</h2>
<?php if ($this->options->showallwords): ?>
<h3><?php echo allwords(); ?></h3>
<?php endif; ?>
+1 -1
View File
@@ -79,7 +79,7 @@ $this->need('header.php');
category: <?php echo json_encode(categoryPostCount()); ?>
};
</script>
<script type="text/javascript" src="<?php $this->options->themeUrl('/dist/js/chart.js'); ?>"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/jkjoy/typecho-theme-farallon@0.5.0/dist/js/chart.js"></script>
<script id="MathJax-script" async src="https://jsd.onmicrosoft.cn/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
// 配置 MathJax
+334 -2
View File
@@ -9,10 +9,342 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<section class="site--main">
<header class="archive--header">
<h1 class="post--single__title"><?php $this->title() ?></h1>
<h2 class="post--single__subtitle">观影数据来源于豆瓣</h2>
<h2 class="post--single__subtitle">数据来源于豆瓣</h2>
</header>
<div class="site--main">
<div class="db--container" data-token="<?php $this->options->doubanID() ?>">
<nav class="db--nav">
<div class="db--navItem JiEun current" data-type="movie">Movie</div>
<div class="db--navItem JiEun" data-type="book">Book</div>
<div class="db--navItem JiEun" data-type="music">Music</div>
</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>
</div>
</div>
<script>
class APIHandler {
constructor(token) {
this.ver = "1.0.1";
this.type = "movie";
this.finished = false;
this.paged = 1;
this.genre_list = [];
this.genre = [];
this.subjects = [];
this.baseAPI = "https://node.wpista.com/v1/outer/";
this.token = token;
this._create();
}
<div data-status="watched" class="douban-movie-list doubanboard-list"></div>
on(event, selector, handler) {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
element.addEventListener(event, handler);
});
}
_fetchGenres() {
document.querySelector(".db--genres").innerHTML = "";
fetch(`${this.baseAPI}genres?token=${this.token}&type=${this.type}`)
.then(response => response.json())
.then(data => {
if (data.data.length) {
this.genre_list = data.data;
this._renderGenre();
}
});
}
_handleGenreClick() {
this.on("click", ".db--genreItem", event => {
const target = event.currentTarget;
if (target.classList.contains("is-active")) {
const index = this.genre.indexOf(target.innerText);
target.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");
target.classList.add("is-active");
this.genre.push(target.innerText);
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
});
}
_renderGenre() {
document.querySelector(".db--genres").innerHTML = this.genre_list.map(genre =>
`<span class="db--genreItem${this.genre.includes(genre.name) ? " is-active" : ""}">${genre.name}</span>`
).join("");
this._handleGenreClick();
}
_fetchData() {
fetch(`${this.baseAPI}faves?token=${this.token}&type=${this.type}&paged=${this.paged}&genre=${JSON.stringify(this.genre)}`)
.then(response => response.json())
.then(data => {
if (data.data.length) {
if (document.querySelector(".db--list").classList.contains("db--list__card"))
{
this.subjects = [...this.subjects, ...data.data];
this._randerDateTemplate();
} else {
this.subjects = [...this.subjects, ...data.data];
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(subject => {
return `<div class="db--item">${
subject.is_top250
? '<span class="top250">Top 250</span>'
: ""
}<img src="${
subject.poster
}" referrerpolicy="no-referrer" class="db--image"><div class="db--score ">${
subject.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>' +
subject.douban_score
: ""
}${
subject.year > 0 ? " · " + subject.year : ""
}</div><div class="db--title"><a href="${
subject.link
}" target="_blank">${subject.name}</a></div></div>`;
})
.join("");
html += `</div></div>`;
}
document.querySelector(".db--list").innerHTML = html;
}
_renderListTemplate() {
document.querySelector(".db--list").innerHTML = this.subjects.map(subject =>
`<div class="db--item">
${subject.is_top250 ? '<span class="top250">Top 250</span>' : ""}
<img src="${subject.poster}" referrerpolicy="no-referrer" class="db--image">
<div class="ipc-signpost">${subject.create_time}</div>
<div class="db--score">${subject.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>` + subject.douban_score : ""}
${subject.year > 0 ? " · " + subject.year : ""}
</div>
<div class="db--title"><a href="${subject.link}" target="_blank">${subject.name}</a></div>
</div>`
).join("");
}
_handleScroll() {
window.addEventListener("scroll", () => {
const scrollY = window.scrollY || window.pageYOffset;
const blockMoreOffsetTop = document.querySelector(".block-more").offsetTop;
if (blockMoreOffsetTop - window.innerHeight < scrollY && 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", event => {
if (event.currentTarget.classList.contains("current")) return;
this.genre = [];
this.type = event.currentTarget.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");
event.target.classList.add("current");
this.paged = 1;
this.finished = false;
this.subjects = [];
this._fetchData();
});
}
_create() {
if (document.querySelector(".db--container")) {
const container = document.querySelector(".db--container");
if (container.dataset.token) {
this.token = container.dataset.token;
} else {
return;
}
const currentNavItem = document.querySelector(".db--navItem.current");
if (currentNavItem instanceof HTMLElement) {
this.type = currentNavItem.dataset.type;
}
const list = document.querySelector(".db--list");
if (list.dataset.type) {
this.type = list.dataset.type;
}
if (this.type == "movie") {
document.querySelector(".db--genres").classList.remove("u-hide");
}
this._fetchGenres();
this._fetchData();
this._handleScroll();
this._handleNavClick();
}
if (document.querySelector(".js-db")) {
document.querySelectorAll(".js-db").forEach(element => {
const id = element.dataset.id;
const type = element.dataset.type;
const parentNode = element.parentNode;
fetch(`${this.baseAPI}${type}/${id}?token=${this.token}`)
.then(response => response.json())
.then(data => {
if (data.data) {
const itemData = data.data;
const div = document.createElement("div");
div.classList.add("doulist-item");
div.innerHTML = `
<div class="doulist-subject">
<div class="doulist-post">
<img decoding="async" referrerpolicy="no-referrer" src="${itemData.poster}">
</div>
<div class="doulist-content">
<div class="doulist-title">
<a href="${itemData.link}" class="cute" target="_blank" rel="external nofollow">${itemData.name}</a>
</div>
<div class="rating">
<span class="allstardark">
<span class="allstarlight" style="width:55%"></span>
</span>
<span class="rating_nums"> ${itemData.douban_score} </span>
</div>
<div class="abstract">${itemData.card_subtitle}</div>
</div>
</div>`;
parentNode.replaceWith(div);
}
});
});
}
if (document.querySelector(".db--collection")) {
document.querySelectorAll(".db--collection").forEach(collection => {
this._fetchCollection(collection);
});
}
}
_fetchCollection(collection) {
const style = collection.dataset.style ? collection.dataset.style : "card";
fetch(`${this.baseAPI}v1/movies?type=${collection.dataset.type}&paged=1&genre=&start_time=${collection.dataset.start}&end_time=${collection.dataset.end}`)
.then(response => response.json())
.then(data => {
if (data.length) {
if (style === "card") {
collection.innerHTML += data.map(item => `
<div class="doulist-item">
<div class="doulist-subject">
<div class="db--viewTime">Marked ${item.create_time}</div>
<div class="doulist-post">
<img referrerpolicy="no-referrer" src="${item.poster}">
</div>
<div class="doulist-content">
<div class="doulist-title">
<a href="${item.link}" class="cute" target="_blank" rel="external nofollow">${item.name}</a>
</div>
<div class="rating">
<span class="allstardark">
<span class="allstarlight" style="width:75%"></span>
</span>
<span class="rating_nums">${item.douban_score}</span>
</div>
<div class="abstract">${item.remark || item.card_subtitle}</div>
</div>
</div>
</div>`).join("");
} else {
const groupedData = data.reduce((acc, item) => {
if (acc[item.create_time]) {
acc[item.create_time].push(item);
} else {
acc[item.create_time] = [item];
}
return acc;
}, {});
let html = "";
for (const date in groupedData) {
html += `<div class="db--date">${date}</div><div class="db--dateList">`;
html += groupedData[date].map(item => `
<div class="db--card__list">
<img referrerpolicy="no-referrer" src="${item.poster}">
<div>
<div class="title">
<a href="${item.link}" class="cute" target="_blank" rel="external nofollow">${item.name}</a>
</div>
<div class="rating">
<span class="allstardark">
<span class="allstarlight" style="width:75%"></span>
</span>
<span class="rating_nums">${item.douban_score}</span>
</div>
${item.remark || item.card_subtitle}
</div>
</div>`).join("");
html += "</div>";
}
collection.innerHTML = html;
}
}
});
}
}
// 在页面加载完成后实例化APIHandler类
document.addEventListener("DOMContentLoaded", () => {
const token = "<?php $this->options->doubanID() ?>"; // 替换为你的API令牌
new APIHandler(token);
});
</script>
</section>
<?php $this->need('footer.php'); ?>