考试宝答题界面优化

优化考试宝答题界面UI,增加按键绑定

目前为 2023-06-28 提交的版本。查看 最新版本

// ==UserScript==
// @name        考试宝答题界面优化
// @namespace   https://github.com/AliubYiero/TemperScripts
// @version     1.2.6
// @description 优化考试宝答题界面UI,增加按键绑定
// @author      Yiero
// @match       https://www.zaixiankaoshi.com/*
// @icon        https://www.zaixiankaoshi.com/favicon.ico
// @license     GPL
// @grant       GM_addStyle
// ==/UserScript==

"use strict";
class FunctionChainCall {
    callChain;
    constructor() {
        this.callChain = [];
    }
    set(fn, params = []) {
        this.callChain.push([fn, params]);
    }
    setList(array) {
        array.forEach((fn) => {
            if (!Array.isArray(fn)) {
                this.set(fn);
                return;
            }
            this.set(fn[0], fn[1]);
        });
    }
    show() {
        console.info(this.callChain);
    }
    async call() {
        let returnString;
        while (this.callChain[0]) {
            if (returnString === 'stop') {
                return;
            }
            else if (returnString === 'skip') {
                this.callChain.shift();
                continue;
            }
            const fn = this.callChain[0];
            returnString = await fn[0].apply(null, fn[1]);
            this.callChain.shift();
        }
    }
}
const functionChainCall = new FunctionChainCall();
class SubmitAnswerStatusChange {
    static isSubmit = false;
    static submit() {
        this.isSubmit = true;
    }
    static close() {
        this.isSubmit = false;
    }
    static fresh() {
        this.close();
    }
}
class OptionObserver extends MutationObserver {
    constructor(Node, callback) {
        super(callback);
        super.observe(Node, {
            childList: true
        });
    }
}
function urlJudge(urlHeader) {
    if (typeof urlHeader === 'string') {
        urlHeader = new RegExp(urlHeader);
    }
    return !!document.URL.match(urlHeader);
}
function bindPageReloadEvent() {
    console.log('Bind page reload event.');
    function reloadPage() {
        console.info('Reload Page.');
        location.reload();
    }
    window.addEventListener('hashchange', reloadPage);
    let _pushState = window.history.pushState;
    window.history.pushState = function () {
        setTimeout(reloadPage, 1000);
        return _pushState.apply(this, arguments);
    };
}
function removeExtraElement() {
    GM_addStyle(`
		/* 居中主容器 */
		.app-main {
			display: flex;
			justify-content: center;
			align-items: center;
			padding: 0;
		}
		
		/* 优化主容器UI */
		.middle-container {
			padding: 10px ${16 + 19 + 16 + 10}px;
			border-radius: 10px;
		}
		
		/* 隐藏多余元素 */
		.vip-quanyi,
		.new-footer,
		.header,
		.answer-box-detail,
		.answer-box-detail,
		.vip-tips,
		.right-float-window,
		.page-main .pull-right > :not(.serch-form)
		{
			display: none;
		}
	`);
}
function unlockRandomOption() {
    if (!urlJudge(/https:\/\/www\.zaixiankaoshi\.com\/mnks\/\?paperid/)) {
        return;
    }
    localStorage.removeItem('openRandomOption');
    console.info('Remove Origin Random Option Btn. ');
    const formContainer = document.querySelectorAll('div.box-card > form > div');
    let randomOptionLabel;
    formContainer.forEach(formItem => {
        if (formItem.querySelector('label')?.innerText === '选项乱序') {
            randomOptionLabel = formItem;
        }
    });
    const randomOptionBtn = randomOptionLabel.querySelector('div');
    randomOptionBtn.remove();
    const reRandomOptionBtnContainer = document.createElement('form');
    reRandomOptionBtnContainer.id = 'random-option-container';
    reRandomOptionBtnContainer.style.height = '40px';
    reRandomOptionBtnContainer.style.lineHeight = '40px';
    reRandomOptionBtnContainer.innerHTML = `
		<input type="radio" name="randomOption" id="random-option--open" value="true">
		<label for="random-option--open">开启</label>
		<input type="radio" name="randomOption" id="random-option--close" value="false">
		<label for="random-option--close">关闭</label>
		<!-- <div style="text-indent: 2em;color:red;background:#f8f8f8;">请注意,当您开启本脚本的随机选项时,您需要使用键盘选择选项,使用鼠标选择选项会出现选项映射错误导致无法获得正确答案。</div> -->
	`;
    randomOptionLabel.append(reRandomOptionBtnContainer);
    reRandomOptionBtnContainer.addEventListener('change', e => {
        localStorage.setItem('openRandomOption', e.target.value);
    });
}
function addQuickOption() {
    if (!urlJudge(/https:\/\/www\.zaixiankaoshi\.com\/mnks\/\?paperid/)) {
        return;
    }
    console.info('Add quick question choose option. ');
    const tableContainer = document.querySelector('.custom-table');
    const colList = tableContainer.querySelectorAll('tr:not(:last-of-type)');
    colList.forEach(col => {
        const row = col.querySelector('td:nth-of-type(2)');
        const colInput = row.querySelector('input');
        const { min, max } = colInput;
        const maxBtn = document.createElement('button');
        maxBtn.classList.add('el-button');
        maxBtn.innerText = 'Max';
        maxBtn.addEventListener('click', e => {
            e.preventDefault();
            colInput.value = max;
        });
        const minBtn = document.createElement('button');
        minBtn.classList.add('el-button');
        minBtn.innerText = 'Min';
        minBtn.addEventListener('click', e => {
            e.preventDefault();
            colInput.value = min;
        });
        const tenPercentBtn = document.createElement('button');
        tenPercentBtn.classList.add('el-button');
        tenPercentBtn.innerText = '10%';
        tenPercentBtn.addEventListener('click', e => {
            e.preventDefault();
            colInput.value = String(Math.ceil(parseInt(max) * 0.1));
        });
        row.append(maxBtn);
        row.append(minBtn);
        row.append(tenPercentBtn);
    });
}
functionChainCall.set(addQuickOption);
function isAnswerUI() {
    const localURL = document.URL.split('/');
    console.log(localURL[localURL.length - 2]);
    if (['online', 'simulation'].indexOf(localURL[localURL.length - 2]) === -1) {
        console.info('非答题界面,已退出');
        bindPageReloadEvent();
        return 'stop';
    }
}
function useRandomOption() {
    if (localStorage.getItem('openRandomOption') !== 'true' || !urlJudge('https://www.zaixiankaoshi.com/mnks/simulation/')) {
        return;
    }
    console.info('Use Random Option.');
    const optionContainer = document.querySelector('.select-left');
    const optionList = optionContainer.querySelectorAll('.option');
    let optionArray = [];
    optionList.forEach(option => {
        optionArray.push(option);
    });
    optionArray = optionArray.sort((a, b) => {
        return Math.random() - 0.5;
    });
    console.log(optionArray);
    const upperAlphaList = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
    for (let i = 0; i < optionArray.length; i++) {
        const option = optionArray[i];
        option.querySelector('.before-icon').innerText = upperAlphaList[i];
    }
    optionArray.forEach(option => {
        optionContainer.append(option);
    });
}
function setLargeFont() {
    if (!urlJudge(/https:\/\/www\.zaixiankaoshi\.com\/mnks\/\?paperid/)) {
        return;
    }
    const LargeFontBtn = document.querySelector('div.clearfix.font-set span:nth-of-type(3)');
    LargeFontBtn.click();
}
function initOption() {
    new OptionObserver(document.querySelector('.qusetion-box'), e => {
        console.info('Change question');
        SubmitAnswerStatusChange.fresh();
    });
}
let optionList;
function getOptionContainer() {
    optionList = document.querySelectorAll('.options-w > .option');
    try {
        new OptionObserver(document.querySelector('.top-hd'), e => {
            new OptionObserver(document.querySelector('.options-w'), e => {
                console.info('Fresh Options: ');
                optionList = document.querySelectorAll('.options-w > .option');
            });
        });
    }
    catch (e) {
    }
}
function bindKeyboardEvent() {
    try {
        window.addEventListener('keydown', e => {
            const chosenOptionNumber = parseInt(e.key) - 1;
            if (chosenOptionNumber >= 0 && chosenOptionNumber < optionList.length) {
                console.info('Enter Option Chosen');
                optionList[chosenOptionNumber]?.click();
                return;
            }
            const submitAnswer = document.querySelectorAll('.topic [style="clear: both;"]');
            if (submitAnswer.length === 2 && !SubmitAnswerStatusChange.isSubmit && ['Enter'].indexOf(e.key) !== -1) {
                SubmitAnswerStatusChange.submit();
                submitAnswer[0].querySelector('button').click();
                return;
            }
            SubmitAnswerStatusChange.fresh();
            if (['ArrowLeft'].indexOf(e.key) !== -1 || ['NumpadSubtract'].indexOf(e.code) !== -1) {
                document.querySelector('.next-preve > button:nth-of-type(1)').click();
            }
            else if (['Enter', '+', 'ArrowRight'].indexOf(e.key) !== -1) {
                const rightBtn = document.querySelector('.next-preve > button:nth-of-type(2)');
                if (rightBtn.disabled && urlJudge('https://www.zaixiankaoshi.com/mnks/simulation/')) {
                    let submitBtn = document.querySelector('.submit-btn');
                    submitBtn.click();
                    return;
                }
                rightBtn.click();
            }
        });
    }
    catch (e) {
        console.error(e);
        const isReloadPage = confirm(`
KeyBoard binding got an error, should fresh this page to reload?
按键绑定失败。是否需要重新刷新页面重新载入脚本?
		`);
        if (isReloadPage) {
            location.reload();
        }
    }
}
const fnList = [
    removeExtraElement,
    unlockRandomOption,
    isAnswerUI,
    useRandomOption,
    setLargeFont,
    initOption,
    getOptionContainer,
    bindKeyboardEvent
];
functionChainCall.setList(fnList);
window.onload = () => {
    setTimeout(() => {
        functionChainCall.call();
    }, 1000);
};

QingJ © 2025

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