diff --git a/package.json b/package.json index ba26c17..7b9ccaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "psnine-enhanced-version", - "version": "1.0.23", + "version": "1.0.24", "description": "数折价格走势图,显示人民币价格,奖杯统计和筛选,发帖字数统计和即时预览,楼主高亮,自动翻页,屏蔽黑名单用户发言,被@用户的发言内容显示等多项功能优化P9体验", "main": "night-mode-css.js", "scripts": { diff --git a/psnineplus.js b/psnineplus.js index 0908b25..c8835bb 100644 --- a/psnineplus.js +++ b/psnineplus.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PSN中文网功能增强 // @namespace https://swsoyee.github.io -// @version 1.0.23 +// @version 1.0.24 // @description 数折价格走势图,显示人民币价格,奖杯统计和筛选,发帖字数统计和即时预览,楼主高亮,自动翻页,屏蔽黑名单用户发言,被@用户的发言内容显示等多项功能优化P9体验 // eslint-disable-next-line max-len // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAMFBMVEVHcEw0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNs0mNuEOyNSAAAAD3RSTlMAQMAQ4PCApCBQcDBg0JD74B98AAABN0lEQVRIx+2WQRaDIAxECSACWLn/bdsCIkNQ2XXT2bTyHEx+glGIv4STU3KNRccp6dNh4qTM4VDLrGVRxbLGaa3ZQSVQulVJl5JFlh3cLdNyk/xe2IXz4DqYLhZ4mWtHd4/SLY/QQwKmWmGcmUfHb4O1mu8BIPGw4Hg1TEvySQGWoBcItgxndmsbhtJd6baukIKnt525W4anygNECVc1UD8uVbRNbumZNl6UmkagHeRJfX0BdM5NXgA+ZKESpiJ9tRFftZEvue2cS6cKOrGk/IOLTLUcaXuZHrZDq3FB2IonOBCHIy8Bs1Zzo1MxVH+m8fQ+nFeCQM3MWwEsWsy8e8Di7meA5Bb5MDYCt4SnUbP3lv1xOuWuOi3j5kJ5tPiZKahbi54anNRaaG7YElFKQBHR/9PjN3oD6fkt9WKF9rgAAAAASUVORK5CYII= @@ -410,16 +410,67 @@ document.head.appendChild(nightModeStyle); } - /* 游戏列表添加按难度排列按钮 */ + /* + 1.游戏列表添加按难度排列按钮 + 2.游戏列表根据已记录的完成度添加染色 + 3.TODO:游戏列表隐藏已经 100% 的游戏(需要添加用户可见的开关) + */ const hdElement = document.querySelector('.hd'); if (hdElement && hdElement.textContent.trim() === '游戏列表') { - // 创建新的 span 元素 + // 添加徽章 CSS 类 + GM_addStyle(` + span.completion-badge { + background-color: rgb(5 96 175); + font-size: 11px; + color: white; + border-radius: 2px; + padding: 2px 6px; + margin-right: 4px; + font-weight: 300; + }`); + + // 背景 CSS 进度条计算,含夜间模式 + const progressPlatinumBG = (p) => `background-image: linear-gradient(90deg, rgba(200,240,255,0.6) ${p}%, rgba(200,255,250,0.15) ${p}%)`; + const progressPlatinumBGNight = (p) => `background-image: linear-gradient(90deg, rgba(200,240,255,0.15) ${p}%, rgba(200,255,250,0.05) ${p}%)`; + const progressGoldBG = (p) => `background-image: linear-gradient(90deg, rgba(220,255,220,0.8) ${p}%, rgba(220,255,220,0.15) ${p}%);`; + const progressGoldBGNight = (p) => `background-image: linear-gradient(90deg, rgba(101,159,19,0.15) ${p}%, rgba(101,159,19,0.05) ${p}%);`; + + // 获取游戏列表下所有游戏的 DOM 元素指针 + const tdElements = document.querySelectorAll('table.list tbody > tr'); + + // 根据已保存的完成度添加染色 + const personalGameCompletions = GM_getValue('personalGameCompletions', []); + + tdElements.forEach((tr) => { + const gameID = tr.getAttribute('id') || 0; + const thisGameCompletion = personalGameCompletions.find((item) => item[0] === gameID); + // if game hase platinum 由于个人页面的白金判断是记录的个人完成度,这里需要判断游戏本身是否有白金 + const gameHasPlatinum = tr.querySelector('td.pd10 > .meta > em.text-platinum').textContent === '白1'; + + if (thisGameCompletion) { + if (gameHasPlatinum && settings.nightMode) { tr.setAttribute('style', progressPlatinumBGNight(thisGameCompletion[1])); } + if (gameHasPlatinum && !settings.nightMode) { tr.setAttribute('style', progressPlatinumBG(thisGameCompletion[1])); } + if (!gameHasPlatinum && settings.nightMode) { tr.setAttribute('style', progressGoldBGNight(thisGameCompletion[1])); } + if (!gameHasPlatinum && !settings.nightMode) { tr.setAttribute('style', progressGoldBG(thisGameCompletion[1])); } + // 添加进度徽章 + const gameText = tr.querySelector('td.pd10 > p > a'); + if (gameText) { + const completion = thisGameCompletion[1]; + const completionBadge = document.createElement('span'); + completionBadge.className = 'completion-badge'; + completionBadge.textContent = `${completion}%`; + completionBadge.title = '奖杯完成度'; + gameText.parentNode.insertBefore(completionBadge, gameText); + } + } + }); + + // 添加按难度排列按钮 const spanElement = document.createElement('span'); spanElement.className = 'btn'; spanElement.textContent = '按难度排列'; - // 添加 span 元素到 .hd 元素中 + // 添加 span 元素并设置样式 hdElement.appendChild(spanElement); - // 添加样式使 span 右对齐 const style = document.createElement('style'); style.textContent = ` .hd { @@ -427,12 +478,7 @@ justify-content: space-between; align-items: center; } - .hd span { - margin-top: 0px; - } - .btn { - cursor: pointer; - } + .hd span { margin-top: 0px; } `; document.head.appendChild(style); @@ -441,11 +487,10 @@ // 为 span 元素添加点击排序功能 spanElement.addEventListener('click', () => { - const tdElements = document.querySelectorAll('table.list tbody > tr'); - const tdArray = Array.from(tdElements).map((td) => { - const valueElement = td.querySelector('td.twoge > em'); + const tdArray = Array.from(tdElements).map((tr) => { + const valueElement = tr.querySelector('td.twoge > em'); const value = valueElement ? parseFloat(valueElement.textContent) : null; - return { td, value }; + return { tr, value }; }); // 根据当前的排序顺序进行排序 @@ -458,7 +503,7 @@ const tbody = document.querySelector('table.list tbody'); tbody.innerHTML = ''; tdArray.forEach((item) => { - tbody.appendChild(item.td); + tbody.appendChild(item.tr); }); // 切换排序顺序 @@ -527,9 +572,59 @@ }`, ); + /* + 在 LocatStorage 中保存个人游戏完成度函数 + 添加于 /psnid\/[A-Za-z0-9_-]+\/?$/ 页面,以及该页自动翻页函数内部 + */ + + const savePersonalGameCompletions = (configifneeded) => { + // if GM_setValue && GM_getValue is enabled + const thisFeatureEnabled = (configifneeded || true) && (typeof GM_setValue === 'function' && typeof GM_getValue === 'function'); + + if (thisFeatureEnabled) { + // 获得当前页的游戏完成度 + const tdElements = document.querySelectorAll('table.list tbody > tr'); + const personalGameCompletions = Array.from(tdElements).map((tr) => { + const completionElement = tr.querySelector('div.progress > div'); + const completion = completionElement ? parseFloat(completionElement.textContent) : 0; + const platinumElement = tr.querySelector('span.text-platinum'); + const platinum = platinumElement ? platinumElement.textContent === '白1' : false; + const gameIDElement = tr.querySelector('a'); + const gameID = gameIDElement.href.match(/\/psngame\/(\d+)/)[1]; + return [gameID, completion, platinum]; + }); + + // 读取已保存的历史 + const history = GM_getValue('personalGameCompletions', []); + + // 用当前覆盖历史 + personalGameCompletions.forEach((currentItem) => { + const index = history.findIndex((historyItem) => historyItem[0] === currentItem[0]); + if (index !== -1) { + history[index] = currentItem; + } else { + history.push(currentItem); + } + }); + + // 保存更新后的历史记录 + GM_setValue('personalGameCompletions', history); + // console.log(GM_getValue('personalGameCompletions')) + return true; + } + return false; + }; + + // 在个人页面或个人游戏列表页更新数据 + if ( + /psnid\/[A-Za-z0-9_-]+\/?$/.test(window.location.href) || /psnid\/[A-Za-z0-9_-]+\/psngame\/?/.test(window.location.href) + ) { + savePersonalGameCompletions(); + } + if ( /psnid\/[A-Za-z0-9_-]+\/?$/.test(window.location.href) - && $('tbody').length > 2 + && $('tbody').length > 2 ) { const windowLocationHref = window.location.href.replace(/\/$/g, ''); // 功能0-7:个人主页下显示所有游戏 @@ -541,9 +636,9 @@ $(window).scroll(function () { if ( $(this).scrollTop() + $(window).height() + 700 - >= $(document).height() - && $(this).scrollTop() > 700 - && isbool2 === true + >= $(document).height() + && $(this).scrollTop() > 700 + && isbool2 === true ) { isbool2 = false; const gamePage = `${windowLocationHref}/psngame?page=${gamePageIndex}`; @@ -559,6 +654,9 @@ $('tbody > tr:last').after(nextGameContent); isbool2 = true; gamePageIndex += 1; + + // 同步更新个人游戏完成度 + savePersonalGameCompletions(); } else { $('#loadingMessage').text('没有更多游戏了...'); } @@ -659,7 +757,7 @@ if ( /(gene|trade|topic)\//.test(window.location.href) - && !/comment/.test(window.location.href) + && !/comment/.test(window.location.href) ) { // 获取楼主ID const authorId = $('.title2').text(); @@ -876,9 +974,9 @@ $('div.meta').each((index, element) => { const replyCount = $(element).text().split(/(\d+)/); if (Number(replyCount[replyCount.length - 2]) > settings.hotTagThreshold - && replyCount[replyCount.length - 1].match('评论|答案|回复') - && replyCount[replyCount.length - 1].match('评论|答案|回复').index > -1 - && $(element).children('a#hot').length === 0 + && replyCount[replyCount.length - 1].match('评论|答案|回复') + && replyCount[replyCount.length - 1].match('评论|答案|回复').index > -1 + && $(element).children('a#hot').length === 0 ) { const tagBackgroundColor = $('body.bg').css('background-color'); $(element) @@ -1096,12 +1194,12 @@ const filterBlockWorld = () => { const windowHref = window.location.href; if (windowHref.indexOf('gene') > -1 // 机因回复 - || windowHref.indexOf('topic') > -1 // 主帖回复 - || windowHref.indexOf('trophy') > -1 // 奖杯TIPS - || windowHref.indexOf('qa') > -1 // 问答回复 - || windowHref.indexOf('trade') > -1 // 交易回复 - || windowHref.match(/\/battle\/[1-9][0-9]+/) !== null // 约战回复 - || windowHref.match(/\/psnid\/[^/]+\/comment/) !== null // 个人主页留言 + || windowHref.indexOf('topic') > -1 // 主帖回复 + || windowHref.indexOf('trophy') > -1 // 奖杯TIPS + || windowHref.indexOf('qa') > -1 // 问答回复 + || windowHref.indexOf('trade') > -1 // 交易回复 + || windowHref.match(/\/battle\/[1-9][0-9]+/) !== null // 约战回复 + || windowHref.match(/\/psnid\/[^/]+\/comment/) !== null // 个人主页留言 ) { FilterWordRegular('div.ml64>div.content.pb10'); } @@ -1350,13 +1448,13 @@ let isbool = true; // 触发开关,防止多次调用事件 let autoPagingLimitCount = 0; $(window).scroll(function () { - // 当内容滚动到底部时加载新的内容 + // 当内容滚动到底部时加载新的内容 if ( $(this).scrollTop() + $(window).height() + 700 - >= $(document).height() - && $(this).scrollTop() > 700 - && isbool === true - && autoPagingLimitCount < settings.autoPaging + >= $(document).height() + && $(this).scrollTop() > 700 + && isbool === true + && autoPagingLimitCount < settings.autoPaging ) { isbool = false; // 获取下一页页码和链接 @@ -1669,7 +1767,7 @@ }; const CNY = price.map((item) => ( Number(item.replace(regionCurrency[region][0], '')) - * regionCurrency[region][1] + * regionCurrency[region][1] )); // 整块增加的价格表示 const addCNYPriceBlock = [ @@ -1895,7 +1993,7 @@ // 页面:数折 > 商品页 if ( /\/dd\//.test(window.location.href) - || /game\/[0-9]+\/dd$/.test(window.location.href) + || /game\/[0-9]+\/dd$/.test(window.location.href) ) { repeatUntilSuccessful(() => { if (httpCSSFixed()) { @@ -2297,9 +2395,9 @@ // 功能3-1:游戏奖杯界面可视化 if ( /psngame\//.test(window.location.href) - && /^(?!.*comment|.*rank|.*battle|.*gamelist|.*topic|.*qa)/.test( - window.location.href, - ) + && /^(?!.*comment|.*rank|.*battle|.*gamelist|.*topic|.*qa)/.test( + window.location.href, + ) ) { $('.box.pd10').append('
'); repeatUntilSuccessful(() => { @@ -2393,7 +2491,7 @@ // 进入游戏页默认查看我自己的奖杯 if ( window.location.href.match(/psngame\/\d+($|\/$)|(#\d+($|\/$))/) - && !/psnid/.test(window.location.href) + && !/psnid/.test(window.location.href) ) { // 检查游戏页 window.onpageshow = (e) => { @@ -3078,7 +3176,7 @@ return ( startOfYear.getTime() + (-((startOfYear.getUTCDay() || 7) - 1) - + (7 * (week - 1) + (day - 1))) * 86400000/* milliseconds of a day */ + + (7 * (week - 1) + (day - 1))) * 86400000/* milliseconds of a day */ ); }; const weekDifference = (date1, date2) => {