岐黄天使刷课助手 - 调试加载器模块

岐黄天使刷课助手的调试与模块状态监控器,用于 @require 架构下的模块状态跟踪和调试支持。

Version vom 24.05.2025. Aktuellste Version

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/537076/1594955/%E5%B2%90%E9%BB%84%E5%A4%A9%E4%BD%BF%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%20-%20%E8%B0%83%E8%AF%95%E5%8A%A0%E8%BD%BD%E5%99%A8%E6%A8%A1%E5%9D%97.js

// ==UserScript==
// @name         岐黄天使刷课助手 - 调试加载器模块
// @namespace    http://tampermonkey.net/qhtx-modules
// @version      1.3.0
// @description  岐黄天使刷课助手的调试与模块状态监控器,用于 @require 架构下的模块状态跟踪和调试支持。
// @author       AI助手
// ==/UserScript==

/**
 * 调试加载器模块 - 重构版本
 *
 * 此模块已重构以适配基于 GreasyFork @require 指令的生产架构:
 * - 移除了所有本地开发服务器 (192.168.1.6:9999) 的 HTTP 请求
 * - 保留模块状态跟踪系统,用于监控 @require 加载的模块状态
 * - 提供备用函数注入功能,用于调试和开发场景
 * - 与 main.user.js 的增强错误处理机制完全兼容
 *
 * 架构说明:
 * - 所有模块现在通过 Tampermonkey 的 @require 机制从 GreasyFork 加载
 * - 版本控制通过 URL 查询参数 (?v=x.x.x&t=timestamp) 实现
 * - 此调试加载器仅负责状态监控和备用功能提供
 */
(function() {
    'use strict';

    // 添加模块加载状态跟踪
    window.moduleStatus = {
      loaded: new Set(),
      pending: new Set([
        // 'styles', 'utils', 'ui', 'videoPlayer',
        // 'videoNavigation', 'courseNavigation', 'questionBank',
        // 'autoAnswer', 'remoteSync'
      ]),
      startTime: Date.now(),
      // 显示模块加载状态
      showStatus: function() {
        const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(2);
        console.log(`
        ========== 模块加载状态 (${elapsed}秒) ==========
        已加载: ${Array.from(this.loaded).join(', ') || '无'}
        待加载: ${Array.from(this.pending).join(', ') || '无'}
        ============================================
        `);
      }
    };

    // 定期显示模块加载状态
    window.moduleStatusInterval = setInterval(() => {
      if (window.moduleStatus.pending.size === 0) {
        clearInterval(window.moduleStatusInterval);
        window.moduleStatus.showStatus();
        console.log('%c所有模块加载完成!', 'color: green; font-size: 14px; font-weight: bold');
      } else {
        window.moduleStatus.showStatus();
      }
    }, 2000);

    // 检查模块加载状态
    function checkModuleLoaded(moduleName) {
      const now = new Date();
      const timeStr = now.toLocaleTimeString() + '.' + now.getMilliseconds();
      console.log(`[模块加载] 正在验证 ${moduleName} 状态,当前时间: ${timeStr}`);

      // 详细检查window对象上的模块属性
      console.log(`[模块加载详情] ${moduleName} 检查:`, {
        '直接访问': window[moduleName],
        '类型': typeof window[moduleName],
        '是否存在': moduleName in window,
        'window属性': Object.keys(window).filter(k => k.includes(moduleName)),
        '全局变量': Object.keys(window).filter(k => k.startsWith('qh') || k.includes('module') || k.includes('Module'))
      });

      // 检查模块是否已加载
      if (typeof window[moduleName] === 'function') {
        window.moduleStatus.loaded.add(moduleName);
        window.moduleStatus.pending.delete(moduleName);

        console.log(`[模块加载] %c${moduleName} 已就绪%c`,
                    'color: green; font-weight: bold', 'color: black');

        // 输出已加载的模块列表
        console.log(`[模块加载] 已加载模块: ${Array.from(window.moduleStatus.loaded).join(', ')}`);
        console.log(`[模块加载] 待加载模块: ${Array.from(window.moduleStatus.pending).join(', ')}`);

        return true;
      }

      // 如果模块未加载,尝试检查是否有其他命名方式
      const possibleNames = [
        moduleName,
        moduleName.charAt(0).toUpperCase() + moduleName.slice(1), // 首字母大写
        moduleName + 'Module',
        'qh' + moduleName.charAt(0).toUpperCase() + moduleName.slice(1), // qh前缀
        'create' + moduleName.charAt(0).toUpperCase() + moduleName.slice(1), // create前缀
        'init' + moduleName.charAt(0).toUpperCase() + moduleName.slice(1), // init前缀
        'apply' + moduleName.charAt(0).toUpperCase() + moduleName.slice(1) // apply前缀
      ];

      console.log(`[模块加载] 尝试其他可能的命名:`, possibleNames.map(name => ({
        name,
        exists: name in window,
        type: typeof window[name]
      })));

      console.warn(`[模块加载] %c${moduleName} 未就绪%c,window[${moduleName}] = ${window[moduleName]}`,
                  'color: red; font-weight: bold', 'color: black');

      return false;
    }

    /**
     * 检查模块文件 (已重构)
     *
     * 此函数已重构为不执行实际的 HTTP 请求。
     * 在 @require 架构下,模块由 Tampermonkey 自动加载,
     * 此函数仅用于兼容性和调试目的。
     *
     * @param {string} moduleName - 模块名称
     * @returns {Promise} - 始终返回成功的 Promise
     */
    function checkModuleFile(moduleName) {
      console.log(`[模块检查] 模块 ${moduleName} 应通过 @require 从 GreasyFork 加载,跳过本地检查`);
      return Promise.resolve({
        module: moduleName,
        content: '@require-loaded',
        status: 200,
        source: 'greasyfork-require'
      });
    }

    /**
     * 加载模块 (已重构)
     *
     * 此函数已重构为不执行实际的模块加载。
     * 在 @require 架构下,模块由 Tampermonkey 在脚本启动时自动加载,
     * 此函数仅用于兼容性和状态跟踪目的。
     *
     * @param {string} moduleName - 模块名称
     * @returns {Promise} - 始终返回成功的 Promise
     */
    function loadModuleWithGM(moduleName) {
      console.log(`[模块加载] 模块 ${moduleName} 应通过 @require 从 GreasyFork 自动加载,跳过手动加载`);
      return Promise.resolve({
        module: moduleName,
        loaded: true,
        source: 'greasyfork-require',
        timestamp: Date.now()
      });
    }

    /**
     * 检查所有模块 (已重构)
     *
     * 此函数已重构为不执行实际的模块检查。
     * 在 @require 架构下,模块状态检查通过检测全局函数是否存在来实现。
     *
     * @returns {Promise} - 返回模块状态检查结果
     */
    function checkAllModules() {
      console.log('[模块检查] @require 架构下的模块状态检查');

      // 检查关键模块函数是否已加载
      const moduleChecks = [
        { name: 'styles', func: 'applyStyles' },
        { name: 'ui', func: 'createPanel' },
        { name: 'utils', func: 'checkPageType' },
        { name: 'questionBank', func: 'getQuestionList' },
        { name: 'autoAnswer', func: 'startAutoAnswer' },
        { name: 'videoPlayer', func: 'toggleAutoLearn' }
      ];

      const results = moduleChecks.map(check => {
        const isLoaded = typeof window[check.func] === 'function';
        const status = isLoaded ? 'loaded' : 'pending';

        if (isLoaded) {
          window.moduleStatus.loaded.add(check.name);
          window.moduleStatus.pending.delete(check.name);
        } else {
          window.moduleStatus.pending.add(check.name);
        }

        return {
          module: check.name,
          function: check.func,
          status: status,
          loaded: isLoaded
        };
      });

      console.log('[模块检查] @require 模块状态检查完成:', results);
      return Promise.resolve(results);
    }

    /**
     * 加载所有模块 (已重构)
     *
     * 此函数已重构为不执行实际的模块加载。
     * 在 @require 架构下,模块由 Tampermonkey 自动加载,
     * 此函数仅用于状态同步和兼容性目的。
     *
     * @returns {Promise} - 返回模块加载状态结果
     */
    function loadAllModules() {
      console.log('[模块加载] @require 架构下的模块状态同步');

      // 重新检查模块状态,确保状态同步
      return checkAllModules().then(results => {
        const loadedModules = results.filter(r => r.loaded);
        const pendingModules = results.filter(r => !r.loaded);

        console.log(`[模块加载] 模块状态同步完成:`, {
          total: results.length,
          loaded: loadedModules.length,
          pending: pendingModules.length,
          loadedModules: loadedModules.map(m => m.module),
          pendingModules: pendingModules.map(m => m.module)
        });

        return results;
      });
    }

    /**
     * 注入备用模块函数到全局作用域
     *
     * 此函数提供备用的模块函数实现,用于以下场景:
     * - @require 模块加载失败时的降级方案
     * - 开发和调试阶段的基本功能支持
     * - 确保核心功能在任何情况下都能正常工作
     *
     * 注意:这些是简化的备用实现,功能有限
     */
    function injectModuleFunctions() {
      console.log('[调试加载器] 开始注入备用模块函数到全局作用域');

      // 注入styles模块
      if (!window.applyStyles) {
        window.applyStyles = function() {
          console.log('[模块注入] 执行注入的 applyStyles 函数');
          GM_addStyle(`
            .qh-assistant-panel {
                position: fixed;
                top: 100px;
                right: 10px;
                width: 280px;
                background: linear-gradient(135deg, #00a8cc, #0062bd);
                border-radius: 12px;
                padding: 15px;
                color: white;
                z-index: 9999;
                font-size: 14px;
                box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
            }
            .qh-assistant-title {
                font-size: 18px;
                font-weight: bold;
                text-align: center;
                margin-bottom: 12px;
                border-bottom: 2px solid rgba(255, 255, 255, 0.3);
                padding-bottom: 8px;
            }
            .qh-assistant-content {
                margin-bottom: 12px;
            }
            .qh-assistant-btn {
                background: linear-gradient(90deg, #4CAF50, #45a049);
                border: none;
                color: white;
                padding: 8px 12px;
                text-align: center;
                display: block;
                width: 100%;
                margin: 5px 0;
                cursor: pointer;
                border-radius: 4px;
            }
          `);
          console.log('[模块注入] applyStyles 函数执行完成');
        };
        console.log('[模块注入] 已注入 applyStyles 函数');
      }

      // 注入ui模块
      if (!window.createPanel) {
        window.createPanel = function() {
          console.log('[模块注入] 执行注入的 createPanel 函数');

          // 检查是否已经创建过面板
          if (document.querySelector('.qh-assistant-panel')) {
            console.log('[模块注入] 面板已存在,不重复创建');
            return;
          }

          const panel = document.createElement('div');
          panel.className = 'qh-assistant-panel';
          panel.innerHTML = `
            <div class="qh-assistant-title">岐黄天使刷课助手 v1.3.0</div>
            <div class="qh-assistant-content">
                <div>状态: 调试模式</div>
                <div>当前页面: ${window.location.href}</div>
            </div>
            <button class="qh-assistant-btn" id="qh-debug-btn">调试信息</button>
          `;
          document.body.appendChild(panel);

          // 添加调试按钮事件
          document.getElementById('qh-debug-btn').addEventListener('click', function() {
            console.log('[调试] 当前页面信息:', {
              'URL': window.location.href,
              '已加载模块': Array.from(window.moduleStatus.loaded),
              '待加载模块': Array.from(window.moduleStatus.pending),
              'window.qh': window.qh
            });
            alert('调试信息已输出到控制台');
          });

          console.log('[模块注入] createPanel 函数执行完成');
        };
        console.log('[模块注入] 已注入 createPanel 函数');
      }

      // 注入utils模块
      if (!window.checkPageType) {
        window.checkPageType = function() {
          console.log('[模块注入] 执行注入的 checkPageType 函数');
          console.log('[页面检查] 当前页面URL:', window.location.href);
        };
        console.log('[模块注入] 已注入 checkPageType 函数');
      }

      console.log('[调试加载器] 模块函数注入完成');
    }

    // 导出模块函数
    window.debugLoader = {
      checkModuleLoaded,
      checkModuleFile,
      loadModuleWithGM,
      checkAllModules,
      loadAllModules,
      injectModuleFunctions
    };

    /**
     * 自动执行模块状态检查和备用函数准备
     *
     * 在 @require 架构下,此函数主要用于:
     * - 检查 @require 加载的模块状态
     * - 在需要时提供备用函数
     * - 与 main.user.js 的初始化流程协调
     */
    setTimeout(() => {
      console.log('[调试加载器] @require 架构下的模块状态检查开始');

      // 首先检查 @require 模块的加载状态
      checkAllModules()
        .then(results => {
          const loadedCount = results.filter(r => r.loaded).length;
          const totalCount = results.length;

          console.log(`[调试加载器] @require 模块状态检查完成: ${loadedCount}/${totalCount} 已加载`);

          // 如果有模块未加载,提供备用函数
          if (loadedCount < totalCount) {
            console.log('[调试加载器] 检测到未加载的模块,准备备用函数');
            injectModuleFunctions();

            // 更新状态,标记备用函数已提供
            results.forEach(result => {
              if (!result.loaded) {
                window.moduleStatus.loaded.add(result.module + '-fallback');
                console.log(`[调试加载器] 为 ${result.module} 提供了备用函数`);
              }
            });
          } else {
            console.log('[调试加载器] 所有 @require 模块已正常加载,无需备用函数');
          }

          return loadAllModules();
        })
        .then(() => {
          console.log('[调试加载器] 模块状态同步完成');
        })
        .catch(error => {
          console.error('[调试加载器] 模块状态检查出错:', error);
          console.log('[调试加载器] 启用备用函数作为安全措施');
          injectModuleFunctions();
        });
    }, 500); // 减少延迟,因为 @require 模块应该已经加载

    console.log('[调试加载器] 模块已加载 - @require 架构兼容版本');
})();