您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
个人主页时光机下面增加一个月度统计的小功能。
当前为
// ==UserScript== // @name 番组计划月度统计 // @namespace http://tampermonkey.net/ // @version 2024-01-03 // @description 个人主页时光机下面增加一个月度统计的小功能。 // @author You // @match https://bangumi.tv/user/* // @match https://bgm.tv/user/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bangumi.tv // @grant GM_addStyle // @license MIT // ==/UserScript== (function() { 'use strict'; const COLLECTION_TYPE = {1: '想看', 2: '看过', 3: '在看', 4: '搁置', 5: '抛弃'} const sourceElement = document.querySelector('#columnA') const tempDiv = document.createElement('div') sourceElement.appendChild(tempDiv) const buttonDiv = document.createElement('div') sourceElement.appendChild(buttonDiv) buttonDiv.innerHTML = `<div class="request-more-data"><div class='request-more-data-button' id='request-more-data-button'>加载更多</div></div>` const requestButton = document.querySelector('#request-more-data-button') if (!sourceElement) { return; } let totalDataArray = [] const limit = 100 let offset = 0 const hasAllMap = {} let hasFinish = false let hasClick = false const d = location.pathname.split('/') const requestUrl = `https://api.bgm.tv/v0/users/${d[d.length - 1]}/collections` requestButton.addEventListener('click', () => { requestButton.innerHTML = '加载中...' if (hasClick) {return} if (hasFinish) { requestButton.innerHTML = '无更多数据' return } hasClick = true requestData() }) requestData() function requestData (){ hasClick = true; const oldhasAllMap = JSON.stringify(hasAllMap) fetch(`${requestUrl}?limit=${limit}&offset=${offset}`,{mode: 'cors'}).then(res => { res.json().then(jes => { totalDataArray.push(...jes.data) hasFinish = totalDataArray.length === jes.total init(totalDataArray) offset = totalDataArray.length hasClick = false requestButton.innerHTML = '加载更多' if (oldhasAllMap === JSON.stringify(hasAllMap)) {requestData()} }) }) } function getMonthItemRender(monthDataMap,year) { let strListRenderStr = '' for(let monthKey in monthDataMap) { const tempObj = {} monthDataMap[monthKey].forEach(dateData => { if (!tempObj[dateData.type]) {tempObj[dateData.type] = []} tempObj[dateData.type].push(dateData) }) let tempRenderStr = '' for(let tempObjKey in tempObj) { tempRenderStr += ` <div class='my-total-month-connect my-total-timeline'>${(() => { let subjectRenderStr = `<div class='my-total-month-type my-total-month-type${tempObjKey}'>${COLLECTION_TYPE[tempObjKey]} <span class='my-total-month-type-number'>${tempObj[tempObjKey].length}</span></div>` tempObj[tempObjKey].forEach(collection => { subjectRenderStr += ` <span class='my-total-month-list-item-span'> <img class='my-total-month-list-item-img' src=${collection.subject.images.small}></img> <span class='my-total-month-list-item-date'>${`${new Date(collection.updated_at).getMonth() + 1}.${new Date(collection.updated_at).getDate()}`}</span> </span> ` }) return subjectRenderStr })()}</div> ` } const monthRenderStr = ` <div class='my-total-month'> <div class='my-total-month-title my-total-timeline'>${monthKey}月</div> ${tempRenderStr} </div>` if (hasAllMap[year][monthKey]) { strListRenderStr = monthRenderStr + strListRenderStr } } return strListRenderStr } function init(data) { const collectionsData = {} let lastCollectionsData = {} data.forEach((item, index) => { const keyYear = new Date(item.updated_at).getFullYear() const keyMonth = new Date(item.updated_at).getMonth() + 1 if (!collectionsData[keyYear]) { collectionsData[keyYear] = {} hasAllMap[keyYear] = {} } if (!collectionsData[keyYear][keyMonth]) { collectionsData[keyYear][keyMonth] = [] } collectionsData[keyYear][keyMonth].push(item) if ((index >0) && (new Date(item.updated_at).getMonth() !== new Date(lastCollectionsData.data.updated_at).getMonth())) { hasAllMap[lastCollectionsData.keyYear][lastCollectionsData.keyMonth] = true } if (hasFinish){hasAllMap[keyYear][keyMonth] = true} lastCollectionsData.data = item lastCollectionsData.keyYear = keyYear lastCollectionsData.keyMonth = keyMonth }) let connectStr = '' for(let yearKey in collectionsData) { let itemStr = ` <div class='my-total-item'> <div class='my-total-item-year-title my-total-timeline'>${yearKey}</div> <div class='my-total-item-year-connect-list'>${getMonthItemRender(collectionsData[yearKey],yearKey)}</div> <div></div> </div> ` connectStr = itemStr + connectStr } const htmlStr = ` <div class="my-month-data"> ${connectStr} </div> ` tempDiv.innerHTML = htmlStr } const style = ` .my-month-data { margin-top: 40px; } .my-total-item-year-title { font-weight: 600; position: relative; font-size: 22px; padding-bottom: 15px; } .my-total-item-year-title::before { content: ''; display: inline-block; position: absolute; left: -3.4px; top: calc(50% - 7.5px); transform: translateY(-50%) rotate(45deg); width: 6px; height: 6px; background-color: #000; } .my-total-month-title { font-weight: 500; position: relative; font-size: 18px; padding-bottom: 10px; } .my-total-month-title::before { content: ''; display: inline-block; position: absolute; left: -6.5px; top: calc(50% - 5px); transform: translateY(-50%); width: 10px; height: 10px; border-radius: 50%; border: 1px solid #ccc; background-color: #fff; } .my-total-month-type { position: relative; font-size: 14px; padding-bottom: 5px; color: #888; } .my-total-month-type::before { content: ''; display: inline-block; position: absolute; left: -24.5px; top: calc(50% - 2.5px); transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; border: 1px solid #F09199; background-color: #F09199; } .my-total-month-type2::before { border: 1px solid #91B876; background-color: #91B876; } .my-total-month-type3::before { border: 1px solid #6BAAE8; background-color: #6BAAE8; } .my-total-month-type4::before { border: 1px solid #E68E46; background-color: #E68E46; } .my-total-month-type5::before { border: 1px solid #9065ED; background-color: #9065ED; } .my-total-month-type-number { color: #369CF8; } .my-total-month-list-item-span { overflow: hidden; display: inline-block; margin-right: 4px; border-radius: 4px; width: 60px; height: 85px; position: relative; } .my-total-month-list-item-img { width: 100%; height: 100%; object-fit: cover; } .my-total-month-list-item-date { position: absolute; right: 0; bottom: 0; font-size: 10px; color: #fff; line-height: 10px; background-color: #F09199; border-radius: 4px; padding: 2px; } .my-total-month-connect { padding-bottom: 25px; } .request-more-data { display: flex; align-item: center; justify-content: center; } .request-more-data-button { cursor: pointer; } .my-total-timeline { border-left: 1px solid #ccc; padding-left: 20px; } ` GM_addStyle(style) })();