⚠️ 推荐全程用 电脑操作,避免出现兼容性问题。
本文保留了所有步骤、细节、截图,完整记录从报名到考试的流程。


第一步:检查和报名

👉 活动链接(含AFF)
点此进入活动并报名。


第二步:领取微认证代金券

成功报名后,可领取 6张微认证代金券

  • 🎫 3张 27元 微认证代金券
  • 🎫 2张 37元 微认证代金券
  • 🎫 1张 47元 微认证代金券

领取代金券

📌 注:
成功通过 任意4门微认证 后(必须生成证书后才可以填问卷),填写问卷可申请:

  • 1张 699元 开发者认证代金券
  • 任意 3张 微认证代金券(可选 27元 / 37元 / 47元 / 57元)

问卷奖励


第三步:支付 1 元购买微认证资格

拿着刚刚领取的 6 张微认证代金券,在活动页面点击下图所示位置,先消耗掉 3 张 27元的代金券

代金券使用

然后,进入下图界面,挑选并购买以下课程:

  • 区块链部署弹珠游戏模拟资产变化(38元)
  • 博客网站 SQL 注入攻击以及防御(38元)
  • HTTPS 加密电商网站(48元)

课程选择

如果找不到课程,可以直接搜索以上内容。

示例:以 “区块链部署弹珠游戏模拟资产变化” 为例,购买方式如下:

购买示例
支付流程


第四步:配置 OBS 虚拟摄像头

  1. 安装 OBS Studio
  2. 选择 只使用虚拟摄像头
  3. 如果没出现虚拟摄像头选项,可在 场景集合 → 工具 → 自动配置向导 开启
  4. 可录制一段 电脑自带摄像头的视频 或用 手机横屏录制,建议 1分钟以上
  5. 这些操作搞完后去https://www.onlinemictest.com/zh/webcam-test/ 测试一下

截图示例:

OBS1
OBS2
OBS3
OBS4


第五步:切屏绕过方法(油猴脚本)

安装 Tampermonkey 插件,并新建脚本。示例:

// ==UserScript==
// @name         通用阻止切屏检测
// @namespace    http://tampermonkey.net/
// @version      0.1.0
// @description  尝试阻止各类网站的切屏、焦点丢失等检测
// @author       nodeseek@小号 && Gemini
// @match        http://*/*
// @match        https://*/*
// @run-at       document-start
// @grant        unsafeWindow
// @license      GPL-3.0
// ==/UserScript==

(function () {
    'use strict';
    const window = unsafeWindow; // 使用原始 window 对象

    // 黑名单事件,这些事件的监听器将被阻止
    const blackListedEvents = new Set([
        "visibilitychange", // 页面可见性改变
        "blur",             // 元素或窗口失去焦点
        "focus",            // 元素或窗口获得焦点 (某些检测可能反向利用focus)
        "pagehide",         // 页面隐藏(例如导航到其他页面)
        "freeze",           // 页面被冻结 (较新的事件)
        "resume",           // 页面从冻结状态恢复 (较新的事件)
        "mouseleave",       // 鼠标移出元素(通常是 document 或 body)
        "mouseout",         // 鼠标移出元素(更通用的移出,但要小心副作用)
        // "focusout",      // 元素将要失去焦点(与blur类似,但更通用,看情况添加)
        // "focusin",       // 元素将要获得焦点(与focus类似,看情况添加)
    ]);

    // 白名单属性,这些属性在 document 对象上将被伪造
    const spoofedDocumentProperties = {
        hidden: { value: false, configurable: true },
        mozHidden: { value: false, configurable: true }, // Firefox (旧版)
        msHidden: { value: false, configurable: true },  // Internet Explorer
        webkitHidden: { value: false, configurable: true }, // Chrome, Safari, Opera (旧版 Blink/WebKit)
        visibilityState: { value: "visible", configurable: true },
        hasFocus: { value: () => true, configurable: true }
    };

    // 需要清空/置空的事件处理器属性 (on-event handlers)
    const eventHandlersToNullifyDocument = [
        "onvisibilitychange",
        "onblur",
        "onfocus",
        "onmouseleave",
        "onmouseout",
        // "onfocusout",
        // "onfocusin",
        "onpagehide",
        "onfreeze",
        "onresume"
    ];

    const eventHandlersToNullifyWindow = [
        "onblur",
        "onfocus",
        "onpagehide",
        "onpageshow", // 有些检测可能通过 pageshow 结合 persisted 属性判断
        "onfreeze",
        "onresume",
        "onmouseleave", // window 也有 onmouseleave
        "onmouseout"
    ];

    const isDebug = false; // 设置为 true 以启用调试日志
    const scriptPrefix = "[通用阻止切屏检测]";
    const log = console.log.bind(console, `%c${scriptPrefix}`, 'color: #4CAF50; font-weight: bold;');
    const warn = console.warn.bind(console, `%c${scriptPrefix}`, 'color: #FFC107; font-weight: bold;');
    const error = console.error.bind(console, `%c${scriptPrefix}`, 'color: #F44336; font-weight: bold;');
    const debug = isDebug ? log : () => { };

    /**
     * 伪装函数的 toString 方法,使其看起来像原始函数。
     * @param {Function} modifiedFunction 被修改的函数
     * @param {Function} originalFunction 原始函数
     */
    function patchToString(modifiedFunction, originalFunction) {
        if (typeof modifiedFunction !== 'function' || typeof originalFunction !== 'function') {
            warn("patchToString: 传入的参数不是函数。", modifiedFunction, originalFunction);
            return;
        }
        try {
            const originalToStringSource = Function.prototype.toString.call(originalFunction);
            modifiedFunction.toString = () => originalToStringSource;

            // 进一步伪装 toString.toString
            const originalToStringToStringSource = Function.prototype.toString.call(originalFunction.toString);
            Object.defineProperty(modifiedFunction.toString, 'toString', {
                value: () => originalToStringToStringSource,
                enumerable: false,
                configurable: true, // 保持可配置,以防万一
                writable: false
            });
            debug(`patchToString applied for: ${originalFunction.name || 'anonymous function'}`);
        } catch (e) {
            error("patchToString failed:", e, "for function:", originalFunction.name);
        }
    }


    /**
     * 劫持并修改对象的 addEventListener 方法。
     * @param {EventTarget} targetObject 要劫持的对象 (window, document, Element)
     * @param {string} objectName 用于日志记录的对象名称
     */
    function patchAddEventListener(targetObject, objectName) {
        if (!targetObject || typeof targetObject.addEventListener !== 'function') {
            warn(`Cannot patch addEventListener for invalid target: ${objectName}`);
            return;
        }
        const originalAddEventListener = targetObject.addEventListener;

        targetObject.addEventListener = function (type, listener, optionsOrCapture) {
            if (blackListedEvents.has(type.toLowerCase())) {
                log(`BLOCKED ${objectName}.addEventListener: ${type}`);
                return undefined; // 阻止添加黑名单中的事件监听器
            }
            debug(`ALLOWED ${objectName}.addEventListener: ${type}`, listener, optionsOrCapture);
            return originalAddEventListener.call(this, type, listener, optionsOrCapture);
        };

        patchToString(targetObject.addEventListener, originalAddEventListener);
        log(`${objectName}.addEventListener patched.`);
    }

    /**
     * 劫持并修改对象的 removeEventListener 方法 (可选,但建议一起修改)。
     * @param {EventTarget} targetObject 要劫持的对象
     * @param {string} objectName 用于日志记录的对象名称
     */
    function patchRemoveEventListener(targetObject, objectName) {
        if (!targetObject || typeof targetObject.removeEventListener !== 'function') {
            warn(`Cannot patch removeEventListener for invalid target: ${objectName}`);
            return;
        }
        const originalRemoveEventListener = targetObject.removeEventListener;

        targetObject.removeEventListener = function (type, listener, optionsOrCapture) {
            if (blackListedEvents.has(type.toLowerCase())) {
                log(`Original call to ${objectName}.removeEventListener for blacklisted event '${type}' would have been ignored by our addEventListener patch anyway. Allowing native call if needed.`);
                // 即使我们阻止了 addEventListener,原始的 removeEventListener 仍然应该能安全调用
                // 因为如果监听器从未被添加,调用 remove 也无害。
            }
            debug(`PASSTHROUGH ${objectName}.removeEventListener: ${type}`, listener, optionsOrCapture);
            return originalRemoveEventListener.call(this, type, listener, optionsOrCapture);
        };
        patchToString(targetObject.removeEventListener, originalRemoveEventListener);
        log(`${objectName}.removeEventListener patched.`);
    }


    /**
     * 修改对象上的属性,使其返回伪造的值。
     * @param {object} targetObject 目标对象 (e.g., document)
     * @param {object} propertiesToSpoof 属性描述对象
     * @param {string} objectName 对象名称
     */
    function spoofProperties(targetObject, propertiesToSpoof, objectName) {
        if (!targetObject) {
            warn(`Cannot spoof properties for invalid target: ${objectName}`);
            return;
        }
        for (const prop in propertiesToSpoof) {
            if (Object.prototype.hasOwnProperty.call(propertiesToSpoof, prop)) {
                try {
                    Object.defineProperty(targetObject, prop, propertiesToSpoof[prop]);
                    debug(`Spoofed ${objectName}.${prop}`);
                } catch (e) {
                    error(`Failed to spoof ${objectName}.${prop}:`, e);
                }
            }
        }
        log(`${objectName} properties spoofed.`);
    }

    /**
     * 清空或置空对象上的事件处理器属性。
     * @param {object} targetObject 目标对象
     * @param {string[]} eventHandlerNames 事件处理器名称数组
     * @param {string} objectName 对象名称
     */
    function nullifyEventHandlers(targetObject, eventHandlerNames, objectName) {
        if (!targetObject) {
            warn(`Cannot nullify event handlers for invalid target: ${objectName}`);
            return;
        }
        eventHandlerNames.forEach(handlerName => {
            try {
                Object.defineProperty(targetObject, handlerName, {
                    get: () => {
                        debug(`Access to ${objectName}.${handlerName} (get), returning undefined.`);
                        return undefined;
                    },
                    set: (newHandler) => {
                        log(`Attempt to set ${objectName}.${handlerName} blocked.`);
                        if (typeof newHandler === 'function') {
                             // 可以选择性地调用 newHandler,或者完全阻止
                             // debug(`(Blocked) Handler function was:`, newHandler);
                        }
                    },
                    configurable: true // 保持可配置,以便脚本可以多次运行或被其他脚本修改
                });
                debug(`Nullified ${objectName}.${handlerName}`);
            } catch (e) {
                error(`Failed to nullify ${objectName}.${handlerName}:`, e);
            }
        });
        log(`${objectName} on-event handlers nullified.`);
    }

    // --- 开始执行 ---

    log("Script starting...");

    // 1. 劫持 window 和 document 的 addEventListener/removeEventListener
    patchAddEventListener(window, "window");
    patchRemoveEventListener(window, "window"); // 也 patch removeEventListener 以保持一致性
    patchAddEventListener(document, "document");
    patchRemoveEventListener(document, "document");

    // 2. 修改 document 的属性
    spoofProperties(document, spoofedDocumentProperties, "document");

    // 3. 置空 document 和 window 上的事件处理器
    nullifyEventHandlers(document, eventHandlersToNullifyDocument, "document");
    nullifyEventHandlers(window, eventHandlersToNullifyWindow, "window");

    // 4. 对于 document.body,需要等待 DOMContentLoaded
    // 使用 MutationObserver 确保 body 存在时立即 patch,比 DOMContentLoaded 更早且更可靠
    const observer = new MutationObserver((mutations, obs) => {
        if (document.body) {
            patchAddEventListener(document.body, "document.body");
            patchRemoveEventListener(document.body, "document.body");
            // 对于 document.body,也可以考虑 nullify onmouseleave, onmouseout 等
            nullifyEventHandlers(document.body, ["onmouseleave", "onmouseout", "onblur", "onfocus"], "document.body");
            log("document.body patched via MutationObserver.");
            obs.disconnect(); // 完成任务后断开观察者
        }
    });

    if (document.body) { // 如果 body 已经存在 (不太可能在 document-start,但以防万一)
        patchAddEventListener(document.body, "document.body");
        patchRemoveEventListener(document.body, "document.body");
        nullifyEventHandlers(document.body, ["onmouseleave", "onmouseout", "onblur", "onfocus"], "document.body");
        log("document.body patched directly.");
    } else {
        observer.observe(document.documentElement || document, { childList: true, subtree: true });
    }


    // 5. 调试:劫持计时器 (如果 isDebug 为 true)
    if (isDebug) {
        const originalSetInterval = window.setInterval;
        window.setInterval = function(...args) {
            const id = originalSetInterval.apply(this, args);
            debug("calling window.setInterval", id, args);
            return id;
        };
        patchToString(window.setInterval, originalSetInterval);

        const originalSetTimeout = window.setTimeout;
        window.setTimeout = function(...args) {
            const id = originalSetTimeout.apply(this, args);
            debug("calling window.setTimeout", id, args);
            return id;
        };
        patchToString(window.setTimeout, originalSetTimeout);
        log("Timer functions (setInterval, setTimeout) wrapped for debugging.");
    }

    log("Script execution finished. Monitoring active.");

})();

第六步:参加考试

完成以上配置后,返回 微认证界面,点击 「开始考试」 即可。
image-1756265728967
确保条件:

  • 已完成微认证课程购买
  • OBS 虚拟摄像头配置完成并运行
  • 油猴脚本生效,避免切屏被检测

第七步:神秘脚本

https://www.abtool.cn/image_compre 把你的照片压缩,压缩到100kb以内。
然后把压缩后的图片在 https://www.json.cn/img2base64 这里转成base64,把base64结果填到 const DEFAULT_BASE64_IMAGE = ’ ’ 两个单引号之间。

// ==UserScript==
// @name         神秘脚本
// @match        https://connect.huaweicloud.com/courses/exam/*
// @match        https://edu.huaweicloud.com/certifications/*
// @match        https://edu.huaweicloud.com/signup/*
// @match        https://www.huaweicloud.com
// @match        https://www.onlinemictest.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=huaweicloud.com
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

/*
报名地址 https://edu.huaweicloud.com/signup/8a8472ec5f054f1596747afbe3e219f5?medium=share_kfzlb&invitation=9677dac753c84b4ea0aba6d2725e2ae4
*/

(function() {
    'use strict';

    // ==================== 配置区 ====================

    const DEFAULT_BASE64_IMAGE = ''

    // ==================== 配置区 ====================
    class Utils {
        static generateRandomBase64(length) {
            const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
            let result = '';
            const charactersLength = characters.length;
            for (let i = 0; i < length; i++) {
                result += characters.charAt(Math.floor(Math.random() * charactersLength));
            }
            return result;
        }

        static async getBase64Image() {
            return DEFAULT_BASE64_IMAGE;
        }
    }



    // -------- 虚拟视频流创建 --------
    class VirtualStream {
        constructor(width = 1280, height = 720, fps = 30) {
            this.width = width;
            this.height = height;
            this.fps = fps;
        }

        async createNoiseLayer(opacity = 0.05) {
            const canvas = document.createElement('canvas');
            canvas.width = this.width;
            canvas.height = this.height;
            const ctx = canvas.getContext('2d');
            const imageData = ctx.createImageData(this.width, this.height);
            const data = imageData.data;

            for (let i = 0; i < data.length; i += 4) {
                const noise = Math.random() * 255;
                data[i] = data[i + 1] = data[i + 2] = noise;
                data[i + 3] = opacity * 255;
            }

            ctx.putImageData(imageData, 0, 0);
            return canvas;
        }

        drawImageCovered(ctx, img, x, y, w, h) {
            const imgRatio = img.width / img.height;
            const canvasRatio = w / h;
            let sx, sy, sWidth, sHeight;

            if (imgRatio > canvasRatio) {
                sHeight = img.height;
                sWidth = sHeight * canvasRatio;
                sx = (img.width - sWidth) / 2;
                sy = 0;
            } else {
                sWidth = img.width;
                sHeight = sWidth / canvasRatio;
                sx = 0;
                sy = (img.height - sHeight) / 2;
            }

            ctx.drawImage(img, sx, sy, sWidth, sHeight, x, y, w, h);
        }

        async createVirtualStream() {
            const canvas = document.createElement('canvas');
            canvas.width = this.width;
            canvas.height = this.height;
            const ctx = canvas.getContext('2d');

            const img = new Image();
            img.src = DEFAULT_BASE64_IMAGE;

            const offscreenCanvas = document.createElement('canvas');
            offscreenCanvas.width = this.width;
            offscreenCanvas.height = this.height;
            const offscreenCtx = offscreenCanvas.getContext('2d');

            img.onload = () => {
                this.drawImageCovered(offscreenCtx, img, 0, 0, offscreenCanvas.width, offscreenCanvas.height);
            };

            let noiseLayer = await this.createNoiseLayer();

            let hue = 0;
            let saturate = 100;
            let brightness = 100;

            function generateFrame() {
                hue = (hue + 0.05) % 1;
                saturate = 99.5 + Math.sin(Date.now() / 2000) * 0.5;
                brightness = 99.5 + Math.random() * 0.5;

                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(offscreenCanvas, 0, 0);
                ctx.filter = `hue-rotate(${hue}deg) saturate(${saturate}%) brightness(${brightness}%)`;
                ctx.drawImage(canvas, 0, 0);
                ctx.filter = 'none';
                ctx.globalCompositeOperation = 'overlay';
                ctx.drawImage(noiseLayer, 0, 0);
                ctx.globalCompositeOperation = 'source-over';
            }

            const stream = canvas.captureStream(this.fps);

            setInterval(generateFrame, 1000 / this.fps);

            setInterval(() => {
                noiseLayer = this.createNoiseLayer();
            }, 500 + Math.sin(Date.now() / 1000) * 100);

            return stream;
        }
    }

    class CameraHook {
        constructor() {
            this.methodsLookupTable = new WeakMap();
            this.virtualDeviceId = Utils.generateRandomBase64(43) + '=';
            this.virtualGroupId = Utils.generateRandomBase64(43) + '=';
            this.hookMediaDevices();
            this.preventDetection();
        }

        preventDetection() {
            const originalToString = Function.prototype.toString;
            const map = this.methodsLookupTable;

            // 防止检测被劫持的函数
            Function.prototype.toString = new Proxy(originalToString, {
                apply(target, thisArg, argumentsList) {
                    if (typeof thisArg?.call !== 'function') {
                        return Reflect.apply(target, thisArg, argumentsList);
                    }

                    if (map.has(thisArg)) {
                        return Reflect.apply(target, map.get(thisArg), argumentsList);
                    }

                    return Reflect.apply(target, thisArg, argumentsList);
                }
            });
        }

        replaceMethod(obj, methodName, newMethod) {
            const oldMethod = obj[methodName];
            obj[methodName] = newMethod;
            this.methodsLookupTable.set(newMethod, oldMethod);
        }

        hookMediaDevices() {
            this.replaceMethod(navigator.mediaDevices, 'enumerateDevices', async () => {
                const originalMethod = this.methodsLookupTable.get(navigator.mediaDevices.enumerateDevices);
                const devices = await originalMethod.call(navigator.mediaDevices);
                const hasVirtualDevice = devices.some(device =>
                    device.deviceId === this.virtualDeviceId && device.kind === 'videoinput'
                );

                if (!hasVirtualDevice) {
                    const virtualDevice = {
                        deviceId: this.virtualDeviceId,
                        groupId: this.virtualGroupId,
                        kind: 'videoinput',
                        label: '神秘摄像头',
                        toJSON: function() {
                            return {
                                deviceId: this.deviceId,
                                groupId: this.groupId,
                                kind: this.kind,
                                label: this.label
                            };
                        }
                    };

                    return [virtualDevice, ...devices];
                }

                return devices;
            });

            // 替换摄像头流
            this.replaceMethod(navigator.mediaDevices, 'getUserMedia', async (constraints) => {
                const originalMethod = this.methodsLookupTable.get(navigator.mediaDevices.getUserMedia);

                if (constraints && constraints.video) {
                    console.log('检测到摄像头请求,返回虚拟摄像头流');
                    return await new VirtualStream().createVirtualStream();
                }

                return originalMethod.call(navigator.mediaDevices, constraints);
            });
        }
    }

    // ==================== 防切屏功能 ====================

    // 防切屏检测功能
    function initBlockingFeatures() {
        const stepEvent = (e) => {
            e.stopImmediatePropagation()
            e.stopPropagation()
            e.preventDefault()
            return false
        }
        // 伪造document.visibilityState为visible,始终显示为可见状态
        Object.defineProperty(unsafeWindow.document, 'visibilityState', {
            configurable: true,
            get: function () {
                return 'visible'
            },
        })

        // 伪造document.hidden为false,始终显示为非隐藏状态
        Object.defineProperty(unsafeWindow.document, 'hidden', {
            configurable: true,
            get: function () {
                return false
            },
        })

        ;[
            'blur', // 阻止焦点事件(失去焦点和获取焦点)
            'focus',
            'focusin',
            'focusout', // 阻止页面显示和隐藏事件
            'pageshow',
            'pagehide',
            'visibilitychange', // 阻止可见性变化事件
        ].forEach((k) => {
            unsafeWindow.addEventListener(k, stepEvent, true)
        })

        // 阻止可见性变化事件
        unsafeWindow.document.addEventListener('visibilitychange', stepEvent, true)

        // 阻止屏幕方向变化监听
        if (unsafeWindow.screen.orientation) {
            unsafeWindow.screen.orientation.addEventListener('change', stepEvent, true)
        }

        // 伪装全屏状态 - 让页面认为已经进入全屏
        Object.defineProperty(unsafeWindow.document, 'fullscreenElement', {
            configurable: true,
            get: function () {
                return unsafeWindow.document.documentElement
            },
        })

        Object.defineProperty(unsafeWindow.document, 'fullscreenEnabled', {
            configurable: true,
            get: function () {
                return true
            },
        })

        // 覆盖requestFullscreen使其无效,但返回成功状态
        unsafeWindow.Element.prototype.requestFullscreen = function () {
            return new Promise((resolve, reject) => {
                // 不执行真正的全屏,直接resolve让调用方认为成功
                resolve()
            })
        }

        // 覆盖exitFullscreen使其无效
        unsafeWindow.document.exitFullscreen = function () {
            return new Promise((resolve, reject) => {
                // 不执行真正的退出全屏,直接resolve
                resolve()
            })
        }

        // 阻止fullscreenchange事件
        unsafeWindow.document.addEventListener('fullscreenchange', stepEvent, true)

        console.log('切屏检测阻止功能已启用')
    }

    // ==================== 辅助功能 ====================

    function createReactiveObject(initialState) {
        let state = { ...initialState }
        return new Proxy(state, {
            get(target, key) {
                return target[key]
            },
            set(target, key, value) {
                target[key] = value
                return true
            },
        })
    }

    function createToggleMenu(config) {
        const { menuName, onStart, onStop, defaultEnabled = true } = config
        const storageKey = `toggle_${menuName}`
        const initialEnabled = GM_getValue(storageKey, defaultEnabled)

        const state = createReactiveObject({
            isEnabled: initialEnabled,
            menuCommandId: null,
        })

        function updateMenuCommand() {
            if (state.menuCommandId) {
                GM_unregisterMenuCommand(state.menuCommandId)
            }

            GM_setValue(storageKey, state.isEnabled)

            if (state.isEnabled) {
                state.menuCommandId = GM_registerMenuCommand(`🟢${menuName}(已启用)`, () => {
                    state.isEnabled = false
                    onStop(state)
                    updateMenuCommand()
                },{
                    autoClose: false
                })
            } else {
                state.menuCommandId = GM_registerMenuCommand(`🔴${menuName}(未启用)`, () => {
                    state.isEnabled = true
                    onStart(state)
                    updateMenuCommand()
                },{
                    autoClose: false
                })
            }
        }

        if (initialEnabled) {
            onStart(state)
        }

        updateMenuCommand()
        return state
    }

    // ==================== 主函数 ====================

    // 初始化脚本
    function initScript() {
        console.log("半自动微认证3.0脚本启动...");

        // 初始化防切屏功能
        initBlockingFeatures();

        // 初始化摄像头替换功能
        new CameraHook();

        // 创建功能开关菜单
        createToggleMenu({
            menuName: '摄像头替换',
            defaultEnabled: true,
            onStart: (state) => {
                console.log('摄像头替换功能已启用')
                // 功能在构造函数中已经初始化,这里不需要额外操作
            },
            onStop: (state) => {
                console.log('摄像头替换功能已禁用')
                alert('摄像头替换功能已禁用,请刷新页面重新启用')
            },
        });

        createToggleMenu({
            menuName: '防切屏功能',
            defaultEnabled: true,
            onStart: (state) => {
                console.log('防切屏功能已启用')
                initBlockingFeatures(); // 重新初始化防切屏功能
            },
            onStop: (state) => {
                console.log('防切屏功能已禁用')
                alert('防切屏功能已禁用,请刷新页面重新启用')
            },
        });

        console.log("神秘脚本初始化完成");
    }

    // 启动脚本
    initScript();

})();