KAAUH Lab Enhancement Suite 1 (Buttons, Alerts, Auto-Actions)

Combines verification buttons (F7/F8), dynamic alerts (>, NO RESULT, X-NORESULT, CL/CH) with modals that persist until dismissed, checkbox automation, toggle back-nav.

当前为 2025-04-04 提交的版本,查看 最新版本

// ==UserScript==
// @name      KAAUH Lab Enhancement Suite 1 (Buttons, Alerts, Auto-Actions)
// @namespace  Violentmonkey Scripts
// @version   5.6.3
// @description Combines verification buttons (F7/F8), dynamic alerts (>, NO RESULT, X-NORESULT, CL/CH) with modals that persist until dismissed, checkbox automation, toggle back-nav.
// @match    *://his.kaauh.org/lab/*
// @grant    none
// @author    Hamad AlShegifi
// @license   MIT
// ==/UserScript==

(function () {
  'use strict';

  // --- Configuration ---
  const CONFIG = {
    // General & Debugging
    DEBUG_MODE: true,
    PERSISTENT_MODALS: true, // Modals require manual dismissal
    NO_RESULT_MESSAGE: "NO-RESULT DETECTED!!", // Standardized message

    // Script 1: Buttons & Verification
    TARGET_EDIT_PAGE_URL_PREFIX: 'https://his.kaauh.org/lab/#/lab-orders/edit-lab-order/',
    EXCLUDE_WORDS: ['culture', "gram's stain", 'stain', 'bacterial', 'fungal', 'culture', 'pcr', 'Meningitis', 'MRSA', 'Mid', 'stream', 'Cryptococcus'],
    VERIFY1_BUTTON_SELECTOR: '#custom-script-buttons button.btn-success',
    VERIFY2_BUTTON_SELECTOR: '#custom-script-buttons button.btn-primary',
    COMPLETE_TECH_VERIFY_SELECTOR: 'button.dropdown-item[translateid="test-results.CompleteTechnicalVerification"]',
    COMPLETE_MED_VERIFY_SELECTOR: 'button.dropdown-item[translateid="test-results.CompleteMedicalVerification"]',
    FINAL_VERIFY_BUTTON_SELECTOR: 'button.btn-success.btn-sm.min-width[translateid="test-verification.Verify"]',
    NEXT_BUTTON_SELECTOR: 'button#btnNext',
    TEST_DESC_SELECTOR: 'div[col-id="TestDesc"]',
    UNCHECKED_BOX_SELECTOR: 'span.ag-icon-checkbox-unchecked[unselectable="on"]',
    CHECKBOX_PARENT_ROW_SELECTOR: '.ag-row',

    // Script 2: Alerts & Scanning
    SCAN_INTERVAL: 150,
    FLASH_COLOR: "pink",
    FLASH_INTERVAL: 500,
    MODAL_TIMEOUT: 10000,
    RESULT_CELL_SELECTOR: 'div[role="gridcell"][col-id="TestResult"] app-result-value-render div',
    CRITICAL_FLAG_SELECTOR: 'div[role="gridcell"][col-id="LTFlag"] app-ref-high-low div span.critial-alret-indication',

    // Script 3 & General Toast Handling
    UNDEFINED_URL_CHECK_INTERVAL: 200,
    TOAST_CONTAINER_SELECTOR: '#toast-container',
    TOAST_CLOSE_BUTTON_SELECTOR: 'button.toast-close-button',
    SUCCESS_TOAST_SELECTOR: '.toast-success',
  };

  // --- State Variables ---
  let verify1Toggle = localStorage.getItem('verify1Toggle') === 'true';
  let verify2Toggle = localStorage.getItem('verify2Toggle') === 'true';
  let verify1Clicked = false;
  let verify2Clicked = false;
  let issueScanIntervalId = null;
  let isScanningActive = false;
  const activeModals = new Set();

  // --- Utility Functions ---
  function logDebug(message) {
    if (CONFIG.DEBUG_MODE) console.log(`[Lab Suite v5.6.3] ${message}`);
  }

  function loadFontAwesome() {
    const existingLink = document.querySelector('link[href*="font-awesome"]');
    if (!existingLink) {
      const link = document.createElement('link');
      link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
      link.rel = 'stylesheet';
      document.head.appendChild(link);
      logDebug('Font Awesome loaded');
    }
  }

  function isVisible(element) {
    return !!(element && (element.offsetWidth || element.offsetHeight || element.getClientRects().length));
  }

  // --- Modal Functions ---
  function showModal(message) {
    // Remove duplicate modals with same message
    document.querySelectorAll('.lab-suite-modal').forEach(modal => {
      if (modal.textContent.includes(message)) {
        const overlay = document.querySelector('.lab-suite-modal-overlay');
        if (overlay) overlay.remove();
        modal.remove();
      }
    });

    logDebug(`Showing modal: ${message}`);
    const overlay = document.createElement("div");
    overlay.className = 'lab-suite-modal-overlay';
    overlay.style.position = "fixed";
    overlay.style.top = "0";
    overlay.style.left = "0";
    overlay.style.width = "100%";
    overlay.style.height = "100%";
    overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
    overlay.style.zIndex = "2000";
    overlay.style.opacity = "0";
    overlay.style.transition = "opacity 0.3s ease";
    document.body.appendChild(overlay);

    const modal = document.createElement("div");
    modal.className = 'lab-suite-modal';
    modal.style.position = "fixed";
    modal.style.top = "50%";
    modal.style.left = "50%";
    modal.style.transform = "translate(-50%, -50%) scale(0.5)";
    modal.style.backgroundColor = "#f4f4f9";
    modal.style.padding = "30px";
    modal.style.boxShadow = "0px 10px 30px rgba(0, 0, 0, 0.15)";
    modal.style.zIndex = "2001";
    modal.style.borderRadius = "15px";
    modal.style.textAlign = "center";
    modal.style.transition = "transform 0.3s ease, opacity 0.3s ease";
    modal.style.opacity = "0";
    modal.style.maxWidth = "450px";
    modal.setAttribute('role', 'alert');
    modal.setAttribute('aria-live', 'assertive');

    const heading = document.createElement("h2");
    heading.textContent = "Attention!";
    heading.style.fontFamily = "'Arial', sans-serif";
    heading.style.color = "#333";
    heading.style.marginBottom = "10px";
    heading.style.fontSize = "24px";
    modal.appendChild(heading);

    const content = document.createElement("p");
    // Standardize NO RESULT messages
    if (message.includes("NO RESULT") || message.includes("X-NORESULT")) {
      message = CONFIG.NO_RESULT_MESSAGE;
    }
    content.textContent = message;
    content.style.fontFamily = "'Arial', sans-serif";
    content.style.color = "#555";
    content.style.marginBottom = "20px";
    content.style.fontSize = "16px";
    content.style.lineHeight = "1.5";
    modal.appendChild(content);

    const okButton = createModalButton("OK", "#ff4081", () => {
      logDebug("Modal manually dismissed.");
      closeModal(modal, overlay);
    });
    modal.appendChild(okButton);

    document.body.appendChild(modal);

    // Animate appearance
    setTimeout(() => {
      overlay.style.opacity = "1";
      modal.style.transform = "translate(-50%, -50%) scale(1)";
      modal.style.opacity = "1";
    }, 10);

    activeModals.add(modal);
  }

  function createModalButton(text, backgroundColor, onClick) {
    const button = document.createElement("button");
    button.textContent = text;
    button.style.padding = "10px 20px";
    button.style.border = "none";
    button.style.backgroundColor = backgroundColor;
    button.style.color = "white";
    button.style.borderRadius = "30px";
    button.style.cursor = "pointer";
    button.style.fontSize = "16px";
    button.style.transition = "background-color 0.3s ease, transform 0.2s ease";
    button.style.minWidth = '80px';
    button.style.margin = '0 5px';

    button.addEventListener("mouseenter", () => {
      button.style.backgroundColor = darkenColor(backgroundColor, 20);
      button.style.transform = "scale(1.05)";
    });
    button.addEventListener("mouseleave", () => {
      button.style.backgroundColor = backgroundColor;
      button.style.transform = "scale(1)";
    });
    button.addEventListener("click", onClick);
    return button;
  }

  function closeModal(modal, overlay) {
    if (!modal || !overlay || !document.body.contains(modal)) return;
    logDebug("Closing modal.");
    modal.style.transform = "translate(-50%, -50%) scale(0.5)";
    modal.style.opacity = "0";
    overlay.style.opacity = "0";

    setTimeout(() => {
      if (document.body.contains(modal)) document.body.removeChild(modal);
      if (document.body.contains(overlay)) document.body.removeChild(overlay);
      activeModals.delete(modal);
    }, 300);
  }

  function darkenColor(color, percent) {
    try {
      let num = parseInt(color.slice(1), 16);
      let amt = Math.round(2.55 * percent);
      let R = (num >> 16) - amt;
      let G = ((num >> 8) & 0x00ff) - amt;
      let B = (num & 0x0000ff) - amt;
      R = R < 0 ? 0 : R;
      G = G < 0 ? 0 : G;
      B = B < 0 ? 0 : B;
      return `#${(0x1000000 + R * 0x10000 + G * 0x100 + B).toString(16).slice(1)}`;
    } catch (e) {
      logDebug(`Error darkening color ${color}: ${e}`);
      return color;
    }
  }

  // --- Script 1 Functions ---
  function isCorrectPage() {
    return window.location.href.startsWith(CONFIG.TARGET_EDIT_PAGE_URL_PREFIX);
  }

  function createVerifyButton(label, className, onClick) {
    let button = document.createElement('button');
    button.type = 'button';
    button.innerHTML = label;
    button.className = className;

    let buttonColors = {
      'btn btn-success btn-sm': '#28a745',
      'btn btn-primary btn-sm': '#2594d9'
    };

    button.style.cssText = `
        font-family: 'Arial', sans-serif !important;
        font-size: 14px !important;
        font-weight: normal !important;
        color: #ffffff !important;
        background-color: ${buttonColors[className] || '#6c757d'} !important;
        padding: 8px 16px !important;
        border: none !important;
        border-radius: 5px !important;
        text-shadow: none !important;
        cursor: pointer !important;
        margin-right: 5px !important;
        line-height: 1.5 !important;
      `;
    button.onclick = onClick;
    return button;
  }

  function createToggleIcon(id, isActive, onClick) {
    let icon = document.createElement('span');
    icon.id = id;
    icon.innerHTML = `<i class="fa fa-arrow-circle-left" aria-hidden="true" style="color: ${isActive ? '#008000' : '#d1cfcf'}; font-size: 1.3em; vertical-align: middle;"></i>`;
    icon.style.cursor = 'pointer';
    icon.style.marginRight = '10px';
    icon.style.marginLeft = '-1px';
    icon.onclick = onClick;
    icon.title = "Go back after this verification";
    return icon;
  }

  function handleVerify1IconToggle() {
    verify1Toggle = !verify1Toggle;
    localStorage.setItem('verify1Toggle', verify1Toggle);
    const iconElement = document.querySelector('#verify1Icon i');
    if (iconElement) iconElement.style.color = verify1Toggle ? '#008000' : '#d1cfcf';
    logDebug(`Verify1 Toggle set to: ${verify1Toggle}`);
  }

  function handleVerify2IconToggle() {
    verify2Toggle = !verify2Toggle;
    localStorage.setItem('verify2Toggle', verify2Toggle);
    const iconElement = document.querySelector('#verify2Icon i');
    if (iconElement) iconElement.style.color = verify2Toggle ? '#008000' : '#d1cfcf';
    logDebug(`Verify2 Toggle set to: ${verify2Toggle}`);
  }

  function addButtons() {
    if (document.getElementById('custom-script-buttons') || !isCorrectPage()) return;

    const nextButton = document.querySelector(CONFIG.NEXT_BUTTON_SELECTOR);
    if (nextButton && nextButton.parentNode) {
      logDebug("Adding custom VERIFY buttons.");
      let buttonDiv = document.createElement('div');
      buttonDiv.id = 'custom-script-buttons';
      buttonDiv.style.display = 'inline-block';
      buttonDiv.style.marginLeft = '10px';
      buttonDiv.style.verticalAlign = 'middle';

      // VERIFY1 Button & Toggle
      let verify1Button = createVerifyButton('VERIFY1 (F7)', 'btn btn-success btn-sm', () => {
        logDebug("VERIFY1 button clicked.");
        verify1Clicked = true;
        verify2Clicked = false;
        checkAllVisibleBoxesWithoutDuplicates();
        setTimeout(() => { clickCompleteTechnicalVerificationButton(); }, 500);
      });
      let verify1Icon = createToggleIcon('verify1Icon', verify1Toggle, handleVerify1IconToggle);

      // VERIFY2 Button & Toggle
      let verify2Button = createVerifyButton('VERIFY2 (F8)', 'btn btn-primary btn-sm', () => {
        logDebug("VERIFY2 button clicked.");
        verify2Clicked = true;
        verify1Clicked = false;
        checkAllVisibleBoxesWithoutDuplicates();
        setTimeout(() => { clickCompleteMedicalVerificationButton(); }, 500);
      });
      let verify2Icon = createToggleIcon('verify2Icon', verify2Toggle, handleVerify2IconToggle);

      // Author Credit
      let modedByText = document.createElement('span');
      modedByText.textContent = "Moded by: Hamad AlShegifi";
      modedByText.style.fontSize = '12px';
      modedByText.style.fontWeight = 'bold';
      modedByText.style.color = '#ff0000';
      modedByText.style.position = 'relative';
      modedByText.style.left = '0px';
      modedByText.style.top = '0px';
      modedByText.style.border = '1.5px solid #ff0000';
      modedByText.style.borderRadius = '8px';
      modedByText.style.padding = '4px';
      modedByText.style.backgroundColor = 'white';

      buttonDiv.appendChild(verify1Button);
      buttonDiv.appendChild(verify1Icon);
      buttonDiv.appendChild(verify2Button);
      buttonDiv.appendChild(verify2Icon);
      buttonDiv.appendChild(modedByText);

      nextButton.parentNode.insertBefore(buttonDiv, nextButton.nextSibling);
    } else {
      logDebug("Could not find Next button to anchor custom buttons.");
    }
  }

  function checkAllVisibleBoxesWithoutDuplicates() {
    logDebug("Checking checkboxes...");
    const testDivs = document.querySelectorAll(CONFIG.TEST_DESC_SELECTOR);
    let seenTests = new Set();
    let boxesChecked = 0;
    const excludeWordsLower = CONFIG.EXCLUDE_WORDS.map(word => word.toLowerCase());

    testDivs.forEach(testDiv => {
      const testName = testDiv.textContent?.trim().toLowerCase() || '';
      if (!testName) return;

      if (excludeWordsLower.some(word => testName.includes(word))) {
        return;
      }

      if (seenTests.has(testName)) {
        return;
      }

      seenTests.add(testName);
      const parentRow = testDiv.closest(CONFIG.CHECKBOX_PARENT_ROW_SELECTOR);
      if (parentRow) {
        const checkbox = parentRow.querySelector(CONFIG.UNCHECKED_BOX_SELECTOR);
        if (checkbox && isVisible(checkbox)) {
          logDebug(`Clicking checkbox for test: ${testName}`);
          const event = new MouseEvent('click', { bubbles: true, cancelable: true, view: window });
          checkbox.dispatchEvent(event);
          boxesChecked++;
        }
      }
    });
    logDebug(`${boxesChecked} unique, non-excluded checkboxes were checked.`);
  }

  function clickCompleteTechnicalVerificationButton() {
    const button = document.querySelector(CONFIG.COMPLETE_TECH_VERIFY_SELECTOR);
    if (button) {
      button.click();
      logDebug("Complete Technical Verification button clicked!");
      setTimeout(() => { clickFinalVerifyButton(); }, 700);
    } else {
      logDebug("Complete Technical Verification button not found!");
      showModal("Error: Unable to find the 'Complete Technical Verification' button.");
    }
  }

  function clickCompleteMedicalVerificationButton() {
    const button = document.querySelector(CONFIG.COMPLETE_MED_VERIFY_SELECTOR);
    if (button) {
      button.click();
      logDebug("Complete Medical Verification button clicked!");
      setTimeout(() => { clickFinalVerifyButton(); }, 700);
    } else {
      logDebug("Complete Medical Verification button not found!");
      showModal("Error: Unable to find the 'Complete Medical Verification' button.");
    }
  }

  function clickFinalVerifyButton() {
    const verifyButton = document.querySelector(CONFIG.FINAL_VERIFY_BUTTON_SELECTOR);
    if (verifyButton) {
      verifyButton.click();
      logDebug("Final Verify button clicked!");
    } else {
      logDebug("Final Verify button not found!");
      showModal("Error: Unable to find the final 'Verify' button.");
    }
  }

  // --- Script 2 Functions ---
  function applyFlashingEffect(rows) {
    rows.forEach(row => {
      if (row.dataset.flashing) return;
      row.dataset.flashing = 'true';
      logDebug("Applying flashing effect to a row.");

      row.style.transition = "background-color 0.5s ease";
      let isPink = false;
      const originalBg = row.style.backgroundColor || 'transparent';

      const intervalId = setInterval(() => {
        if (!document.contains(row)) {
          clearInterval(intervalId);
          delete row.dataset.flashing;
          return;
        }
        isPink = !isPink;
        row.style.backgroundColor = isPink ? CONFIG.FLASH_COLOR : originalBg;
      }, CONFIG.FLASH_INTERVAL);

      row.dataset.flashIntervalId = intervalId;
    });
  }

  function getNotificationSessionKey(type, identifier = 'general') {
    return `labSuiteNotified_${window.location.pathname}_${type}_${identifier}`;
  }

  function hasAlreadyNotified(type, identifier = 'general') {
    const key = getNotificationSessionKey(type, identifier);
    return sessionStorage.getItem(key) === 'true';
  }

  function setNotificationFlag(type, identifier = 'general') {
    const key = getNotificationSessionKey(type, identifier);
    logDebug(`Setting notification flag for key: ${key}`);
    sessionStorage.setItem(key, 'true');
  }

  function checkForIssues() {
    const resultDivs = document.querySelectorAll(CONFIG.RESULT_CELL_SELECTOR);
    const criticalDivs = document.querySelectorAll(CONFIG.CRITICAL_FLAG_SELECTOR);

    function scrollToRow(element) {
      const row = element.closest(CONFIG.CHECKBOX_PARENT_ROW_SELECTOR);
      if (row) {
        const rowId = row.getAttribute('row-id');
        logDebug(`Attempting to scroll to row with ID: ${rowId || 'ID not found'}`);
        row.scrollIntoView({ behavior: 'smooth', block: 'start' });
        return { scrolled: true, rowId: rowId };
      }
      return { scrolled: false };
    }

    let alertShownThisCycle = false;

    // 1. Check for Critical Flags (CL/CH)
    if (!alertShownThisCycle && !hasAlreadyNotified('critical')) {
      criticalDivs.forEach(div => {
        if (alertShownThisCycle) return;

        const text = div.textContent?.trim() || '';
        if (text === "CL" || text === "CH") {
          const scrollResult = scrollToRow(div);
          if (scrollResult.scrolled) {
            const specificRowKey = scrollResult.rowId || text;
            if (!hasAlreadyNotified('critical', specificRowKey)) {
              logDebug(`Found ${text} for row ${specificRowKey}`);
              const message = text === "CL" ? "CRITICAL LOW RESULT DETECTED !!" : "CRITICAL HIGH RESULT DETECTED !!";
              showModal(message);
              setNotificationFlag('critical', specificRowKey);
              setNotificationFlag('critical');
              alertShownThisCycle = true;
            }
          }
        }
      });
    }

    // 2. Check for "NO RESULT" / "X-NORESULT"
    if (!alertShownThisCycle && !hasAlreadyNotified('noresult')) {
      resultDivs.forEach(div => {
        if (alertShownThisCycle) return;

        const text = div.textContent?.trim().toLowerCase() || '';
        const isNoResultType = (text === "no result" || text === "no-xresult" || text === "x-noresult");

        if (isNoResultType) {
          const scrollResult = scrollToRow(div);
          if (scrollResult.scrolled) {
            const specificRowKey = scrollResult.rowId || text.replace(/[\s-]+/g, '_');
            if (!hasAlreadyNotified('noresult', specificRowKey)) {
              logDebug(`Found ${text} for row ${specificRowKey}`);
              showModal(CONFIG.NO_RESULT_MESSAGE);
              setNotificationFlag('noresult', specificRowKey);
              setNotificationFlag('noresult');
              alertShownThisCycle = true;
            }
          }
        }
      });
    }

    // 3. Check for ">" (Dilution Required)
    if (!alertShownThisCycle) {
      resultDivs.forEach(div => {
        const text = div.textContent?.trim().toLowerCase() || '';
        if (text.includes(">")) {
          const rowElement = div.closest(CONFIG.CHECKBOX_PARENT_ROW_SELECTOR);
          const rowId = rowElement?.getAttribute('row-id') || text;
          const eventKey = `greaterThan_${rowId}`;

          if (!hasAlreadyNotified('greaterThan', rowId)) {
            if (rowElement) {
              logDebug(`Found '>' for row ${rowId}`);
              applyFlashingEffect([rowElement]);
              showModal("Dilution is required for this sample (> detected)!");
              setNotificationFlag('greaterThan', rowId);
              scrollToRow(div);
            }
          }
        }
      });
    }

    return alertShownThisCycle;
  }

  function startContinuousScanning() {
    if (isScanningActive) return;
    logDebug("Starting continuous issue scanning...");
    isScanningActive = true;

    if (issueScanIntervalId) clearInterval(issueScanIntervalId);

    issueScanIntervalId = setInterval(() => {
      const resultsGridExists = document.querySelector(CONFIG.RESULT_CELL_SELECTOR) || document.querySelector(CONFIG.CRITICAL_FLAG_SELECTOR);
      if (!resultsGridExists) {
        logDebug("Monitored elements disappeared, stopping issue scan.");
        stopContinuousScanning();
        return;
      }
      checkForIssues();
    }, CONFIG.SCAN_INTERVAL);
  }

  function stopContinuousScanning() {
    if (issueScanIntervalId) {
      clearInterval(issueScanIntervalId);
      issueScanIntervalId = null;
      logDebug("Stopped continuous issue scanning.");
    }
    isScanningActive = false;
  }

  // --- Script 3 Function ---
  function checkUrlAndTriggerClickForUndefined() {
    const currentUrl = window.location.href;
    if (currentUrl.endsWith('/undefined')) {
      const toastContainer = document.querySelector(CONFIG.TOAST_CONTAINER_SELECTOR);
      if (toastContainer) {
        const closeButton = toastContainer.querySelector(CONFIG.TOAST_CLOSE_BUTTON_SELECTOR);
        if (closeButton && isVisible(closeButton)) {
          logDebug('URL ends with /undefined. Found visible toast close button. Clicking...');
          closeButton.click();
        }
      }
    }
  }

  // --- Event Listeners & Observers ---
  document.addEventListener('keydown', function (event) {
    if (event.key === 'F7') {
      event.preventDefault();
      logDebug("F7 pressed: Triggering VERIFY1 button click");
      const verify1Button = document.querySelector(CONFIG.VERIFY1_BUTTON_SELECTOR);
      if (verify1Button) verify1Button.click();
      else logDebug("VERIFY1 button not found for F7.");
    } else if (event.key === 'F8') {
      event.preventDefault();
      logDebug("F8 pressed: Triggering VERIFY2 button click");
      const verify2Button = document.querySelector(CONFIG.VERIFY2_BUTTON_SELECTOR);
      if (verify2Button) verify2Button.click();
      else logDebug("VERIFY2 button not found for F8.");
    }
  });

  const toastObserver = new MutationObserver((mutations) => {
    mutations.forEach(mutation => {
      mutation.addedNodes.forEach(node => {
        if (node.nodeType === Node.ELEMENT_NODE && node.matches && node.matches(CONFIG.SUCCESS_TOAST_SELECTOR)) {
          logDebug('Success toast added. Adding click listener for back navigation.');
          node.addEventListener('click', () => {
            logDebug('Success toast clicked.');
            if (verify1Clicked && verify1Toggle) {
              logDebug('Verify1 was clicked and toggle is on. Going back.');
              window.history.back();
            } else if (verify2Clicked && verify2Toggle) {
              logDebug('Verify2 was clicked and toggle is on. Going back.');
              window.history.back();
            }
            verify1Clicked = false;
            verify2Clicked = false;
          });
        }
      });
    });
  });

  const mainObserver = new MutationObserver(() => {
    if (isCorrectPage()) {
      addButtons();
    } else {
      const buttonDiv = document.getElementById('custom-script-buttons');
      if (buttonDiv) {
        logDebug("Leaving edit page, removing custom buttons.");
        buttonDiv.remove();
      }
    }

    const resultsGridExists = document.querySelector(CONFIG.RESULT_CELL_SELECTOR) || document.querySelector(CONFIG.CRITICAL_FLAG_SELECTOR);
    if (resultsGridExists) {
      if (!isScanningActive) {
        startContinuousScanning();
      }
    } else {
      if (isScanningActive) {
        stopContinuousScanning();
      }
    }
  });

  // --- Initialization ---
  try {
    logDebug("KAAUH Lab Enhancement Suite Initializing (v5.6.3)...");
    loadFontAwesome();

    setInterval(checkUrlAndTriggerClickForUndefined, CONFIG.UNDEFINED_URL_CHECK_INTERVAL);
    logDebug(`Started URL check interval (${CONFIG.UNDEFINED_URL_CHECK_INTERVAL}ms) for /undefined toasts.`);

    mainObserver.observe(document.body, { childList: true, subtree: true });
    logDebug("Started main MutationObserver.");

    toastObserver.observe(document.body, { childList: true, subtree: true });
    logDebug("Started toast MutationObserver for back-navigation.");

    window.addEventListener('load', () => {
      logDebug("Page fully loaded. Performing initial checks.");
      if (isCorrectPage()) { addButtons(); }
      const resultsGridExists = document.querySelector(CONFIG.RESULT_CELL_SELECTOR) || document.querySelector(CONFIG.CRITICAL_FLAG_SELECTOR);
      if (resultsGridExists && !isScanningActive) {
        startContinuousScanning();
      }
    });

    logDebug("Initialization complete.");

  } catch (error) {
    console.error("[Lab Suite] Critical error during initialization:", error);
    showModal("A critical error occurred in the Lab Enhancement Suite. Please check the browser console (F12) for details.");
  }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址