switch shuoshuo function to ech0
This commit is contained in:
@@ -1167,6 +1167,7 @@ inject:
|
||||
- <link rel="stylesheet" href="/css/style.css">
|
||||
- <link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/rightmenu/rightmenu.css">
|
||||
- <link rel="stylesheet" href="/css/shuoshuo.css">
|
||||
- <link rel="stylesheet" href="/css/shuoshuoshouye.css">
|
||||
- <link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/webfont/font.css">
|
||||
- <link rel="stylesheet" href="/css/poem.css">
|
||||
- <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="all" onload="this.media="all"">
|
||||
@@ -1183,6 +1184,7 @@ inject:
|
||||
- <script src="https://cdn.jsdmirror.com/gh/bishshi/sidecalendar/calendar.js"></script>
|
||||
- <script src="https://unpkg.com/chinese-lunar@0.1.4/lib/chinese-lunar.js"></script>
|
||||
- <script src="/js/random.js"></script>
|
||||
- <script src="/js/shuoshuoshouye.js"></script>
|
||||
|
||||
# CDN Settings
|
||||
# Don't modify the following settings unless you know how they work
|
||||
|
||||
@@ -41,6 +41,7 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside
|
||||
|
||||
#body-wrap(class=pageType)
|
||||
include ./header/index.pug
|
||||
include ./others/memos_home.pug
|
||||
|
||||
main#content-inner.layout(class=hideAside)
|
||||
if body
|
||||
|
||||
7
themes/butterfly/layout/includes/others/memos_home.pug
Normal file
7
themes/butterfly/layout/includes/others/memos_home.pug
Normal file
@@ -0,0 +1,7 @@
|
||||
if (is_home())
|
||||
#main_top
|
||||
#bber-talk.cardHover.bb_talk_swipper(onclick=`pjax.loadUrl("/shuoshuo/")`)
|
||||
svg.icon(t='1660960757124', viewBox='0 0 1024 1024', version='1.1', xmlns='http://www.w3.org/2000/svg', p-id='3946', width='200', height='200')
|
||||
path(d='M526.432 924.064c-20.96 0-44.16-12.576-68.96-37.344L274.752 704H192c-52.928 0-96-43.072-96-96V416c0-52.928 43.072-96 96-96h82.752l182.624-182.624c24.576-24.576 47.744-37.024 68.864-37.024C549.184 100.352 576 116 576 160v704c0 44.352-26.72 60.064-49.568 60.064zM192 384c-17.632 0-32 14.368-32 32v192c0 17.664 14.368 32 32 32h96c8.48 0 16.64 3.36 22.624 9.376l192.064 192.096c3.392 3.36 6.496 6.208 9.312 8.576V174.016a145.824 145.824 0 0 0-9.376 8.608l-192 192C304.64 380.64 296.48 384 288 384h-96zM687.584 730.368a31.898 31.898 0 0 1-18.656-6.016c-14.336-10.304-17.632-30.304-7.328-44.672l12.672-17.344C707.392 617.44 736 578.624 736 512c0-69.024-25.344-102.528-57.44-144.928-5.664-7.456-11.328-15.008-16.928-22.784-10.304-14.336-7.04-34.336 7.328-44.672 14.368-10.368 34.336-7.04 44.672 7.328 5.248 7.328 10.656 14.464 15.968 21.504C764.224 374.208 800 421.504 800 512c0 87.648-39.392 141.12-74.144 188.32l-12.224 16.736c-6.272 8.704-16.064 13.312-26.048 13.312z', p-id='3947')
|
||||
path(d='M796.448 839.008a31.906 31.906 0 0 1-21.088-7.936c-13.28-11.648-14.624-31.872-2.976-45.152C836.608 712.672 896 628.864 896 512s-59.392-200.704-123.616-273.888c-11.648-13.312-10.304-33.504 2.976-45.184 13.216-11.648 33.44-10.336 45.152 2.944C889.472 274.56 960 373.6 960 512s-70.528 237.472-139.488 316.096c-6.368 7.232-15.2 10.912-24.064 10.912z', p-id='3948')
|
||||
ul.talk-list 说说加载中。。。
|
||||
@@ -1,3 +1,27 @@
|
||||
:root {
|
||||
--liushen-card-bg: #fff;
|
||||
--liushen-card-border: 1px solid #e3e8f7;
|
||||
--card-box-shadow: 0 3px 8px 6px rgba(7,17,27,0.09);
|
||||
--card-hover-box-shadow: 0 3px 8px 6px rgba(7,17,27,0.2);
|
||||
--liushen-card-secondbg: #f1f3f8;
|
||||
--liushen-button-hover-bg: #2679cc;
|
||||
--liushen-text: #4c4948;
|
||||
--liushen-button-bg: #f1f3f8;
|
||||
--liushen-fancybox-bg: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
:root, [data-theme=dark] {
|
||||
--liushen-card-bg: #181818;
|
||||
--liushen-card-secondbg: #30343f;
|
||||
--liushen-card-border: 1px solid #42444a;
|
||||
--card-box-shadow: 0 3px 8px 6px rgba(7,17,27,0.09);
|
||||
--card-hover-box-shadow: 0 3px 8px 6px rgba(7,17,27,0.2);
|
||||
--liushen-button-bg: #30343f;
|
||||
--liushen-button-hover-bg: #2679cc;
|
||||
--liushen-text: rgba(255,255,255,0.702);
|
||||
--liushen-fancybox-bg: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* 卡片初始化 */
|
||||
#talk .talk_item {
|
||||
width: calc(33.333% - 6px);
|
||||
@@ -174,56 +198,6 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.douban-card .douban-card-bgimg {
|
||||
background-position: 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
filter: blur(15px) brightness(.6);
|
||||
height: 115%;
|
||||
position: absolute;
|
||||
width: 115%;
|
||||
}
|
||||
|
||||
.douban-card .douban-card-left {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.douban-card .douban-card-left .douban-card-img {
|
||||
transition: all .5s ease;
|
||||
height: 130px;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
background-position: 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.douban-card .douban-card-left:hover .douban-card-img {
|
||||
filter: blur(5px) brightness(.6);
|
||||
transform: perspective(800px) rotateX(180deg);
|
||||
}
|
||||
|
||||
.douban-card .douban-card-right {
|
||||
color: #faebd7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
margin-left: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.douban-card .douban-card-right .douban-card-item {
|
||||
margin-top: 4px;
|
||||
max-width: 95%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 外链卡片 */
|
||||
#talk .talk_item .talk_content .shuoshuo-external-link {
|
||||
/* 无下划线 */
|
||||
|
||||
123
themes/butterfly/source/css/shuoshuoshouye.css
Normal file
123
themes/butterfly/source/css/shuoshuoshouye.css
Normal file
@@ -0,0 +1,123 @@
|
||||
/* maintop */
|
||||
|
||||
#main_top {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
max-width: 1400px;
|
||||
margin: 20px auto;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.hide-aside #main_top {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.hide-aside #main_top #bber-talk {
|
||||
max-width: 936px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 2000px) {
|
||||
.hide-aside #main_top #bber-talk {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
#main_top {
|
||||
max-width: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1210px) {
|
||||
.hide-aside #main_top {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.hide-aside #main_top {
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.hide-aside #main_top {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
div#main_top {
|
||||
margin-top: 20px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
#bber-talk {
|
||||
/* border-radius: 8px; */
|
||||
/* background: var(--card-bg); */
|
||||
/* box-shadow: none; */
|
||||
box-sizing: border-box;
|
||||
/* transition: all .3s ease-in-out; */
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
min-height: 50px;
|
||||
padding: .5rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#bber-talk,
|
||||
#bber-talk a {
|
||||
color: var(--font-color);
|
||||
}
|
||||
|
||||
#bber-talk svg.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#bber-talk .item i {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#bber-talk > i {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
#bber-talk .talk-list {
|
||||
flex: 1;
|
||||
max-height: 32px;
|
||||
font-size: 16px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#bber-talk .talk-list:hover {
|
||||
color: var(--default-bg-color);
|
||||
transition: all .2s ease-in-out;
|
||||
}
|
||||
|
||||
#bber-talk .talk-list li {
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 770px) {
|
||||
#bber-talk .talk-list {
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,5 @@
|
||||
/* #card-newest-comments img {border-radius: 10px; /* 设置最新评论圆角半径为10px,可以根据需要调整} */
|
||||
|
||||
/* 说说轮播 */
|
||||
#bber-talk {
|
||||
background: linear-gradient(-45deg, rgba(255, 255, 255, .7),
|
||||
rgba(255, 255, 255, .8),
|
||||
rgba(255, 255, 255, .8),
|
||||
rgba(255, 255, 255, .7));
|
||||
backdrop-filter: blur(10px);
|
||||
/* -webkit-backdrop-filter: blur(10px);兼容性前缀,适用于一些旧版本的浏览器 */
|
||||
}
|
||||
|
||||
/* 说说轮播 */
|
||||
[data-theme=dark] #bber-talk {
|
||||
background: linear-gradient(-45deg, rgba(24, 40, 72, .7),
|
||||
rgba(35, 37, 58, .8),
|
||||
rgba(35, 37, 58, .8),
|
||||
rgba(24, 40, 72, .7));
|
||||
backdrop-filter: blur(10px);
|
||||
/* -webkit-backdrop-filter: blur(10px);兼容性前缀,适用于一些旧版本的浏览器 */
|
||||
}
|
||||
|
||||
/* 侧边栏个人信息卡片动态渐变色 */
|
||||
#aside-content>.card-widget.card-info {
|
||||
position: relative;
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
initializeCard();
|
||||
});
|
||||
|
||||
document.addEventListener("pjax:complete", () => {
|
||||
initializeCard();
|
||||
});
|
||||
|
||||
function initializeCard() {
|
||||
cardTimes();
|
||||
cardRefreshTimes();
|
||||
}
|
||||
|
||||
let year, month, week, date, dates, weekStr, monthStr, asideTime, asideDay, asideDayNum, animalYear, ganzhiYear, lunarMon, lunarDay;
|
||||
const now = new Date();
|
||||
|
||||
function cardRefreshTimes() {
|
||||
const e = document.getElementById("card-widget-schedule");
|
||||
if (e) {
|
||||
asideDay = (now - asideTime) / 1e3 / 60 / 60 / 24;
|
||||
e.querySelector("#pBar_year").value = asideDay;
|
||||
e.querySelector("#p_span_year").innerHTML = (asideDay / 365 * 100).toFixed(1) + "%";
|
||||
e.querySelector(".schedule-r0 .schedule-d1 .aside-span2").innerHTML = `还剩<a> ${(365 - asideDay).toFixed(0)} </a>天`;
|
||||
e.querySelector("#pBar_month").value = date;
|
||||
e.querySelector("#pBar_month").max = dates;
|
||||
e.querySelector("#p_span_month").innerHTML = (date / dates * 100).toFixed(1) + "%";
|
||||
e.querySelector(".schedule-r1 .schedule-d1 .aside-span2").innerHTML = `还剩<a> ${(dates - date)} </a>天`;
|
||||
e.querySelector("#pBar_week").value = week === 0 ? 7 : week;
|
||||
e.querySelector("#p_span_week").innerHTML = ((week === 0 ? 7 : week) / 7 * 100).toFixed(1) + "%";
|
||||
e.querySelector(".schedule-r2 .schedule-d1 .aside-span2").innerHTML = `还剩<a> ${(7 - (week === 0 ? 7 : week))} </a>天`;
|
||||
}
|
||||
}
|
||||
|
||||
function cardTimes() {
|
||||
year = now.getFullYear();
|
||||
month = now.getMonth();
|
||||
week = now.getDay();
|
||||
date = now.getDate();
|
||||
|
||||
const e = document.getElementById("card-widget-calendar");
|
||||
if (e) {
|
||||
const isLeapYear = year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
||||
weekStr = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"][week];
|
||||
const monthData = [
|
||||
{ month: "1月", days: 31 },
|
||||
{ month: "2月", days: isLeapYear ? 29 : 28 },
|
||||
{ month: "3月", days: 31 },
|
||||
{ month: "4月", days: 30 },
|
||||
{ month: "5月", days: 31 },
|
||||
{ month: "6月", days: 30 },
|
||||
{ month: "7月", days: 31 },
|
||||
{ month: "8月", days: 31 },
|
||||
{ month: "9月", days: 30 },
|
||||
{ month: "10月", days: 31 },
|
||||
{ month: "11月", days: 30 },
|
||||
{ month: "12月", days: 31 }
|
||||
];
|
||||
monthStr = monthData[month].month;
|
||||
dates = monthData[month].days;
|
||||
|
||||
const t = (week + 8 - date % 7) % 7;
|
||||
let n = "", d = false, s = 7 - t;
|
||||
const o = (dates - s) % 7 === 0 ? Math.floor((dates - s) / 7) + 1 : Math.floor((dates - s) / 7) + 2;
|
||||
const c = e.querySelector("#calendar-main");
|
||||
const l = e.querySelector("#calendar-date");
|
||||
|
||||
l.style.fontSize = ["64px", "48px", "36px"][Math.min(o - 3, 2)];
|
||||
|
||||
for (let i = 0; i < o; i++) {
|
||||
if (!c.querySelector(`.calendar-r${i}`)) {
|
||||
c.innerHTML += `<div class='calendar-r${i}'></div>`;
|
||||
}
|
||||
for (let j = 0; j < 7; j++) {
|
||||
if (i === 0 && j === t) {
|
||||
n = 1;
|
||||
d = true;
|
||||
}
|
||||
const r = n === date ? " class='now'" : "";
|
||||
if (!c.querySelector(`.calendar-r${i} .calendar-d${j} a`)) {
|
||||
c.querySelector(`.calendar-r${i}`).innerHTML += `<div class='calendar-d${j}'><a${r}>${n}</a></div>`;
|
||||
}
|
||||
if (n >= dates) {
|
||||
n = "";
|
||||
d = false;
|
||||
}
|
||||
if (d) {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lunarDate = chineseLunar.solarToLunar(new Date(year, month, date));
|
||||
animalYear = chineseLunar.format(lunarDate, "A");
|
||||
ganzhiYear = chineseLunar.format(lunarDate, "T").slice(0, -1);
|
||||
lunarMon = chineseLunar.format(lunarDate, "M");
|
||||
lunarDay = chineseLunar.format(lunarDate, "d");
|
||||
|
||||
const newYearDate = new Date("2026/02/16 00:00:00");
|
||||
const daysUntilNewYear = Math.floor((newYearDate - now) / 1e3 / 60 / 60 / 24);
|
||||
asideTime = new Date(`${new Date().getFullYear()}/01/01 00:00:00`);
|
||||
asideDay = (now - asideTime) / 1e3 / 60 / 60 / 24;
|
||||
asideDayNum = Math.floor(asideDay);
|
||||
const weekNum = week - asideDayNum % 7 >= 0 ? Math.ceil(asideDayNum / 7) : Math.ceil(asideDayNum / 7) + 1;
|
||||
|
||||
e.querySelector("#calendar-week").innerHTML = `第${weekNum}周 ${weekStr}`;
|
||||
e.querySelector("#calendar-date").innerHTML = date.toString().padStart(2, "0");
|
||||
e.querySelector("#calendar-solar").innerHTML = `${year}年${monthStr} 第${asideDay.toFixed(0)}天`;
|
||||
e.querySelector("#calendar-lunar").innerHTML = `${ganzhiYear}${animalYear}年 ${lunarMon}${lunarDay}`;
|
||||
document.getElementById("schedule-days").innerHTML = daysUntilNewYear;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
function renderTalks() {
|
||||
const talkContainer = document.querySelector('#talk');
|
||||
const domain = 'https://mm.biss.click';
|
||||
if (!talkContainer) return;
|
||||
talkContainer.innerHTML = '';
|
||||
const generateIconSVG = () => {
|
||||
@@ -77,235 +76,162 @@ function renderTalks() {
|
||||
};
|
||||
|
||||
const fetchAndRenderTalks = () => {
|
||||
const url = 'https://mm.biss.click/api/memo/list';
|
||||
const url = 'https://mm.biss.click/api/echo/page';
|
||||
const cacheKey = 'talksCache';
|
||||
const cacheTimeKey = 'talksCacheTime';
|
||||
const cacheDuration = 30 * 60 * 1000; // 半个小时 (30 分钟)
|
||||
|
||||
const cacheDuration = 30 * 60 * 1000;
|
||||
const cachedData = localStorage.getItem(cacheKey);
|
||||
const cachedTime = localStorage.getItem(cacheTimeKey);
|
||||
const currentTime = new Date().getTime();
|
||||
const now = Date.now();
|
||||
|
||||
// 判断缓存是否有效
|
||||
if (cachedData && cachedTime && (currentTime - cachedTime < cacheDuration)) {
|
||||
const data = JSON.parse(cachedData);
|
||||
renderTalks(data); // 使用缓存渲染数据
|
||||
if (cachedData && cachedTime && (now - cachedTime < cacheDuration)) {
|
||||
renderTalksList(JSON.parse(cachedData));
|
||||
} else {
|
||||
if (talkContainer) {
|
||||
talkContainer.innerHTML = '';
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
size: 30
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.code === 0 && data.data && Array.isArray(data.data.list)) {
|
||||
// 缓存数据
|
||||
localStorage.setItem(cacheKey, JSON.stringify(data.data.list));
|
||||
localStorage.setItem(cacheTimeKey, currentTime.toString());
|
||||
renderTalks(data.data.list); // 渲染数据
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching data:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染函数
|
||||
function renderTalks(list) {
|
||||
// 确保 data 是一个数组
|
||||
if (Array.isArray(list)) {
|
||||
let items = list.map(item => formatTalk(item, url));
|
||||
items.forEach(item => talkContainer.appendChild(generateTalkElement(item)));
|
||||
waterfall('#talk');
|
||||
} else {
|
||||
console.error('Data is not an array:', list);
|
||||
}
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ page: 1, pageSize: 30 })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.code === 1 && data.data && Array.isArray(data.data.items)) {
|
||||
localStorage.setItem(cacheKey, JSON.stringify(data.data.items));
|
||||
localStorage.setItem(cacheTimeKey, now.toString());
|
||||
renderTalksList(data.data.items);
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Error fetching:', err));
|
||||
}
|
||||
};
|
||||
|
||||
const renderTalksList = (list) => {
|
||||
list.map(formatTalk).forEach(item => talkContainer.appendChild(generateTalkElement(item)));
|
||||
waterfall('#talk');
|
||||
};
|
||||
|
||||
const formatTalk = (item, url) => {
|
||||
let date = formatTime(new Date(item.createdAt).toString());
|
||||
let content = item.content;
|
||||
let imgs = item.imgs ? item.imgs.split(',') : [];
|
||||
let text = content;
|
||||
content = text.replace(/\[(.*?)\]\((.*?)\)/g, `<a href="$2">@$1</a>`)
|
||||
.replace(/- \[ \]/g, '⚪')
|
||||
.replace(/- \[x\]/g, '⚫');
|
||||
// 保留换行符,转换 \n 为 <br>
|
||||
content = content.replace(/\n/g, '<br>');
|
||||
// 将content用一个类包裹,便于后续处理
|
||||
const formatTalk = (item) => {
|
||||
const date = formatTime(item.created_at);
|
||||
let content = item.content || '';
|
||||
content = content.replace(/\[(.*?)\]\((.*?)\)/g, `<a href="$2" target="_blank" rel="nofollow noopener">@$1</a>`)
|
||||
.replace(/- \[ \]/g, '⚪')
|
||||
.replace(/- \[x\]/g, '⚫')
|
||||
.replace(/\n/g, '<br>');
|
||||
content = `<div class="talk_content_text">${content}</div>`;
|
||||
if (imgs.length > 0) {
|
||||
|
||||
// 图片
|
||||
if (Array.isArray(item.images) && item.images.length > 0) {
|
||||
const imgDiv = document.createElement('div');
|
||||
imgDiv.className = 'zone_imgbox';
|
||||
imgs.forEach(e => {
|
||||
const imgLink = document.createElement('a');
|
||||
const imgUrl = domain + e;
|
||||
imgLink.href = imgUrl;
|
||||
imgLink.setAttribute('data-fancybox', 'gallery');
|
||||
imgLink.className = 'fancybox';
|
||||
imgLink.setAttribute('data-thumb', e);
|
||||
item.images.forEach(img => {
|
||||
const link = document.createElement('a');
|
||||
link.href = img.image_url + "?fmt=webp&q=75";
|
||||
link.setAttribute('data-fancybox', 'gallery');
|
||||
link.className = 'fancybox';
|
||||
const imgTag = document.createElement('img');
|
||||
imgTag.src = domain + e;
|
||||
imgLink.appendChild(imgTag);
|
||||
imgDiv.appendChild(imgLink);
|
||||
imgTag.src = img.image_url + "?fmt=webp&q=75";
|
||||
link.appendChild(imgTag);
|
||||
imgDiv.appendChild(link);
|
||||
});
|
||||
content += imgDiv.outerHTML;
|
||||
}
|
||||
|
||||
// 外链分享功能
|
||||
if (item.externalUrl) {
|
||||
const externalUrl = item.externalUrl;
|
||||
const externalTitle = item.externalTitle;
|
||||
const externalFavicon = item.externalFavicon;
|
||||
// 外链 / GitHub 项目
|
||||
// 外链 / GitHub 项目
|
||||
if (['WEBSITE', 'GITHUBPROJ'].includes(item.extension_type)) {
|
||||
let siteUrl = '', title = '';
|
||||
let extensionBack = "https://p.liiiu.cn/i/2024/07/27/66a4632bbf06e.webp";
|
||||
|
||||
const externalContainer = `
|
||||
<div class="shuoshuo-external-link">
|
||||
<a class="external-link" href="${externalUrl}" target="_blank" rel="external nofollow noopener noreferrer">
|
||||
<div class="external-link-left" style="background-image: url(${externalFavicon})"></div>
|
||||
<div class="external-link-right">
|
||||
<div class="external-link-title">${externalTitle}</div>
|
||||
<div>点击跳转<i class="fa-solid fa-angle-right"></i></div>
|
||||
</div>
|
||||
</a>
|
||||
</div>`;
|
||||
// 解析 extension 字段
|
||||
try {
|
||||
const extObj = typeof item.extension === 'string' ? JSON.parse(item.extension) : item.extension;
|
||||
siteUrl = extObj.site || extObj.url || item.extension;
|
||||
title = extObj.title || siteUrl;
|
||||
} catch {
|
||||
siteUrl = item.extension;
|
||||
title = siteUrl;
|
||||
}
|
||||
|
||||
content += externalContainer;
|
||||
}
|
||||
// 特殊处理 GitHub 项目
|
||||
if (item.extension_type === 'GITHUBPROJ') {
|
||||
extensionBack = "https://p.liiiu.cn/i/2024/07/27/66a461a3098aa.webp";
|
||||
|
||||
const ext = JSON.parse(item.ext || '{}');
|
||||
// 提取 GitHub 项目名
|
||||
const match = siteUrl.match(/^https?:\/\/github\.com\/[^/]+\/([^/?#]+)/i);
|
||||
if (match) {
|
||||
title = match[1]; // 获取仓库名
|
||||
} else {
|
||||
// fallback:从最后一个路径段提取
|
||||
try {
|
||||
const parts = new URL(siteUrl).pathname.split('/').filter(Boolean);
|
||||
title = parts.pop() || siteUrl;
|
||||
} catch {
|
||||
// 如果 URL 无效则保留原始
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ext.music && ext.music.id) {
|
||||
const music = ext.music;
|
||||
const musicUrl = music.api.replace(':server', music.server)
|
||||
.replace(':type', music.type)
|
||||
.replace(':id', music.id);
|
||||
// 输出 HTML 结构
|
||||
content += `
|
||||
<meting-js server="${music.server}" type="${music.type}" id="${music.id}" api="${music.api}"></meting-js>
|
||||
`;
|
||||
}
|
||||
|
||||
if (ext.doubanMovie && ext.doubanMovie.id) {
|
||||
const doubanMovie = ext.doubanMovie;
|
||||
const doubanMovieUrl = doubanMovie.url;
|
||||
const doubanTitle = doubanMovie.title;
|
||||
// const doubanDesc = doubanMovie.desc || '暂无描述';
|
||||
const doubanImage = doubanMovie.image;
|
||||
const doubanDirector = doubanMovie.director || '未知导演';
|
||||
const doubanRating = doubanMovie.rating || '暂无评分';
|
||||
// const doubanReleaseDate = doubanMovie.releaseDate || '未知上映时间';
|
||||
// const doubanActors = doubanMovie.actors || '未知演员';
|
||||
const doubanRuntime = doubanMovie.runtime || '未知时长';
|
||||
|
||||
content += `
|
||||
<a class="douban-card" href="${doubanMovieUrl}" target="_blank">
|
||||
<div class="douban-card-bgimg" style="background-image: url('${doubanImage}');"></div>
|
||||
<div class="douban-card-left">
|
||||
<div class="douban-card-img" style="background-image: url('${doubanImage}');"></div>
|
||||
</div>
|
||||
<div class="douban-card-right">
|
||||
<div class="douban-card-item"><span>电影名: </span><strong>${doubanTitle}</strong></div>
|
||||
<div class="douban-card-item"><span>导演: </span><span>${doubanDirector}</span></div>
|
||||
<div class="douban-card-item"><span>评分: </span><span>${doubanRating}</span></div>
|
||||
<div class="douban-card-item"><span>时长: </span><span>${doubanRuntime}</span></div>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
if (ext.doubanBook && ext.doubanBook.id) {
|
||||
const doubanBook = ext.doubanBook;
|
||||
const bookUrl = doubanBook.url;
|
||||
const bookTitle = doubanBook.title;
|
||||
// const bookDesc = doubanBook.desc;
|
||||
const bookImage = doubanBook.image;
|
||||
const bookAuthor = doubanBook.author;
|
||||
const bookRating = doubanBook.rating;
|
||||
const bookPubDate = doubanBook.pubDate;
|
||||
|
||||
const bookTemplate = `
|
||||
<a class="douban-card" href="${bookUrl}" target="_blank">
|
||||
<div class="douban-card-bgimg" style="background-image: url('${bookImage}');"></div>
|
||||
<div class="douban-card-left">
|
||||
<div class="douban-card-img" style="background-image: url('${bookImage}');"></div>
|
||||
<div class="shuoshuo-external-link">
|
||||
<a class="external-link" href="${siteUrl}" target="_blank" rel="nofollow noopener">
|
||||
<div class="external-link-left" style="background-image:url(${extensionBack})"></div>
|
||||
<div class="external-link-right">
|
||||
<div class="external-link-title">${title}</div>
|
||||
<div>点击跳转<i class="fa-solid fa-angle-right"></i></div>
|
||||
</div>
|
||||
<div class="douban-card-right">
|
||||
<div class="douban-card-item">
|
||||
<span>书名: </span><strong>${bookTitle}</strong>
|
||||
</div>
|
||||
<div class="douban-card-item">
|
||||
<span>作者: </span><span>${bookAuthor}</span>
|
||||
</div>
|
||||
<div class="douban-card-item">
|
||||
<span>出版年份: </span><span>${bookPubDate}</span>
|
||||
</div>
|
||||
<div class="douban-card-item">
|
||||
<span>评分: </span><span>${bookRating}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
|
||||
content += bookTemplate;
|
||||
</a>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
if (ext.video && ext.video.type) {
|
||||
const videoType = ext.video.type;
|
||||
const videoUrl = ext.video.value;
|
||||
if (videoType === 'bilibili') {
|
||||
// Bilibili 视频模板
|
||||
// 从形如https://www.bilibili.com/video/BV1VGAPeAEMQ/?vd_source=91b3158d27d98ff41f842508c3794a13 的链接中提取视频 BV1VGAPeAEMQ
|
||||
const biliTemplate = `
|
||||
<div style="position: relative; padding: 30% 45%; margin-top: 10px;">
|
||||
<iframe
|
||||
style="position: absolute; width: 100%; height: 100%; left: 0; top: 0; border-radius: 12px;"
|
||||
src="${videoUrl}&autoplay=0"
|
||||
scrolling="no"
|
||||
frameborder="no"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
`;
|
||||
// 将模板插入到 DOM 中
|
||||
content += biliTemplate;
|
||||
|
||||
} else if (videoType === 'youtube') {
|
||||
// YouTube 视频模板
|
||||
// 从形如https://youtu.be/2V6lvCUPT8I?si=DVhUas6l6qlAr6Ru的链接中提取视频 ID2V6lvCUPT8I
|
||||
const youtubeTemplate = `
|
||||
<div style="position: relative; padding: 30% 45%; margin-top: 10px;">
|
||||
<iframe width="100%"
|
||||
style="position: absolute; width: 100%; height: 100%; left: 0; top: 0; border-radius: 12px;"
|
||||
src="${videoUrl}"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
`;
|
||||
// 将模板插入到 DOM 中
|
||||
content += youtubeTemplate;
|
||||
// 音乐
|
||||
if (item.extension_type === 'MUSIC' && item.extension) {
|
||||
const link = item.extension;
|
||||
let server = '';
|
||||
if (link.includes('music.163.com')) server = 'netease';
|
||||
else if (link.includes('y.qq.com')) server = 'tencent';
|
||||
const idMatch = link.match(/id=(\d+)/);
|
||||
const id = idMatch ? idMatch[1] : '';
|
||||
if (server && id) {
|
||||
content += `<meting-js server="${server}" type="song" id="${id}" api="https://met.liiiu.cn/meting/api?server=:server&type=:type&id=:id&auth=:auth&r=:r"></meting-js>`;
|
||||
}
|
||||
}
|
||||
|
||||
// 视频
|
||||
if (item.extension_type === 'VIDEO' && item.extension) {
|
||||
const video = item.extension;
|
||||
if (video.startsWith('BV')) {
|
||||
const bilibiliUrl = `https://www.bilibili.com/blackboard/html5mobileplayer.html?bvid=${video}&as_wide=1&high_quality=1&danmaku=0`;
|
||||
content += `
|
||||
<div style="position: relative; padding: 30% 45%; margin-top: 10px;">
|
||||
<iframe style="position:absolute;width:100%;height:100%;left:0;top:0;border-radius:12px;"
|
||||
src="${bilibiliUrl}"
|
||||
frameborder="no"
|
||||
allowfullscreen="true"
|
||||
loading="lazy"></iframe>
|
||||
</div>`;
|
||||
} else {
|
||||
const youtubeUrl = `https://www.youtube.com/embed/${video}`;
|
||||
content += `
|
||||
<div style="position: relative; padding: 30% 45%; margin-top: 10px;">
|
||||
<iframe style="position:absolute;width:100%;height:100%;left:0;top:0;border-radius:12px;"
|
||||
src="${youtubeUrl}"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen></iframe>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: content,
|
||||
user: item.user.nickname || '匿名',
|
||||
avatar: item.user.avatarUrl || 'https://p.liiiu.cn/i/2024/03/29/66061417537af.png',
|
||||
date: date,
|
||||
location: item.location || '山西',
|
||||
tags: item.tags ? item.tags.split(',').filter(tag => tag.trim() !== '') : ['无标签'],
|
||||
text: content.replace(/\[(.*?)\]\((.*?)\)/g, '[链接]' + `${imgs.length ? '[图片]' : ''}`)
|
||||
content,
|
||||
user: item.username || '匿名',
|
||||
avatar: 'https://p.liiiu.cn/i/2025/03/13/67d2fc82d329c.webp',
|
||||
date,
|
||||
location: '',
|
||||
tags: Array.isArray(item.tags) && item.tags.length ? item.tags.map(t => t.name) : ['无标签'],
|
||||
text: content.replace(/\[(.*?)\]\((.*?)\)/g, '[链接]')
|
||||
};
|
||||
};
|
||||
|
||||
@@ -315,21 +241,22 @@ function renderTalks() {
|
||||
|
||||
const talkMeta = document.createElement('div');
|
||||
talkMeta.className = 'talk_meta';
|
||||
|
||||
const avatar = document.createElement('img');
|
||||
avatar.className = 'no-lightbox avatar';
|
||||
avatar.src = item.avatar;
|
||||
|
||||
const info = document.createElement('div');
|
||||
info.className = 'info';
|
||||
|
||||
const talkNick = document.createElement('span');
|
||||
talkNick.className = 'talk_nick';
|
||||
talkNick.innerHTML = `${item.user} ${generateIconSVG()}`;
|
||||
|
||||
const talkDate = document.createElement('span');
|
||||
talkDate.className = 'talk_date';
|
||||
talkDate.textContent = item.date;
|
||||
const nick = document.createElement('span');
|
||||
nick.className = 'talk_nick';
|
||||
nick.innerHTML = `${item.user} ${generateIconSVG()}`;
|
||||
const date = document.createElement('span');
|
||||
date.className = 'talk_date';
|
||||
date.textContent = item.date;
|
||||
info.appendChild(nick);
|
||||
info.appendChild(date);
|
||||
talkMeta.appendChild(avatar);
|
||||
talkMeta.appendChild(info);
|
||||
|
||||
const talkContent = document.createElement('div');
|
||||
talkContent.className = 'talk_content';
|
||||
@@ -337,38 +264,29 @@ function renderTalks() {
|
||||
|
||||
const talkBottom = document.createElement('div');
|
||||
talkBottom.className = 'talk_bottom';
|
||||
|
||||
const TagContainer = document.createElement('div');
|
||||
|
||||
const talkTag = document.createElement('span');
|
||||
talkTag.className = 'talk_tag';
|
||||
talkTag.textContent = `🏷️${item.tags}`;
|
||||
|
||||
const locationTag = document.createElement('span');
|
||||
locationTag.className = 'location_tag';
|
||||
locationTag.textContent = `🌍${item.location}`;
|
||||
|
||||
TagContainer.appendChild(talkTag);
|
||||
TagContainer.appendChild(locationTag);
|
||||
const tags = document.createElement('div');
|
||||
const tag = document.createElement('span');
|
||||
tag.className = 'talk_tag';
|
||||
tag.textContent = `🏷️${item.tags}`;
|
||||
//const loc = document.createElement('span');
|
||||
//loc.className = 'location_tag';
|
||||
//loc.textContent = `🌍${item.location}`;
|
||||
tags.appendChild(tag);
|
||||
//tags.appendChild(loc);
|
||||
|
||||
const commentLink = document.createElement('a');
|
||||
commentLink.href = 'javascript:;';
|
||||
commentLink.onclick = () => goComment(item.text);
|
||||
const commentIcon = document.createElement('span');
|
||||
commentIcon.className = 'icon';
|
||||
const commentIconInner = document.createElement('i');
|
||||
commentIconInner.className = 'fa-solid fa-message fa-fw';
|
||||
commentIcon.appendChild(commentIconInner);
|
||||
commentLink.appendChild(commentIcon);
|
||||
const icon = document.createElement('span');
|
||||
icon.className = 'icon';
|
||||
icon.innerHTML = '<i class="fa-solid fa-message fa-fw"></i>';
|
||||
commentLink.appendChild(icon);
|
||||
|
||||
talkBottom.appendChild(tags);
|
||||
talkBottom.appendChild(commentLink);
|
||||
|
||||
talkMeta.appendChild(avatar);
|
||||
info.appendChild(talkNick);
|
||||
info.appendChild(talkDate);
|
||||
talkMeta.appendChild(info);
|
||||
talkItem.appendChild(talkMeta);
|
||||
talkItem.appendChild(talkContent);
|
||||
talkBottom.appendChild(TagContainer);
|
||||
talkBottom.appendChild(commentLink);
|
||||
talkItem.appendChild(talkBottom);
|
||||
|
||||
return talkItem;
|
||||
@@ -377,28 +295,16 @@ function renderTalks() {
|
||||
const goComment = (e) => {
|
||||
const match = e.match(/<div class="talk_content_text">([\s\S]*?)<\/div>/);
|
||||
const textContent = match ? match[1] : "";
|
||||
const n = document.querySelector(".tk-input el-textarea");
|
||||
n.value = `> ${textContent}\n\n`;
|
||||
n.focus();
|
||||
const textarea = document.querySelector("tk-input el-textarea");
|
||||
textarea.value = `> ${textContent}\n\n`;
|
||||
textarea.focus();
|
||||
btf.snackbarShow("已为您引用该说说,不删除空格效果更佳");
|
||||
// const n = document.querySelector(".atk-textarea");
|
||||
// n.value = `> ${e}\n\n`;
|
||||
// n.focus();
|
||||
// btf.snackbarShow("已为您引用该说说,不删除空格效果更佳");
|
||||
};
|
||||
|
||||
const formatTime = (time) => {
|
||||
const d = new Date(time);
|
||||
const ls = [
|
||||
d.getFullYear(),
|
||||
d.getMonth() + 1,
|
||||
d.getDate(),
|
||||
d.getHours(),
|
||||
d.getMinutes(),
|
||||
d.getSeconds(),
|
||||
];
|
||||
const r = ls.map((a) => (a.toString().length === 1 ? '0' + a : a));
|
||||
return `${r[0]}-${r[1]}-${r[2]} ${r[3]}:${r[4]}`;
|
||||
const pad = (n) => n.toString().padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
};
|
||||
|
||||
fetchAndRenderTalks();
|
||||
|
||||
97
themes/butterfly/source/js/shuoshuoshouye.js
Normal file
97
themes/butterfly/source/js/shuoshuoshouye.js
Normal file
@@ -0,0 +1,97 @@
|
||||
let talkTimer = null;
|
||||
|
||||
const cacheKey = 'talksCache';
|
||||
const cacheTimeKey = 'talksCacheTime';
|
||||
const cacheDuration = 30 * 60 * 1000; // 缓存有效期 30分钟
|
||||
|
||||
function indexTalk() {
|
||||
if (talkTimer) {
|
||||
clearInterval(talkTimer);
|
||||
talkTimer = null;
|
||||
}
|
||||
|
||||
if (!document.getElementById('bber-talk')) return;
|
||||
|
||||
function toText(ls) {
|
||||
return ls.map(item => {
|
||||
let c = item.content || '';
|
||||
|
||||
const hasImg = /\!\[.*?\]\(.*?\)/.test(c);
|
||||
const hasLink = /\[.*?\]\(.*?\)/.test(c);
|
||||
|
||||
c = c
|
||||
.replace(/#(.*?)\s/g, '')
|
||||
.replace(/\{.*?\}/g, '')
|
||||
.replace(/\!\[.*?\]\(.*?\)/g, '<i class="fa-solid fa-image"></i>')
|
||||
.replace(/\[.*?\]\(.*?\)/g, '<i class="fa-solid fa-link"></i>');
|
||||
|
||||
const icons = [];
|
||||
|
||||
if (item.images?.length && !hasImg) icons.push('fa-solid fa-image');
|
||||
if (item.extension_type === 'VIDEO') icons.push('fa-solid fa-video');
|
||||
if (item.extension_type === 'MUSIC') icons.push('fa-solid fa-music');
|
||||
if (item.extension_type === 'WEBSITE' && !hasLink) icons.push('fa-solid fa-link');
|
||||
if (item.extension_type === 'GITHUBPROJ' && !hasLink) icons.push('fab fa-github');
|
||||
|
||||
if (icons.length) c += ' ' + icons.map(i => `<i class="${i}"></i>`).join(' ');
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染与轮播
|
||||
function talk(ls) {
|
||||
let html = '';
|
||||
ls.forEach((item, i) => {
|
||||
html += `<li class="item item-${i + 1}">${item}</li>`;
|
||||
});
|
||||
|
||||
let box = document.querySelector("#bber-talk .talk-list");
|
||||
if (!box) return;
|
||||
|
||||
box.innerHTML = html;
|
||||
|
||||
talkTimer = setInterval(() => {
|
||||
if (box.children.length > 0) {
|
||||
box.appendChild(box.children[0]);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
const cachedData = localStorage.getItem(cacheKey);
|
||||
const cachedTime = localStorage.getItem(cacheTimeKey);
|
||||
const currentTime = new Date().getTime();
|
||||
|
||||
// 判断缓存是否有效
|
||||
if (cachedData && cachedTime && (currentTime - cachedTime < cacheDuration)) {
|
||||
const data = toText(JSON.parse(cachedData));
|
||||
talk(data.slice(0, 6)); // 使用缓存渲染数据
|
||||
} else {
|
||||
fetch('https://mm.biss.click/api/echo/page', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ page: 1, pageSize: 30 })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
// 适配新版结构:code=1 且 data.items 存在
|
||||
if (data.code === 1 && data.data && Array.isArray(data.data.items)) {
|
||||
localStorage.setItem(cacheKey, JSON.stringify(data.data.items));
|
||||
localStorage.setItem(cacheTimeKey, currentTime.toString());
|
||||
|
||||
const formattedData = toText(data.data.items);
|
||||
talk(formattedData.slice(0, 6));
|
||||
} else {
|
||||
console.warn('Unexpected API response format:', data);
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching data:', error));
|
||||
}
|
||||
}
|
||||
|
||||
// pjax 支持
|
||||
function whenDOMReady() {
|
||||
indexTalk();
|
||||
}
|
||||
|
||||
whenDOMReady();
|
||||
document.addEventListener("pjax:complete", whenDOMReady);
|
||||
Reference in New Issue
Block a user