您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
也可以干别的
当前为
// ==UserScript== // @name 条目讨论页显示用户评价 // @namespace https://bgm.tv/group/topic/411796 // @version 0.0.1 // @description 也可以干别的 // @author mmv // @include http*://bgm.tv/subject/topic/* // @include http*://bgm.tv/blog/* // @include http*://bgm.tv/ep/* // @include http*://bgm.tv/character/* // @include http*://bgm.tv/group/topic/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bgm.tv // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; const styleSheet = document.createElement("style"); styleSheet.innerText = ` .ccf-star { margin-left: 5px; } .ccf-status { margin-left: 5px; color: #999; font-size: 12px; font-weight: normal; } .ccf-comment { margin-left: 5px; position: relative; cursor: help; } .ccf-comment::after { content: attr(data-comment); position: absolute; top: 100%; left: 0; background-color: rgba(254, 254, 254, 0.9); box-shadow: inset 0 1px 1px hsla(0, 0%, 100%, 0.3), inset 0 -1px 0 hsla(0, 0%, 100%, 0.1), 0 2px 4px hsla(0, 0%, 0%, 0.2); backdrop-filter: blur(5px); border-radius: 5px; padding: 5px; width: 250px; z-index: 1000; font-weight: normal; font-size: 12px; color: rgba(0, 0, 0, .7); cursor: text; transform: scale(0); } .ccf-comment:hover::after { transform: scale(1); } html[data-theme="dark"] .ccf-comment::after { background: rgba(80, 80, 80, 0.7); color: rgba(255, 255, 255, .7); } .loader { margin-left: 5px; border: 2px solid transparent; /* Light grey */ border-top: 2px solid #F09199; /* Blue */ border-radius: 50%; width: 10px; height: 10px; animation: spin 2s linear infinite; display: inline-block; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; document.head.appendChild(styleSheet); if (location.pathname.startsWith('/subject/topic') || location.pathname.startsWith('/ep')) { const userLinks = document.querySelectorAll('.inner strong a'); const subject_id = document.querySelector('#subject_inner_info a').href.split('/').pop(); if (!userLinks || !subject_id) return; lazyRender(userLinks, subject_id); } else if (location.pathname.startsWith('/blog')) { const userLinks = [document.querySelector('#pageHeader a')].concat([...document.querySelectorAll('#columnA .inner strong a')]); const relatedSubjects = document.querySelectorAll('#related_subject_list .ll a'); if (!userLinks || !relatedSubjects) return; multiSubjectsRender(userLinks, relatedSubjects); } else if (location.pathname.startsWith('/character')) { const userLinks = document.querySelectorAll('.inner strong a'); const castSubjects = document.querySelectorAll('.browserList .inner a[href^="/subject/"]'); if (!userLinks || !castSubjects) return; multiSubjectsRender(userLinks, castSubjects); } else if (location.pathname.startsWith('/group/topic')) { const userLinks = document.querySelectorAll('#columnInSubjectA .inner strong a'); if (!userLinks) return; window.ccf = subject_id => { lazyRender(userLinks, subject_id, true); } } async function getUserData(username, subject_id) { const cachedData = sessionStorage.getItem(`userData_${username}_${subject_id}`); if (cachedData) return JSON.parse(cachedData); const response = await fetch(`https://api.bgm.tv/v0/users/${username}/collections/${subject_id}`); if (response.ok) { const data = await response.json(); sessionStorage.setItem(`userData_${username}_${subject_id}`, JSON.stringify(data)); return data; } else if (response.status === 404) { const data = { not_found: true } sessionStorage.setItem(`userData_${username}_${subject_id}`, JSON.stringify(data)); return data; } else { throw new Error('Network response was not ok: ', response); } } async function renderUserData(userLink, subject_id, showSubject=false) { const username = userLink.href.split('/').pop(); let html = ''; const loader = document.createElement('div'); loader.classList.add('loader'); userLink.after(loader); try { const data = await getUserData(username, subject_id); const { not_found, subject_type, rate, type, ep_status, vol_status, comment, subject } = data; const name = subject?.name; loader.remove(); if (!not_found) { const verb = ['读', '看', '听', '玩', '', '看'][subject_type - 1]; if (rate && rate !== 0) { html += `<span class="ccf-star starstop-s"><span class="starlight stars${rate}"></span></span>`; } if (type) { html += `<span class="ccf-status">${[`想${verb}`, `${verb}过`, `在${verb}`, '搁置', '抛弃'][type-1]}${ showSubject && name || '' }</span>`; } if (ep_status) { html += `<span class="ccf-status">${verb}到ep${ep_status}</span>`; } if (vol_status) { html += `<span class="ccf-status">${verb}到vol${ep_status}</span>`; } if (comment) { html += `<span class="ccf-comment" data-comment="${comment.replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"')}">💬</span>`; } html = `<span id="ccf-${subject_id}">${html}</span>`; userLink.insertAdjacentHTML('afterend', html); } else { userLink.insertAdjacentElement('afterend', loadBtn('未标记该条目', userLink, subject_id)); } } catch (error) { console.error('Error fetching user data:', error); userLink.insertAdjacentElement('afterend', loadBtn('加载失败', userLink, subject_id)); } userLink.parentElement.querySelector('.loader')?.remove(); } function loadBtn(text, userLink, subject_id) { const btn = document.createElement('span'); btn.classList.add('ccf-status'); btn.textContent = text; btn.style.cursor = 'pointer'; btn.addEventListener('click', () => { const username = userLink.href.split('/').pop(); sessionStorage.removeItem(`userData_${username}_${subject_id}`); btn.remove(); renderUserData(userLink, subject_id); }); return btn; } function lazyRender(userLinks, subject_id, showSubject) { const observer = new IntersectionObserver(entries => { if (entries[0].intersectionRatio <= 0) return; for (const { isIntersecting, target } of entries) { if (!isIntersecting) continue; observer.unobserve(target); renderUserData(target, subject_id, showSubject); } }); for (const userLink of userLinks) observer.observe(userLink); } function multiSubjectsRender(userLinks, subjectLinks) { if (subjectLinks.length === 1) { lazyRender(userLinks, subjectLinks[0].href.split('/').pop()); return; } for (const subjectLink of subjectLinks) { const frag = document.createDocumentFragment(); const br = document.createElement('br'); const btn = document.createElement('a'); btn.href = 'javascript:;'; btn.textContent = '显示评价'; btn.classList.add('l'); btn.addEventListener('click', function() { const status = document.createElement('span'); status.classList.add('ccf-status'); status.textContent = '已显示本作评价'; this.insertAdjacentElement('afterend', status); this.remove(); lazyRender(userLinks, subjectLink.href.split('/').pop(), true); }); frag.append(br, btn); subjectLink.after(frag); } } })();