pt站选种插件

在表格第一行插入一个按钮并通过右键弹出下拉框实现全选、取消全选和复制URL的功能,左键直接复制所有选中的URL

当前为 2025-06-27 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         pt站选种插件
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  在表格第一行插入一个按钮并通过右键弹出下拉框实现全选、取消全选和复制URL的功能,左键直接复制所有选中的URL
// @author       joshua2117
// @match        https://audiences.me/*
// @match        https://hhanclub.top/*
// @match        https://ptchdbits.co/*
// @match        https://next.m-team.cc/*
// @match        https://zmpt.cc/*
// @match        https://sewerpt.com/*
// @match        https://springsunday.net/*
// @match        https://www.hddolby.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 站点配置
    const siteConfigs = {
        观众: {
            rowSelector: 'table.torrents-table > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('.torrentname table tbody tr:first-child td:nth-child(2) img.download');
                if (downloadImg) {
                    const aTag = downloadImg.closest('a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/id=(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                const response = await fetch(`https://audiences.me/details.php?id=${id}`);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.text();
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(text, 'text/html');
                                const bTag = doc.getElementById('torrent_dl_url');
                                if (bTag) {
                                    const dlUrlATag = bTag.querySelector('a');
                                    if (dlUrlATag) {
                                        return dlUrlATag.href;
                                    } else {
                                        console.log('A 标签未找到在 torrent_dl_url b 标签内,ID:', id);
                                    }
                                } else {
                                    console.log('torrent_dl_url b 标签未找到,ID:', id);
                                }
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                } else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        },
        憨憨: {
            rowSelector: '.torrent-table-sub-info',
            urlFetcher: async function(row) {
                const manageDiv = row.querySelector('div.torrent-manage'); // 获取当前行下的 class 为 torrent-manage 的 div 标签
                if (manageDiv) {
                    const downloadLink = manageDiv.querySelectorAll('a')[1];
                    if (downloadLink) {
                        return downloadLink.href;
                    } else {
                        console.log('下载链接未找到,在行:', row);
                    }
                } else {
                    console.log('torrent-manage div 未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                const xpath = '//*[@id="mainContent"]/div/div[2]/div[1]/div';
                const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                const element = result.singleNodeValue;
                return element;
            },
            skipFirstRowForCheckboxes: false
        },
        彩虹岛: {
            rowSelector: '.torrents > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('.torrentname > tbody > tr:first-child > td:nth-child(2) > a');
                if (downloadImg) {
                    const aTag = downloadImg.closest('a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/id=(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                const response = await fetch(`https://ptchdbits.co/details.php?id=${id}`);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.text();
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(text, 'text/html');
                                const bTag = doc.getElementById('outer');
                                if (bTag) {
                                    const dlUrlATag = bTag.querySelectorAll('.details >tbody >tr > .rowfollow >a')[4]
                                    if (dlUrlATag) {
                                        return dlUrlATag.href;
                                    } else {
                                        console.log('A 标签未找到在 torrent_dl_url b 标签内,ID:', id);
                                    }
                                } else {
                                    console.log('torrent_dl_url b 标签未找到,ID:', id);
                                }
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                } else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        },
        馒头: {
            isDelay: true,
            rowSelector: '.ant-spin-container > div > table > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('td:nth-child(2) > div > div:nth-child(2) > div');
                if (downloadImg) {
                    const aTag = downloadImg.querySelector('td:nth-child(2) > div > div:nth-child(2) > div >a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                var apiUrls = (() => {
                                    let urls = [];
                                    try {
                                        urls = _APIHOSTS.map((u) => new URL(u));
                                    } catch (e) {
                                        console.warn("get _APIHOSTS error:", e);
                                    }
                                    urls.push(new URL(location.origin + "/api"));
                                    return urls;
                                })();
                                const apiUrl = localStorage.getItem("apiHost") || apiUrls[Math.random() * apiUrls.length | 0].href;
                                const f = new FormData();
                                f.set("id", id);
                                const opts ={
                                    method: "POST",
                                    headers: {
                                        authorization: localStorage.getItem("auth"),
                                        visitorId: localStorage.getItem("visitorId"),
                                        did: localStorage.getItem("did"),
                                        ts: Math.floor(Date.now() / 1e3)
                                    }
                                }
                                opts.body = f;
                                const response = await fetch(apiUrl + "/torrent/genDlToken",opts);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.json();
                                console.log('接口返回数据:',text)
                                return text.data
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                }else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('td');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return document.querySelector('.ant-spin-container > div > table > thead > tr');
            },
            skipFirstRowForCheckboxes: false
        },
        织梦: {
            rowSelector: '.torrents > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('td:nth-child(3) img.download');
                if (downloadImg) {
                    const aTag = downloadImg.closest('a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/id=(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                const response = await fetch(`https://zmpt.cc/details.php?id=${id}`);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.text();
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(text, 'text/html');
                                const bTag = doc.getElementById('content');
                                if (bTag) {
                                    console.log(bTag);
                                    return bTag.textContent.trim();
                                } else {
                                    console.log('torrent_dl_url b 标签未找到,ID:', id);
                                }
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                } else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        },
        下水道: {
            rowSelector: '.torrents > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('td:nth-child(3) img.download');
                if (downloadImg) {
                    const aTag = downloadImg.closest('a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/id=(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                const response = await fetch(`https://sewerpt.com/details.php?id=${id}`);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.text();
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(text, 'text/html');
                                const bTag = doc.getElementById('content');
                                if (bTag) {
                                    console.log(bTag);
                                    return bTag.textContent.trim();
                                } else {
                                    console.log('torrent_dl_url b 标签未找到,ID:', id);
                                }
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                } else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        },
        高清杜比: {
            rowSelector: '.torrents > tbody > tr',
            urlFetcher: async function(row) {
                const downloadImg = row.querySelector('td:nth-child(3) img.download');
                if (downloadImg) {
                    const aTag = downloadImg.closest('a');
                    if (aTag) {
                        const idMatch = aTag.href.match(/id=(\d+)/);
                        if (idMatch && idMatch[1]) {
                            const id = idMatch[1];
                            try {
                                const response = await fetch(`https://www.hddolby.com/details.php?id=${id}`);
                                if (!response.ok) {
                                    throw new Error(`Network response was not ok: ${response.statusText}`);
                                }
                                const text = await response.text();
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(text, 'text/html');
                                const bTag = doc.getElementById('content');
                                if (bTag) {
                                    console.log(bTag);
                                    return bTag.textContent.trim();
                                } else {
                                    console.log('torrent_dl_url b 标签未找到,ID:', id);
                                }
                            } catch (err) {
                                console.error('获取详情页失败,ID:', id, err);
                            }
                        } else {
                            console.log('ID 未找到在 href 中:', aTag.href);
                        }
                    } else {
                        console.log('下载链接 A 标签未找到,在行:', row);
                    }
                } else {
                    console.log('下载图片未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        },
        不可说: {
            rowSelector: '.torrents > tbody > tr',
            urlFetcher: async function(row) {
                const manageDiv = row.querySelector('.torrentname >tbody >tr >td:nth-child(2) >div >a');
                if (manageDiv) {

                        return manageDiv.href;

                } else {
                    console.log('torrent-manage div 未找到,在行:', row);
                }
                return null;
            },
            insertCheckbox: function(row) {
                const checkboxCell = document.createElement('div');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkboxCell.appendChild(checkbox);
                row.insertBefore(checkboxCell, row.firstElementChild);
            },
            getHeaderRow: function(rows) {
                return rows[0];
            },
            skipFirstRowForCheckboxes: true
        }
    };

    // 获取当前站点配置
    function getCurrentSiteConfig() {
        const currentUrl = window.location.href;
        if (currentUrl.includes('audiences.me')) {
            return siteConfigs['观众'];
        } else if (currentUrl.includes('hhanclub.top')) {
            return siteConfigs['憨憨'];
        } else if (currentUrl.includes('ptchdbits.co')) {
            return siteConfigs['彩虹岛'];
        }else if (currentUrl.includes('next.m-team.cc')) {
            return siteConfigs['馒头'];
        }else if (currentUrl.includes('zmpt.cc')) {
            return siteConfigs['织梦'];
        }else if (currentUrl.includes('sewerpt.com')) {
            return siteConfigs['下水道'];
        }else if (currentUrl.includes('springsunday.net')) {
            return siteConfigs['不可说'];
        }else if (currentUrl.includes('www.hddolby.com')) {
            return siteConfigs['高清杜比'];
        }
        return null;
    }

    // 获取表格行
    function getTableRows(config) {
        return document.querySelectorAll(config.rowSelector);
    }

    // 创建自定义弹窗
    function createCustomAlert(message) {
        const alertBox = document.createElement('div');
        alertBox.style.position = 'fixed';
        alertBox.style.top = '50%';
        alertBox.style.left = '50%';
        alertBox.style.transform = 'translate(-50%, -50%)';
        alertBox.style.backgroundColor = 'white';
        alertBox.style.border = '1px solid #ccc';
        alertBox.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
        alertBox.style.padding = '20px';
        alertBox.style.zIndex = '9999';
        alertBox.style.fontSize = '16px';
        alertBox.style.fontFamily = 'Arial, sans-serif';
        alertBox.style.color = '#333';
        alertBox.style.borderRadius = '5px';

        const messageText = document.createElement('span');
        messageText.textContent = message;

        const closeButton = document.createElement('button');
        closeButton.textContent = '关闭';
        closeButton.style.marginLeft = '10px';
        closeButton.style.padding = '5px 10px';
        closeButton.style.border = 'none';
        closeButton.style.borderRadius = '3px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.backgroundColor = '#007bff';
        closeButton.style.color = 'white';
        closeButton.style.transition = 'background-color 0.3s ease';
        closeButton.addEventListener('mouseover', () => {
            closeButton.style.backgroundColor = '#0056b3';
        });
        closeButton.addEventListener('mouseout', () => {
            closeButton.style.backgroundColor = '#007bff';
        });
        closeButton.addEventListener('click', () => {
            document.body.removeChild(alertBox);
        });

        alertBox.appendChild(messageText);
        alertBox.appendChild(closeButton);

        document.body.appendChild(alertBox);

        setTimeout(() => {
            document.body.removeChild(alertBox);
        }, 3000); // 自动关闭弹窗,3秒后消失
    }

    // 初始化功能
    function initFeatures() {
        const config = getCurrentSiteConfig();
        if (!config) {
            console.log('不支持的站点');
            return;
        }

        const rows = getTableRows(config);

        if (rows.length > 0) {
            // 创建一个按钮
            const headerRow = config.getHeaderRow(rows);
            if (headerRow) {
                const selectCell = document.createElement('th');
                selectCell.style.width = '30px';
                const dropdownButton = document.createElement('button');
                dropdownButton.textContent = '操作';
                dropdownButton.style.padding = '5px 10px';
                dropdownButton.style.border = 'none';
                dropdownButton.style.borderRadius = '3px';
                dropdownButton.style.cursor = 'pointer';
                dropdownButton.style.backgroundColor = '#007bff';
                dropdownButton.style.color = 'white';

                dropdownButton.style.transition = 'background-color 0.3s ease';
                dropdownButton.addEventListener('mouseover', () => {
                    dropdownButton.style.backgroundColor = '#0056b3';
                });
                dropdownButton.addEventListener('mouseout', () => {
                    dropdownButton.style.backgroundColor = '#007bff';
                });

                // 创建下拉菜单
                const dropdownMenu = document.createElement('div');
                dropdownMenu.style.position = 'fixed'; // 使用 fixed 定位
                dropdownMenu.style.display = 'none';
                dropdownMenu.style.backgroundColor = 'white';
                dropdownMenu.style.border = '1px solid #ccc';
                dropdownMenu.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
                dropdownMenu.style.zIndex = '9999'; // 设置更高的 z-index 确保在最顶层

                const selectAllItem = document.createElement('div');
                selectAllItem.textContent = '全选';
                selectAllItem.style.padding = '5px 10px';
                selectAllItem.style.cursor = 'pointer';
                selectAllItem.addEventListener('click', () => {
                    rows.forEach((row, index) => {
                        if (index !== 0 || !config.skipFirstRowForCheckboxes) { // 根据配置决定是否跳过第一行
                            const checkbox = row.querySelector('input[type="checkbox"]');
                            if (checkbox) {
                                checkbox.checked = true;
                            }
                        }
                    });
                    dropdownMenu.style.display = 'none';
                });

                const deselectAllItem = document.createElement('div');
                deselectAllItem.textContent = '取消全选';
                deselectAllItem.style.padding = '5px 10px';
                deselectAllItem.style.cursor = 'pointer';
                deselectAllItem.addEventListener('click', () => {
                    rows.forEach((row, index) => {
                        if (index !== 0 || !config.skipFirstRowForCheckboxes) { // 根据配置决定是否跳过第一行
                            const checkbox = row.querySelector('input[type="checkbox"]');
                            if (checkbox) {
                                checkbox.checked = false;
                            }
                        }
                    });
                    dropdownMenu.style.display = 'none';
                });

                const copyButtonItem = document.createElement('div');
                copyButtonItem.textContent = '复制URL';
                copyButtonItem.style.padding = '5px 10px';
                copyButtonItem.style.cursor = 'pointer';
                copyButtonItem.addEventListener('click', async () => {
                    await performCopyUrls();
                    dropdownMenu.style.display = 'none';
                });

                dropdownMenu.appendChild(selectAllItem);
                dropdownMenu.appendChild(deselectAllItem);
                dropdownMenu.appendChild(copyButtonItem);

                // 将按钮和下拉菜单添加到表头第一列
                selectCell.appendChild(dropdownButton);
                selectCell.appendChild(dropdownMenu);
                headerRow.insertBefore(selectCell, headerRow.firstElementChild);

                // 显示和隐藏下拉菜单
                dropdownButton.addEventListener('contextmenu', (e) => {
                    e.preventDefault();
                    showDropdownMenu(e);
                });

                document.addEventListener('click', (e) => {
                    if (!dropdownMenu.contains(e.target)) {
                        dropdownMenu.style.display = 'none';
                    }
                });

                // 左键点击按钮直接复制所有选中的URL
                dropdownButton.addEventListener('click', async (e) => {
                    if (e.button === 0) { // 左键点击
                        await performCopyUrls();
                    }
                });

                // 复制URL的函数
                async function performCopyUrls() {
                    const checkedRows = Array.from(rows).filter((row, index) => {
                        if (index === 0 && config.skipFirstRowForCheckboxes) {
                            return false; // 跳过第一行
                        }
                        const checkbox = row.querySelector('input[type="checkbox"]');
                        return checkbox && checkbox.checked;
                    });
                    let urls = [];
                    let processedCount = 0;

                    // 禁用按钮并更改文本和样式
                    dropdownButton.textContent = `正在复制... (${processedCount}/${checkedRows.length})`;
                    dropdownButton.style.backgroundColor = '#cccccc';
                    dropdownButton.style.pointerEvents = 'none'; // 禁用点击事件

                    for (const [index, row] of checkedRows.entries()) {
                        const url = await config.urlFetcher(row);
                        if (url) {
                            urls.push(url);
                        }
                        processedCount++;
                        dropdownButton.textContent = `正在复制... (${processedCount}/${checkedRows.length})`;
                    }

                    if (urls.length > 0) {
                        navigator.clipboard.writeText(urls.join('\n'))
                            .then(() => {
                                console.log('URL 已复制到剪贴板:', urls.join('\n'));
                                createCustomAlert('已复制完成');
                            })
                            .catch(err => {
                                console.error('复制 URL 失败:', err);
                            });
                    } else {
                        console.log('没有选择要复制的 URL。');
                    }

                    // 恢复按钮的状态
                    dropdownButton.textContent = '操作';
                    dropdownButton.style.backgroundColor = '#007bff';
                    dropdownButton.style.pointerEvents = 'auto'; // 启用点击事件
                }

                // 显示下拉菜单的函数
                function showDropdownMenu(event) {
                    const rect = event.target.getBoundingClientRect();
                    dropdownMenu.style.left = `${rect.right}px`; // 出现在按钮右侧
                    dropdownMenu.style.top = `${rect.bottom}px`; // 出现在按钮下方
                    dropdownMenu.style.display = 'block';
                }
            }

            // 在每个<tr>元素的第一<td>前插入复选框(根据配置决定是否跳过第一行)
            rows.forEach((row, index) => {
                if (!(index === 0 && config.skipFirstRowForCheckboxes)) { // 根据配置决定是否跳过第一行
                    config.insertCheckbox(row);
                }
            });
        } else {
            console.log('表格未找到。');
        }
    }

    function waitForElement(selector, callback) {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach(() => {
                const element = document.querySelector(selector);
                if (element) {
                    observer.disconnect();
                    callback(element);
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
    }


    const siteconfig = getCurrentSiteConfig();
    let isInit = false;
    if(siteconfig.isDelay){
        waitForElement(siteconfig.rowSelector, function (el) {
            if(!isInit){
                console.log('表格元素已加载:', el);
                // 初始化功能
                setTimeout(initFeatures, 1000); // 可选延迟
                isInit = true;
            }
        });
    }else{
        // 初始化功能
        initFeatures();
    }

})();