标记已访问的帖子标题,支持搜同网和 TT1069 论坛,在任何排序方式下生效,标记放文字标题左边。
// ==UserScript==
// @name Multi Forum Read Marker (Soutong + TT1069)
// @namespace https://felixchristian.dev/userscripts/multi-forum-read-marker
// @version 1.2.1
// @description 标记已访问的帖子标题,支持搜同网和 TT1069 论坛,在任何排序方式下生效,标记放文字标题左边。
// @author FelixChristian
// @license MIT
// @match https://soutong.men/forum.php?mod=forumdisplay&fid=*
// @match https://soutong.men/forum.php?mod=viewthread&tid=*
// @match https://www.tt1069.com/bbs/thread-*-*-*.html
// @match https://www.tt1069.com/bbs/forum-*-*.html
// @match https://www.tt1069.com/bbs/forum.php?mod=forumdisplay&fid=*
// @match https://www.tt1069.com/bbs/forum.php?mod=forumdisplay&fid=*&*
// @match https://www.tt1069.com/bbs/forum.php?mod=viewthread&tid=*
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
(function () {
'use strict';
const HOST = location.hostname;
const isSoutong = HOST.includes('soutong.men');
const isTT1069 = HOST.includes('tt1069.com');
const STORAGE_KEY = 'visitedTids';
let visitedTids = GM_getValue(STORAGE_KEY, {});
// 获取当前帖子 TID
function getCurrentTid() {
if (location.href.includes('tid=')) {
const url = new URL(location.href);
return url.searchParams.get('tid');
}
const match = location.href.match(/thread-(\d+)-/);
return match ? match[1] : null;
}
function recordTidVisit(tid) {
if (tid) {
visitedTids[tid] = Date.now();
GM_setValue(STORAGE_KEY, visitedTids);
}
}
// 标记已访问帖子
function markReadThreads() {
const threadLinks = document.querySelectorAll('a.s.xst');
threadLinks.forEach(link => {
let tid = null;
try {
const fullUrl = new URL(link.href, location.origin);
tid = fullUrl.searchParams.get('tid');
if (!tid) {
const match = link.href.match(/thread-(\d+)-/);
tid = match ? match[1] : null;
}
} catch (e) {
return;
}
if (tid && visitedTids[tid] && !link.dataset.markedVisited) {
const tag = document.createElement('span');
tag.textContent = '[已读] ';
tag.style.color = 'red';
tag.style.fontWeight = 'bold';
tag.style.marginRight = '4px';
link.insertBefore(tag, link.firstChild);
link.dataset.markedVisited = 'true';
}
});
}
const isViewThread = location.href.includes('mod=viewthread') || /thread-\d+-/.test(location.pathname);
const isForumDisplay = location.href.includes('mod=forumdisplay') || /forum-\d+-\d+\.html/.test(location.pathname);
if (isViewThread) {
const tid = getCurrentTid();
recordTidVisit(tid);
}
if (isForumDisplay) {
window.addEventListener('load', markReadThreads);
const observer = new MutationObserver(markReadThreads);
observer.observe(document.body, { childList: true, subtree: true });
}
})();