From 39fcced835ab1b3e4194fda16a62ca7823aeb663 Mon Sep 17 00:00:00 2001 From: bisnsh Date: Tue, 20 Jan 2026 09:22:42 +0800 Subject: [PATCH] switch shuoshuo function to ech0 --- _config.butterfly.yml | 2 + themes/butterfly/layout/includes/layout.pug | 1 + .../layout/includes/others/memos_home.pug | 7 + themes/butterfly/source/css/shuoshuo.css | 74 +--- .../butterfly/source/css/shuoshuoshouye.css | 123 ++++++ themes/butterfly/source/css/style.css | 20 - themes/butterfly/source/js/calendar.js | 111 ----- themes/butterfly/source/js/shuoshuo.js | 410 +++++++----------- themes/butterfly/source/js/shuoshuoshouye.js | 97 +++++ 9 files changed, 412 insertions(+), 433 deletions(-) create mode 100644 themes/butterfly/layout/includes/others/memos_home.pug create mode 100644 themes/butterfly/source/css/shuoshuoshouye.css delete mode 100644 themes/butterfly/source/js/calendar.js create mode 100644 themes/butterfly/source/js/shuoshuoshouye.js diff --git a/_config.butterfly.yml b/_config.butterfly.yml index c65334d..9a64d22 100644 --- a/_config.butterfly.yml +++ b/_config.butterfly.yml @@ -1167,6 +1167,7 @@ inject: - - - + - - - - @@ -1183,6 +1184,7 @@ inject: - - - + - # CDN Settings # Don't modify the following settings unless you know how they work diff --git a/themes/butterfly/layout/includes/layout.pug b/themes/butterfly/layout/includes/layout.pug index 20b5865..735ad8d 100644 --- a/themes/butterfly/layout/includes/layout.pug +++ b/themes/butterfly/layout/includes/layout.pug @@ -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 diff --git a/themes/butterfly/layout/includes/others/memos_home.pug b/themes/butterfly/layout/includes/others/memos_home.pug new file mode 100644 index 0000000..6ecb1b7 --- /dev/null +++ b/themes/butterfly/layout/includes/others/memos_home.pug @@ -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 说说加载中。。。 diff --git a/themes/butterfly/source/css/shuoshuo.css b/themes/butterfly/source/css/shuoshuo.css index c1c8995..641f774 100644 --- a/themes/butterfly/source/css/shuoshuo.css +++ b/themes/butterfly/source/css/shuoshuo.css @@ -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 { /* 无下划线 */ diff --git a/themes/butterfly/source/css/shuoshuoshouye.css b/themes/butterfly/source/css/shuoshuoshouye.css new file mode 100644 index 0000000..97a5f49 --- /dev/null +++ b/themes/butterfly/source/css/shuoshuoshouye.css @@ -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; + } +} diff --git a/themes/butterfly/source/css/style.css b/themes/butterfly/source/css/style.css index 28c762f..5872058 100644 --- a/themes/butterfly/source/css/style.css +++ b/themes/butterfly/source/css/style.css @@ -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; diff --git a/themes/butterfly/source/js/calendar.js b/themes/butterfly/source/js/calendar.js deleted file mode 100644 index 16e9b2c..0000000 --- a/themes/butterfly/source/js/calendar.js +++ /dev/null @@ -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 = `还剩 ${(365 - asideDay).toFixed(0)} 天`; - 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 = `还剩 ${(dates - date)} 天`; - 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 = `还剩 ${(7 - (week === 0 ? 7 : week))} 天`; - } -} - -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 += `
`; - } - 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 += `
${n}
`; - } - 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; - } -} diff --git a/themes/butterfly/source/js/shuoshuo.js b/themes/butterfly/source/js/shuoshuo.js index 5397d8a..9bd65b1 100644 --- a/themes/butterfly/source/js/shuoshuo.js +++ b/themes/butterfly/source/js/shuoshuo.js @@ -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(); - - // 判断缓存是否有效 - if (cachedData && cachedTime && (currentTime - cachedTime < cacheDuration)) { - const data = JSON.parse(cachedData); - renderTalks(data); // 使用缓存渲染数据 + const now = Date.now(); + + 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 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, `@$1`) - .replace(/- \[ \]/g, '⚪') - .replace(/- \[x\]/g, '⚫'); - // 保留换行符,转换 \n 为
- content = content.replace(/\n/g, '
'); - // 将content用一个类包裹,便于后续处理 + const renderTalksList = (list) => { + list.map(formatTalk).forEach(item => talkContainer.appendChild(generateTalkElement(item))); + waterfall('#talk'); + }; + + const formatTalk = (item) => { + const date = formatTime(item.created_at); + let content = item.content || ''; + content = content.replace(/\[(.*?)\]\((.*?)\)/g, `@$1`) + .replace(/- \[ \]/g, '⚪') + .replace(/- \[x\]/g, '⚫') + .replace(/\n/g, '
'); content = `
${content}
`; - 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 = ` - `; + // 解析 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 += ` - - `; - } - - 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 += ` - -
-
-
-
-
-
电影名: ${doubanTitle}
-
导演: ${doubanDirector}
-
评分: ${doubanRating}
-
时长: ${doubanRuntime}
-
-
- `; - } - - 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 = ` - -
-
-
+
`; } - 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 = ` -
- -
- `; - // 将模板插入到 DOM 中 - content += biliTemplate; - } else if (videoType === 'youtube') { - // YouTube 视频模板 - // 从形如https://youtu.be/2V6lvCUPT8I?si=DVhUas6l6qlAr6Ru的链接中提取视频 ID2V6lvCUPT8I - const youtubeTemplate = ` -
- -
- `; - // 将模板插入到 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 += ``; + } + } + + // 视频 + 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 += ` +
+ +
`; + } else { + const youtubeUrl = `https://www.youtube.com/embed/${video}`; + content += ` +
+ +
`; } } 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 = ''; + 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(/
([\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(); diff --git a/themes/butterfly/source/js/shuoshuoshouye.js b/themes/butterfly/source/js/shuoshuoshouye.js new file mode 100644 index 0000000..f5a2594 --- /dev/null +++ b/themes/butterfly/source/js/shuoshuoshouye.js @@ -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, '') + .replace(/\[.*?\]\(.*?\)/g, ''); + + 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 => ``).join(' '); + return c; + }); + } + + // 渲染与轮播 + function talk(ls) { + let html = ''; + ls.forEach((item, i) => { + html += `
  • ${item}
  • `; + }); + + 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);