// ==UserScript==
// @name         广东省国家工作人员学法考试系统自动刷课&&2025年自动考试
// @namespace    http://tampermonkey.net/
// @version      2025.11.11
// @description  广东省专用
// @author       yygdz1921&hzqim
// @match        http*://xfks-study.gdsf.gov.cn/study/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=gdsf.gov.cn
// @require      https://fastly.jsdelivr.net/npm/sweetalert2@11
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // Your code here...
    var log = console.log;
    log("load...");
    function main() {
        log("main...");
        study();
    }
    // 考试
    function exam() {
        log("exam...");
        var answers = [
            //2025年题库
    {"q": "习近平总书记在中国共产党第二十次全国代表大会上的报告中指出", "a": "B"},
    {"q": "习近平总书记2020年11月16日在中央全面依法治国工作会议上的讲话指出", "a": "A"},
    {"q": "习近平总书记在中国共产党第二十次全国代表大会上的报告中指出", "a": "B"},
    {"q": "作出关于全面推进依法治国若干重大问题的决定", "a": "C"},
    {"q": "执行全国代表大会的决议,领导党的全部工作,对外代表中国共产党", "a": "C"},
    {"q": "对于党员因不服纪委或者其他党组织给予本人的处理", "a": "C"},
    {"q": "党政领导干部选拔任用工作条例", "a": "C"},
    {"q": "政法工作条例", "a": "A"},
    {"q": "信访工作条例", "a": "D"},
    {"q": "政治协商工作条例", "a": "A"},
    {"q": "党政机关厉行节约反对浪费条例", "a": "C"},
    {"q": "落实全面从严治党主体责任规定", "a": "B"},
    {"q": "统一战线工作条例", "a": "D"},
    {"q": "全国人民代表大会会议每年举行一次", "a": "D"},
    {"q": "反间谍法", "a": "B"},
    {"q": "反恐怖主义法", "a": "B"},
    {"q": "保守国家秘密法", "a": "C"},
    {"q": "国家坚持经济建设和国防建设", "a": "A"},
    {"q": "科学技术进步法", "a": "A"},
    {"q": "优化营商环境条例", "a": "A"},
    {"q": "张三和李四是邻居", "a": "C"},
    {"q": "国内国际双循环相互促进的新发展格局", "a": "C"},
    {"q": "未成年人网络保护条例", "a": "C"},
    {"q": "古树名木保护条例", "a": "D"},
    {"q": "政务数据共享条例", "a": "C"},
    {"q": "住房租赁条例", "a": "A"},
    {"q": "反不正当竞争法", "a": "C"},
    {"q": "监察法", "a": "B"},
    {"q": "能源法", "a": "D"},
    {"q": "治安管理处罚法", "a": "C"},
    {"q": "法治宣传教育法", "a": "A"},
    {"q": "公职人员政务处分法", "a": "A"},
    {"q": "行政处罚法", "a": "A"},
    {"q": "行政诉讼法", "a": "B"},
    {"q": "重大行政决策程序暂行条例", "a": "C"},
    {"q": "立法法", "a": "A"},
    {"q": "公司法", "a": "C"},
    {"q": "统计法", "a": "B"},
    {"q": "刑法", "a": "D"},
    {"q": "全国人民代表大会和地方各级人民代表大会代表法", "a": "D"},
    {"q": "中共中央关于进一步全面深化改革推进中国式现代化的决定", "a": "ACD"},
    {"q": "坚持党的领导,是社会主义法治的根本要求,是党和国家的", "a": "AB"},
    {"q": "党章规定,国有企业党委", "a": "BCD"},
    {"q": "推进领导干部能上能下规定", "a": "ABC"},
    {"q": "重大事项请示报告条例", "a": "AB"},
    {"q": "机构编制工作情况和纪律要求执行情况应当纳入", "a": "ABCD"},
    {"q": "中国共产党问责条例", "a": "ABD"},
    {"q": "国家保护和改善", "a": "AB"},
    {"q": "突发事件应对法", "a": "ABC"},
    {"q": "国家安全法", "a": "ABCD"},
    {"q": "赵某在下班途中看到一位老人摔倒在地", "a": "ACD"},
    {"q": "中华人民共和国国防教育法", "a": "BC"},
    {"q": "增值税法", "a": "ABCD"},
    {"q": "国家实行公民终身法治教育制度", "a": "ABC"},
    {"q": "公务员法", "a": "AB"},
    {"q": "行政强制法", "a": "ABC"},
    {"q": "循环经济促进法", "a": "BCD"},
    {"q": "未成年人保护法", "a": "ABCD"},
    {"q": "预防未成年人犯罪法", "a": "BD"},
    {"q": "负有法治宣传教育职责的部门", "a": "ABD"},
    {"q": "中国共产党纪律检查委员会工作条例", "a": "对"},
    {"q": "部门规章和规范性文件不得就机构编制事项作出具体规定", "a": "对"},
    {"q": "中国共产党纪律处分条例", "a": "错"},
    {"q": "中国共产党党内监督条例", "a": "错"},
    {"q": "中国共产党党组工作条例", "a": "错"},
    {"q": "中小企业促进法", "a": "对"},
    {"q": "金融机构违反与民营经济组织借款人的约定", "a": "对"},
    {"q": "保障中小企业款项支付条例", "a": "错"},
    {"q": "中华人民共和国国防动员法", "a": "对"},
    {"q": "农村公路条例", "a": "对"},
    {"q": "农村集体经济组织法", "a": "错"},
    {"q": "县级以上人民政府司法行政部门应当建立法治文化场所名录", "a": "错"},
    {"q": "行政复议法", "a": "对"},
    {"q": "行政许可法", "a": "错"},
    {"q": "反垄断法", "a": "错"},
    {"q": "中华人民共和国国家安全法", "a": "错"},
    {"q": "网络安全法", "a": "错"},
    {"q": "外商投资法", "a": "对"},
    {"q": "公共安全视频图像信息系统管理条例", "a": "对"},
    {"q": "国家赔偿法", "a": "错"},
    {"q": "数据安全法", "a": "对"}, 
        ];
        var items = document.getElementsByClassName("item");
        if (answers.length < items.length) {
            Swal.fire("脚本内置答案数量小于当前试题数量,无法答题!!!");
            return;
        }
        function abcd_to_index(s) {
            var l = [];
            for(let i = 0; i < s.length; i++){
                let char = s[i];
                if(char === "a" || char === "A"){ l.push(0);}
                else if(char === "b" || char === "B"){ l.push(1);}
                else if(char === "c" || char === "C"){ l.push(2);}
                else if(char === "d" || char === "D"){ l.push(3);}
                else if(char === "e" || char === "E"){ l.push(4);}
                else if(char === "f" || char === "F"){ l.push(5);}
                else if(char === "g" || char === "G"){ l.push(6);}
                else if(char === "对"){ l.push(0);}
                else if(char === "错"){ l.push(1);}
            }
            return l;
        }
        let count = 0;
        for (let index = 0; index < items.length; index++){
            let item = items[index];
            let question = item.getElementsByClassName("question-title")[0].innerText
            let answer = null;
            for(let i = 0; i < answers.length; i++){
                if(question.includes( answers[i].q)){
                    answer = answers[i];
                    break;
                }
            }
            if(!answer){
                // 变色标记
                item.style.background="yellow";
                // 计数&&弹窗
                count = count + 1;
                let msg = `【${question}】\n\n此题没有配置答案,已经自动跳过,请自行谷歌!!!`;
                log(msg);
                alert(msg);
                continue;
            }
            let options = item.getElementsByClassName("question-option");
            let a_list = abcd_to_index(answer.a);
            for(let i = 0; i < a_list.length; i++){
                let a = a_list[i];
                options[a].getElementsByTagName("label")[0].click();
            }
        }
        let txt = "【广东省学法考试年度考试】已经自动作答完毕,请认真核对,手动交卷!";
        if(count > 0){
            txt = `【广东省学法考试年度考试】已经自动作答完毕,因题库不足已跳过【${count}】题,请自行作答。最后,请认真核对,手动交卷!`;
        }
        Swal.fire(txt);
    }
    // 刷分
    function study() {
        log("study")
        var pathname = window.location.pathname;
        if (pathname.includes("index")) {
            log("index...");
            var all_finish = true;
            var cols = document.getElementsByClassName("column");
            for (let index = 0; index < cols.length; index++) {
                var col = cols[index];
                var catalogdesc = col.getAttribute("catalogdesc");
                var course = col.querySelector(".card.current").innerText.replace(/\s+/g, "");
                if (catalogdesc.includes("庭审") || catalogdesc.includes("题库")) {
                    continue;
                }
                // 判断是否完成
                var btn = col.getElementsByClassName("btn")[0];
                if (btn) {
                    log("未完成", col);
                    all_finish = false;
                    btn.click();
                    break;
                } else {
                    log(catalogdesc, course);
                }
            }
            if (all_finish) {
                Swal.fire({
                    icon: "success",
                    title: "全部课程已经学习完毕!",
                    html: `请在规定时间自行进入考场作答!<br>开始考试后,按一下键盘<strong style="color: red;">【G】</strong>键!`,
                });
            }
        } else if (pathname.includes("chapter")) {
            log("chapter...");
            var ms = 3000 + Math.floor(Math.random() * 1000);
            submitLearn();
            Swal.fire({
                title: "学习强国",
                text: `自动学习中,【${ms}】【毫秒】后自动跳转!`,
                timer: ms,
                timerProgressBar: true
            });
            setTimeout(() => {
                var next_chapter = document.querySelector(".next_chapter")
                if (next_chapter) {
                    next_chapter.click();
                } else {
                    window.location.pathname = "study/index";
                }
            }, ms);

        } else if (pathname.includes("course")) {
            log("course...");
            var finish = true;
            var lis = document.getElementsByClassName("chapter")[0].getElementsByTagName("li");
            for (let index = 0; index < lis.length; index++) {
                var li = lis[index];
                var sub_title = li.getElementsByClassName("sub_title")[0].innerText;
                if (sub_title.includes("获得") || sub_title.includes("未开放")) {
                    continue;
                }
                finish = false;
                li.querySelector(".title a").click();
                break;
            }
            if (finish) {
                //document.querySelector(".menu-ic-note").click();
                let ms = 3 * 1000;
                Swal.fire({
                    icon: "question",
                    title: "温馨提示",
                    text: `本页课程已经学完,${ms / 1000}秒后将返回主页,点击按钮留在当前页面。`,
                    confirmButtonText: "留在当前页",
                    timer: ms,
                    timerProgressBar: true,
                }).then((result) => {
                    if (result.isConfirmed) {
                        console.log('确定按钮被点击,取消执行函数 f');
                    } else {
                        // 只有在用户未点击确定按钮且定时器结束时才执行 f
                        document.querySelector(".menu-ic-note").click();
                    }
                });
            }
        } else if (pathname.includes("login")) {
            log("login...")
        } else if (pathname.includes("exam")) {
            log("exam...")
        } else {
            log("未知页面", pathname);
        }
    }

    if (document.readyState === "complete") {
        // DOM 已经加载完成
        main();
    } else {
        // DOM 还未加载完成
        // document.addEventListener("DOMContentLoaded", main);
        window.addEventListener("load", main);
    }

    document.addEventListener("keydown", function (event) {
        log("keydown", event.code);
        if (event.code === "KeyG") {
            exam();
        } else if (event.code === "KeyT"){
            let ms = 3000;
            Swal.fire({
                title: "学习强国",
                text: `自动学习中,【${ms}】【毫秒】后自动跳转!`,
                timer: ms,
                timerProgressBar: true
            });
        }
    });
})();

本作品特点

  • 系统方面不追新,不求全,以稳定、纯粹的版本为基础,力求稳定和干净
  • 安装微软、金山两套办公软件,根据使用习惯选用
  • Windows 系统与 Office 软件自动激活,系统开启 Administrator 管理员账号以减少使用过程中的各种烦人问题。
  • 以办公为导向,删除系统自带的 UWP 软件
  • 自带微软的系统还原功能,本功能默认关闭,内存紧张的电脑不建议开启
  • 本系统以 wim 格式封装,容量约为 10GB,建议在 PE 环境下用 WinNTSetup 等工具释放

主要软件模板

  • Windows_10_ltsc_2021_19044.2728_x64
  • MS_Office_2024_x64 (Word,Excel,PowerPoint 三件套)
  • WPS2023专业增强版

安装软件

  1. Winrar 压缩/解压缩软件(可酌情加装 7zip)
  2. 微信
  3. QQ
  4. 粤政易
  5. 纯净版 flash — 去广告
  6. 小狼豪输入法
  7. 几何画板
  8. VC进行库
  9. Power toys
  10. 火绒杀毒软件(部署系统过程中安装)

添加的绿色软件

  1. wubilex — 可修改微软五笔输入方案,如选用 86/98/新世纪五笔
  2. Potplayer — 视频播放器
  3. foobar2000 — 音频播放器
  4. notepad-- — 记事本平替
  5. Honeyview — 看图软件
  6. 增值税电子发票阅读器 — 实为 ofd 文件阅读器
  7. Xmind — 思维导图软件
  8. CCleaner 系统清理软件
  9. 软件屏蔽器 — 拦截流氓软件的安装行为
  10. 若干自用和其它专用工具

系统优化

  1. 安装 revision 工具,关闭系统进程(可以减少50多个进程),
  2. 通过导入注册表,为微软拼音添加“小鹤双拼”方案
  3. 通过导入注册表,开启 Office 对 flash 的支持
  4. 添加常用办公字体
  5. 替换为 Windows 11 24H2 的宋体,以支持大字集(支持到扩I)

下一次封装优化计划

  1. 打开 PowerPoint 播放 flash 控件的支持(PowerPoint 信任中心)
  2. Word/PowerPoint 显示标尺
  3. 重新设置 微信/QQ 快捷方式
  4. 添加 Office Tag 软件
  5. 集成 Hashtab
  6. 安装 IDM 下载软件
  7. 尝试提前安装火绒
  8. 启用 administrator 的 UAC
  9. wps 三件套合并图标
  10. 调整右键菜单
  11. 待发现

PVE 作为虚拟平台,以稳定为主,其 WEB 介面类似于 IPMI。如果因数据盘坏掉导致挂载不了目录,进而进不了 PVE 系统,那就失去了“稳定”的可能性。

为了避免发生以上情况,数据盘不要在PVE中挂载,而是直通给 LXC 文件共享容器,这个容器通过fstab专门挂载数据盘,提供 SAMBA/NFS 等基础共享服务。之后再把文件通过SAMBA/NFS网络共享给 PVE 数据中心,挂载在 PVE 下的 /mnt/pve/ 目录下。其它 LXC 容器通知添加挂载点,使用数据盘进行数据的读写。

过程如下:

  1. 在文件共享容器的操作。
    “资源”、“添加”、“Device Passthrough”,把 /dev/disk/by-uuid/***** 硬盘分区添加到 LXC 容器资源中。其中数据盘分区的 uuid 可以在 PVE 中通过 blkid 命令查看。

在此容器中,添加自动挂载服务,让添加的硬盘通过fstab自动挂载到目录中。代码如下:

sudo vi /etc/systemd/system/mount-fstab.service
[Unit]
Description=Mount all filesystems from fstab
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/bin/mount -a
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
systemctl enable mount-fstab.service

之后,通过 SAMBA 或 NFS 服务,把挂载的目录分享出来。

  1. PVE数据中心操作
    定位到“数据中心”,“存储”,选择“填加”,选择 SAMBA 或 NFS 类型把上述的共享,添加到数据中心供其它 LXC 使用,顺利添加后,添加的项目会在 WEB 顶级菜单中的“存储”中呈现,在这个菜单下可见默认的"local"和"local-lvm"项。
  2. 为其它 LXC 容器挂载共享目录
    在 PVE 的 shell 下通过以下命令挂载:
    
    pct set lxc容器号 -mp* /mnt/pve/*,mp=/mnt/*

代码如下:

Sub DeletePW()
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, AllowFiltering:=True
ActiveSheet.Protect DrawingObjects:=False, Contents:=True, AllowFiltering:=True
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, AllowFiltering:=True
ActiveSheet.Protect DrawingObjects:=False, Contents:=True, AllowFiltering:=True
ActiveSheet.Unprotect
End Sub

使用方法:鼠标右键点击工作表标签,选择“查看代码”,把上面的代码粘贴到代码框中,点击菜单进行代码即可。

=(A1-INT((A1-0.5)/页数)*页数-1)*每张纸成绩条数量+INT((A1-0.5)/页数)+1

如设置每张纸打印5张成绩条,共打印12张纸,那么公式就是:
=(A1-INT((A1-0.5)/12)12-1)5+INT((A1-0.5)/12)+1

其中,A1为原学号,公式的结果为打印时的排序序号。

=5*(ROUNDUP(MOD(B2-0.5,12),0)-1)+ROUNDUP((B2-0.5)/12,0)

这个公式也可以。