// ==UserScript== // @name NGA优化摸鱼体验-帖子浏览记录 // @namespace https://github.com/kisshang1993/NGA-BBS-Script/tree/master/plugins/PostReadingRecord // @version 1.1.1 // @author HLD // @description 记录帖子的阅读状态,着色以阅读帖子标题,跟踪后续新回复数量 // @license MIT // @match *://bbs.nga.cn/* // @match *://ngabbs.com/* // @match *://nga.178.com/* // @match *://g.nga.cn/* // @grant unsafeWindow // @run-at document-start // @inject-into content // @downloadURL https://update.greasyfork.icu/scripts/478054/NGA%E4%BC%98%E5%8C%96%E6%91%B8%E9%B1%BC%E4%BD%93%E9%AA%8C-%E5%B8%96%E5%AD%90%E6%B5%8F%E8%A7%88%E8%AE%B0%E5%BD%95.user.js // @updateURL https://update.greasyfork.icu/scripts/478054/NGA%E4%BC%98%E5%8C%96%E6%91%B8%E9%B1%BC%E4%BD%93%E9%AA%8C-%E5%B8%96%E5%AD%90%E6%B5%8F%E8%A7%88%E8%AE%B0%E5%BD%95.meta.js // ==/UserScript== (function (registerPlugin) { 'use strict'; const PostReadingRecord = { name: 'PostReadingRecord', title: '帖子浏览记录', desc: '记录帖子的阅读状态,着色以阅读帖子标题,跟踪后续新回复数量', settings: [{ key: 'markColor', title: '标记着色颜色', default: '#000000' }, { key: 'markOpacity', title: '颜色不透明度', desc: '0~100之间的数字,0为完全透明,100为完全不透明', default: 50 }, { key: 'replyCountEnable', title: '显示新增回复', default: true }, { key: 'replyCountStyle', title: '新增回复样式', default: 'tag', options: [{ label: '绿色标签', value: 'tag' }, { label: '极简文本', value: 'text' }] }, { key: 'expireDays', title: '记录过期天数', desc: '记录帖子状态的数据过期天数,数据过期后将会自动删除状态数据,用于释放储存空间,-1为永不过期', default: 90 }], buttons: [{ title: '清理所有记录数据', action: 'cleanLocalData' }], store: null, beforeSaveSettingFunc(settings) { const $ = this.mainScript.libs.$ if (!$.isNumeric(settings['markOpacity'])) { return '颜色不透明度必须是个数字' } if (!$.isNumeric(settings['expireDays'])) { return '记录过期天数必须是个数字' } }, initFunc() { const $ = this.mainScript.libs.$ // 创建储存实例 this.store = this.mainScript.createStorageInstance('NGA_BBS_Script__PostReadingRecord') // 调用标准模块authorMark初始化颜色选择器 this.mainScript.getModule('AuthorMark').initSpectrum(`[plugin-id="${this.pluginID}"][plugin-setting-key="markColor"]`) // 初始化的时候根据设置清理超过一定时间的数据,避免无限增长数据 const currentTime = Math.ceil(new Date().getTime() / 1000) const expireTime = this.pluginSettings['expireDays'] == -1 ? -1 : this.pluginSettings['expireDays'] * 24 * 60 * 60 if (expireTime > -1) { let removedCount = 0 this.store.iterate((value, key) => { if (currentTime - value.lastReadTime >= expireTime) { this.store.removeItem(key) removedCount += 1 } }) .then(() => { this.mainScript.printLog(`${this.title}: 已清除${removedCount}条超期(>${this.pluginSettings['expireDays']}d)数据`) }) .catch(err => { console.error(`${this.title}清除超期数据失败,错误原因:`, err) }) } // 自动记录阅读位置 $(window).on('scroll resize', () => { if (!this.mainScript.isForms()) return this.calcReadCount() }) // 绑定继续阅览事件 $(document).on('click', '.hld__unread-label', function() { unsafeWindow.__LOADERREAD.go(1, { fromUrl: window.location.href, url: $(this).attr('data-continueurl') }) }) }, async renderThreadsFunc($el) { const markStyle = `color: ${this.pluginSettings['markColor']}; opacity: ${parseInt(this.pluginSettings['markOpacity']) / 100};` // 提取数据 const $a = $el.find('.c1 > a') const tid = this.mainScript.getModule('AuthorMark').getQueryString('tid', $a.attr('href')) const currentCount = parseInt($a.text()) if (!tid || isNaN(currentCount)) return // 检查并标记已读帖子 const record = await this.store.getItem(tid) const recordCount = record?.lastReadCount || -1 if (record) { $el.find('.c2 > a').attr('style', markStyle) } if (this.pluginSettings['replyCountEnable'] && recordCount > -1 && currentCount > recordCount) { const url = `https://${window.location.host}${$a.attr('href')}&page=${record.lastReadPage}#anchorid=${record.lastReadCount}` $el.find('.c2 > span[id^=t_pc]').append(` `) } }, renderFormsFunc($el) { if ($el.index() == 0) { this.calcReadCount() } }, renderAlwaysFunc() { if (!this.mainScript.isForms()) return const $ = this.mainScript.libs.$ const [originalURL, anchorid] = window.location.href.split('#anchorid=') if (anchorid && !isNaN(parseInt(anchorid))) { // 滚动至锚点处 for (let i=parseInt(anchorid)-1;i>0;i--) { const $posterinfo = $(`#post1strow${anchorid}`) if ($posterinfo.length > 0) { $posterinfo.parents('table.forumbox.postbox') const $parentrow = $posterinfo.parents('table.forumbox.postbox') if (!$parentrow.next().hasClass('hld__readnow')) { $parentrow.after(`