nowcoder extend class

展开多少届。直观看到用户是多少届的

Fra 30.03.2025. Se den seneste versjonen.

// ==UserScript==
// @name nowcoder extend class
// @description  展开多少届。直观看到用户是多少届的
// @version  1.1
// @include  https://www.nowcoder.com/search/*
// @include  https://www.nowcoder.com/feed/main/detail/*
// @namespace    baojie.nowcoder
// @license      MIT
// @grant        GM_xmlhttpRequest
// ==/UserScript==
// prompt archive https://markdownpastebin.com/?id=44bc3d7d7a8345968817f865646c1f91
(function() {
    'use strict';

    // Cache to store user IDs and their graduation years
    const userCache = new Map();
    // Set to track user IDs that have been processed
    const processedUserIds = new Set();

    // Add CSS styles for graduation year display
    function addStyles() {
        // Check if styles already added
        if (document.getElementById('nowcoder-grad-year-styles')) {
            return;
        }
        
        const styleElement = document.createElement('style');
        styleElement.id = 'nowcoder-grad-year-styles';
        styleElement.textContent = `
            .grad-year-display {
                color: #ff7830;
                margin-left: 5px;
                font-size: 12px;
                font-weight: bold;
            }
        `;
        document.head.appendChild(styleElement);
    }

    // Extract user ID from element
    function getUserIdFromElement(element) {
        // For links with href attribute
        if (element.tagName === 'A' && element.href) {
            const match = element.href.match(/\/users\/(\d+)/);
            if (match && match[1]) {
                return match[1];
            }
        }
        
        // For other elements, check parent or child links
        const link = element.closest('a[href*="/users/"]') || 
                     element.querySelector('a[href*="/users/"]');
        
        if (link) {
            const match = link.href.match(/\/users\/(\d+)/);
            if (match && match[1]) {
                return match[1];
            }
        }
        
        return null;
    }

    // Display the graduation year next to the user name
    function displayGradYear(element, gradYear) {
        // Find the appropriate container
        const nameSpan = element.querySelector('.name-text');
        
        // Check if we already added to this specific element
        if (nameSpan.querySelector('.grad-year-display') || element.hasAttribute('data-grad-displayed')) {
            return;
        }
        
        // Create the graduation year display
        const gradYearElement = document.createElement('span');
        gradYearElement.className = 'grad-year-display';
        gradYearElement.textContent = `(${gradYear})`;
        gradYearElement.setAttribute('data-userid', element.getAttribute('data-userid'));
        
        // Add to the page
        nameSpan.appendChild(gradYearElement);
        
        // Mark this element as having the graduation year displayed
        element.setAttribute('data-grad-displayed', 'true');
    }

    // Fetch user info using GM_xmlhttpRequest
    function fetchUserInfo(userId) {
        return new Promise((resolve) => {
            const url = `https://gw-c.nowcoder.com/api/sparta/user/info/card/${userId}?_=${Date.now()}`;
            
            // Use GM_xmlhttpRequest directly, avoiding the unsafe header issue
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                headers: {
                    'Accept': 'application/json',
                    'X-Requested-With': 'XMLHttpRequest'
                    // Removed Referer header to avoid the 'unsafe header' error
                },
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.success && data.data && data.data.workTime) {
                            resolve(data.data.workTime);
                        } else {
                            resolve(null);
                        }
                    } catch (e) {
                        console.error('Failed to parse response', e);
                        resolve(null);
                    }
                },
                onerror: function() {
                    resolve(null);
                }
            });
        });
    }

    // Process a single user element
    async function processUserElement(element) {
        // Skip if already fully processed
        if (element.hasAttribute('data-grad-displayed')) {
            return;
        }
        
        const userId = getUserIdFromElement(element);
        if (!userId) {
            return;
        }
        
        // Store userId as data attribute to help with duplicate detection
        element.setAttribute('data-userid', userId);
        
        // Skip if already in progress for this user ID
        if (processedUserIds.has(userId)) {
            // If we already know this user's info, display it
            if (userCache.has(userId)) {
                displayGradYear(element, userCache.get(userId));
            }
            return;
        }
        
        // Mark as being processed
        processedUserIds.add(userId);
        
        // Check cache first
        if (userCache.has(userId)) {
            displayGradYear(element, userCache.get(userId));
            return;
        }
        
        // Fetch user info
        const gradYear = await fetchUserInfo(userId);
        if (gradYear) {
            userCache.set(userId, gradYear);
            
            // Update all instances of this user on the page
            document.querySelectorAll(`[data-userid="${userId}"]:not([data-grad-displayed])`).forEach(el => {
                displayGradYear(el, gradYear);
            });
        }
    }

    // Process all user elements visible on the page
    function processVisibleElements() {
        // Find all user name links
        document.querySelectorAll('a[href*="/users/"]').forEach(link => {
            if (link.closest('.user-nickname') || link.querySelector('.name-text')) {
                processUserElement(link);
            }
        });
    }

    // Simple debounce function
    function debounce(func, wait) {
        let timeout;
        return function() {
            const context = this, args = arguments;
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(context, args), wait);
        };
    }

    // Initialize
    function init() {
        console.log('Nowcoder graduation year display script initialized');
        addStyles();
        
        // Initial processing with a short delay
        setTimeout(processVisibleElements, 500);
        
        // Process on scroll (debounced)
        window.addEventListener('scroll', debounce(processVisibleElements, 300));
        
        // Process on content changes
        const observer = new MutationObserver(debounce(mutations => {
            let hasNewNodes = false;
            mutations.forEach(mutation => {
                if (mutation.addedNodes.length > 0) {
                    hasNewNodes = true;
                }
            });
            
            if (hasNewNodes) {
                processVisibleElements();
            }
        }, 300));
        
        observer.observe(document.body, { childList: true, subtree: true });
    }

    // Run after page has loaded
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();