获取确认ID免登录GM版

获取微软激活确认ID,带悬浮面板,支持剪贴板操作和精准IID合法性校验*://visualsupport.microsoft.com/*

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

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         获取确认ID免登录GM版
// @namespace    http://tampermonkey.net/
// @version      2026.07.11
// @description  获取微软激活确认ID,带悬浮面板,支持剪贴板操作和精准IID合法性校验*://visualsupport.microsoft.com/*
// @author       福建-兮
// @match        *://visualsupport.microsoft.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @connect      visualsupport.microsoft.com
// @connect      cidtoken.x2ray.cfd
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    /**
     * 校验IID区块合法性
     * @param {string} block - IID的单个区块
     * @returns {boolean} 区块是否合法
     */
    function checkBlock(block) {
        if (!/^\d+$/.test(block) || block.length < 2) return false;

        const check = Number(block.at(-1));
        let sum = 0;

        for (let i = 0; i < block.length - 1; i++) {
            const d = Number(block[i]);
            sum += i % 2 === 0 ? d : d * 2;
        }

        return sum % 7 === check;
    }

    /**
     * 校验整个IID的合法性(增强版,返回具体错误信息)
     * @param {string} iid - 待校验的IID字符串
     * @returns {object} 校验结果 {valid: boolean, error?: string, failedBlocks?: array}
     */
    function validateIID(iid) {
        // 检查是否全为数字
        if (!/^\d+$/.test(iid))
            return { valid: false, error: "not_numeric" };

        // 检查长度是否为54或63位
        if (iid.length !== 54 && iid.length !== 63)
            return { valid: false, error: "invalid_length", length: iid.length };

        // 检查每个区块的合法性
        const blockSize = iid.length / 9;
        const failedBlocks = [];

        for (let i = 0; i < 9; i++) {
            const block = iid.slice(i * blockSize, (i + 1) * blockSize);

            if (!checkBlock(block)) {
                failedBlocks.push({
                    index: i + 1,
                    value: block
                });
            }
        }

        return {
            valid: failedBlocks.length === 0,
            failedBlocks
        };
    }

    /**
     * 创建悬浮提示框(通用,支持成功/错误提示)
     * @param {string} mainText - 主要提示文本
     * @param {string} detailText - 详细错误/成功信息
     * @param {string} content - 额外展示的内容(IID/响应结果)
     * @param {string} type - 提示类型(error/success)
     * @param {number} duration - 显示时长(毫秒)
     */
    function showFloatTip(mainText, detailText = "", content = "", type = "error", duration = 5000) {
        // 移除已存在的提示框
        const oldTip = document.getElementById("ms-iid-tip");
        if (oldTip) oldTip.remove();

        // 创建新提示框容器
        const tipContainer = document.createElement("div");
        tipContainer.id = "ms-iid-tip";
        tipContainer.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px;
            background: ${type === "error" ? "#f8d7da" : "#d4edda"};
            color: ${type === "error" ? "#721c24" : "#155724"};
            border: 1px solid ${type === "error" ? "#f5c6cb" : "#c3e6cb"};
            border-radius: 8px;
            font-size: 16px;
            z-index: 9999999;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
            opacity: 0;
            transition: opacity 0.3s ease;
            max-width: 80%;
            max-height: 80vh;
            overflow-y: auto;
            word-break: break-all;
            text-align: left;
        `;

        // 1. 主要提示文本
        const tipTitle = document.createElement("div");
        tipTitle.style.cssText = `
            margin-bottom: 12px;
            font-weight: bold;
            font-size: 16px;
        `;
        tipTitle.textContent = mainText;
        tipContainer.appendChild(tipTitle);

        // 2. 详细信息(如有)
        if (detailText) {
            const tipDetail = document.createElement("div");
            tipDetail.style.cssText = `
                margin-bottom: 10px;
                font-size: 14px;
                line-height: 1.5;
            `;
            tipDetail.textContent = type === "error" ? `错误详情:${detailText}` : `响应信息:${detailText}`;
            tipContainer.appendChild(tipDetail);
        }

        // 3. 显示额外内容(IID/响应结果)
        if (content) {
            const contentWrapper = document.createElement("div");
            contentWrapper.style.cssText = `
                margin-top: 10px;
            `;

            const contentLabel = document.createElement("div");
            contentLabel.style.cssText = `
                font-size: 14px;
                margin-bottom: 5px;
                font-weight: bold;
            `;
            contentLabel.textContent = type === "error" ? "校验的IID:" : "响应结果:";
            contentWrapper.appendChild(contentLabel);

            const contentDisplay = document.createElement("div");
            contentDisplay.style.cssText = `
                font-size: 13px;
                padding: 8px;
                background: rgba(255,255,255,0.8);
                border-radius: 4px;
                white-space: pre-wrap;
                line-height: 1.4;
                font-family: Consolas, monospace;
            `;
            // 格式化展示内容
            let displayContent = content;
            try {
                // 如果是JSON字符串,格式化显示
                if (type === "success" && typeof content === "object") {
                    displayContent = JSON.stringify(content, null, 2);
                } else if (typeof content === "string" && content.startsWith("{")) {
                    displayContent = JSON.stringify(JSON.parse(content), null, 2);
                }
            } catch (e) {
                // 非JSON格式则原样显示
                displayContent = content;
            }

            // 超长内容换行处理
            if (displayContent.length > 60) {
                displayContent = displayContent.match(/.{1,60}/g)?.join('\n') || displayContent;
            }

            contentDisplay.textContent = displayContent;
            contentWrapper.appendChild(contentDisplay);

            tipContainer.appendChild(contentWrapper);
        }

        document.body.appendChild(tipContainer);

        // 显示提示框(淡入效果)
        setTimeout(() => {
            tipContainer.style.opacity = "1";
        }, 10);

        // 自动隐藏(淡出效果)
        setTimeout(() => {
            tipContainer.style.opacity = "0";
            setTimeout(() => {
                tipContainer.remove();
            }, 300);
        }, duration);
    }

    /**
     * 错误码转中文提示
     * @param {object} validateResult - 校验结果对象
     * @returns {object} {mainText: string, detailText: string}
     */
    function getErrorText(validateResult) {
        let mainText = "IID格式不合法";
        let detailText = "";

        if (validateResult.error === "not_numeric") {
            mainText = "⚠️ IID包含非数字字符";
            detailText = "IID必须全部由数字组成,不能包含字母、符号或空格";
        } else if (validateResult.error === "invalid_length") {
            mainText = "⚠️ IID长度不正确";
            detailText = `当前长度:${validateResult.length}位,合法长度应为54位或63位`;
        } else if (validateResult.failedBlocks && validateResult.failedBlocks.length > 0) {
            mainText = `⚠️ IID不合法,有${validateResult.failedBlocks.length}个区块校验失败`;
            const failedBlockStr = validateResult.failedBlocks.map(block =>
                                                                   `第${block.index}区块 (${block.value})`
            ).join("、");
            detailText = `失败的区块:${failedBlockStr}(区块校验位计算错误)`;
        }

        return { mainText, detailText };
    }

    /**
     * 获取微软激活配置项(改用GM_xmlhttpRequest)
     * @returns {Promise<any>} 返回服务器响应的 JSON 数据
     */
    async function getGovUrlConfig() {
        const url = "https://visualsupport.microsoft.com/api/configuration/govUrlID";

        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                headers: {
                    "accept": "application/json",
                    "cache-control": "no-cache"
                },
                onload: function (response) {
                    if (response.status >= 200 && response.status < 300) {
                        try {
                            resolve(JSON.parse(response.responseText));
                        } catch (e) {
                            reject(new Error("解析配置数据失败: " + e.message));
                        }
                    } else {
                        reject(new Error(`HTTP 错误! 状态码: ${response.status}`));
                    }
                },
                onerror: function (error) {
                    reject(new Error("请求配置失败: " + error.message));
                }
            });
        });
    }

    // 1. Base64URL编码函数(eI):JWT/DPoP标准编码方式
    function eI(t) {
        let e = t instanceof ArrayBuffer ? new Uint8Array(t) : new TextEncoder().encode(t);
        let n = "";
        for (let o of e) {
            n += String.fromCharCode(o);
        }
        return btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
    }

    // 2. 全局缓存密钥对的变量(单例模式)
    let tI = null;

    // 3. 生成/获取ECDSA P-256密钥对(yT)
    async function yT() {
        if (!tI) {
            tI = await crypto.subtle.generateKey({
                name: "ECDSA",
                namedCurve: "P-256"
            }, true,
                                                 ["sign", "verify"]
                                                );
        }
        return tI;
    }

    // 4. 核心:生成DPoP令牌(c1e)
    async function c1e(t, e) {
        try {
            const { privateKey: n, publicKey: o } = await yT();

            const i = {
                alg: "ES256",
                typ: "dpop+jwt",
                jwk: await crypto.subtle.exportKey("jwk", o)
            };

            const a = {
                htu: t,
                htm: e,
                jti: crypto.randomUUID(),
                iat: Math.floor(Date.now() / 1000)
            };

            const s = eI(JSON.stringify(i));
            const l = eI(JSON.stringify(a));
            const u = `${s}.${l}`;

            const p = await crypto.subtle.sign({
                name: "ECDSA",
                hash: "SHA-256"
            }, n, new TextEncoder().encode(u));

            const g = eI(p);
            return `${s}.${l}.${g}`;
        } catch (error) {
            console.error("生成DPoP令牌失败:", error);
            throw error;
        }
    }

    // 生成DPoP令牌
    async function testGenerateDPoP() {
        const dpopToken = await c1e(
            "/api/productActivation/validateIID",
            "POST"
        );
        return dpopToken;
    }

    //生成x-session-id app_mmsj2c31_x1nrlz06b
    function GenerateSessionId() {
        const t = Date.now().toString(36);
        const e = Math.random().toString(36).substr(2, 9);
        return `app_${t}_${e}`;
    }

    /**
     * ✅ 获取 Token JSON 数据(可返回,供全局使用)
     * @returns {Promise<Object>}
     */
    function getTokenData() {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: "https://cidtoken.x2ray.cfd",
                timeout: 10000,
                responseType: "json",
                onload: (res) => {
                    try {
                        const data = res.response;
                        if (!data || !data.access_token) {
                            reject("无效的 Token 数据");
                            return;
                        }
                        resolve(data);
                    } catch (err) {
                        reject("解析 JSON 失败:" + err);
                    }
                },
                onerror: (err) => reject("网络请求失败:" + err),
                ontimeout: () => reject("请求超时")
            });
        });
    }

    /**
     * 发送激活请求(改用GM_xmlhttpRequest)- 移除内部的IID校验
     * @param {string} iid - 从剪贴板获取的IID参数
     * @returns {Promise<any>} 响应结果
     */
    async function sendActivationRequest(iid) {
        if (!iid || iid.trim() === "") {
            throw new Error("剪贴板中未获取到有效的IID参数");
        }

        try {
            const dpopToken = await testGenerateDPoP();
            const govUrlConfig = await getGovUrlConfig();
            const numberOfDigits = Math.floor(iid.length / 9);
            const sid = GenerateSessionId();

            // ✅ 这里正确获取 token
            const tokenJson = await getTokenData();
            if (!tokenJson || !tokenJson.access_token) {
                throw new Error("获取 AccessToken 失败,请检查网络或接口");
            }

            return new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: "POST",
                    url: "https://visualsupport.microsoft.com/api/productActivation/validateIID",
                    headers: {
                        "content-type": "application/json",
                        //"authorization": "Bearer govUrlID",
                        "authorization": "Bearer " + tokenJson.id_token, // ✅ 已修复
                        "dpop": dpopToken,
                        "x-session-id": sid,
                        "referrer": `https://visualsupport.microsoft.com/${govUrlConfig}/activate`,
                    },
                    data: JSON.stringify({
                        IID: iid,
                        ProductType: "windows",
                        productGroup: "Windows",
                        productName: "Windows 11",
                        numberOfDigits: numberOfDigits,
                        Country: "CHN",
                        Region: "APGC",
                        InstalledDevices: 1,
                        OverrideStatusCode: "MUL",
                        InitialReasonCode: "45164"
                    }),
                    onload: function (response) {
                        if (response.status >= 200 && response.status < 300) {
                            try {
                                const result = JSON.parse(response.responseText);
                                resolve(result);
                            } catch (e) {
                                reject(new Error("解析响应数据失败: " + e.message));
                            }
                        } else {
                            reject(new Error(`请求失败! 状态码: ${response.status}, 响应: ${response.responseText}`));
                        }
                    },
                    onerror: function (error) {
                        reject(new Error("请求发送失败: " + error.message));
                    }
                });
            });
        } catch (error) {
            console.error("请求失败:", error);
            throw error;
        }
    }

    /**
     * 创建可拖拽的悬浮面板(美化版)
     */
    function createFloatPanel() {
        // 1. 创建面板容器(美化样式)
        const panel = document.createElement("div");
        panel.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 220px; /* 加宽一点更美观 */
            background: rgba(255,255,255,0.95); /* 半透明背景 */
            border: 1px solid #e5e7eb;
            border-radius: 12px; /* 更大圆角 */
            box-shadow: 0 8px 24px rgba(0,0,0,0.12); /* 更柔和的阴影 */
            z-index: 999999;
            padding: 16px;
            transition: background 0.3s, transform 0.2s; /* 过渡动画 */
            backdrop-filter: blur(8px); /* 毛玻璃效果 */
            cursor: move; /* 提示整个面板可拖拽 */
            user-select: none; /* 禁止选中文字 */
        `;
        panel.id = "ms-activation-panel";

        // 2. 创建标题
        const panelTitle = document.createElement("div");
        panelTitle.style.cssText = `
            font-size: 15px;
            font-weight: 600;
            margin-bottom: 12px;
            color: #1f2937;
            text-align: center;
            padding-bottom: 8px;
            border-bottom: 1px solid #f3f4f6; /* 分割线样式 */
        `;
        panelTitle.textContent = "微软激活ID获取 · 免登录版";
        panel.appendChild(panelTitle);

        // 3. 创建按钮(美化样式)
        const btn = document.createElement("button");
        btn.style.cssText = `
            width: 100%;
            padding: 10px;
            background: #0078d4;
            color: white;
            border: none;
            border-radius: 8px;
            cursor: pointer; /* 按钮保持点击光标 */
            font-size: 14px;
            margin-bottom: 10px;
            transition: background 0.2s, transform 0.1s; /* 交互动画 */
            font-weight: 500;
        `;
        // 按钮hover/active效果
        btn.addEventListener("mouseenter", () => {
            btn.style.background = "#0086e5";
        });
        btn.addEventListener("mouseleave", () => {
            btn.style.background = "#0078d4";
        });
        btn.addEventListener("mousedown", () => {
            btn.style.transform = "scale(0.98)";
        });
        btn.addEventListener("mouseup", () => {
            btn.style.transform = "scale(1)";
        });
        btn.textContent = "获取确认ID";
        panel.appendChild(btn);

        // 4. 创建状态提示(美化样式)
        const status = document.createElement("div");
        status.style.cssText = `
            font-size: 13px;
            color: #4b5563;
            text-align: center;
            min-height: 18px;
            line-height: 1.4;
            padding: 4px 0;
            border-radius: 6px;
        `;
        status.textContent = "✅ 就绪";
        panel.appendChild(status);

        // ===================== 悬浮面板拖拽(PC + Android + 防止出屏) =====================
        // 是否正在拖拽
        let isDragging = false;
        // 鼠标 / 手指 与 面板左上角 的偏移量
        let offsetX = 0;
        let offsetY = 0;

        /**
         * 开始拖拽
         * @param {number} clientX 鼠标/手指的 X 坐标
         * @param {number} clientY 鼠标/手指的 Y 坐标
         */
        function startDrag(clientX, clientY) {
            // 如果点击的是按钮,不触发拖拽
            if (event.target === btn) return;

            isDragging = true;
            // 获取面板当前在视口中的位置和尺寸
            const rect = panel.getBoundingClientRect();
            // ★ 关键:将 right/bottom 转换为 left/top,否则拖拽时位置会错乱
            panel.style.left = rect.left + "px";
            panel.style.top = rect.top + "px";
            panel.style.right = "auto";
            panel.style.bottom = "auto";
            // 计算鼠标 / 手指 与 面板左上角 的偏移量
            offsetX = clientX - rect.left;
            offsetY = clientY - rect.top;
            // 拖动时取消动画,保证跟手
            panel.style.transition = "none";
            // 拖动时轻微放大,提升交互感
            panel.style.transform = "scale(1.02)";
        }

        /**
         * 限制数值在 min ~ max 之间,防止面板被拖出屏幕
         */
        function clamp(value, min, max) {
            return Math.min(Math.max(value, min), max);
        }

        /**
         * 拖拽移动
         * @param {number} clientX
         * @param {number} clientY
         */
        function moveDrag(clientX, clientY) {
            if (!isDragging) return;
            // 计算屏幕最大可移动范围
            const maxX = window.innerWidth - panel.offsetWidth;
            const maxY = window.innerHeight - panel.offsetHeight;
            // 计算新位置,并限制在屏幕内
            const newLeft = clamp(clientX - offsetX, 0, maxX);
            const newTop = clamp(clientY - offsetY, 0, maxY);
            // 应用位置
            panel.style.left = newLeft + "px";
            panel.style.top = newTop + "px";
        }

        /**
         * 结束拖拽
         */
        function endDrag() {
            if (!isDragging) return;
            isDragging = false;
            // 恢复过渡动画
            panel.style.transition = "background 0.3s, transform 0.2s";
            // 恢复缩放
            panel.style.transform = "scale(1)";
        }

        /* ===================== PC 鼠标事件 ===================== */
        // 鼠标按下(整个面板监听)
        panel.addEventListener("mousedown", (e) => {
            e.preventDefault(); // 防止选中文字
            startDrag(e.clientX, e.clientY);
        });
        // 鼠标移动
        document.addEventListener("mousemove", (e) => {
            moveDrag(e.clientX, e.clientY);
        });
        // 鼠标松开
        document.addEventListener("mouseup", endDrag);

        /* ===================== Android 触摸事件 ===================== */
        // 手指按下
        panel.addEventListener("touchstart", (e) => {
            const touch = e.touches[0]; // 第一个触摸点
            startDrag(touch.clientX, touch.clientY);
        }, { passive: false }); // ★ 必须 passive:false
        // 手指移动
        document.addEventListener("touchmove", (e) => {
            if (!isDragging) return;
            e.preventDefault(); // ★ 关键:阻止页面滚动
            const touch = e.touches[0];
            moveDrag(touch.clientX, touch.clientY);
        }, { passive: false });
        // 手指松开 / 被打断
        document.addEventListener("touchend", endDrag);
        document.addEventListener("touchcancel", endDrag);

        // ===================== 页面悬浮提示(Toast) =====================
        function showToast(message, type = "info", duration = 5000) {
            const toast = document.createElement("div");
            const colors = {
                success: "rgba(40,167,69,0.9)", // 绿
                warning: "rgba(255,193,7,0.9)", // 黄
                error: "rgba(220,53,69,0.9)", // 红
                info: "rgba(0,0,0,0.85)"     // 黑
            };
            toast.textContent = message;
            toast.style.cssText = `
                position: fixed;
                top: 20px;
                left: 50%;
                transform: translateX(-50%) translateY(-10px);
                background: ${colors[type] || colors.info};
                color: #fff;
                padding: 10px 16px;
                border-radius: 6px;
                font-size: 14px;
                z-index: 10000;
                box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                opacity: 0;
                transition: opacity 0.3s, transform 0.3s;
                pointer-events: none;
                white-space: nowrap;
            `;
            document.body.appendChild(toast);
            // 淡入
            requestAnimationFrame(() => {
                toast.style.opacity = "1";
                toast.style.transform = "translateX(-50%) translateY(0)";
            });
            // 到时间淡出并移除
            setTimeout(() => {
                toast.style.opacity = "0";
                toast.style.transform = "translateX(-50%) translateY(-10px)";
                setTimeout(() => toast.remove(), 300);
            }, duration);
        }

        // 6. 按钮点击事件 - 保留原有逻辑,替换提示方式为Toast
        btn.addEventListener("click", async () => {
            // 定义恢复按钮状态的通用函数
            const resetButton = (text = "获取确认ID", statusText = "✅ 就绪") => {
                btn.disabled = false;
                btn.textContent = text;
                status.textContent = statusText;
            };

            try {
                // 禁用按钮防止重复点击
                btn.disabled = true;
                btn.textContent = "处理中...";
                status.textContent = "🔍 读取剪贴板中...";
                showToast("正在读取剪贴板内容", "info");

                // 从剪贴板获取IID(处理权限拒绝)
                let clipboardText;
                try {
                    clipboardText = await navigator.clipboard.readText();
                } catch (clipboardError) {
                    throw new Error("剪贴板访问被拒绝,请允许页面访问剪贴板权限");
                }

                if (!clipboardText) {
                    throw new Error("剪贴板为空,请先复制IID内容");
                }
                const original_iid = clipboardText.trim();
                status.textContent = "✅ 校验IID合法性...";
                showToast("正在校验IID合法性", "info");

                // 修复:兼容旧版JS的空值处理
                let aB = t => (t == null ? "" : t.replace(/[^a-zA-Z0-9]/g, "")) || "";
                const iid = aB(original_iid);

                // 第一步:校验IID合法性
                const validateResult = validateIID(iid);
                if (!validateResult.valid) {
                    // 获取错误提示文本
                    const errorInfo = getErrorText(validateResult);
                    // 显示精准的错误提示
                    showFloatTip(errorInfo.mainText, errorInfo.detailText, original_iid);
                    showToast(errorInfo.mainText, "error");
                    // 恢复按钮状态
                    resetButton();
                    return; // 终止后续流程
                }

                // IID合法,继续发送请求
                status.textContent = "📡 发送请求中...";
                showToast("IID验证通过,正在发送请求", "info");
                const result = await sendActivationRequest(iid);

                // 显示成功提示
                showToast("请求成功!结果已复制到剪贴板", "success");
                showFloatTip(
                    "✅ 请求成功!结果已复制到剪贴板",
                    "响应数据如下,已自动复制到剪贴板",
                    result,
                    "success",
                    5000
                );

                // 将结果复制到剪贴板
                GM_setClipboard(JSON.stringify(result, null, 2), "text");

                // 更新状态提示并恢复按钮
                resetButton("获取确认ID", "✅ 结果已复制到剪贴板");
                // 延迟重置状态(仅成功场景)
                setTimeout(() => {
                    status.textContent = "✅ 就绪";
                }, 3000);

            } catch (error) {
                // 处理所有类型的错误,确保按钮恢复
                console.error("操作失败:", error);
                // 显示错误提示
                showToast(error.message, "error");
                showFloatTip(
                    "❌ 操作失败",
                    error.message,
                    "",
                    "error",
                    5000
                );
                // 恢复按钮状态
                resetButton("重新获取", `❌ 失败: ${error.message}`);
            } finally {
                // 仅在错误状态下延迟重置(避免覆盖成功提示)
                if (btn.textContent.includes("重新获取")) {
                    setTimeout(() => {
                        status.textContent = "✅ 就绪";
                    }, 5000);
                }
            }
        });

        // 7. 将面板添加到页面
        document.body.appendChild(panel);
        console.info("✅ 微软激活ID获取面板已启用(美化版)");
    }

    // 页面加载完成后创建悬浮面板
    if (document.readyState === "complete" || document.readyState === "interactive") {
        createFloatPanel();
    } else {
        document.addEventListener("DOMContentLoaded", createFloatPanel);
    }

})();