Greasy Fork

Greasy Fork is available in English.

问卷星自动重复提交

自动重复提交问卷星问卷

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         问卷星自动重复提交
// @namespace    http://tampermonkey.net/
// @version      2024-09-26
// @description  自动重复提交问卷星问卷
// @author       xuhaibo
// @match        https://www.wjx.cn/*
// @icon         https://img.wxcha.com/m00/55/20/fb56b8fbf0b1da032771414c3dcee029.jpg
// @grant        none
// @license      MIT
// ==/UserScript==


(function () {
    'use strict';

    // ===============================================参数================================
    // 选中停留
    let time_interval = 200


    // ===============================================依赖数据================================
    // 读取和存放数据
    let user_obj = {
        get: function (key) {
            console.log('读取 key = ', key, ' value = ', JSON.parse(sessionStorage.getItem(key)))
            return JSON.parse(sessionStorage.getItem(key));
        },
        set: function (key, value) {
            console.log('存储 key = ', key, ' value = ', value)
            sessionStorage.setItem(key, JSON.stringify(value));
        }
    }

    // ===============================================创建元素================================
    let create_button = function (text, bottom, fun) {
        console.log('添加按钮 = ', text)
        // 创建按钮
        const button = document.createElement('button');
        // 设置按钮样式
        button.style.position = 'fixed'; // 固定定位
        button.style.zIndex = '9999999999';
        button.style.bottom = bottom + 'px'; // 距离底部20像素
        button.style.right = '20px'; // 距离右侧20像素
        button.style.maxWidth = '250px'; // 按钮宽度
        button.style.padding = '15px';
        button.style.backgroundColor = '#007bff'; // 背景颜色
        button.style.color = '#ffffff'; // 文字颜色
        button.style.border = 'none'; // 无边框
        button.style.borderRadius = '10px'; // 圆角
        button.style.cursor = 'pointer'; // 鼠标指针样式
        button.style.fontSize = '20px';
        button.innerText = text; // 按钮文本
        button.style.boxShadow = '0 4px 10px rgba(0, 0, 0, 0.3)'; // 添加阴影
        button.style.border = '2px solid white'; // 添加白色边框
        // 添加悬停效果
        button.style.transition = 'transform 0.5s ease'; // 将过渡时间设置为 1 秒

        button.addEventListener('mouseenter', () => {
            button.style.transform = 'scale(1.1)'; // 悬停放大

        });
        button.addEventListener('mouseleave', () => {
            button.style.transform = 'scale(1)'; // 还原大小
        });

        // 定义点击事件处理函数
        function handleClick() {
            console.log(text + '按钮被点击了!');
            fun(button);
            // button.style.backgroundColor = '#9dd4fa';
            // button.innerText = click_text;
            // 移除事件监听器
            // button.removeEventListener('click', handleClick);
        }

        // 添加点击事件
        button.addEventListener('click', handleClick);

        // 将按钮添加到页面
        document.body.appendChild(button);

        return button;
    }

    let create_input = function (text, bottom, id, fun = (input) => {
    }) {
        // 创建容器
        const container = document.createElement('div');
        container.style.position = 'fixed';
        container.style.zIndex = '9999999999';
        container.style.bottom = bottom + 'px';
        container.style.right = '20px'; // 距离右侧20像素
        container.style.backgroundColor = '#3192fa'; // 设置背景颜色为蓝色
        container.style.color = '#ffffff';
        container.style.border = '2px solid white'; // 添加白色边框
        container.style.padding = '6px';
        container.style.borderRadius = '10px';
        // 创建标题
        const label = document.createElement('label');
        label.textContent = text + ':';

        // 创建输入框
        const input = document.createElement('input');
        input.type = 'number';
        input.min = 1;
        input.max = 99999;
        input.style.width = '100px';
        input.style.fontSize = '18px';
        input.style.border = '2px solid white';
        input.id = id
        input.value = 100;
        // 添加输入事件监听器以限制输入值
        input.addEventListener('input', function () {
            // 转换输入值为数字
            console.log('触发输入事件 = ',)
            const value = Number(input.value);
            // 如果输入的值小于1或大于99999,则重置为空
            if (value < 1 || value > 9999999 || isNaN(value)) {
                input.value = '';
            }
        });

        // 将标题和输入框添加到容器中
        container.appendChild(label);
        container.appendChild(input);

        fun(input)

        // 将容器添加到网页中
        document.body.appendChild(container);

        return input
    }

    let create_input_min_max = function (text, bottom) {
        // 创建容器
        const container = document.createElement('div');
        container.style.position = 'fixed';
        container.style.zIndex = '9999999999';
        container.style.bottom = bottom + 'px';
        container.style.right = '20px'; // 距离右侧20像素
        container.style.backgroundColor = '#3192fa'; // 设置背景颜色为蓝色
        container.style.color = '#ffffff';
        container.style.border = '2px solid white'; // 添加白色边框
        container.style.padding = '6px';
        container.style.borderRadius = '10px';
        // 创建标题
        const label = document.createElement('label');
        label.textContent = text + ':';

        // 创建输入框
        const input = document.createElement('input');
        input.type = 'number';
        input.min = 1;
        input.max = 99999;
        input.style.width = '100px';
        input.style.fontSize = '18px';
        input.style.border = '2px solid white';
        input.value = 1;
        input.style.width = '50px';
        input.style.display = 'inline-block'; // 设置为行内块元素
        input.style.marginLeft = '10px'; // 左边距为10px
        // 添加输入事件监听器以限制输入值
        input.addEventListener('input', function () {
            // 转换输入值为数字
            console.log('触发输入事件 = ',)
            const value = Number(input.value);
            // 如果输入的值小于1或大于99999,则重置为空
            if (value < 1 || value > 9999999 || isNaN(value)) {
                input.value = '';
            }
        });

        // 创建输入框
        const input2 = document.createElement('input');
        input2.type = 'number';
        input2.min = 1;
        input2.max = 99999;
        input2.style.fontSize = '18px';
        input2.style.border = '2px solid white';
        input2.style.width = '50px';
        input2.style.display = 'inline-block'; // 设置为行内块元素
        input2.style.marginLeft = '10px'; // 左边距为10px
        input2.value = 2;
        // 添加输入事件监听器以限制输入值
        input2.addEventListener('input', function () {
            // 转换输入值为数字
            console.log('触发输入事件 = ',)
            const value = Number(input.value);
            // 如果输入的值小于1或大于99999,则重置为空
            if (value < 1 || value > 9999999 || isNaN(value)) {
                input2.value = '';
            }
        });

        // 创建伪类内容(文本)
        const span = document.createElement('span');
        span.textContent = '到'; // 伪类内容
        span.style.marginLeft = '7px'; // 左边距
        span.style.color = 'white'; // 文字颜

        // 将标题和输入框添加到容器中
        container.appendChild(label);
        container.appendChild(input);
        container.appendChild(span);
        container.appendChild(input2);

        // 将容器添加到网页中
        document.body.appendChild(container);

        return function () {
            return [Number(input.value), Number(input2.value)]
        }
    }


    // 处理选项,思路是取当前提交的数据,为下一次选择做参数
    // ===============================================处理单选================================
    let save_ui_radio_value = function () {
        let arr_ui_radio_value = []
        let arr_ui_radio_checked = document.querySelectorAll('.ui-radio.checked')

        for (let i = 0; i < arr_ui_radio_checked.length; i++) {
            arr_ui_radio_value.push(arr_ui_radio_checked[i].innerText)
        }
        user_obj.set('arr_ui_radio_value', arr_ui_radio_value);
    }


    let auto_do_ui_radio = async function () {
        let arr_value = user_obj.get('arr_ui_radio_value')
        let arr_note_ui_radio = document.querySelectorAll('.ui-radio')

        for (let note of arr_note_ui_radio) {
            if (!arr_value.length) return
            if (note.innerText == arr_value[0]) {

                // 闭包
                await new Promise((resolve) => {
                    setTimeout(() => {
                        note.click()
                        resolve()
                    }, time_interval)
                })

                console.log('单选选中 = ', note.innerText)

                arr_value.shift()
            }
        }
    }

    // ===============================================处理多选================================
    let save_ui_checkbox_value = function () {
        let arr_ui_checkbox_value = []
        let arr_note_ui_checkbox_value = document.querySelectorAll('.ui-checkbox.checked')
        console.log(' arr_note_ui_checkbox_value= ', arr_note_ui_checkbox_value)

        for (let i = 0; i < arr_note_ui_checkbox_value.length; i++) {
            arr_ui_checkbox_value.push(arr_note_ui_checkbox_value[i].innerText)
        }
        user_obj.set('arr_ui_checkbox_value', arr_ui_checkbox_value);
    }


    let auto_do_ui_checkbox = async function () {
        let arr_value = user_obj.get('arr_ui_checkbox_value')
        let arr_note_ui_checkbox = document.querySelectorAll('.ui-checkbox')

        for (let note of arr_note_ui_checkbox) {
            if (!arr_value.length) return
            if (note.innerText == arr_value[0]) {

                // 闭包
                await new Promise((resolve) => {
                    setTimeout(() => {
                        note.click()
                        resolve()
                    }, time_interval)
                })


                console.log('多选选中 = ', note.innerText)

                arr_value.shift()
            }
        }
    }
    // ===============================================处理评分================================
    // rate-off rate-on rate-ontxt
    let save_rate_value = function () {
        let arr_value = []
        let arr_note = document.querySelectorAll('.rate-off.rate-on.rate-ontxt')

        for (let i = 0; i < arr_note.length; i++) {
            arr_value.push(arr_note[i].innerText)
        }
        user_obj.set('arr_rate_value', arr_value);
    }


    let auto_do_rate = async function () {
        let arr_value = user_obj.get('arr_rate_value')
        let arr_note = document.querySelectorAll('.scale-rating')
        console.log('arr_note = ', arr_note)
        for (let i = 0; i < arr_note.length; i++) {
            await new Promise((resolve) => {
                setTimeout(() => {
                    arr_note[i].querySelector('ul').querySelectorAll('li')[arr_value[i] - 1].click()
                    resolve()
                }, time_interval)
            })
        }
    }
    // ========================================流程控制=========================================

    // 通过智能点击验证
    let pass_sure = async function () {
        new Promise((resolve) => {
            let time_id = setInterval(() => {
                console.log('找智能按钮认证按钮')
                let pass_bt = document.querySelector('#SM_BTN_1')
                if (pass_bt) {
                    pass_bt.click()
                    console.log('能按钮认 = ', pass_bt)
                    clearInterval(time_id)
                    resolve()
                }
            }, 200)
        })
    }

    // 通过滑块
    let pass_slide = async function () {
        var btn = ''

        await new Promise((resolve) => {
            let time_id = setInterval(() => {
                console.log('找滑块找滑块 = ')
                btn = document.querySelector("#nc_1_n1z");
                if (btn) {
                    console.log('找到滑块btn = ', btn)
                    clearInterval(time_id)
                    resolve()
                }
            }, 200)
        })

        const rect = btn.getBoundingClientRect();
        const startX = rect.left + window.scrollX; // 计算滑块的起始位置
        const startY = rect.top + window.scrollY;

        // 模拟鼠标按下
        btn.dispatchEvent(new MouseEvent('mousedown', {
            bubbles: true,
            clientX: startX,
            clientY: startY,
        }));

        let dx = 0;
        const totalDistance = 308; // 滑块需要移动的总距离
        const interval = setInterval(() => {
            const mouseX = startX + dx;

            // 模拟鼠标移动
            btn.dispatchEvent(new MouseEvent('mousemove', {
                bubbles: true,
                clientX: mouseX,
                clientY: startY,
            }));
            dx += Math.ceil(Math.random() * 50); // 随机增加移动距离
        }, 60);
    }

    // 取消叫去点验证对话框
    let pass_dialog = function () {
        let time_id = setInterval(() => {
            let note = document.querySelector('.layui-layer.layui-layer-dialog')
            if (note) {
                note = note.querySelector('.layui-layer-btn0')
                if (note) {
                    note.click()
                    clearInterval(time_id)
                }
            }
        }, 200)
    }

    // 取消上一次记录
    let pass_dialog_before = function () {
        let time_id = setInterval(() => {
            let note = document.querySelector('.layui-layer.layui-layer-dialog')
            if (note) {
                note = note.querySelector('.layui-layer-btn1')
                if (note) {
                    console.log('取消上一次填写记录 = ')
                    note.click()
                    clearInterval(time_id)
                }
            }
        }, 200)
        setTimeout(() => {
            clearInterval(time_id)
        }, 5000)
    }

    // 确认提交
    let sure_submit = async function () {
        await new Promise(async (resolve) => {
            setTimeout(async () => {
                document.querySelector('.submitbtn.mainBgColor').click()

                // 关闭提示点智能验证
                pass_dialog()
                // 等点智能验证
                await pass_sure()
                // 滚动条,这个之后就结束了
                pass_slide()
                resolve()

            }, 200)
        })
    }

    // 是否存在必填未填
    let hasErrorMessage = function () {
        return new Promise(async (resolve, reject) => {
            setTimeout(() => {

                let arr_field = document.querySelectorAll('.field.ui-field-contain')

                //  ==================是否选过了一个
                let has_one_checked = false
                for (let i = 0; i < arr_field.length; i++) {
                    let temp = arr_field[i].querySelector('.checked')
                    if (temp) {
                        console.log('填写了 = ', temp)
                        has_one_checked = true
                    }
                }
                if (!has_one_checked) {
                    console.log('一个都没有填写!!!!!!!!!!!!! = ')
                    return reject('先填写完所有必填选项噢,填后点我重试')
                }

                // ==================如果有东西没填写
                for (let i = 0; i < arr_field.length; i++) {
                    let temp = arr_field[i].querySelector('.errorMessage')
                    temp = temp.style.display
                    if (temp == 'block') {
                        console.log('必填未填 = ', temp)
                        return reject('你的必填选项未填噢,填后点我重试')
                    }
                }

                return resolve()

            }, 300 + 100)
        })
    }

    // 移除原来的确认框
    let remove_divSubmit = function () {
        let divSubmit = document.querySelector('#divSubmit')
        divSubmit.style.visibility = 'hidden'
    }


    // 开启脚本
    let start_script = function () {
        // 开启自动选中
        let auto_select = async function () {
            await auto_do_ui_radio()
            await auto_do_ui_checkbox()
            await auto_do_rate()
            await sure_submit()
        }

        // 保存当前选中的数据
        let save_data = function () {
            save_ui_radio_value()
            save_ui_checkbox_value()
            save_rate_value()
        }

        // 是否开启自动提交
        let start_auto = user_obj.get('start_auto')

        if (start_auto) {
            // 创建按钮
            create_button('🔵自动提交中....点我停止自动提交', 50, (button) => {
                user_obj.set('start_auto', false)
                button.innerText = '🟦提交完这份后就会停止'
                button.style.backgroundColor = '#a4dcf5'
                let note_auto_do_num = document.querySelector('#auto_do_num')
                note_auto_do_num.value = '1'
            })

            // 获取数量
            let auto_do_num = user_obj.get('auto_do_num')
            create_input('剩余提交数量', 150, 'auto_do_num', (input) => {
                input.value = auto_do_num
                input.readOnly = true; // 设置输入框为只读
            })

            // 获取数量
            let finish_do_num = user_obj.get('finish_do_num')
            create_input('已提交的数量', 200, 'finish_do_num', (input) => {
                input.value = finish_do_num
                input.readOnly = true; // 设置输入框为只读
            })

            let getRandomInt = function (n, m) {
                console.log('放进来 = ', n, m)
                if(n == m) return 0
                // 确保 n 小于等于 m
                if (n > m) {
                    [n, m] = [m, n];
                }
                return Math.floor(Math.random() * (m - n + 1)) + n;
            }

            if (auto_do_num < 2) {
                // 下次停止
                user_obj.set('start_auto', false)
            } else {
                // 每次减1
                user_obj.set('auto_do_num', auto_do_num - 1)
                // 加1
                user_obj.set('finish_do_num', finish_do_num + 1)
            }

            // Nan和0为false
            let stop_time = getRandomInt( Number(user_obj.get('min_time')), Number(user_obj.get('max_time')))

            if (stop_time) {
                console.log(' 时间限制 = ', stop_time)
                let note_input = ''
                create_input('停留倒计时', 250, 'stop_time', (input) => {
                    input.value = stop_time
                    input.readOnly = true; // 设置输入框为只读
                    note_input = input
                })

                // 显示倒计时
                let time_id = setInterval(function () {
                    stop_time--
                    note_input.value = stop_time
                    if (stop_time == 0) {
                        clearInterval(time_id)
                        auto_select()
                    }
                }, 1000)
            } else {
                console.log('没有时间限制 = ')
                auto_select()
            }

        } else {

            // 获取数量
            // let finish_do_num = user_obj.get('finish_do_num')
            // if(finish_do_num){
            //     create_input('上次完成提交数', 200, 'finish_do_num', (input) => {
            //         input.value = finish_do_num
            //         input.readOnly = true; // 设置输入框为只读
            //     })
            // }

            let get_min_max = create_input_min_max('随机停留时间区间(秒)', 200)

            // let note_stop_time = create_input('提交停留时间(秒)', '200', 'stop_time', (input) => {
            //     input.value = 5
            // })

            let note_auto_do_num = create_input('提交数量', 150, 'auto_do_num')

            create_button('👉点我自动重复提交', 50, async (button) => {
                document.querySelector('.submitbtn.mainBgColor').click()
                hasErrorMessage().then(
                    () => {

                        button.innerText = '✅成功!开启自动提交.........'

                        let [min_time, max_time] = get_min_max()

                        // 保存数据
                        user_obj.set('auto_do_num', note_auto_do_num.value - 1)
                        user_obj.set('min_time',min_time)
                        user_obj.set('max_time',max_time)
                        user_obj.set('finish_do_num', 1)
                        user_obj.set('start_auto', true)
                        save_data()

                        // 最后再通过
                        pass_sure()
                        pass_slide()
                    },
                    err => {
                        button.innerText = '✖️'+err
                    }
                )
            })
        }
    }


    // ===============================================程序入口================================
    let id = setInterval(function () {

        // 跳转界面
        let go_write_Page = function () {
            let writePage = user_obj.get('writePage')
            console.log('跳转 writePage= ', writePage)
            window.location.href = writePage; // 跳转到保存的页面
        }

        // 记录当前界面
        let save_write_Page = function () {
            let writePage = window.location.href;
            user_obj.set('writePage', writePage)
        }

        // 广告界面
        let divContent2 = document.querySelector('.chuangGuanWrap.wrapmargin')
        if (divContent2) {
            // 先选中页面
            go_write_Page()
            clearInterval(id)
        } else {
            // 不是广告界面
            let divContent = document.querySelector('.divContent')
            if (divContent) {
                console.log('获取元素成功,开启脚本')

                // 保存界面
                save_write_Page()

                // 取消上次
                pass_dialog_before()

                // 移除提交
                // remove_divSubmit()

                // 开启脚本
                start_script()

                clearInterval(id)
            } else {
                console.log('页面没加载完!!!!进入下一次查询 = ',)
            }
        }
    }, 100)

})();