网页字数统计

在网页上选中文字时,通过浮层显示字数,针对ChatGPT官网(2025.4.12)优化

// ==UserScript==
// @name         网页字数统计
// @namespace    http://tampermonkey.net/
// @version      0.15
// @license      MIT
// @description  在网页上选中文字时,通过浮层显示字数,针对ChatGPT官网(2025.4.12)优化
// @author       PPPotatooo
// @match        *://*/*
// @grant        none
// ==/UserScript==
(function() {
    'use strict';
    // 创建浮层元素
    const floatDiv = document.createElement('div');
    floatDiv.style.cssText = 'position: absolute; z-index: 1000; padding: 5px; background: white; border: 1px solid black; border-radius: 4px; font-size: 12px; display: none; opacity: 1; transition: opacity 1s ease;';
    document.body.appendChild(floatDiv);
    let fadeOutTimeout;
    // 新增函数:计算中英文字数
    function countWords(text) {
        // 移除标点符号和特殊字符
        text = text.replace(/[^\w\s\u4e00-\u9fa5]/g, '');
        // 分别匹配中文字符和英文单词
        const chineseChars = text.match(/[\u4e00-\u9fa5]/g) || [];
        const englishWords = text.match(/\b[a-zA-Z]+\b/g) || [];
        // 返回中文字符和英文单词的总数
        return chineseChars.length + englishWords.length;
    }
    document.addEventListener('mouseup', function() {
        clearTimeout(fadeOutTimeout);
        const selection = window.getSelection();
        const selectedText = selection.toString();
        if (selectedText.length > 0) {
            // 调用计算字数的函数
            const totalWords = countWords(selectedText);
            floatDiv.textContent = `字数: ${totalWords}`;
            // 获取选中文字的范围
            const range = selection.getRangeAt(0);
            const rect = range.getBoundingClientRect();
            // 设置浮层位置
            floatDiv.style.left = `${rect.left + window.scrollX}px`;
            floatDiv.style.top = `${rect.bottom + window.scrollY}px`;
            floatDiv.style.display = 'block';
            floatDiv.style.opacity = '1';
            // 设置2秒后开始消失
            fadeOutTimeout = setTimeout(() => {
                floatDiv.style.opacity = '0';
                setTimeout(() => floatDiv.style.display = 'none', 1000); // 1秒后完全隐藏
            }, 2000);
        } else {
            floatDiv.style.display = 'none';
        }
    });

    // ==================== 专门适用于ChatGPT官网 ====================
    // 检测是否在ChatGPT.com网站
    if (window.location.hostname.includes('chatgpt.com')) {
        function handleChatGPTSelection() {
            const selection = window.getSelection();
            const selectedText = selection.toString();
            
            if (selectedText.length > 0) {
                const totalWords = countWords(selectedText);
                floatDiv.textContent = `字数: ${totalWords}`;
                
                try {
                    // 获取选中文字的位置信息
                    const range = selection.getRangeAt(0);
                    const rect = range.getBoundingClientRect();
                    floatDiv.style.zIndex = '10000000';
                    floatDiv.style.position = 'fixed';
                    floatDiv.style.left = `${rect.left}px`;
                    floatDiv.style.top = `${rect.bottom + 5}px`;
                    
                    // 如果位置在视口外,调整位置
                    if (rect.top < 0 || rect.bottom > window.innerHeight) {
                        floatDiv.style.top = `${Math.min(window.innerHeight - 30, Math.max(30, rect.top))}px`;
                    }
                    
                    floatDiv.style.display = 'block';
                    floatDiv.style.opacity = '1';
                    
                    clearTimeout(fadeOutTimeout);
                    fadeOutTimeout = setTimeout(() => {
                        floatDiv.style.opacity = '0';
                        setTimeout(() => floatDiv.style.display = 'none', 1000);
                    }, 2000);
                } catch (e) {
                    console.log('ChatGPT字数统计出错:', e);
                }
            }
        }
        
        // 为ChatGPT特定元素添加事件监听器
        function addChatGPTEventListeners() {
            const messageElements = document.querySelectorAll('.text-token-text-primary, .markdown, .prose');
            
            messageElements.forEach(element => {
                if (!element.dataset.wordcountEnabled) {
                    element.dataset.wordcountEnabled = 'true';
                    element.addEventListener('mouseup', handleChatGPTSelection, true);
                }
            });
        }
        
        addChatGPTEventListeners();
        const observer = new MutationObserver(() => {
            addChatGPTEventListeners();
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
        
        document.addEventListener('mouseup', function(e) {
            setTimeout(() => {
                const selection = window.getSelection();
                const selectedText = selection.toString();
                
                if (selectedText.length > 0) {
                    handleChatGPTSelection();
                }
            }, 10);
        }, true);
    }
    
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址