Greasy Fork

Greasy Fork is available in English.

去你妈的劳关评教

很喜欢点吗

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         去你妈的劳关评教
// @namespace    https://github.com/Cindy-Master
// @version      0.0.3
// @description  很喜欢点吗
// @author       Cindy-Master
// @match        *://culr.mycospxk.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let isProcessing = false;

    // 默认填空题内容
    const defaultAnswers = {
        answer1: '实践和理论结合',
        answer2: '无',
        answer3: '老师讲的非常好,教学很清晰明了。'
    };

    // 从localStorage获取保存的答案
    function getSavedAnswers() {
        const saved = localStorage.getItem('teachingEvaluationAnswers');
        if (saved) {
            try {
                return JSON.parse(saved);
            } catch (e) {
                console.log('解析保存的答案失败:', e);
            }
        }
        return defaultAnswers;
    }

    // 保存答案到localStorage
    function saveAnswers(answers) {
        localStorage.setItem('teachingEvaluationAnswers', JSON.stringify(answers));
        console.log('答案已保存:', answers);
    }

    // 创建配置界面
    function createConfigModal() {
        // 创建遮罩层
        const overlay = document.createElement('div');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 10000;
            display: flex;
            justify-content: center;
            align-items: center;
        `;

        // 创建配置窗口
        const modal = document.createElement('div');
        modal.style.cssText = `
            background: white;
            padding: 30px;
            border-radius: 8px;
            width: 500px;
            max-width: 90%;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
        `;

        const savedAnswers = getSavedAnswers();

        modal.innerHTML = `
            <h3 style="margin: 0 0 20px 0; text-align: center; color: #333;">填空题内容设置</h3>

            <div style="margin-bottom: 15px;">
                <label style="display: block; margin-bottom: 5px; font-weight: bold;">第一道填空题内容:</label>
                <input type="text" id="answer1" value="${savedAnswers.answer1}"
                       style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box;">
                <div style="font-size: 12px; color: #666; margin-top: 2px;">推荐内容:实践和理论结合</div>
            </div>

            <div style="margin-bottom: 15px;">
                <label style="display: block; margin-bottom: 5px; font-weight: bold;">第二道填空题内容:</label>
                <input type="text" id="answer2" value="${savedAnswers.answer2}"
                       style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box;">
                <div style="font-size: 12px; color: #666; margin-top: 2px;">推荐内容:无</div>
            </div>

            <div style="margin-bottom: 20px;">
                <label style="display: block; margin-bottom: 5px; font-weight: bold;">弹窗评价原因内容:</label>
                <textarea id="answer3" rows="3"
                          style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; resize: vertical;">${savedAnswers.answer3}</textarea>
                <div style="font-size: 12px; color: #666; margin-top: 2px;">推荐内容:老师讲的非常好,教学很清晰明了。</div>
            </div>

            <div style="text-align: center;">
                <button id="saveConfig" style="
                    background: #1890ff;
                    color: white;
                    border: none;
                    padding: 10px 20px;
                    border-radius: 4px;
                    cursor: pointer;
                    margin-right: 10px;
                    font-size: 14px;
                ">保存设置</button>
                <button id="cancelConfig" style="
                    background: #ccc;
                    color: #333;
                    border: none;
                    padding: 10px 20px;
                    border-radius: 4px;
                    cursor: pointer;
                    font-size: 14px;
                ">取消</button>
            </div>
        `;

        overlay.appendChild(modal);
        document.body.appendChild(overlay);

        // 保存按钮事件
        document.getElementById('saveConfig').addEventListener('click', () => {
            const answers = {
                answer1: document.getElementById('answer1').value.trim() || defaultAnswers.answer1,
                answer2: document.getElementById('answer2').value.trim() || defaultAnswers.answer2,
                answer3: document.getElementById('answer3').value.trim() || defaultAnswers.answer3
            };

            saveAnswers(answers);
            document.body.removeChild(overlay);

            // 显示保存成功提示
            showNotification('设置已保存成功!', 'success');
        });

        // 取消按钮事件
        document.getElementById('cancelConfig').addEventListener('click', () => {
            document.body.removeChild(overlay);
        });

        // 点击遮罩层关闭
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                document.body.removeChild(overlay);
            }
        });
    }

    // 显示通知
    function showNotification(message, type = 'info') {
        const notification = document.createElement('div');
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 20px;
            border-radius: 4px;
            color: white;
            font-size: 14px;
            z-index: 10001;
            transition: all 0.3s;
            ${type === 'success' ? 'background: #52c41a;' : 'background: #1890ff;'}
        `;
        notification.textContent = message;
        document.body.appendChild(notification);

        setTimeout(() => {
            notification.style.opacity = '0';
            setTimeout(() => {
                if (document.body.contains(notification)) {
                    document.body.removeChild(notification);
                }
            }, 300);
        }, 2000);
    }

    // 等待页面加载完成
    function waitForElements() {
        const radioGroups = document.querySelectorAll('.ant-radio-group');
        const textareas = document.querySelectorAll('textarea.ant-input');

        if (radioGroups.length > 0 || textareas.length > 0) {
            fillForm();
        } else {
            setTimeout(waitForElements, 1000);
        }
    }

    function fillForm() {
        if (isProcessing) return;
        isProcessing = true;

        console.log('开始自动填写表单...');

        // 处理所有单选题
        fillRadioQuestions();

        // 等待一下再处理填空题
        setTimeout(() => {
            fillTextAreas();

            // 再等待一下后自动提交
            setTimeout(() => {
                autoSubmit();
            }, 2000);
        }, 1000);
    }

    function fillRadioQuestions() {
        const radioGroups = document.querySelectorAll('.ant-radio-group');

        radioGroups.forEach((group, index) => {
            const veryMatch = group.querySelector('input[value="1"]'); // 非常符合
            const match = group.querySelector('input[value="2"]'); // 符合

            if (veryMatch && match) {
                const random = Math.random();
                let selectedOption;

                if (random < 0.3) {
                    selectedOption = match; // 符合
                } else {
                    selectedOption = veryMatch; // 非常符合
                }

                selectedOption.click();
                selectedOption.dispatchEvent(new Event('change', { bubbles: true }));

                console.log(`第${index + 1}题已选择: ${random < 0.3 ? '符合' : '非常符合'}`);
            }
        });
    }

    function fillTextAreas() {
        const textareas = document.querySelectorAll('textarea.ant-input');
        const savedAnswers = getSavedAnswers();

        if (textareas.length >= 2) {
            // 第一个填空题:使用自定义内容
            fillTextAreaWithTyping(textareas[0], savedAnswers.answer1, 0);

            // 第二个填空题:使用自定义内容
            setTimeout(() => {
                fillTextAreaWithTyping(textareas[1], savedAnswers.answer2, 1);
            }, 1000);

            console.log('开始填写填空题...');
            console.log('第一道填空题内容:', savedAnswers.answer1);
            console.log('第二道填空题内容:', savedAnswers.answer2);
        }
    }

    // 模拟真实打字过程来触发字数检测
    function fillTextAreaWithTyping(textarea, text, index) {
        console.log(`开始填写第${index + 1}个填空题: "${text}"`);

        // 先清空
        textarea.value = '';
        textarea.focus();

        // 触发清空事件
        triggerAllEvents(textarea);

        // 模拟逐字输入
        let currentIndex = 0;
        const typingInterval = setInterval(() => {
            if (currentIndex < text.length) {
                textarea.value += text[currentIndex];
                currentIndex++;

                // 每输入一个字符就触发事件
                triggerAllEvents(textarea);

                console.log(`第${index + 1}个填空题当前内容: "${textarea.value}"`);
            } else {
                clearInterval(typingInterval);

                // 输入完成后再次触发所有事件
                setTimeout(() => {
                    triggerAllEvents(textarea);
                    textarea.blur();
                    console.log(`第${index + 1}个填空题填写完成: "${textarea.value}"`);

                    // 检查字数显示是否更新
                    setTimeout(() => {
                        checkWordCount(index + 1);
                    }, 500);
                }, 200);
            }
        }, 100); // 每100ms输入一个字符
    }

    // 触发所有可能的事件
    function triggerAllEvents(element) {
        const events = [
            'input', 'change', 'keydown', 'keyup', 'keypress',
            'focus', 'blur', 'paste', 'cut', 'propertychange'
        ];

        events.forEach(eventType => {
            const event = new Event(eventType, {
                bubbles: true,
                cancelable: true
            });
            element.dispatchEvent(event);
        });

        // 特殊的input事件
        const inputEvent = new InputEvent('input', {
            bubbles: true,
            cancelable: true,
            inputType: 'insertText',
            data: element.value
        });
        element.dispatchEvent(inputEvent);

        // React特定的事件
        if (element._valueTracker) {
            element._valueTracker.setValue('');
        }

        // 尝试触发React的onChange
        const reactHandler = element._reactInternalFiber || element._reactInternalInstance;
        if (reactHandler) {
            const onChange = reactHandler.memoizedProps?.onChange;
            if (onChange) {
                onChange({ target: element });
            }
        }
    }

    // 检查字数是否更新
    function checkWordCount(textareaIndex) {
        const countElements = document.querySelectorAll('.index__numCount--pECDw, .index__count_wrap--m1keW');
        console.log(`检查第${textareaIndex}个填空题的字数显示...`);

        countElements.forEach((element, index) => {
            console.log(`字数显示${index + 1}: ${element.textContent}`);
        });
    }

    function autoSubmit() {
        // 使用您提供的精确选择器
        const submitButton = document.querySelector('button.ant-btn.index__submit--jiKIA.ant-btn-primary');

        if (submitButton) {
            console.log('找到提交按钮,准备提交...');
            submitButton.click();

            // 开始监听弹窗
            startModalWatcher();
        } else {
            console.log('未找到提交按钮,尝试其他选择器...');

            // 备用选择器
            const backupButton = document.querySelector('.index__submit--jiKIA') ||
                                document.querySelector('button[class*="submit"]') ||
                                document.querySelector('button:contains("提交")');

            if (backupButton) {
                console.log('使用备用选择器找到提交按钮');
                backupButton.click();
                startModalWatcher();
            } else {
                console.log('完全找不到提交按钮');
            }
        }
    }

    function startModalWatcher() {
        console.log('开始监听弹窗...');

        // 监听DOM变化,检测弹窗出现
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    // 检查是否出现评价原因弹窗
                    const reasonModal = document.querySelector('.ant-modal-content .ant-modal-title');
                    if (reasonModal && reasonModal.textContent.includes('评价原因')) {
                        observer.disconnect(); // 找到后停止监听,避免重复触发
                        handleReasonModal();
                        return;
                    }
                }
            });
        });

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

        // 15秒后停止监听
        setTimeout(() => {
            observer.disconnect();
            console.log('停止监听弹窗');
        }, 15000);
    }

    function handleReasonModal() {
        console.log('检测到评价原因弹窗');

        setTimeout(() => {
            // 使用更精确的选择器来查找弹窗中的文本框
            let modalTextarea = document.querySelector('.index__reason_modal_content--N1LsY textarea.ant-input');

            // 备用选择器
            if (!modalTextarea) {
                modalTextarea = document.querySelector('.index__root--sPKi7 textarea.ant-input');
            }

            // 再次备用选择器
            if (!modalTextarea) {
                modalTextarea = document.querySelector('.ant-modal-body textarea.ant-input');
            }

            if (modalTextarea) {
                console.log('找到弹窗文本框,开始强制填写评价原因');

                // 使用保存的自定义内容
                const savedAnswers = getSavedAnswers();
                const text = savedAnswers.answer3;
                console.log('弹窗评价原因内容:', text);
                forceInputText(modalTextarea, text);

                // 等待一下后点击确定
                setTimeout(() => {
                    const confirmButton = document.querySelector('.ant-modal-footer .ant-btn-primary');
                    if (confirmButton) {
                        confirmButton.click();
                        console.log('已点击评价原因确定按钮');

                        // 等待7秒后处理最终确认弹窗
                        setTimeout(() => {
                            handleFinalConfirmModal();
                        }, 7000);
                    }
                }, 2000);

            } else {
                console.log('未找到弹窗中的文本框');
            }
        }, 500);
    }

    // 强制输入文本的方法
    function forceInputText(element, text) {
        console.log('开始强制输入文本:', text);

        // 方法1: 直接设置value并触发事件
        element.focus();
        element.value = '';
        triggerAllEvents(element);

        element.value = text;
        triggerAllEvents(element);

        // 方法2: 使用execCommand (如果支持)
        try {
            element.focus();
            element.select();
            document.execCommand('insertText', false, text);
            triggerAllEvents(element);
        } catch(e) {
            console.log('execCommand方法失败:', e);
        }

        // 方法3: 模拟键盘输入
        element.focus();
        element.value = '';

        for (let i = 0; i < text.length; i++) {
            const char = text[i];

            // 模拟keydown事件
            const keydownEvent = new KeyboardEvent('keydown', {
                key: char,
                code: `Key${char.toUpperCase()}`,
                bubbles: true,
                cancelable: true
            });
            element.dispatchEvent(keydownEvent);

            // 设置值
            element.value += char;

            // 模拟input事件
            const inputEvent = new InputEvent('input', {
                bubbles: true,
                cancelable: true,
                inputType: 'insertText',
                data: char
            });
            element.dispatchEvent(inputEvent);

            // 模拟keyup事件
            const keyupEvent = new KeyboardEvent('keyup', {
                key: char,
                code: `Key${char.toUpperCase()}`,
                bubbles: true,
                cancelable: true
            });
            element.dispatchEvent(keyupEvent);
        }

        // 方法4: 强制设置并触发React事件
        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
        nativeInputValueSetter.call(element, text);

        const inputEvent = new Event('input', { bubbles: true });
        element.dispatchEvent(inputEvent);

        // 最后再次触发所有事件
        triggerAllEvents(element);

        console.log('强制输入完成,当前值:', element.value);

        // 检查字数显示
        setTimeout(() => {
            const countElement = document.querySelector('.index__count_wrap--m1keW span:first-child');
            if (countElement) {
                console.log('弹窗字数显示:', countElement.textContent);
            }
        }, 100);
    }

    // 处理最终确认弹窗 - 点击所有确定按钮
    function handleFinalConfirmModal() {
        console.log('等待7秒后,开始处理最终确认弹窗...');

        // 查找当前页面上的所有确定按钮
        const confirmButtons = [
            // 精确选择器
            document.querySelector('.ant-modal-content .ant-btn-primary'),
            // 包含"确定"文本的按钮
            ...Array.from(document.querySelectorAll('button')).filter(btn =>
                btn.textContent.includes('确定') || btn.textContent.includes('确 定')
            ),
            // 通用的primary按钮
            document.querySelector('.ant-btn-primary'),
            // 弹窗中的primary按钮
            document.querySelector('.ant-modal-body ~ div .ant-btn-primary'),
            // 更多备用选择器
            ...Array.from(document.querySelectorAll('.ant-btn-primary')),
            ...Array.from(document.querySelectorAll('button[class*="primary"]')),
            ...Array.from(document.querySelectorAll('.ant-modal .ant-btn'))
        ].filter(Boolean); // 过滤掉null值

        // 去重
        const uniqueButtons = [...new Set(confirmButtons)];

        console.log(`找到 ${uniqueButtons.length} 个可能的确定按钮,准备全部点击`);

        if (uniqueButtons.length > 0) {
            // 依次点击所有按钮,每个按钮间隔500ms
            uniqueButtons.forEach((button, index) => {
                setTimeout(() => {
                    try {
                        // 如果按钮被禁用,先启用它
                        if (button.disabled || button.hasAttribute('disabled')) {
                            console.log(`按钮${index + 1}被禁用,正在启用...`);
                            button.removeAttribute('disabled');
                            button.disabled = false;

                            // 移除倒计时文本
                            const countdownSpan = button.querySelector('span[style*="margin-left"]');
                            if (countdownSpan) {
                                countdownSpan.remove();
                                console.log(`已移除按钮${index + 1}的倒计时文本`);
                            }
                        }

                        // 点击按钮
                        console.log(`点击第${index + 1}个确定按钮:`, button);
                        console.log(`按钮文本: "${button.textContent.trim()}"`);
                        button.click();

                        // 如果是最后一个按钮,等待3秒后查找成功弹窗
                        if (index === uniqueButtons.length - 1) {
                            console.log('所有确定按钮已点击完成!等待3秒后查找成功弹窗...');
                            setTimeout(() => {
                                handleSuccessModal();
                            }, 3000);
                        }
                    } catch (error) {
                        console.log(`点击按钮${index + 1}时出错:`, error);
                    }
                }, index * 500); // 每个按钮间隔500ms
            });
        } else {
            console.log('未找到任何确定按钮,尝试重新查找...');

            // 如果没找到,再等待3秒重试一次
            setTimeout(() => {
                const retryButtons = Array.from(document.querySelectorAll('button')).filter(btn =>
                    btn.textContent.includes('确定') ||
                    btn.textContent.includes('确 定') ||
                    btn.classList.contains('ant-btn-primary')
                );

                if (retryButtons.length > 0) {
                    console.log(`重试找到${retryButtons.length}个确定按钮,全部点击...`);
                    retryButtons.forEach((button, index) => {
                        setTimeout(() => {
                            button.removeAttribute('disabled');
                            button.disabled = false;
                            button.click();
                            console.log(`重试点击按钮${index + 1}`);

                            // 如果是最后一个按钮,等待3秒后查找成功弹窗
                            if (index === retryButtons.length - 1) {
                                setTimeout(() => {
                                    handleSuccessModal();
                                }, 3000);
                            }
                        }, index * 200);
                    });
                } else {
                    console.log('重试后仍未找到确定按钮');
                    isProcessing = false;
                }
            }, 3000);
        }
    }

    // 处理提交成功弹窗
    function handleSuccessModal() {
        console.log('开始查找提交成功弹窗...');

        // 查找包含"提交成功"的弹窗
        const successModal = Array.from(document.querySelectorAll('.ant-modal-body')).find(modal =>
            modal.textContent.includes('提交成功')
        );

        if (successModal) {
            console.log('找到提交成功弹窗');

            // 查找"下一门课程"按钮
            const nextCourseButton = Array.from(successModal.querySelectorAll('button')).find(btn =>
                btn.textContent.includes('下一门课程')
            );

            if (nextCourseButton) {
                console.log('找到"下一门课程"按钮,准备点击...');
                nextCourseButton.click();
                console.log('已点击"下一门课程"按钮');

                // 重置处理状态,准备处理下一门课程
                setTimeout(() => {
                    isProcessing = false;
                    console.log('准备开始下一门课程的评价...');

                    // 等待页面加载后重新开始
                    setTimeout(() => {
                        waitForElements();
                    }, 2000);
                }, 1000);
            } else {
                console.log('未找到"下一门课程"按钮,查找其他可能的按钮...');

                // 查找primary按钮作为备选
                const primaryButton = successModal.querySelector('.ant-btn-primary');
                if (primaryButton) {
                    console.log('找到primary按钮,尝试点击:', primaryButton.textContent);
                    primaryButton.click();

                    setTimeout(() => {
                        isProcessing = false;
                        setTimeout(() => {
                            waitForElements();
                        }, 2000);
                    }, 1000);
                } else {
                    console.log('未找到任何可点击的按钮');
                    isProcessing = false;
                }
            }
        } else {
            console.log('未找到提交成功弹窗,尝试重新查找...');

            // 重新查找,使用更宽泛的条件
            setTimeout(() => {
                const allButtons = Array.from(document.querySelectorAll('button')).filter(btn =>
                    btn.textContent.includes('下一门课程') ||
                    btn.textContent.includes('下一门') ||
                    btn.textContent.includes('下一')
                );

                if (allButtons.length > 0) {
                    console.log(`找到${allButtons.length}个可能的"下一门课程"按钮`);
                    allButtons[0].click();
                    console.log('已点击第一个"下一门课程"按钮');

                    setTimeout(() => {
                        isProcessing = false;
                        setTimeout(() => {
                            waitForElements();
                        }, 2000);
                    }, 1000);
                } else {
                    console.log('完全未找到"下一门课程"按钮');
                    isProcessing = false;
                }
            }, 2000);
        }
    }

    // 添加控制按钮
    function addControlButtons() {
        // 自动填写评价按钮
        const fillButton = document.createElement('button');
        fillButton.innerText = '自动填写评价';
        fillButton.style.cssText = `
            position: fixed;
            top: 10px;
            right: 10px;
            z-index: 9999;
            padding: 10px 15px;
            background-color: #1890ff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        `;

        fillButton.addEventListener('click', () => {
            isProcessing = false;
            fillForm();
        });

        // 设置按钮
        const configButton = document.createElement('button');
        configButton.innerText = '设置填空题';
        configButton.style.cssText = `
            position: fixed;
            top: 10px;
            right: 140px;
            z-index: 9999;
            padding: 10px 15px;
            background-color: #52c41a;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        `;

        configButton.addEventListener('click', createConfigModal);

        document.body.appendChild(fillButton);
        document.body.appendChild(configButton);
    }

    // 页面加载完成后开始执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(() => {
                waitForElements();
                addControlButtons();
            }, 2000);
        });
    } else {
        setTimeout(() => {
            waitForElements();
            addControlButtons();
        }, 2000);
    }

})();