吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5516|回复: 97
收起左侧

[其他原创] 【神器分享】油猴脚本!网页元素可视化调试管家:支持 HTML 原位修改代码不用开启

    [复制链接]
29176413 发表于 2026-1-20 20:16
本帖最后由 29176413 于 2026-1-26 14:57 编辑

也就是可以根据这个工具进行拓展更多的功能,当然现在这个只是一部分功能,
可以根据这个思路做很多工具,也就是浏览器开发者模式中的那些功能都可以进行拓展,例如css查看修改等等,
完结撒花~~~~~~
我觉得去网页广告应该很管用,也实用点吧,他的规则是持久化的保存的,也就是这次去掉了广告,下次打开就没有了,当然这只是一种功能,更多的功能大家自己发掘

1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 8.jpg
核心功能介绍

- 智能元素选择 :采用类似 Chrome DevTools 的高亮遮罩,鼠标悬停即可实时锁定网页元素。
- 双重 HTML 编辑模式 :
  - 原位编辑 :直接在网页当前位置弹出输入框,像改文档一样修改 HTML 结构。
  - 弹窗编辑 :在独立的大窗口中编辑,支持 HTML 格式化预览。
- CSS 样式探针 :在弹窗编辑时,右侧会自动列出该元素匹配的所有 CSS 规则(包括内联样式和外部样式表)。
- 永久性规则管理 :
  - 隐藏与删除 :一键隐藏( display: none )或彻底移除元素,操作会自动保存。
  - 域名分组 :规则按网站域名自动分类,支持折叠/展开,管理井然有序。
- 交互式控制面板 :
  - 自由拖拽 :面板可随处停放,不遮挡视线。
  - 智能展开 :打开面板时自动定位并展开当前网站的规则列表。
操作指南

1. 开启选择模式

- 点击控制面板上的 “开启选择模式” 按钮。此时鼠标在页面上移动时,所经过的元素会被蓝色遮罩高亮显示。
- 注意 :该模式会一直保持,直到你手动点击“停止选择”或关闭面板。
2. 元素操作菜单

- 在选择模式下,对准目标元素 点击鼠标右键 ,将弹出功能菜单:
  - 隐藏元素 :将元素设为不可见(保留位置)。
  - 彻底删除 :直接从 DOM 树中移除。
  - 原位编辑 HTML :在元素位置直接开启快速编辑。
  - 弹窗编辑 HTML :开启带 CSS 预览的高级编辑器。
  - 选择父元素 :当目标太小时,可通过此项逐级向上选取更大的容器。
3. 编辑 HTML

- 保存更改 :在编辑器中修改代码后,点击 “✅ 保存” 按钮即可实时看到效果。
- 查看 CSS :在“弹窗编辑”模式下,右侧面板会显示该元素受哪些 CSS 规则影响,方便你参考样式。
4. 规则管理

- 查看规则 :在控制面板底部,点击各个域名标题即可查看已保存的屏蔽规则。
- 取消屏蔽 :点击规则右侧出现的 × 号,即可恢复被隐藏/删除的元素。
- 当前网站高亮 :当前访问的网站在列表中会以蓝色字体标注,并带有点亮图标。
快捷特性

- 最大化层级 :控制面板和遮罩层拥有最高 Z-Index,确保不会被网页原有元素遮挡。
- 边界识别 :右键菜单会自动检测屏幕边缘,防止菜单弹出在屏幕外。
- 格式化支持 :编辑器会自动对 HTML 进行缩进处理,提升阅读体验。
技术信息

- 存储机制 :使用 Tampermonkey 的 GM_setValue 存储,跨页面、跨会话持久化。
- 代码参考 :
  - 拖拽逻辑实现: makeDraggable
  - CSS 匹配引擎: getMatchedCSSRules
  - 规则列表构造: updateRulesList

代码太长放在附件中
下载:https://xbl.lanzoue.com/izNtX3gmjoch 密码:br33


[JavaScript] 纯文本查看 复制代码

(function() {
    'use strict';

    // 配置
    const CONFIG = {
        storageKey: 'element_hider_rules',
        highlightColor: '#ff0000',
        highlightBorder: '2px dashed #ff0000',
        modeIndicatorColor: '#4CAF50'
    };

    // 全局变量
    let isSelectionMode = false;
    let isMenuOpen = false;
    let isMenuHovered = false;
    let currentRules = [];
    let currentDomain = '';
    let overlay = null;
    let overlayInfo = null;

    // 初始化
    function init() {
        currentDomain = getRootDomain(window.location.hostname);
        loadRules();
        applyRules();
        createUI();
        createOverlay();
    }

    // 获取根域名
    function getRootDomain(hostname) {
        const parts = hostname.split('.');
        if (parts.length <= 2) return hostname;
        return parts.slice(-2).join('.');
    }

    // 格式化HTML
    function formatHTML(html) {
        let tab = '    ';
        let result = '';
        let indent = '';
        html.split(/>\s*</).forEach(function(element) {
            if (element.match(/^\/\w/)) {
                indent = indent.substring(tab.length);
            }
            result += indent + '<' + element + '>\r\n';
            if (element.match(/^<?\w[^>]*[^\/]$/) && !element.startsWith('input') && !element.startsWith('img') && !element.startsWith('br') && !element.startsWith('hr')) {
                indent += tab;
            }
        });
        return result.substring(1, result.length - 3);
    }

    // 创建HTML编辑器
    function openHTMLEditor(element) {
        const modal = document.createElement('div');
        modal.id = 'element-hider-editor-modal';
        modal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 80%;
            height: 80%;
            background: white;
            border: 1px solid #ccc;
            border-radius: 8px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            z-index: 2147483647;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            font-family: Arial, sans-serif;
        `;

        const header = document.createElement('div');
        header.style.cssText = `
            padding: 15px 20px;
            background: #f5f5f5;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: move;
        `;
        header.innerHTML = '<h3 style="margin:0;font-size:16px;">编辑元素 HTML</h3>';
        
        const closeBtn = document.createElement('span');
        closeBtn.innerHTML = '×';
        closeBtn.style.cssText = 'cursor:pointer;font-size:24px;color:#999;';
        closeBtn.onclick = () => modal.remove();
        header.appendChild(closeBtn);

        const body = document.createElement('div');
        body.style.cssText = 'flex: 1; padding: 20px; display: flex; flex-direction: column;';

        const textarea = document.createElement('textarea');
        textarea.style.cssText = `
            flex: 1;
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-family: monospace;
            font-size: 13px;
            line-height: 1.5;
            resize: none;
            outline: none;
            tab-size: 4;
        `;
        textarea.value = formatHTML(element.outerHTML);
        body.appendChild(textarea);

        const footer = document.createElement('div');
        footer.style.cssText = `
            padding: 15px 20px;
            border-top: 1px solid #eee;
            display: flex;
            justify-content: flex-end;
            gap: 10px;
        `;

        const saveBtn = document.createElement('button');
        saveBtn.textContent = '&#9989; 应用更改';
        saveBtn.style.cssText = `
            padding: 8px 20px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
        saveBtn.onclick = () => {
            try {
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = textarea.value.trim();
                const newElement = tempDiv.firstElementChild;
                if (newElement) {
                    element.outerHTML = textarea.value.trim();
                    showNotification('HTML 已更新');
                    modal.remove();
                } else {
                    alert('无效的 HTML 代码');
                }
            } catch (e) {
                alert('应用更改失败: ' + e.message);
            }
        };

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '取消';
        cancelBtn.style.cssText = `
            padding: 8px 20px;
            background: #eee;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
        cancelBtn.onclick = () => modal.remove();

        footer.appendChild(cancelBtn);
        footer.appendChild(saveBtn);

        modal.appendChild(header);
        modal.appendChild(body);
        modal.appendChild(footer);
        document.body.appendChild(modal);

        // 使编辑器可拖动
        makeDraggable(modal, header);
    }

    // 创建原位 HTML 编辑器
    function openInlineHTMLEditor(element) {
        // 移除旧的内联编辑器
        const oldEditor = document.getElementById('element-hider-inline-editor');
        if (oldEditor) oldEditor.remove();

        const rect = element.getBoundingClientRect();
        const editorContainer = document.createElement('div');
        editorContainer.id = 'element-hider-inline-editor';
        editorContainer.style.cssText = `
            position: absolute;
            top: ${rect.top + window.scrollY}px;
            left: ${rect.left + window.scrollX}px;
            width: ${Math.max(rect.width, 300)}px;
            height: ${Math.max(rect.height, 200)}px;
            background: white;
            border: 2px solid #2196F3;
            border-radius: 4px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.3);
            z-index: 2147483647;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            font-family: Arial, sans-serif;
        `;

        const textarea = document.createElement('textarea');
        textarea.style.cssText = `
            flex: 1;
            width: 100%;
            padding: 8px;
            border: none;
            font-family: monospace;
            font-size: 13px;
            resize: none;
            outline: none;
            tab-size: 4;
        `;
        textarea.value = formatHTML(element.outerHTML);
        editorContainer.appendChild(textarea);

        const actions = document.createElement('div');
        actions.style.cssText = `
            padding: 5px 10px;
            background: #f0f0f0;
            border-top: 1px solid #ddd;
            display: flex;
            justify-content: flex-end;
            gap: 8px;
        `;

        const saveBtn = document.createElement('button');
        saveBtn.textContent = '&#9989; 保存';
        saveBtn.style.cssText = 'padding: 4px 12px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;';
        saveBtn.onclick = () => {
            try {
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = textarea.value.trim();
                if (tempDiv.firstElementChild) {
                    element.outerHTML = textarea.value.trim();
                    showNotification('HTML 已更新');
                    editorContainer.remove();
                } else {
                    alert('无效的 HTML 代码');
                }
            } catch (e) {
                alert('应用更改失败: ' + e.message);
            }
        };

        const cancelBtn = document.createElement('button');
        cancelBtn.textContent = '取消';
        cancelBtn.style.cssText = 'padding: 4px 12px; background: #ccc; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;';
        cancelBtn.onclick = () => editorContainer.remove();

        actions.appendChild(cancelBtn);
        actions.appendChild(saveBtn);
        editorContainer.appendChild(actions);
        document.body.appendChild(editorContainer);
        
        // 自动聚焦并滚动到编辑区
        textarea.focus();
        editorContainer.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }

    // 生成元素选择器
    function generateSelector(element) {
        if (element.id) {
            return `#${CSS.escape(element.id)}`;
        }
        
        let path = [];
        while (element && element.nodeType === Node.ELEMENT_NODE) {
            let selector = element.nodeName.toLowerCase();
            
            if (element.className && typeof element.className === 'string') {
                const classes = element.className.split(/\s+/).filter(c => c.length);
                if (classes.length) {
                    selector += '.' + classes.map(c => CSS.escape(c)).join('.');
                }
            }
            
            // 添加位置索引
            let sibling = element;
            let siblingIndex = 1;
            while (sibling.previousElementSibling) {
                sibling = sibling.previousElementSibling;
                siblingIndex++;
            }
            selector += `:nth-child(${siblingIndex})`;
            
            path.unshift(selector);
            element = element.parentElement;
        }
        
        return path.join(' > ');
    }

    // 应用元素规则
    function applyElementRule(rule) {
        try {
            const elements = document.querySelectorAll(rule.selector);
            elements.forEach(element => {
                if (rule.action === 'hide') {
                    element.style.display = 'none';
                    element.setAttribute('data-element-hider-hidden', 'true');
                } else if (rule.action === 'remove') {
                    element.remove();
                }
            });
            return elements.length;
        } catch (error) {
            console.error('应用规则失败:', rule, error);
            return 0;
        }
    }

    // 加载规则
    function loadRules() {
        const allRules = GM_getValue(CONFIG.storageKey, {});
        currentRules = allRules[currentDomain] || [];
    }

    // 保存规则
    function saveRules() {
        const allRules = GM_getValue(CONFIG.storageKey, {});
        allRules[currentDomain] = currentRules;
        GM_setValue(CONFIG.storageKey, allRules);
    }

    // 应用所有规则
    function applyRules() {
        let totalHidden = 0;
        currentRules.forEach(rule => {
            totalHidden += applyElementRule(rule);
        });
        
        if (totalHidden > 0) {
            showNotification(`已隐藏/删除 ${totalHidden} 个元素`);
        }
    }

    // 添加新规则
    function addRule(selector, action) {
        // 检查是否已存在相同规则
        const exists = currentRules.some(rule => 
            rule.selector === selector && rule.action === action
        );
        
        if (!exists) {
            currentRules.push({
                selector,
                action,
                date: new Date().toISOString()
            });
            saveRules();
            applyElementRule({ selector, action });
            
            // 立即更新面板中的规则列表
            const rulesList = document.getElementById('rules-list');
            if (rulesList) updateRulesList(rulesList);
            
            return true;
        }
        return false;
    }

    // 删除规则
    function deleteRule(domain, index) {
        const allRules = GM_getValue(CONFIG.storageKey, {});
        if (allRules[domain]) {
            allRules[domain].splice(index, 1);
            // 如果该域名没有规则了,删除域名键
            if (allRules[domain].length === 0) {
                delete allRules[domain];
            }
            GM_setValue(CONFIG.storageKey, allRules);
            
            // 更新当前内存中的规则(如果是当前域名)
            if (domain === currentDomain) {
                currentRules = allRules[domain] || [];
                // 如果是当前域名,需要刷新页面来恢复元素显示
                if (confirm('规则已删除。是否立即刷新页面以恢复元素显示?')) {
                    location.reload();
                } else {
                    // 如果不刷新,只更新UI
                    const rulesList = document.getElementById('rules-list');
                    if (rulesList) updateRulesList(rulesList);
                }
            } else {
                // 非当前域名,只更新UI
                const rulesList = document.getElementById('rules-list');
                if (rulesList) updateRulesList(rulesList);
            }
        }
    }

    // 清除当前域名的所有规则
    function clearRules() {
        currentRules = [];
        saveRules();
        location.reload();
    }

    // 显示通知
    function showNotification(message, duration = 2000) {
        const notification = document.createElement('div');
        notification.className = 'element-hider-notification';
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: #4CAF50;
            color: white;
            padding: 12px 24px;
            border-radius: 4px;
            z-index: 999999;
            font-family: Arial, sans-serif;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        `;
        notification.textContent = message;
        document.body.appendChild(notification);
        
        setTimeout(() => {
            notification.remove();
        }, duration);
    }

    // 使元素可拖动
    function makeDraggable(element, handle) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        handle.onmousedown = dragMouseDown;
        handle.style.cursor = 'move';

        function dragMouseDown(e) {
            e = e || window.event;
            // 只有左键点击才触发拖拽
            if (e.button !== 0) return;
            
            e.preventDefault();
            
            // 核心修复:在点击的一瞬间,获取元素当前的绝对像素位置
            // 这样可以解决 top: 50% 和 transform 导致的初始拖拽跳动问题
            const rect = element.getBoundingClientRect();
            element.style.top = rect.top + "px";
            element.style.left = rect.left + "px";
            element.style.transform = 'none'; // 移除 transform
            element.style.right = 'auto';     // 移除 right: 20px 等定位
            element.style.bottom = 'auto';    // 移除 bottom 定位
            element.style.margin = '0';       // 移除 margin 干扰

            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            // 计算位移
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            // 设置新位置
            element.style.top = (element.offsetTop - pos2) + "px";
            element.style.left = (element.offsetLeft - pos1) + "px";
        }

        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    // 创建UI
    function createUI() {
        // 创建控制面板
        const panel = document.createElement('div');
        panel.id = 'element-hider-panel';
        panel.style.cssText = `
            position: fixed;
            top: 100px;
            right: 20px;
            background: white;
            border: 1px solid #ccc;
            border-radius: 8px;
            padding: 0;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
            z-index: 2147483647;
            min-width: 300px;
            max-width: 400px;
            font-family: Arial, sans-serif;
            display: none;
            overflow: hidden;
        `;

        // 内部容器
        const content = document.createElement('div');
        content.style.padding = '20px';

        // 面板标题 (拖动句柄)
        const titleBar = document.createElement('div');
        titleBar.style.cssText = `
            padding: 10px 20px;
            background: #f5f5f5;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: move;
            user-select: none;
        `;
        
        const title = document.createElement('h3');
        title.textContent = '元素隐藏器';
        title.style.cssText = 'margin: 0; color: #333; font-size: 16px;';
        
        // 最小化/关闭按钮区
        const controls = document.createElement('div');
        
        const closeIcon = document.createElement('span');
        closeIcon.innerHTML = '×';
        closeIcon.style.cssText = `
            font-size: 20px;
            cursor: pointer;
            color: #666;
            margin-left: 10px;
        `;
        closeIcon.onclick = () => panel.style.display = 'none';
        
        controls.appendChild(closeIcon);
        titleBar.appendChild(title);
        titleBar.appendChild(controls);
        panel.appendChild(titleBar);
        panel.appendChild(content);

        // 应用拖动功能
        makeDraggable(panel, titleBar);

        // 模式切换按钮
        const modeBtn = document.createElement('button');
        modeBtn.textContent = '&#128269; 进入选择模式';
        modeBtn.style.cssText = `
            background: ${CONFIG.modeIndicatorColor};
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            margin-bottom: 15px;
            width: 100%;
        `;
        modeBtn.addEventListener('click', toggleSelectionMode);
        content.appendChild(modeBtn);

        // 当前规则列表
        const rulesTitle = document.createElement('h4');
        rulesTitle.textContent = '已保存的规则';
        rulesTitle.style.marginBottom = '10px';
        rulesTitle.style.marginTop = '0';
        content.appendChild(rulesTitle);

        const rulesList = document.createElement('div');
        rulesList.id = 'rules-list';
        rulesList.style.cssText = `
            max-height: 300px;
            overflow-y: auto;
            margin-bottom: 15px;
            border: 1px solid #eee;
            padding: 10px;
            border-radius: 4px;
        `;
        updateRulesList(rulesList);
        content.appendChild(rulesList);

        // 清除按钮
        const clearBtn = document.createElement('button');
        clearBtn.textContent = '&#128465;&#65039; 清除所有规则';
        clearBtn.style.cssText = `
            background: #f44336;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 13px;
            width: 100%;
        `;
        clearBtn.addEventListener('click', () => {
            if (confirm('确定要清除所有网站的规则吗?')) {
                // 清除所有规则
                GM_setValue(CONFIG.storageKey, {});
                location.reload();
            }
        });
        content.appendChild(clearBtn);

        document.body.appendChild(panel);

        // 创建悬浮按钮
        const floatBtn = document.createElement('button');
        floatBtn.id = 'element-hider-float-btn';
        floatBtn.textContent = '&#127919;';
        floatBtn.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: ${CONFIG.modeIndicatorColor};
            color: white;
            border: none;
            font-size: 24px;
            cursor: pointer;
            z-index: 2147483647;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        floatBtn.addEventListener('click', () => {
            panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
        });
        document.body.appendChild(floatBtn);
    }

    // 创建覆盖层
    function createOverlay() {
        overlay = document.createElement('div');
        overlay.id = 'element-hider-overlay';
        overlay.style.cssText = `
            position: fixed;
            pointer-events: none;
            background: rgba(76, 175, 80, 0.3);
            border: 1px solid #4CAF50;
            z-index: 999998;
            display: none;
            transition: all 0.1s ease;
            box-sizing: border-box;
        `;
        
        overlayInfo = document.createElement('div');
        overlayInfo.style.cssText = `
            position: absolute;
            top: -24px;
            left: 0;
            background: #333;
            color: white;
            padding: 2px 6px;
            font-size: 12px;
            border-radius: 3px;
            white-space: nowrap;
            pointer-events: none;
            font-family: monospace;
            z-index: 999999;
        `;
        
        overlay.appendChild(overlayInfo);
        document.body.appendChild(overlay);
    }

    // 更新覆盖层位置
    function updateOverlay(element) {
        if (!element || !overlay) return;
        
        const rect = element.getBoundingClientRect();
        
        overlay.style.display = 'block';
        overlay.style.top = rect.top + 'px';
        overlay.style.left = rect.left + 'px';
        overlay.style.width = rect.width + 'px';
        overlay.style.height = rect.height + 'px';
        
        // 移除标签路径显示,只保留高亮框
        overlayInfo.textContent = '';
        overlayInfo.style.display = 'none';
    }

    // 更新规则列表显示
    function updateRulesList(container) {
        container.innerHTML = '';
        
        const allRules = GM_getValue(CONFIG.storageKey, {});
        const domains = Object.keys(allRules).sort();
        
        if (domains.length === 0) {
            const emptyMsg = document.createElement('div');
            emptyMsg.textContent = '暂无规则';
            emptyMsg.style.color = '#999';
            emptyMsg.style.textAlign = 'center';
            emptyMsg.style.padding = '20px';
            container.appendChild(emptyMsg);
            return;
        }

        domains.forEach(domain => {
            const domainRules = allRules[domain];
            if (!domainRules || domainRules.length === 0) return;

            const domainGroup = document.createElement('div');
            domainGroup.style.marginBottom = '8px';
            domainGroup.style.border = '1px solid #eee';
            domainGroup.style.borderRadius = '6px';
            domainGroup.style.overflow = 'hidden';

            // 域名标题栏 (折叠开关)
            const domainHeader = document.createElement('div');
            const isCurrent = domain === currentDomain;
            domainHeader.style.cssText = `
                padding: 10px 12px;
                background: ${isCurrent ? '#f0f7ff' : '#fcfcfc'};
                cursor: pointer;
                display: flex;
                justify-content: space-between;
                align-items: center;
                user-select: none;
                transition: background 0.2s;
                border-bottom: 1px solid ${isCurrent ? '#e0eeff' : '#eee'};
            `;
            
            const titleLeft = document.createElement('div');
            titleLeft.style.display = 'flex';
            titleLeft.style.alignComponents = 'center';
            titleLeft.style.gap = '8px';
            
            // 状态箭头
            const arrow = document.createElement('span');
            arrow.innerHTML = '&#9654;';
            arrow.style.cssText = `
                display: inline-block;
                transition: transform 0.3s;
                font-size: 10px;
                color: ${isCurrent ? '#2196F3' : '#999'};
            `;
            
            const domainName = document.createElement('span');
            domainName.textContent = domain;
            domainName.style.fontWeight = 'bold';
            domainName.style.fontSize = '13px';
            domainName.style.color = isCurrent ? '#2196F3' : '#444';
            
            if (isCurrent) {
                const badge = document.createElement('span');
                badge.textContent = '当前';
                badge.style.cssText = 'font-size: 10px; background: #2196F3; color: white; padding: 1px 4px; border-radius: 3px; margin-left: 5px;';
                domainName.appendChild(badge);
            }

            titleLeft.appendChild(arrow);
            titleLeft.appendChild(domainName);

            const count = document.createElement('span');
            count.textContent = `${domainRules.length} 条`;
            count.style.cssText = 'font-size: 11px; color: #999;';

            domainHeader.appendChild(titleLeft);
            domainHeader.appendChild(count);

            // 规则内容区域
            const rulesContainer = document.createElement('div');
            rulesContainer.style.cssText = `
                display: none;
                padding: 5px;
                background: white;
            `;

            // 折叠逻辑实现
            let isOpen = false;
            const toggle = (forceOpen = false) => {
                isOpen = forceOpen || !isOpen;
                rulesContainer.style.display = isOpen ? 'block' : 'none';
                arrow.style.transform = isOpen ? 'rotate(90deg)' : 'rotate(0deg)';
                domainHeader.style.background = isOpen ? (isCurrent ? '#e6f2ff' : '#f5f5f5') : (isCurrent ? '#f0f7ff' : '#fcfcfc');
            };

            domainHeader.onclick = () => toggle();
            domainHeader.onmouseenter = () => { if(!isOpen) domainHeader.style.background = isCurrent ? '#e6f2ff' : '#f5f5f5'; };
            domainHeader.onmouseleave = () => { if(!isOpen) domainHeader.style.background = isCurrent ? '#f0f7ff' : '#fcfcfc'; };

            // 规则项
            domainRules.forEach((rule, index) => {
                const ruleItem = document.createElement('div');
                ruleItem.style.cssText = `
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: 8px 10px;
                    margin: 4px;
                    background: #f8f9fa;
                    border-radius: 4px;
                    font-size: 12px;
                    border: 1px solid transparent;
                    transition: all 0.2s;
                `;
                ruleItem.onmouseenter = () => { ruleItem.style.borderColor = '#ddd'; ruleItem.style.background = '#fff'; };
                ruleItem.onmouseleave = () => { ruleItem.style.borderColor = 'transparent'; ruleItem.style.background = '#f8f9fa'; };
                
                const ruleText = document.createElement('div');
                ruleText.style.cssText = 'overflow: hidden; white-space: nowrap; text-overflow: ellipsis; flex: 1; margin-right: 10px; color: #666;';
                ruleText.title = rule.selector;
                ruleText.innerHTML = `<span style="color: ${rule.action === 'hide' ? '#4CAF50' : '#f44336'}; font-weight: bold;">[${rule.action === 'hide' ? '隐藏' : '删除'}]</span> ${rule.selector}`;
                
                const deleteBtn = document.createElement('button');
                deleteBtn.innerHTML = '×';
                deleteBtn.title = '删除规则';
                deleteBtn.style.cssText = `
                    background: none;
                    border: none;
                    color: #ccc;
                    font-size: 18px;
                    cursor: pointer;
                    padding: 0 5px;
                    line-height: 1;
                    transition: color 0.2s;
                `;
                deleteBtn.onmouseenter = () => deleteBtn.style.color = '#f44336';
                deleteBtn.onmouseleave = () => deleteBtn.style.color = '#ccc';
                deleteBtn.onclick = (e) => {
                    e.stopPropagation();
                    if (confirm('确定要删除这条规则吗?')) {
                        deleteRule(domain, index);
                    }
                };
                
                ruleItem.appendChild(ruleText);
                ruleItem.appendChild(deleteBtn);
                rulesContainer.appendChild(ruleItem);
            });

            // 默认展开当前网站
            if (isCurrent) {
                toggle(true);
            }

            domainGroup.appendChild(domainHeader);
            domainGroup.appendChild(rulesContainer);
            container.appendChild(domainGroup);
        });
    }

    // 切换选择模式
    function toggleSelectionMode() {
        isSelectionMode = !isSelectionMode;
        const modeBtn = document.querySelector('#element-hider-panel button');
        const floatBtn = document.getElementById('element-hider-float-btn');
        
        if (isSelectionMode) {
            modeBtn.textContent = '&#128683; 退出选择模式';
            modeBtn.style.background = '#f44336';
            floatBtn.style.background = '#f44336';
            floatBtn.textContent = '&#127919;';
            
            document.addEventListener('mouseover', handleMouseOver);
            document.addEventListener('click', handleClick, true);
            document.addEventListener('contextmenu', handleContextMenu, true);
            document.body.style.cursor = 'crosshair';
            
            showNotification('选择模式已开启 - 左键显示菜单,右键直接删除');
        } else {
            isMenuOpen = false;
            isMenuHovered = false;
            const oldMenu = document.querySelector('.element-hider-menu');
            if (oldMenu) oldMenu.remove();
            
            modeBtn.textContent = '&#128269; 进入选择模式';
            modeBtn.style.background = CONFIG.modeIndicatorColor;
            floatBtn.style.background = CONFIG.modeIndicatorColor;
            floatBtn.textContent = '&#127919;';
            
            document.removeEventListener('mouseover', handleMouseOver);
            document.removeEventListener('click', handleClick, true);
            document.removeEventListener('contextmenu', handleContextMenu, true);
            document.body.style.cursor = '';
            
            if (overlay) overlay.style.display = 'none';
            
            showNotification('选择模式已关闭');
        }
    }

    // 处理右键点击
    function handleContextMenu(e) {
        if (!isSelectionMode) return;
        
        // 忽略UI元素
        if (e.target.closest('#element-hider-panel') || 
            e.target.closest('#element-hider-float-btn') || 
            e.target.closest('.element-hider-menu') ||
            e.target.closest('.element-hider-notification') ||
            e.target.closest('#element-hider-editor-modal') ||
            e.target.closest('#element-hider-inline-editor')) {
            return;
        }

        e.preventDefault();
        e.stopPropagation();
        
        const selector = generateSelector(e.target);
        if (addRule(selector, 'remove')) {
            showNotification('元素已通过右键删除');
        }
    }

    // 处理鼠标悬停
    function handleMouseOver(e) {
        // 如果鼠标在菜单上,不更新
        if (isMenuHovered) return;

        // 忽略UI元素
        if (e.target.closest('#element-hider-panel') || 
            e.target.closest('#element-hider-float-btn') || 
            e.target.closest('.element-hider-menu') ||
            e.target.closest('.element-hider-notification') ||
            e.target.closest('#element-hider-editor-modal') ||
            e.target.closest('#element-hider-inline-editor') ||
            e.target.id === 'element-hider-overlay') {
            return;
        }

        updateOverlay(e.target);
        
        // 如果菜单已经打开,让它跟随鼠标更新
        if (isMenuOpen) {
            showMenu(e.target, e.clientX, e.clientY);
        }
        
        e.stopPropagation();
    }

    // 显示操作菜单
    function showMenu(targetElement, x, y) {
        isMenuOpen = true;
        const selector = generateSelector(targetElement);

        let menu = document.querySelector('.element-hider-menu');
        if (!menu) {
            menu = document.createElement('div');
            menu.className = 'element-hider-menu';
            document.body.appendChild(menu);
        }
        
        menu.style.cssText = `
            position: fixed;
            left: ${x - 20}px;
            top: ${y - 20}px;
            background: white;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.2);
            z-index: 2147483647;
            width: 200px;
            max-width: 250px;
            font-family: Arial, sans-serif;
            font-size: 13px;
            overflow: hidden;
            pointer-events: auto;
        `;
        
        // 清空旧内容
        menu.innerHTML = '';
        
        // 鼠标悬停逻辑
        menu.onmouseenter = () => { isMenuHovered = true; };
        menu.onmouseleave = () => { isMenuHovered = false; };
        
        // 辅助函数:创建菜单项
        const createMenuItem = (text, onClick, color = '#333') => {
            const btn = document.createElement('button');
            btn.textContent = text;
            btn.style.cssText = `
                display: block;
                width: 100%;
                padding: 8px 12px;
                border: none;
                background: none;
                text-align: left;
                cursor: pointer;
                color: ${color};
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            `;
            btn.addEventListener('mouseover', () => btn.style.background = '#f5f5f5');
            btn.addEventListener('mouseout', () => btn.style.background = 'none');
            btn.addEventListener('click', (event) => {
                event.stopPropagation();
                onClick();
            });
            return btn;
        };

        const closeMenu = () => {
            isMenuOpen = false;
            isMenuHovered = false;
            menu.remove();
        };

        // 标题(显示选择器)
        const title = document.createElement('div');
        title.style.cssText = `
            padding: 8px 12px;
            background: #f9f9f9;
            border-bottom: 1px solid #eee;
            font-weight: bold;
            color: #666;
            font-size: 11px;
            word-break: break-all;
        `;
        title.textContent = selector;
        menu.appendChild(title);

        // 隐藏按钮
        menu.appendChild(createMenuItem('&#128065;&#65039; 隐藏元素', () => {
            if (addRule(selector, 'hide')) {
                showNotification('元素已隐藏');
            }
            closeMenu();
        }));
        
        // 删除按钮
        menu.appendChild(createMenuItem('&#128465;&#65039; 删除元素', () => {
            if (addRule(selector, 'remove')) {
                showNotification('元素已删除');
            }
            closeMenu();
        }, '#f44336'));

        // 编辑 HTML 按钮 (原位编辑)
        menu.appendChild(createMenuItem('&#127919; 原位编辑 HTML', () => {
            closeMenu();
            openInlineHTMLEditor(targetElement);
        }, '#2196F3'));

        // 编辑 HTML 按钮 (弹窗编辑)
        menu.appendChild(createMenuItem('&#128221; 弹窗编辑 HTML', () => {
            closeMenu();
            openHTMLEditor(targetElement);
        }, '#FF9800'));

        // 选择父级按钮
        if (targetElement.parentElement && targetElement.parentElement !== document.body) {
            menu.appendChild(createMenuItem('&#11014;&#65039; 选择父级元素', () => {
                // 更新Overlay
                updateOverlay(targetElement.parentElement);
                // 递归更新菜单,但锁定位置在当前
                showMenu(targetElement.parentElement, x, y);
            }, '#2196F3'));
        }
        
        // 取消按钮
        const cancelBtn = createMenuItem('&#10060; 取消', () => {
            closeMenu();
        });
        cancelBtn.style.borderTop = '1px solid #eee';
        menu.appendChild(cancelBtn);
        
        // 确保菜单不超出屏幕
        const menuRect = menu.getBoundingClientRect();
        if (x + menuRect.width - 20 > window.innerWidth) {
            menu.style.left = (window.innerWidth - menuRect.width - 10) + 'px';
        }
        if (y + menuRect.height - 20 > window.innerHeight) {
            menu.style.top = (window.innerHeight - menuRect.height - 10) + 'px';
        }
        if (parseInt(menu.style.left) < 0) menu.style.left = '10px';
        if (parseInt(menu.style.top) < 0) menu.style.top = '10px';
    }

    // 处理点击
    function handleClick(e) {
        // 移除旧菜单并重置状态
        const oldMenu = document.querySelector('.element-hider-menu');
        if (oldMenu) {
            // 如果点击的是菜单内部,由菜单内部的点击事件处理
            if (e.target.closest('.element-hider-menu')) {
                return;
            }
            oldMenu.remove();
            isMenuOpen = false;
            isMenuHovered = false;
        }

        // 忽略UI元素
        if (e.target.closest('#element-hider-panel') || 
            e.target.closest('#element-hider-float-btn') || 
            e.target.closest('.element-hider-notification') ||
            e.target.closest('#element-hider-editor-modal') ||
            e.target.closest('#element-hider-inline-editor')) {
            return;
        }

        e.preventDefault();
        e.stopPropagation();
        
        showMenu(e.target, e.clientX, e.clientY);
    }

    // 启动
    setTimeout(init, 1000); // 等待页面完全加载

})();

免费评分

参与人数 29吾爱币 +22 热心值 +25 收起 理由
安道尔的鱼 + 1 + 1 我很赞同!
cccfind911 + 1 + 1 谢谢@Thanks!
aries9115 + 1 + 1 我很赞同!
弑神者91511 + 1 + 1 谢谢@Thanks!
fansxie + 1 + 1 我很赞同!
xiongwang + 1 谢谢@Thanks!
VisualBasicYYDS + 1 谢谢@Thanks!
qsj521521 + 1 + 1 谢谢@Thanks!
wangpengfei770 + 1 鼓励转贴优秀软件安全工具和文档!
王乐乐 + 1 我很赞同!
aa20221101 + 1 + 1 热心回复!
yanglinman + 1 + 1 谢谢@Thanks!
repack9527 + 1 谢谢@Thanks!
hupoquan + 1 您方便的时候看看51楼的功能好实现吗,谢谢
xuxudong1110 + 1 + 1 谢谢@Thanks!
striveenFei + 1 谢谢@Thanks!
陆仁嘉 + 1 我很赞同!
花心乞丐 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lky357951 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
52kail + 1 + 1 谢谢@Thanks!
Muuu2333 + 1 + 1
DANHUANGJIANGYO + 1 + 1 谢谢@Thanks!
lbdcyy + 1 热心回复!
cioceo + 1 + 1 谢谢@Thanks!
xlln + 1 + 1 我很赞同!
Ariel0710 + 1 + 1 谢谢@Thanks!
yaoxuemeng + 1 谢谢@Thanks!
thornjay + 1 + 1 谢谢@Thanks!
zhanglei1371 + 1 + 1 鼓励转贴优秀软件安全工具和文档!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Kissmeet 发表于 2026-1-21 10:01
本帖最后由 Kissmeet 于 2026-1-21 10:05 编辑

用codebuddy IDE优化和增加了部分功能:
1、元素获取方式改用自定义的locateNewElement(x, y)这个函数
2、增了隐藏元素后的预览功能(点击眼睛按钮可以切换元素的隐藏与显示)
3、优化了删除隐藏元素的规则为立即恢复显示被隐藏的元素,不再重新刷新页面后才显示

网页元素可视化调试管家含源码:支持 HTML 原位编辑 CSS 实时探针 永久规则管理..txt

45.46 KB, 下载次数: 121, 下载积分: 吾爱币 -1 CB

Char007 发表于 2026-1-21 11:02
lzy8108 发表于 2026-1-20 20:30
君月栩 发表于 2026-1-20 20:36
感谢楼主分享
lpf2003 发表于 2026-1-20 20:39
感谢分享,能不能把网页本来隐藏的元素显示出来
Yoz666 发表于 2026-1-20 20:41
有意思的插件,下载试试,感谢分享
 楼主| 29176413 发表于 2026-1-20 20:46
lpf2003 发表于 2026-1-20 20:39
感谢分享,能不能把网页本来隐藏的元素显示出来

这个里面没有那个功能,你要针对需要的功能进行分析,让后丢给AI去实现不久好了,是不是很简单
MichaelAHN 发表于 2026-1-20 21:06
不知道有啥用
双十一 发表于 2026-1-20 21:08
这个可以用来去网页广告
sky木木 发表于 2026-1-20 21:16
虽然看不懂,但感觉好厉害的样子
Dickxie 发表于 2026-1-20 21:17
主要是用于干嘛?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-1-28 09:59

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表