您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
论坛列表显示图片,支持phpwind和discuz
当前为
// ==UserScript== // @name 论坛列表显示图片 // @namespace form_show_images_in_list // @version 1.1 // @description 论坛列表显示图片,支持phpwind和discuz // @license MIT // @author Gloduck // @match */forum.php?mod=forumdisplay* // @match */thread.php?fid* // @grant GM_xmlhttpRequest // @grant GM_addStyle // ==/UserScript== (function () { 'use strict'; GM_addStyle(` .zoomable-image { cursor: pointer; } .zoomable-image.zoomed { position: fixed; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; background: rgba(0, 0, 0, 0.9); z-index: 9999; } `); // todo 添加extend继承的功能 let settings = [ { name: "discuz", articleListSelector: 'tbody[id^="normalthread_"]', postContentSelector: 'td[id^="postmessage_"]', ignoreImageRegs: [ "/uc_server/images/*", "static/image/*", "/uc_server/data/avatar/*" ], maxShowLimit: 3, lazyLoad: true, postImageLinkCallback: function (element) { let fileLink = element.getAttribute('file'); if (fileLink) { return fileLink; } return element.getAttribute('src'); }, initElementDecorator: function (element) { let tbody = document.createElement("tbody"); let tr = document.createElement("tr"); tr.appendChild(element); tbody.appendChild(tr); return tbody; } }, { name: "phpwind", articleListSelector: '#ajaxtable tbody:last-of-type tr[align=center]', postContentSelector: '#read_tpc', ignoreImageRegs: [], maxShowLimit: 3, lazyLoad: true, postImageLinkCallback: function (element) { return element.getAttribute('src'); }, initElementDecorator: function (element) { let tr = document.createElement("tr"); tr.align = "center"; let td = document.createElement("td"); td.colSpan = 5; tr.appendChild(td); td.appendChild(element); return tr; } } ] let urlMatchers = [ { name: "discuz", urlMatch: [ "forum\\.php\\?mod=forumdisplay" ] }, { name: "phpwind", urlMatch: [ "thread\\.php\\?fid" ] } ] activeByUrl(); function activeByUrl() { let activeSetting = ""; for (let urlMatcher of urlMatchers) { let urlRegs = regStrToReg(urlMatcher.urlMatch); if (checkRegMatchStr(urlRegs, window.location.href)) { activeSetting = urlMatcher.name; break; } } if (!activeSetting) { console.log("无法找到要激活的配置"); } else { console.log("激活的配置为:" + activeSetting); showImageInList(activeSetting); } } function showImageInList(type) { let setting = getSettingByType(type); let articleListElement = document.querySelectorAll(setting.articleListSelector); articleListElement.forEach(element => { if (setting.lazyLoad) { lazyLoadImageInList(element, setting); } else { loadImageInList(element, setting); } }) } function lazyLoadImageInList(element, setting){ // 注册(不可用)滚动事件,实现懒加载。同时通过节流来避免重复加载 window.addEventListener('scroll', throttle(function () { const targetElementRect = element.getBoundingClientRect(); if (targetElementRect.top < window.innerHeight && !element.getAttribute("imageLoad")) { handleSingleArticle(element, setting).then(toAppendElement => { if (!element.getAttribute("imageLoad")) { insertElementBelow(element, toAppendElement); element.setAttribute("imageLoad", "true"); } }) } }, 200, 500)); } function loadImageInList(element, setting){ handleSingleArticle(element, setting).then(toAppendElement => { insertElementBelow(element, toAppendElement); }) } function insertElementBelow(targetElement, newElement) { var parentElement = targetElement.parentNode; parentElement.insertBefore(newElement, targetElement.nextSibling); } function getSettingByType(type) { let setting = settings.find(value => { return value.name === type; }); if (setting == null) { throw new Error("不支持的类型"); } return setting; } /** * 处理单个文章,返回最后需要拼接的element * @param element {Element} * @returns {Promise<void>} */ async function handleSingleArticle(element, setting) { if (!element) { throw new Error("参数不能为空"); } let link = findFirstAnchorLink(element); if (!link) { throw new Error("找不到链接"); } let postResult = await httpRequest("GET", "/" + link); if (!postResult) { throw new Error("请求文章错误"); } var htmlDivElement = document.createElement("div"); // 初始化图片区域 htmlDivElement.appendChild(getImagesDiv(setting, postResult)); // todo 添加自定义元素 return setting.initElementDecorator(htmlDivElement); } function getImagesDiv(setting, content) { let images = parsePostImages(setting, content); if (setting.maxShowLimit && setting.maxShowLimit > 0) { images = images.slice(0, setting.maxShowLimit); } let imageDiv = document.createElement("div"); imageDiv.style = "display: flex;"; imageDiv.className = "image_list"; images.forEach(value => { let imgElement = document.createElement("img"); imgElement.src = value; imgElement.style = "max-width: 300px;max-height: 300px;margin-right: 10px" imageDiv.appendChild(imgElement); imgElement.addEventListener('click', function () { // 创建一个新的图片元素 var zoomedImg = document.createElement('img'); zoomedImg.src = imgElement.src; // 添加类名以应用放大样式 zoomedImg.classList.add('zoomable-image', 'zoomed'); // 点击放大的功能 zoomedImg.addEventListener('click', function () { // 移除放大的图片元素 document.body.removeChild(zoomedImg); }); // 将放大的图片元素添加到文档中 document.body.appendChild(zoomedImg); }); }) return imageDiv; } /** * * @param setting * @param postDetails {string} */ function parsePostImages(setting, postDetails) { let images = []; let content = new DOMParser().parseFromString(postDetails, "text/html"); if (!content) { return images; } let postContentSelector = setting.postContentSelector; let postContent = content.querySelector(postContentSelector); if (!postContent) { return images; } let ignoreImageRegs = regStrToReg(setting.ignoreImageRegs); let imageElements = postContent.querySelectorAll('img'); imageElements.forEach(imageElement => { let imageLink = setting.postImageLinkCallback(imageElement); if (checkRegMatchStr(ignoreImageRegs, imageLink)) { return; } images.push(imageLink); }) return images; } function findFirstAnchorLink(element) { const linkElement = element.querySelector("a"); if (linkElement) { return linkElement.getAttribute("href"); } else { const childElements = element.children; for (let i = 0; i < childElements.length; i++) { const link = findFirstAnchorLink(childElements[i]); if (link) { return link; } } } return null; } function regStrToReg(regs) { return regs.map(value => { return new RegExp(value); }); } function checkRegMatchStr(regs, content) { if (!content || !regs) { throw new Error("参数不能为空"); } for (var i = 0; i < regs.length; i++) { if (regs[i].test(content)) { return true; } } return false; } /** * 防抖 * @param func * @param wait * @param immediate * @returns {(function(): void)|*} */ function debounce(func, wait, immediate) { // 定时器变量 var timeout; return function () { // 每次触发 scroll handler 时先清除定时器 clearTimeout(timeout); // 指定 xx ms 后触发真正想进行的操作 handler timeout = setTimeout(func, wait); }; }; /** * 节流 * @param func * @param wait * @param mustRun * @returns {(function(): void)|*} */ function throttle(func, wait, mustRun) { var timeout, startTime = new Date(); return function () { var context = this, args = arguments, curTime = new Date(); clearTimeout(timeout); // 如果达到了规定的触发时间间隔,触发 handler if (curTime - startTime >= mustRun) { func.apply(context, args); startTime = curTime; // 没达到触发间隔,重新设定定时器 } else { timeout = setTimeout(func, wait); } }; }; function httpRequest(method, url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: method, url: url, onload: function (response) { resolve(response.responseText); }, onerror: function (error) { reject(error); } }); }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址