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

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

Устаревшая версия за 24.05.2025. Перейдите к последней версии.

Этот скрипт недоступен для установки пользователем. Он является библиотекой, которая подключается к другим скриптам мета-ключом // @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 架构兼容版本');
})();