Greasy Fork

Greasy Fork is available in English.

webAI聊天问题列表导航

通过点击按钮显示用户问题列表,支持导航到特定问题、分页功能、正序/倒序切换,智能脉冲式加载历史记录突破懒加载,自动适配暗黑模式,按钮可拖动并保存位置,悬浮窗智能展开方向,无极调整按钮大小,新增NotebookLM支持

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         webAI聊天问题列表导航
// @namespace    http://tampermonkey.net/
// @version      3.9.6
// @description  通过点击按钮显示用户问题列表,支持导航到特定问题、分页功能、正序/倒序切换,智能脉冲式加载历史记录突破懒加载,自动适配暗黑模式,按钮可拖动并保存位置,悬浮窗智能展开方向,无极调整按钮大小,新增NotebookLM支持
// @author       yutao
// @match        https://github.com/copilot/*
// @match        https://yuanbao.tencent.com/chat/*
// @match        https://chat.qwen.ai/c/*
// @match        https://copilot.microsoft.com/chats/*
// @match        https://chatgpt.com/c/*
// @match        https://chat.deepseek.com/a/chat/*
// @match        https://www.tongyi.com/*
// @match        https://www.qianwen.com/*
// @match        https://www.doubao.com/*
// @match        https://www.chatglm.cn/*
// @match        https://www.kimi.com/chat/*
// @match        https://copilot.wps.cn/*
// @match        https://notebooklm.google.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// MIT License
//
// Copyright (c) [2025] [yutao]
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.@license
// ==/UserScript==

(function () {
  "use strict";

  // 配置工厂函数 - 创建统一的网站配置结构
  function createSiteConfig(options) {
    return {
      messageSelector: options.messageSelector,
      textSelector: options.textSelector !== undefined ? options.textSelector : null,
      userCondition: options.userCondition || ((element) => true),
      scrollContainerSelector: options.scrollContainerSelector || 
        'div[class*="overflow"], div[class*="scroll"], main',
      useScrollContainerForMessages: options.useScrollContainerForMessages || false,
    };
  }

  // 预定义的用户条件函数
  const userConditions = {
    // 默认条件:所有消息都是用户消息
    alwaysTrue: (element) => true,
    
    // 检查类名是否包含特定字符串
    hasClass: (className) => (element) => element.classList.contains(className),
  };

  // 配置对象,定义不同网站的聊天消息选择器和条件
  const config = {
    "chat.qwen.ai": createSiteConfig({
      messageSelector: "div.rounded-3xl.bg-gray-50.dark\\:bg-gray-850",
      textSelector: "p",
      scrollContainerSelector: 'div.overflow-y-auto, div[class*="chat-content"]',
    }),

    "tongyi.com": createSiteConfig({
      messageSelector: 'div[class*="questionItem"]',
      textSelector: 'div[class*="contentBox"] div[class*="bubble"]',
      scrollContainerSelector: 'div[class*="contentWrapper"], main, div[class*="chat-content"], div[class*="chatContent"]',
    }),

    "qianwen.com": createSiteConfig({
      messageSelector: 'div[class*="questionItem"]',
      textSelector: 'div[class*="contentBox"] div[class*="bubble"]',
      scrollContainerSelector: 'div[class*="contentWrapper"], main, div[class*="chat-content"], div[class*="chatContent"]',
    }),

    "yuanbao.tencent.com": createSiteConfig({
      messageSelector: "div.agent-chat__bubble__content",
      textSelector: "div.hyc-content-text",
      scrollContainerSelector: ".agent-chat__bubble-wrap",
    }),

    "doubao.com": createSiteConfig({
      messageSelector: 'div[data-testid="send_message"]',
      textSelector: 'div[data-testid="message_text_content"]',
      scrollContainerSelector: 'div[class*="scrollable-"][class*="show-scrollbar-"]',
    }),

    "copilot.wps.cn": createSiteConfig({
      messageSelector: 'li.item--user, div[class*="item--user"], li[class*="item--user"], .item.item--user',
      textSelector: '.item__value span, div[class*="item__value"] span, .item__value, [class*="item__value"]',
      scrollContainerSelector: '.chat, .p__main, div[class*="scrollbar"], div[class*="chat-list"], div[class*="scroll"], .scroll-container',
    }),

    "www.kimi.com": createSiteConfig({
      messageSelector: 'div.segment-user, div[class*="segment-user"]',
      textSelector: '.user-content, div[class*="user-content"]',
      scrollContainerSelector: 'div[class*="scrollbar"], div[class*="chat-history"]',
    }),

    "chatglm.cn": createSiteConfig({
      messageSelector: 'div.conversation.question, div[id*="row-question"]',
      textSelector: '.question-txt span, div[id*="row-question-p"] span',
      scrollContainerSelector: 'div[class*="chat-history"], div[class*="scrollable"]',
    }),

    "chat.deepseek.com": createSiteConfig({
      messageSelector: "div.fbb737a4",
      scrollContainerSelector: ".scroll-container",
    }),

    "github.com": createSiteConfig({
      messageSelector: "div.UserMessage-module__container--cAvvK.ChatMessage-module__userMessage--xvIFp",
      userCondition: userConditions.hasClass("ChatMessage-module__userMessage--xvIFp"),
      scrollContainerSelector: ".react-scroll-to-bottom--css-xgtui-79elbk",
    }),

    "copilot.microsoft.com": createSiteConfig({
      messageSelector: "div.self-end.rounded-2xl",
      userCondition: userConditions.hasClass("self-end"),
      scrollContainerSelector: ".overflow-y-auto.flex-1",
    }),

    "chatgpt.com": createSiteConfig({
      messageSelector: "div.rounded-3xl.bg-token-message-surface",
      textSelector: "div.whitespace-pre-wrap",
      scrollContainerSelector: "main div.overflow-y-auto",
    }),

    "notebooklm.google.com": createSiteConfig({
      messageSelector: '.from-user-container',
      textSelector: 'div, p, span',
      userCondition: userConditions.hasClass('from-user-container'),
      scrollContainerSelector: '.chat-panel-content, chat-pane, .chat-panel, main, div[class*="scroll"]',
      useScrollContainerForMessages: true,
    }),
  };

  const genericConfig = {
    // 消息选择器:匹配常见的消息元素模式
    messageSelector:
      'div[class*="message"], div[class*="chat"], div[class*="user"], div[class*="question"], div[class*="questionItem"]',

    // 文本选择器:匹配常见的文本容器
    textSelector:
      'div[class*="text"], div[class*="content"], p, span[class*="content"], div[class*="contentBox"]',

    // 用户消息条件:使用多种通用的方法识别用户消息
    userCondition: (element) => {
      // 检查常见的用户消息类名
      if (
        element.classList.toString().includes("user") ||
        element.classList.toString().includes("question") ||
        element.classList.toString().includes("self") ||
        element.classList.toString().includes("right") ||
        element.classList.toString().includes("message")
      )
        return true;

      // 检查常见的用户角色属性
      if (
        element.getAttribute("data-role") === "user" ||
        element.getAttribute("data-author") === "user" ||
        element.getAttribute("data-message-author-role") === "user"
      )
        return true;

      // 检查布局特征 (右对齐通常表示用户消息)
      const style = window.getComputedStyle(element);
      if (
        style.justifyContent === "flex-end" ||
        style.textAlign === "right" ||
        style.alignSelf === "flex-end"
      )
        return true;

      // 检查文本内容特征:如果没有包含AI常用的前缀标识
      const text = element.textContent.trim().toLowerCase();
      if (
        text &&
        text.length > 0 &&
        !text.startsWith("ai:") &&
        !text.startsWith("assistant:") &&
        !text.startsWith("bot:")
      )
        return true;

      return false;
    },

    // 滚动容器选择器:匹配常见的滚动容器
    scrollContainerSelector:
      'div[class*="overflow"], div[class*="scroll"], div[class*="chat-container"], div[class*="message-container"], #messages-container, main',
  };

  // 获取当前域名并选择配置
  const hostname = window.location.hostname;

  // 获取当前网站的配置,如果没有特定配置则使用通用配置
  const currentConfig = config[hostname] || genericConfig;

  // 暗黑模式检测和主题管理
  const themeManager = {
    isDark: false,
    
    // 检测暗黑模式
    detectDarkMode() {
      // 1. 检查系统偏好
      const systemDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
      
      // 2. 检查网站是否使用暗黑模式
      const htmlDark = document.documentElement.classList.contains('dark') || 
                       document.documentElement.getAttribute('data-theme') === 'dark';
      const bodyDark = document.body.classList.contains('dark') || 
                       document.body.getAttribute('data-theme') === 'dark';
      
      // 3. 检查背景色
      const bodyBg = window.getComputedStyle(document.body).backgroundColor;
      const bgDark = this.isColorDark(bodyBg);
      
      this.isDark = htmlDark || bodyDark || bgDark || systemDark;
      return this.isDark;
    },
    
    // 判断颜色是否为暗色
    isColorDark(color) {
      const rgb = color.match(/\d+/g);
      if (!rgb || rgb.length < 3) return false;
      const brightness = (parseInt(rgb[0]) * 299 + parseInt(rgb[1]) * 587 + parseInt(rgb[2]) * 114) / 1000;
      return brightness < 128;
    },
    
    // 获取主题颜色
    getColors() {
      if (this.isDark) {
        return {
          // 暗黑模式
          buttonBg: "linear-gradient(135deg, #1e40af, #0ea5e9)",
          buttonColor: "#e5e7eb",
          windowBg: "#1f2937",
          windowBorder: "#374151",
          windowShadow: "0 4px 12px rgba(0,0,0,0.5)",
          textPrimary: "#f3f4f6",
          textSecondary: "#9ca3af",
          itemHoverBg: "#374151",
          itemBorder: "#4b5563",
          buttonPrimaryBg: "#10b981",
          buttonPrimaryHover: "#059669",
          buttonSecondaryBg: "#3b82f6",
          buttonSecondaryHover: "#2563eb",
          statusBg: "#374151",
          statusBorder: "#4b5563",
          paginationBg: "#374151",
          paginationActiveBg: "#3b82f6",
          paginationColor: "#e5e7eb",
        };
      } else {
        return {
          // 亮色模式
          buttonBg: "linear-gradient(135deg, #007BFF, #00C4FF)",
          buttonColor: "#fff",
          windowBg: "#ffffff",
          windowBorder: "#e0e0e0",
          windowShadow: "0 4px 12px rgba(0,0,0,0.15)",
          textPrimary: "#333",
          textSecondary: "#666",
          itemHoverBg: "#f5f5f5",
          itemBorder: "#f0f0f0",
          buttonPrimaryBg: "#28a745",
          buttonPrimaryHover: "#218838",
          buttonSecondaryBg: "#007BFF",
          buttonSecondaryHover: "#0069d9",
          statusBg: "#f8f9fa",
          statusBorder: "#e0e0e0",
          paginationBg: "#f0f0f0",
          paginationActiveBg: "#007BFF",
          paginationColor: "#333",
        };
      }
    }
  };

  // 初始化主题
  themeManager.detectDarkMode();
  const colors = themeManager.getColors();

  // 按钮样式工厂 - 类似 Vue 组件的按钮创建器
  const ButtonFactory = {
    // 按钮样式预设(类似 Vue 的 props)
    presets: {
      primary: {
        background: colors.buttonPrimaryBg,
        hoverBackground: colors.buttonPrimaryHover,
        color: "#fff",
      },
      secondary: {
        background: colors.buttonSecondaryBg,
        hoverBackground: colors.buttonSecondaryHover,
        color: "#fff",
      },
      default: {
        background: colors.paginationBg,
        hoverBackground: colors.itemHoverBg,
        color: colors.paginationColor,
      },
      disabled: {
        background: colors.paginationBg,
        hoverBackground: colors.paginationBg,
        color: colors.textSecondary,
      },
    },

    // 创建按钮(类似 Vue 的 render 函数)
    create(options = {}) {
      const {
        text = "",
        preset = "default",
        onClick = null,
        disabled = false,
        padding = "5px 10px",
        fontSize = "12px",
        borderRadius = "4px",
        customStyle = {},
      } = options;

      const button = document.createElement("button");
      const style = this.presets[disabled ? "disabled" : preset];

      // 设置按钮文本
      button.textContent = text;

      // 应用基础样式
      Object.assign(button.style, {
        padding,
        background: style.background,
        color: style.color,
        border: "none",
        borderRadius,
        cursor: disabled ? "not-allowed" : "pointer",
        fontSize,
        transition: "background 0.2s",
        fontFamily: "Arial, sans-serif",
        ...customStyle,
      });

      // 设置禁用状态
      button.disabled = disabled;

      // 添加悬停效果(类似 Vue 的事件处理)
      if (!disabled) {
        button.addEventListener("mouseover", () => {
          button.style.background = style.hoverBackground;
        });
        button.addEventListener("mouseout", () => {
          button.style.background = style.background;
        });
      }

      // 添加点击事件
      if (onClick && !disabled) {
        button.addEventListener("click", onClick);
      }

      return button;
    },

    // 创建分页按钮(特殊类型)
    createPaginationButton(options = {}) {
      const { page, isActive = false, onClick = null } = options;

      return this.create({
        text: String(page),
        preset: isActive ? "secondary" : "default",
        onClick,
        customStyle: {
          background: isActive ? colors.paginationActiveBg : colors.paginationBg,
          color: isActive ? "#fff" : colors.paginationColor,
        },
      });
    },

    // 创建导航按钮(上一页/下一页)
    createNavButton(options = {}) {
      const { text, disabled = false, onClick = null } = options;

      return this.create({
        text,
        preset: disabled ? "disabled" : "secondary",
        disabled,
        onClick,
        customStyle: {
          background: disabled ? colors.paginationBg : colors.paginationActiveBg,
          color: disabled ? colors.textSecondary : "#fff",
        },
      });
    },
  };

  // 右键菜单管理器
  const contextMenuManager = {
    menu: null,
    
    // 创建菜单
    create() {
      if (this.menu) {
        this.destroy();
      }
      
      this.menu = document.createElement('div');
      this.menu.style.cssText = `
        position: fixed;
        background: ${colors.windowBg};
        border: 1px solid ${colors.windowBorder};
        border-radius: 8px;
        box-shadow: ${colors.windowShadow};
        padding: 8px 0;
        min-width: 160px;
        z-index: 10000;
        font-family: Arial, sans-serif;
        font-size: 13px;
        display: none;
      `;
      
      document.body.appendChild(this.menu);
      return this.menu;
    },
    
    // 添加菜单项
    addItem(text, icon, onClick, isActive = false) {
      const item = document.createElement('div');
      item.style.cssText = `
        padding: 8px 16px;
        cursor: pointer;
        color: ${colors.textPrimary};
        display: flex;
        align-items: center;
        gap: 8px;
        transition: background 0.2s;
        ${isActive ? `background: ${colors.itemHoverBg};` : ''}
      `;
      
      // 使用 DOM API 而不是 innerHTML,避免 Trusted Types 问题
      const iconSpan = document.createElement('span');
      iconSpan.style.cssText = 'width: 16px; text-align: center;';
      iconSpan.textContent = icon;
      
      const textSpan = document.createElement('span');
      textSpan.style.cssText = 'flex: 1;';
      textSpan.textContent = text;
      
      item.appendChild(iconSpan);
      item.appendChild(textSpan);
      
      if (isActive) {
        const checkSpan = document.createElement('span');
        checkSpan.style.color = colors.buttonSecondaryBg;
        checkSpan.textContent = '✓';
        item.appendChild(checkSpan);
      }
      
      item.addEventListener('mouseover', () => {
        item.style.background = colors.itemHoverBg;
      });
      
      item.addEventListener('mouseout', () => {
        item.style.background = isActive ? colors.itemHoverBg : 'transparent';
      });
      
      item.addEventListener('click', (e) => {
        e.stopPropagation();
        onClick();
        this.hide();
      });
      
      this.menu.appendChild(item);
    },
    
    // 添加分隔线
    addSeparator() {
      const separator = document.createElement('div');
      separator.style.cssText = `
        height: 1px;
        background: ${colors.itemBorder};
        margin: 4px 0;
      `;
      this.menu.appendChild(separator);
    },
    
    // 显示菜单
    show(x, y) {
      if (!this.menu) return;
      
      // 清空现有内容(使用 DOM API 避免 Trusted Types 问题)
      while (this.menu.firstChild) {
        this.menu.removeChild(this.menu.firstChild);
      }
      
      // 构建菜单项
      this.buildMenu();
      
      // 调整位置防止超出屏幕
      const rect = this.menu.getBoundingClientRect();
      const maxX = window.innerWidth - rect.width - 10;
      const maxY = window.innerHeight - rect.height - 10;
      
      x = Math.min(x, maxX);
      y = Math.min(y, maxY);
      
      this.menu.style.left = x + 'px';
      this.menu.style.top = y + 'px';
      this.menu.style.display = 'block';
      
      // 点击其他地方关闭菜单
      setTimeout(() => {
        document.addEventListener('click', this.hide.bind(this), { once: true });
      }, 0);
    },
    
    // 构建菜单内容
    buildMenu() {
      // 按钮大小调整
      this.addItem('调整按钮大小', '📏', () => this.openSizeAdjuster());
      
      this.addSeparator();
      
      // 位置和其他设置
      this.addItem('重置位置', '📍', () => this.resetPosition());
      this.addItem('重置所有设置', '🔄', () => this.resetAllSettings());
      
      // 未来可扩展的设置项
      // this.addSeparator();
      // this.addItem('主题设置', '🎨', () => this.openThemeSettings());
      // this.addItem('高级设置', '⚙️', () => this.openAdvancedSettings());
    },
    
    // 打开大小调整器
    openSizeAdjuster() {
      sizeAdjusterManager.show();
    },
    

    
    // 重置位置
    resetPosition() {
      const defaultPos = settingsManager.defaults.position;
      settingsManager.set('position', defaultPos);
      button.style.bottom = defaultPos.bottom + 'px';
      button.style.right = defaultPos.right + 'px';
      updateFloatWindowPosition();
    },
    
    // 重置所有设置
    resetAllSettings() {
      if (confirm('确定要重置所有设置吗?这将恢复默认的按钮大小和位置。')) {
        settingsManager.reset();
        location.reload(); // 简单粗暴的重置方法
      }
    },
    
    // 隐藏菜单
    hide() {
      if (this.menu) {
        this.menu.style.display = 'none';
      }
    },
    
    // 销毁菜单
    destroy() {
      if (this.menu) {
        this.menu.remove();
        this.menu = null;
      }
    }
  };
  
  // 应用按钮大小
  function applyButtonSize(scale) {
    const style = settingsManager.getButtonStyle(scale);
    button.style.padding = style.padding;
    button.style.fontSize = style.fontSize;
    button.style.borderRadius = style.borderRadius;
    
    // 更新悬浮窗位置(因为按钮大小变了)
    setTimeout(updateFloatWindowPosition, 0);
  }

  // 统一存储适配器 - 优先使用 GM API,回退到 localStorage
  const StorageAdapter = {
    // 检测是否支持 GM API
    hasGMSupport() {
      const hasSupport = typeof GM_setValue !== 'undefined' && typeof GM_getValue !== 'undefined';
      // 首次检测时输出日志
      if (!this._loggedSupport) {
        console.log('[存储适配器] GM API 支持:', hasSupport ? '✅ 是' : '❌ 否,使用 localStorage');
        this._loggedSupport = true;
      }
      return hasSupport;
    },
    
    // 设置值
    set(key, value) {
      try {
        if (this.hasGMSupport()) {
          GM_setValue(key, value);
        } else {
          localStorage.setItem(key, JSON.stringify(value));
        }
        return true;
      } catch (e) {
        console.warn(`存储失败: ${key}`, e);
        return false;
      }
    },
    
    // 获取值
    get(key, defaultValue = null) {
      try {
        if (this.hasGMSupport()) {
          return GM_getValue(key, defaultValue);
        } else {
          const value = localStorage.getItem(key);
          return value ? JSON.parse(value) : defaultValue;
        }
      } catch (e) {
        console.warn(`读取失败: ${key}`, e);
        return defaultValue;
      }
    },
    
    // 删除值
    delete(key) {
      try {
        if (this.hasGMSupport()) {
          GM_deleteValue(key);
        } else {
          localStorage.removeItem(key);
        }
        return true;
      } catch (e) {
        console.warn(`删除失败: ${key}`, e);
        return false;
      }
    },
    
    // 列出所有键
    listKeys() {
      try {
        if (this.hasGMSupport()) {
          return GM_listValues();
        } else {
          return Object.keys(localStorage);
        }
      } catch (e) {
        console.warn('列出键失败', e);
        return [];
      }
    }
  };

  // 设置管理器 - 统一管理所有用户设置
  const settingsManager = {
    storageKeys: {
      position: 'questionListButton_position',
      size: 'questionListButton_size',
      theme: 'questionListButton_theme',
      pageSize: 'questionListButton_pageSize'
    },
    
    // 默认设置
    defaults: {
      position: { bottom: 20, right: 20 },
      buttonScale: 100, // 按钮缩放比例 (50-200)
      theme: 'auto',
      pageSize: 10
    },
    
    // 根据缩放比例计算按钮样式
    getButtonStyle(scale) {
      // 基础样式 (scale = 100 时的标准大小)
      const basePadding = 10; // 10px
      const baseFontSize = 14; // 14px
      const baseBorderRadius = 8; // 8px
      
      // 计算实际值
      const factor = scale / 100;
      const padding = Math.round(basePadding * factor);
      const fontSize = Math.round(baseFontSize * factor);
      const borderRadius = Math.round(baseBorderRadius * factor);
      
      return {
        padding: `${padding}px ${Math.round(padding * 1.5)}px`,
        fontSize: `${fontSize}px`,
        borderRadius: `${borderRadius}px`
      };
    },
    
    // 获取设置
    get(key) {
      return StorageAdapter.get(this.storageKeys[key], this.defaults[key]);
    },
    
    // 保存设置
    set(key, value) {
      return StorageAdapter.set(this.storageKeys[key], value);
    },
    
    // 重置所有设置
    reset() {
      Object.keys(this.storageKeys).forEach(key => {
        StorageAdapter.delete(this.storageKeys[key]);
      });
    }
  };

  // 创建美化后的浮动按钮
  const button = document.createElement("button");
  button.textContent = "问题列表";
  button.style.position = "fixed";
  button.style.zIndex = "1000";
  button.style.background = colors.buttonBg;
  button.style.color = colors.buttonColor;
  button.style.border = "none";
  button.style.boxShadow = "0 2px 4px rgba(0,0,0,0.2)";
  button.style.cursor = "move";
  button.style.fontFamily = "Arial, sans-serif";
  button.style.transition = "transform 0.2s, box-shadow 0.2s";
  button.style.userSelect = "none";
  
  // 恢复保存的位置和大小
  const savedPos = settingsManager.get('position');
  const savedScale = settingsManager.get('buttonScale');
  
  button.style.bottom = savedPos.bottom + "px";
  button.style.right = savedPos.right + "px";
  
  // 应用保存的按钮大小
  applyButtonSize(savedScale);
  
  // 创建右键菜单
  contextMenuManager.create();

  // 大小调整器管理器
  const sizeAdjusterManager = {
    panel: null,
    slider: null,
    input: null,
    
    // 创建调整面板
    create() {
      if (this.panel) {
        this.destroy();
      }
      
      this.panel = document.createElement('div');
      this.panel.style.cssText = `
        position: fixed;
        background: ${colors.windowBg};
        border: 1px solid ${colors.windowBorder};
        border-radius: 12px;
        box-shadow: ${colors.windowShadow};
        padding: 20px;
        width: 300px;
        z-index: 10001;
        font-family: Arial, sans-serif;
        display: none;
      `;
      
      // 标题
      const title = document.createElement('div');
      title.textContent = '调整按钮大小';
      title.style.cssText = `
        font-size: 16px;
        font-weight: bold;
        color: ${colors.textPrimary};
        margin-bottom: 15px;
        text-align: center;
      `;
      
      // 滑块容器
      const sliderContainer = document.createElement('div');
      sliderContainer.style.cssText = `
        display: flex;
        align-items: center;
        gap: 12px;
        margin-bottom: 15px;
      `;
      
      // 滑块
      this.slider = document.createElement('input');
      this.slider.type = 'range';
      this.slider.min = '50';
      this.slider.max = '200';
      this.slider.step = '5';
      this.slider.style.cssText = `
        flex: 1;
        height: 6px;
        border-radius: 3px;
        background: ${colors.itemBorder};
        outline: none;
        cursor: pointer;
      `;
      
      // 数值输入框
      this.input = document.createElement('input');
      this.input.type = 'number';
      this.input.min = '50';
      this.input.max = '200';
      this.input.step = '5';
      this.input.style.cssText = `
        width: 60px;
        padding: 6px 8px;
        border: 1px solid ${colors.windowBorder};
        border-radius: 4px;
        background: ${colors.windowBg};
        color: ${colors.textPrimary};
        font-size: 13px;
        text-align: center;
      `;
      
      // 按钮容器
      const buttonContainer = document.createElement('div');
      buttonContainer.style.cssText = `
        display: flex;
        gap: 10px;
        justify-content: center;
      `;
      
      // 确定按钮
      const okButton = document.createElement('button');
      okButton.textContent = '确定';
      okButton.style.cssText = `
        padding: 8px 16px;
        background: ${colors.buttonSecondaryBg};
        color: white;
        border: none;
        border-radius: 6px;
        cursor: pointer;
        font-size: 13px;
      `;
      
      // 取消按钮
      const cancelButton = document.createElement('button');
      cancelButton.textContent = '取消';
      cancelButton.style.cssText = `
        padding: 8px 16px;
        background: ${colors.paginationBg};
        color: ${colors.textPrimary};
        border: 1px solid ${colors.windowBorder};
        border-radius: 6px;
        cursor: pointer;
        font-size: 13px;
      `;
      
      // 组装面板
      sliderContainer.appendChild(this.slider);
      sliderContainer.appendChild(this.input);
      buttonContainer.appendChild(okButton);
      buttonContainer.appendChild(cancelButton);
      
      this.panel.appendChild(title);
      this.panel.appendChild(sliderContainer);
      this.panel.appendChild(buttonContainer);
      
      document.body.appendChild(this.panel);
      
      // 事件监听
      this.setupEvents(okButton, cancelButton);
    },
    
    // 设置事件监听
    setupEvents(okButton, cancelButton) {
      // 滑块变化
      this.slider.addEventListener('input', () => {
        const value = parseInt(this.slider.value);
        this.input.value = value;
        this.previewSize(value);
      });
      
      // 输入框变化
      this.input.addEventListener('input', () => {
        let value = parseInt(this.input.value);
        if (isNaN(value)) return;
        
        value = Math.max(50, Math.min(200, value));
        this.slider.value = value;
        this.previewSize(value);
      });
      
      // 确定按钮
      okButton.addEventListener('click', () => {
        const value = parseInt(this.slider.value);
        settingsManager.set('buttonScale', value);
        this.hide();
      });
      
      // 取消按钮
      cancelButton.addEventListener('click', () => {
        // 恢复原始大小
        const originalScale = settingsManager.get('buttonScale');
        applyButtonSize(originalScale);
        this.hide();
      });
      
      // 点击外部关闭
      setTimeout(() => {
        document.addEventListener('click', (e) => {
          if (!this.panel.contains(e.target)) {
            cancelButton.click();
          }
        }, { once: true });
      }, 0);
    },
    
    // 预览大小变化
    previewSize(scale) {
      applyButtonSize(scale);
    },
    
    // 显示面板
    show() {
      if (!this.panel) {
        this.create();
      }
      
      // 设置当前值
      const currentScale = settingsManager.get('buttonScale');
      this.slider.value = currentScale;
      this.input.value = currentScale;
      
      // 居中显示
      const rect = this.panel.getBoundingClientRect();
      const x = (window.innerWidth - 300) / 2;
      const y = (window.innerHeight - rect.height) / 2;
      
      this.panel.style.left = x + 'px';
      this.panel.style.top = y + 'px';
      this.panel.style.display = 'block';
      
      // 聚焦到滑块
      setTimeout(() => this.slider.focus(), 100);
    },
    
    // 隐藏面板
    hide() {
      if (this.panel) {
        this.panel.style.display = 'none';
      }
    },
    
    // 销毁面板
    destroy() {
      if (this.panel) {
        this.panel.remove();
        this.panel = null;
        this.slider = null;
        this.input = null;
      }
    }
  };
  
  // 拖动功能
  let isDragging = false;
  let dragStartX = 0;
  let dragStartY = 0;
  let buttonStartBottom = 0;
  let buttonStartRight = 0;
  
  button.addEventListener("mousedown", (e) => {
    // 只在左键点击时开始拖动
    if (e.button !== 0) return;
    
    isDragging = true;
    dragStartX = e.clientX;
    dragStartY = e.clientY;
    buttonStartBottom = parseInt(button.style.bottom);
    buttonStartRight = parseInt(button.style.right);
    
    button.style.cursor = "grabbing";
    e.preventDefault();
  });
  
  document.addEventListener("mousemove", (e) => {
    if (!isDragging) return;
    
    const deltaX = dragStartX - e.clientX;
    const deltaY = dragStartY - e.clientY; // 修正:向下拖动时 deltaY 应该为负
    
    let newBottom = buttonStartBottom + deltaY;
    let newRight = buttonStartRight + deltaX;
    
    // 限制在窗口范围内
    const maxBottom = window.innerHeight - button.offsetHeight - 10;
    const maxRight = window.innerWidth - button.offsetWidth - 10;
    
    newBottom = Math.max(10, Math.min(newBottom, maxBottom));
    newRight = Math.max(10, Math.min(newRight, maxRight));
    
    button.style.bottom = newBottom + "px";
    button.style.right = newRight + "px";
    
    e.preventDefault();
  });
  
  document.addEventListener("mouseup", (e) => {
    if (isDragging) {
      isDragging = false;
      button.style.cursor = "move";
      
      // 保存位置
      const bottom = parseInt(button.style.bottom);
      const right = parseInt(button.style.right);
      settingsManager.set('position', { bottom, right });
      
      // 更新悬浮窗位置
      updateFloatWindowPosition();
      
      // 如果移动距离很小,视为点击
      const moveDistance = Math.sqrt(
        Math.pow(e.clientX - dragStartX, 2) + 
        Math.pow(e.clientY - dragStartY, 2)
      );
      
      if (moveDistance < 5) {
        // 触发点击事件
        setTimeout(() => {
          toggleFloatWindow();
        }, 0);
      }
    }
  });
  
  button.addEventListener("mouseover", () => {
    if (!isDragging) {
      button.style.transform = "scale(1.05)";
      button.style.boxShadow = "0 4px 8px rgba(0,0,0,0.3)";
    }
  });
  button.addEventListener("mouseout", () => {
    if (!isDragging) {
      button.style.transform = "scale(1)";
      button.style.boxShadow = "0 2px 4px rgba(0,0,0,0.2)";
    }
  });
  
  // 右键菜单事件
  button.addEventListener("contextmenu", (e) => {
    e.preventDefault();
    e.stopPropagation();
    contextMenuManager.show(e.clientX, e.clientY);
  });
  
  document.body.appendChild(button);

  // 创建美化后的悬浮窗
  const floatWindow = document.createElement("div");
  floatWindow.style.position = "fixed";
  floatWindow.style.width = "320px";
  floatWindow.style.maxHeight = "420px";
  floatWindow.style.background = colors.windowBg;
  floatWindow.style.border = `1px solid ${colors.windowBorder}`;
  floatWindow.style.borderRadius = "10px";
  floatWindow.style.boxShadow = colors.windowShadow;
  floatWindow.style.padding = "15px";
  floatWindow.style.overflowY = "auto";
  floatWindow.style.display = "none";
  floatWindow.style.zIndex = "1000";
  floatWindow.style.fontFamily = "Arial, sans-serif";
  floatWindow.style.transition = "opacity 0.2s";
  
  // 更新悬浮窗位置的函数 - 智能选择展开方向
  function updateFloatWindowPosition() {
    const buttonBottom = parseInt(button.style.bottom);
    const buttonRight = parseInt(button.style.right);
    const buttonWidth = button.offsetWidth;
    const buttonHeight = button.offsetHeight;
    
    const windowWidth = window.innerWidth;
    const windowHeight = window.innerHeight;
    
    const floatWindowWidth = 320;
    const floatWindowHeight = 420; // maxHeight
    const gap = 10; // 间距
    
    // 计算按钮在屏幕上的实际位置
    const buttonLeft = windowWidth - buttonRight - buttonWidth;
    const buttonTop = windowHeight - buttonBottom - buttonHeight;
    
    // 重置之前的定位属性
    floatWindow.style.top = 'auto';
    floatWindow.style.bottom = 'auto';
    floatWindow.style.left = 'auto';
    floatWindow.style.right = 'auto';
    
    // 1. 判断垂直方向:上方还是下方展开
    const spaceAbove = buttonTop; // 按钮上方的空间
    const spaceBelow = windowHeight - buttonTop - buttonHeight; // 按钮下方的空间
    
    if (spaceAbove >= floatWindowHeight || spaceAbove >= spaceBelow) {
      // 上方空间足够,在按钮上方展开
      floatWindow.style.bottom = (buttonBottom + buttonHeight + gap) + "px";
    } else {
      // 上方空间不足,在按钮下方展开
      floatWindow.style.top = (buttonTop + buttonHeight + gap) + "px";
    }
    
    // 2. 判断水平方向:左侧还是右侧对齐
    const spaceOnRight = buttonLeft + buttonWidth;
    const spaceOnLeft = windowWidth - buttonLeft;
    
    if (spaceOnRight >= floatWindowWidth) {
      // 右对齐(悬浮窗在按钮左侧或与按钮右边缘对齐)
      floatWindow.style.right = buttonRight + "px";
    } else if (spaceOnLeft >= floatWindowWidth) {
      // 左对齐(悬浮窗在按钮右侧或与按钮左边缘对齐)
      floatWindow.style.left = buttonLeft + "px";
    } else {
      // 空间不足,居中显示
      const centerLeft = Math.max(gap, (windowWidth - floatWindowWidth) / 2);
      floatWindow.style.left = centerLeft + "px";
    }
  }
  
  // 初始化悬浮窗位置
  updateFloatWindowPosition();
  
  document.body.appendChild(floatWindow);

  // 存储测试函数(开发调试用)
  window.testStorage = function() {
    console.log('=== 存储测试开始 ===');
    
    // 测试1: 检测 GM API
    console.log('1. GM API 支持:', StorageAdapter.hasGMSupport());
    
    // 测试2: 写入测试
    const testKey = 'test_storage_' + Date.now();
    const testValue = { time: Date.now(), data: '测试数据' };
    console.log('2. 写入测试数据:', testValue);
    const writeSuccess = StorageAdapter.set(testKey, testValue);
    console.log('   写入结果:', writeSuccess ? '✅ 成功' : '❌ 失败');
    
    // 测试3: 读取测试
    const readValue = StorageAdapter.get(testKey);
    console.log('3. 读取测试数据:', readValue);
    console.log('   读取结果:', JSON.stringify(readValue) === JSON.stringify(testValue) ? '✅ 成功' : '❌ 失败');
    
    // 测试4: 删除测试
    StorageAdapter.delete(testKey);
    const afterDelete = StorageAdapter.get(testKey);
    console.log('4. 删除后读取:', afterDelete);
    console.log('   删除结果:', afterDelete === null ? '✅ 成功' : '❌ 失败');
    
    // 测试5: 收藏功能
    console.log('5. 当前页面ID:', FavoriteManager.getPageId());
    console.log('   当前收藏:', FavoriteManager.getAll());
    
    console.log('=== 存储测试完成 ===');
    console.log('提示: 刷新页面后再次运行 testStorage() 检查数据是否持久化');
  };

  // 消息计数管理器 - 记录每个页面的消息总数
  const MessageCountManager = {
    storageKey: 'questionList_messageCounts',
    
    // 获取当前页面的唯一标识
    getPageId() {
      return window.location.pathname + window.location.search;
    },
    
    // 获取记录的消息总数
    getCount() {
      const pageId = this.getPageId();
      const allCounts = StorageAdapter.get(this.storageKey, {});
      return allCounts[pageId] || 0;
    },
    
    // 保存消息总数
    saveCount(count) {
      const pageId = this.getPageId();
      const allCounts = StorageAdapter.get(this.storageKey, {});
      allCounts[pageId] = count;
      StorageAdapter.set(this.storageKey, allCounts);
      console.log('[消息计数] 保存消息总数:', {
        pageId,
        消息总数: count
      });
    },
    
    // 检查是否需要加载历史
    shouldLoadHistory(currentCount) {
      const savedCount = this.getCount();
      const needLoad = savedCount > 0 && currentCount < savedCount;
      console.log('[消息计数] 检查是否需要加载历史:', {
        当前消息数: currentCount,
        记录的总数: savedCount,
        需要加载: needLoad
      });
      return needLoad;
    }
  };

  // 收藏管理器
  const FavoriteManager = {
    storageKey: 'questionList_favorites',
    
    // 获取当前页面的唯一标识(用于区分不同对话)
    getPageId() {
      return window.location.pathname + window.location.search;
    },
    
    // 获取所有收藏
    getAll() {
      const pageId = this.getPageId();
      const allFavorites = StorageAdapter.get(this.storageKey, {});
      const favorites = allFavorites[pageId] || [];
      console.log('[收藏管理器] 读取收藏:', {
        pageId,
        收藏数量: favorites.length,
        收藏列表: favorites
      });
      return favorites;
    },
    
    // 保存收藏
    saveAll(favorites) {
      const pageId = this.getPageId();
      const allFavorites = StorageAdapter.get(this.storageKey, {});
      allFavorites[pageId] = favorites;
      const success = StorageAdapter.set(this.storageKey, allFavorites);
      console.log('[收藏管理器] 保存收藏:', {
        pageId,
        收藏数量: favorites.length,
        保存成功: success
      });
    },
    
    // 检查是否已收藏
    isFavorite(questionText) {
      return this.getAll().includes(questionText);
    },
    
    // 添加收藏
    add(questionText) {
      const favorites = this.getAll();
      if (!favorites.includes(questionText)) {
        favorites.push(questionText);
        this.saveAll(favorites);
      }
    },
    
    // 移除收藏
    remove(questionText) {
      const favorites = this.getAll().filter(text => text !== questionText);
      this.saveAll(favorites);
    },
    
    // 切换收藏状态
    toggle(questionText) {
      if (this.isFavorite(questionText)) {
        this.remove(questionText);
        return false;
      } else {
        this.add(questionText);
        return true;
      }
    },
    
    // 获取收藏的问题对象
    getFavoriteQuestions(allQuestions) {
      const favorites = this.getAll();
      return allQuestions.filter(q => favorites.includes(q.text));
    }
  };

  // 分页相关变量
  let questions = [];
  const pageSize = 10;
  let currentPage = 1;
  let isReversed = false;
  let isLoading = false; // 加载状态标志
  let autoLoadCompleted = false; // 标记自动加载是否已完成

  // 创建顶部按钮容器
  const topButtonContainer = document.createElement("div");
  topButtonContainer.style.display = "flex";
  topButtonContainer.style.justifyContent = "space-between";
  topButtonContainer.style.marginBottom = "15px";

  // 使用按钮工厂创建加载历史按钮
  const loadButton = ButtonFactory.create({
    text: "加载历史",
    preset: "primary",
    onClick: () => loadHistoryRecords(),
  });

  // 使用按钮工厂创建排序切换按钮
  const sortButton = ButtonFactory.create({
    text: "正序",
    preset: "secondary",
    onClick: () => {
      isReversed = !isReversed;
      sortButton.textContent = isReversed ? "倒序" : "正序";
      findAllQuestionsWithDeduplication();
    },
  });

  // 状态显示标签
  const statusLabel = document.createElement("div");
  statusLabel.textContent = "正在加载历史...";
  statusLabel.style.fontSize = "12px";
  statusLabel.style.color = colors.textSecondary;
  statusLabel.style.padding = "5px 0";
  statusLabel.style.display = "none"; // 默认隐藏

  // 将按钮添加到容器中
  topButtonContainer.appendChild(statusLabel);
  topButtonContainer.appendChild(loadButton);
  topButtonContainer.appendChild(sortButton);
  floatWindow.appendChild(topButtonContainer);

  // 创建分页控件
  const paginationContainer = document.createElement("div");
  paginationContainer.style.display = "flex";
  paginationContainer.style.justifyContent = "center";
  paginationContainer.style.marginTop = "10px";
  paginationContainer.style.gap = "5px";

  // 创建收藏区域容器
  const favoriteContainer = document.createElement("div");
  favoriteContainer.style.marginBottom = "10px";
  favoriteContainer.style.display = "none"; // 默认隐藏,有收藏时才显示
  
  const favoriteTitle = document.createElement("div");
  favoriteTitle.style.fontSize = "12px";
  favoriteTitle.style.fontWeight = "bold";
  favoriteTitle.style.color = colors.textPrimary;
  favoriteTitle.style.padding = "5px 0";
  favoriteTitle.style.borderBottom = `2px solid ${colors.buttonPrimaryBg}`;
  favoriteTitle.style.marginBottom = "5px";
  favoriteTitle.textContent = "📌 收藏";
  
  const favoriteList = document.createElement("ul");
  favoriteList.style.listStyle = "none";
  favoriteList.style.padding = "0";
  favoriteList.style.margin = "0 0 10px 0";
  
  favoriteContainer.appendChild(favoriteTitle);
  favoriteContainer.appendChild(favoriteList);
  floatWindow.appendChild(favoriteContainer);

  // 创建问题计数显示区域
  const questionCountDisplay = document.createElement("div");
  questionCountDisplay.style.fontSize = "12px";
  questionCountDisplay.style.color = colors.textSecondary;
  questionCountDisplay.style.textAlign = "center";
  questionCountDisplay.style.margin = "5px 0 10px 0";
  floatWindow.appendChild(questionCountDisplay);

  // 问题列表容器
  const listContainer = document.createElement("ul");
  listContainer.style.listStyle = "none";
  listContainer.style.padding = "0";
  listContainer.style.margin = "0";
  floatWindow.appendChild(listContainer);
  floatWindow.appendChild(paginationContainer);

  // 更新问题计数显示
  function updateQuestionCountDisplay() {
    questionCountDisplay.textContent = `共找到 ${questions.length} 个问题`;
  }

  // 获取文本内容的辅助函数
  function getTextContent(element) {
    return element ? element.textContent.trim() : "";
  }

  // 查找所有用户问题并去重的函数
  function findAllQuestionsWithDeduplication() {
    // 选择聊天容器
    let chatContainer = null;
    
    // 检查配置是否要求使用滚动容器来查找消息
    if (currentConfig.useScrollContainerForMessages && currentConfig.scrollContainerSelector) {
      // 使用配置的滚动容器选择器
      const selectors = currentConfig.scrollContainerSelector.split(',');
      for (const selector of selectors) {
        chatContainer = document.querySelector(selector.trim());
        if (chatContainer) break;
      }
    }
    
    // 如果没找到,使用通用选择器
    if (!chatContainer) {
      chatContainer = document.querySelector(".chat-container, #chat, main, article") || document.body;
    }
    
    const potentialMessages = chatContainer.querySelectorAll(
      currentConfig.messageSelector
    );

    // 调试信息(仅在找不到消息时输出)
    if (potentialMessages.length === 0) {
      console.log('[问题列表导航] 调试信息:', {
        网站: hostname,
        消息选择器: currentConfig.messageSelector,
        找到的元素数量: potentialMessages.length,
        提示: '如果一直为0,说明选择器不匹配当前页面结构'
      });
    }

    // 临时存储所有找到的问题
    const foundQuestions = [];
    const seenTexts = new Set(); // 用于去重
    let filteredCount = 0; // 被过滤掉的消息数量

    for (let i = 0; i < potentialMessages.length; i++) {
      const element = potentialMessages[i];
      const textElement = currentConfig.textSelector
        ? element.querySelector(currentConfig.textSelector)
        : element;
      const text = getTextContent(textElement);

      // 如果文本内容有效且符合用户消息条件
      if (text && text.length > 2) {
        if (currentConfig.userCondition(element)) {
          // 使用文本内容进行去重
          if (!seenTexts.has(text)) {
            seenTexts.add(text);
            foundQuestions.push({ element, text });
          }
        } else {
          filteredCount++;
        }
      }
    }

    // 调试信息(仅在找到元素但没有用户消息时输出)
    if (potentialMessages.length > 0 && foundQuestions.length === 0) {
      console.log('[问题列表导航] 调试信息:', {
        网站: hostname,
        找到的消息元素: potentialMessages.length,
        通过用户条件的: foundQuestions.length,
        被过滤的: filteredCount,
        提示: '找到了消息元素,但 userCondition 过滤掉了所有消息。可能需要调整 userCondition 逻辑'
      });
    }

    // 更新全局问题列表
    questions = foundQuestions;

    // 确保排序正确
    if (isReversed) {
      questions.reverse();
    }

    // 更新界面
    updateQuestionCountDisplay();
    renderPage(currentPage);
    updatePagination();
  }

  // 改进的懒加载突破函数 - 使用脉冲式滚动和智能检测
  async function loadHistoryRecords() {
    if (isLoading) {
      // 如果正在加载,点击按钮可以停止加载
      isLoading = false;
      statusLabel.textContent = "已停止加载";
      setTimeout(() => {
        statusLabel.style.display = "none";
      }, 2000);
      return;
    }

    isLoading = true;
    statusLabel.textContent = "正在加载历史... (再次点击停止)";
    statusLabel.style.display = "block";

    // 智能查找滚动容器(排除侧边栏)
    function findScrollContainer() {
      // 辅助函数:判断是否是侧边栏(通常宽度较小,在左侧)
      function isSidebar(element) {
        const rect = element.getBoundingClientRect();
        const windowWidth = window.innerWidth;
        // 侧边栏特征:宽度小于窗口的30%,且在左侧
        return rect.width < windowWidth * 0.3 && rect.left < 100;
      }

      // 1. 尝试配置的选择器(支持多个选择器,用逗号分隔)
      const selectors = currentConfig.scrollContainerSelector.split(",");
      for (const selector of selectors) {
        const container = document.querySelector(selector.trim());
        if (
          container &&
          container.scrollHeight > container.clientHeight &&
          !isSidebar(container)
        ) {
          return container;
        }
      }

      // 2. 尝试常见的容器
      const commonSelectors = [
        "main",
        "#chat-history",
        '[class*="chat-content"]',
        '[class*="message-container"]',
        '[class*="chatContent"]',
      ];

      for (const selector of commonSelectors) {
        const container = document.querySelector(selector);
        if (
          container &&
          container.scrollHeight > container.clientHeight &&
          !isSidebar(container)
        ) {
          return container;
        }
      }

      // 3. 启发式查找:找到最后一条消息的可滚动父元素(排除侧边栏)
      const lastMessage = document.querySelector(
        currentConfig.messageSelector
      );
      if (lastMessage) {
        let parent = lastMessage.parentElement;
        while (parent && parent !== document.body) {
          const style = window.getComputedStyle(parent);
          if (
            (style.overflowY === "auto" || style.overflowY === "scroll") &&
            parent.scrollHeight > parent.clientHeight &&
            !isSidebar(parent)
          ) {
            return parent;
          }
          parent = parent.parentElement;
        }
      }

      // 4. 回退到 documentElement
      return document.documentElement;
    }

    const container = findScrollContainer();
    const originalScrollTop = container.scrollTop;
    const initialQuestionCount = questions.length;

    let consecutiveNoChange = 0;
    let lastQuestionCount = questions.length;
    let iteration = 0;
    const maxRetryAfterNoChange = 2; // 没有新内容后,再尝试2次确认

    // 脉冲式滚动加载循环
    while (isLoading && consecutiveNoChange <= maxRetryAfterNoChange) {
      iteration++;

      // 1. 脉冲式滚动 - 模拟用户滚动行为
      // 先向下滚动一点,再滚动到顶部,触发懒加载机制
      container.scrollTop = Math.min(100, container.scrollHeight * 0.1);
      await new Promise((resolve) => setTimeout(resolve, 100));

      container.scrollTop = 0;
      await new Promise((resolve) => setTimeout(resolve, 100));

      // 2. 触发滚动事件(某些框架需要)
      container.dispatchEvent(new Event("scroll", { bubbles: true }));

      // 3. 动态等待 - 根据是否有新内容调整
      // 如果一直有新内容,等待时间短一些;如果没有新内容,等待时间长一些确认
      const waitTime = consecutiveNoChange === 0 ? 600 : 1000;
      await new Promise((resolve) => setTimeout(resolve, waitTime));

      // 4. 扫描新内容
      const preCount = questions.length;
      findAllQuestionsWithDeduplication();
      const postCount = questions.length;

      // 5. 检测变化
      const questionsChanged = postCount > lastQuestionCount;
      const newQuestionsCount = postCount - lastQuestionCount;

      if (questionsChanged) {
        // 发现新内容
        consecutiveNoChange = 0;
        lastQuestionCount = postCount;

        statusLabel.textContent = `已加载 ${postCount} 个问题 (+${newQuestionsCount})`;
        console.log(`[历史加载] 第${iteration}次: 新增 ${newQuestionsCount} 个问题,总计 ${postCount} 个`);
      } else {
        // 没有新内容
        consecutiveNoChange++;
        statusLabel.textContent = `检查中... (${consecutiveNoChange}/${maxRetryAfterNoChange + 1})`;
        console.log(`[历史加载] 第${iteration}次: 没有新内容,连续 ${consecutiveNoChange} 次`);
        
        // 如果已经连续多次没有新内容,说明已经到底了
        if (consecutiveNoChange > maxRetryAfterNoChange) {
          console.log(`[历史加载] 连续 ${consecutiveNoChange} 次没有新内容,停止加载`);
          break;
        }
      }

      // 6. 额外的触发机制:模拟鼠标滚轮事件(每3次触发一次)
      if (iteration % 3 === 0) {
        const wheelEvent = new WheelEvent("wheel", {
          deltaY: -100,
          bubbles: true,
          cancelable: true,
        });
        container.dispatchEvent(wheelEvent);
      }
    }

    // 恢复原始滚动位置
    container.scrollTop = originalScrollTop;

    // 完成加载
    const newQuestions = questions.length - initialQuestionCount;
    isLoading = false;
    autoLoadCompleted = true;

    // 生成加载结果提示
    let resultMessage;
    if (newQuestions > 0) {
      resultMessage = `✓ 成功加载 ${newQuestions} 条新记录 (共${questions.length}条)`;
      console.log(`[历史加载] 完成: 新增 ${newQuestions} 条,总计 ${questions.length} 条,共尝试 ${iteration} 次`);
    } else {
      resultMessage = consecutiveNoChange > maxRetryAfterNoChange 
        ? "已加载所有历史记录" 
        : "未找到更多历史记录";
      console.log(`[历史加载] 完成: 没有新内容,共尝试 ${iteration} 次`);
    }
    
    statusLabel.textContent = resultMessage;

    // 保存消息总数(用于下次刷新时判断)
    if (questions.length > 0) {
      MessageCountManager.saveCount(questions.length);
    }

    // 延迟隐藏状态标签
    setTimeout(() => {
      statusLabel.style.display = "none";
    }, 4000);
  }

  // 创建问题列表项(带收藏功能)
  function createQuestionItem(q, index, isFavoriteItem = false) {
    const listItem = document.createElement("li");
    listItem.style.padding = "8px 12px";
    listItem.style.fontSize = "13px";
    listItem.style.color = colors.textPrimary;
    listItem.style.borderBottom = `1px solid ${colors.itemBorder}`;
    listItem.style.transition = "background 0.2s";
    listItem.style.borderRadius = "4px";
    listItem.style.display = "flex";
    listItem.style.alignItems = "center";
    listItem.style.gap = "8px";
    listItem.title = q.text;
    
    // 问题文本容器
    const textContainer = document.createElement("div");
    textContainer.style.flex = "1";
    textContainer.style.cursor = "pointer";
    textContainer.style.whiteSpace = "nowrap";
    textContainer.style.overflow = "hidden";
    textContainer.style.textOverflow = "ellipsis";
    
    const shortText = q.text.substring(0, 20) + (q.text.length > 20 ? "..." : "");
    textContainer.textContent = `${index}: ${shortText}`;
    
    // 星标按钮
    const starButton = document.createElement("span");
    starButton.textContent = FavoriteManager.isFavorite(q.text) ? "⭐" : "☆";
    starButton.style.cursor = "pointer";
    starButton.style.fontSize = "16px";
    starButton.style.flexShrink = "0";
    starButton.style.transition = "transform 0.2s";
    starButton.title = FavoriteManager.isFavorite(q.text) ? "取消收藏" : "收藏";
    
    // 星标按钮事件
    starButton.addEventListener("click", (e) => {
      e.stopPropagation();
      const isFavorited = FavoriteManager.toggle(q.text);
      starButton.textContent = isFavorited ? "⭐" : "☆";
      starButton.title = isFavorited ? "取消收藏" : "收藏";
      
      // 重新渲染收藏区域和当前页
      renderFavorites();
      renderPage(currentPage);
    });
    
    starButton.addEventListener("mouseover", () => {
      starButton.style.transform = "scale(1.2)";
    });
    
    starButton.addEventListener("mouseout", () => {
      starButton.style.transform = "scale(1)";
    });
    
    // 文本容器点击事件
    textContainer.addEventListener("click", () => {
      q.element.scrollIntoView({ behavior: "smooth", block: "start" });
      floatWindow.style.opacity = "0";
      setTimeout(() => (floatWindow.style.display = "none"), 200);
      button.textContent = "问题列表";
    });
    
    // 悬停效果
    listItem.addEventListener("mouseover", () => {
      listItem.style.background = colors.itemHoverBg;
    });
    listItem.addEventListener("mouseout", () => {
      listItem.style.background = "none";
    });
    
    listItem.appendChild(textContainer);
    listItem.appendChild(starButton);
    
    return listItem;
  }

  // 渲染收藏区域
  function renderFavorites() {
    // 清空收藏列表
    while (favoriteList.firstChild) {
      favoriteList.removeChild(favoriteList.firstChild);
    }
    
    const favoriteQuestions = FavoriteManager.getFavoriteQuestions(questions);
    
    if (favoriteQuestions.length > 0) {
      favoriteContainer.style.display = "block";
      favoriteTitle.textContent = `📌 收藏 (${favoriteQuestions.length})`;
      
      favoriteQuestions.forEach((q) => {
        // 找到问题的原始索引
        const originalIndex = questions.findIndex(item => item.text === q.text);
        const displayIndex = isReversed ? questions.length - originalIndex : originalIndex + 1;
        
        const item = createQuestionItem(q, displayIndex, true);
        favoriteList.appendChild(item);
      });
    } else {
      favoriteContainer.style.display = "none";
    }
  }

  // 使找到的问题定位在屏幕中
  function renderPage(page) {
    // 清空列表容器
    while (listContainer.firstChild) {
      listContainer.removeChild(listContainer.firstChild);
    }

    const start = (page - 1) * pageSize;
    const end = page * pageSize;
    const pageQuestions = questions.slice(start, end);

    pageQuestions.forEach((q, idx) => {
      const displayIndex = isReversed ? questions.length - start - idx : start + idx + 1;
      const item = createQuestionItem(q, displayIndex);
      listContainer.appendChild(item);
    });
    
    // 同时更新收藏区域
    renderFavorites();
  }

  // 更新分页控件
  function updatePagination() {
    // 清空分页容器
    while (paginationContainer.firstChild) {
      paginationContainer.removeChild(paginationContainer.firstChild);
    }

    const totalPages = Math.ceil(questions.length / pageSize);
    if (totalPages) {
      // 使用按钮工厂创建上一页按钮
      const prevButton = ButtonFactory.createNavButton({
        text: "上一页",
        disabled: currentPage === 1,
        onClick: () => {
          if (currentPage > 1) {
            currentPage--;
            renderPage(currentPage);
            updatePagination();
          }
        },
      });
      paginationContainer.appendChild(prevButton);

      // 显示页码按钮,但限制最多显示5个
      const maxButtons = 5;
      let startPage = Math.max(
        1,
        Math.min(
          currentPage - Math.floor(maxButtons / 2),
          totalPages - maxButtons + 1
        )
      );
      if (startPage < 1) startPage = 1;
      const endPage = Math.min(startPage + maxButtons - 1, totalPages);

      if (startPage > 1) {
        // 使用按钮工厂创建第一页按钮
        const firstPageButton = ButtonFactory.createPaginationButton({
          page: 1,
          isActive: false,
          onClick: () => {
            currentPage = 1;
            renderPage(currentPage);
            updatePagination();
          },
        });
        paginationContainer.appendChild(firstPageButton);

        if (startPage > 2) {
          const ellipsis = document.createElement("span");
          ellipsis.textContent = "...";
          ellipsis.style.padding = "5px";
          ellipsis.style.color = colors.textSecondary;
          paginationContainer.appendChild(ellipsis);
        }
      }

      // 使用按钮工厂创建页码按钮
      for (let i = startPage; i <= endPage; i++) {
        const pageButton = ButtonFactory.createPaginationButton({
          page: i,
          isActive: currentPage === i,
          onClick: () => {
            currentPage = i;
            renderPage(currentPage);
            updatePagination();
          },
        });
        paginationContainer.appendChild(pageButton);
      }

      if (endPage < totalPages) {
        if (endPage < totalPages - 1) {
          const ellipsis = document.createElement("span");
          ellipsis.textContent = "...";
          ellipsis.style.padding = "5px";
          ellipsis.style.color = colors.textSecondary;
          paginationContainer.appendChild(ellipsis);
        }

        // 使用按钮工厂创建最后一页按钮
        const lastPageButton = ButtonFactory.createPaginationButton({
          page: totalPages,
          isActive: false,
          onClick: () => {
            currentPage = totalPages;
            renderPage(currentPage);
            updatePagination();
          },
        });
        paginationContainer.appendChild(lastPageButton);
      }

      // 使用按钮工厂创建下一页按钮
      const nextButton = ButtonFactory.createNavButton({
        text: "下一页",
        disabled: currentPage === totalPages,
        onClick: () => {
          if (currentPage < totalPages) {
            currentPage++;
            renderPage(currentPage);
            updatePagination();
          }
        },
      });
      paginationContainer.appendChild(nextButton);
    }
  }

  // 切换悬浮窗显示状态的函数
  function toggleFloatWindow() {
    if (
      floatWindow.style.display === "none" ||
      floatWindow.style.display === ""
    ) {
      findAllQuestionsWithDeduplication();
      updateFloatWindowPosition(); // 更新位置
      floatWindow.style.display = "block";
      floatWindow.style.opacity = "1";
      button.textContent = "隐藏列表";
    } else {
      floatWindow.style.opacity = "0";
      setTimeout(() => {
        floatWindow.style.display = "none";
        button.textContent = "问题列表";
      }, 200);
    }
  }
  
  // 注意:点击事件已在拖动逻辑中处理(mouseup 事件)

  // 监听用户输入新问题后触发查找
  function setupInputListener() {
    const input = document.querySelector(
      'textarea, input[type="text"], [contenteditable]'
    );
    if (input) {
      input.addEventListener("keypress", (e) => {
        if (e.key === "Enter" && !e.shiftKey) {
          setTimeout(findAllQuestionsWithDeduplication, 1000);
        }
      });
    }

    // 监听可能的发送按钮点击
    const sendButtons = document.querySelectorAll(
      'button[type="submit"], button[aria-label*="send"], button[aria-label*="发送"]'
    );
    sendButtons.forEach((btn) => {
      btn.addEventListener("click", () => {
        setTimeout(findAllQuestionsWithDeduplication, 1000);
      });
    });
  }

  // 页面加载后初始化
  window.addEventListener("load", () => {
    // 先找一次所有问题
    // NotebookLM 等 Angular 应用需要更长的加载时间
    const isAngularApp = hostname.includes('notebooklm') || document.querySelector('[ng-version]');
    const delay = isAngularApp ? 5000 : 1000;
    
    setTimeout(() => {
      findAllQuestionsWithDeduplication();
      setupInputListener();
      
      // NotebookLM 特殊处理:如果第一次没找到,再尝试几次
      if (isAngularApp && questions.length === 0) {
        let retryCount = 0;
        const retryInterval = setInterval(() => {
          findAllQuestionsWithDeduplication();
          retryCount++;
          
          if (questions.length > 0 || retryCount >= 3) {
            clearInterval(retryInterval);
            if (questions.length > 0) {
              console.log('[问题列表导航] NotebookLM 重试成功,找到', questions.length, '个问题');
            }
          }
        }, 2000); // 每2秒重试一次,最多3次
      }
      
      // 智能加载历史记录
      setTimeout(() => {
        const currentCount = questions.length;
        const shouldLoad = MessageCountManager.shouldLoadHistory(currentCount);
        
        if (shouldLoad) {
          console.log('[问题列表导航] 检测到消息数量减少,自动加载历史记录...');
          // 自动加载历史,但不显示状态(静默加载)
          const originalDisplay = statusLabel.style.display;
          statusLabel.style.display = 'none';
          loadHistoryRecords().finally(() => {
            statusLabel.style.display = originalDisplay;
            console.log('[问题列表导航] 历史记录加载完成');
          });
        } else {
          console.log('[问题列表导航] 消息数量正常,无需加载历史');
          // 即使不需要加载历史,也保存当前的消息数量
          if (currentCount > 0) {
            MessageCountManager.saveCount(currentCount);
          }
        }
      }, delay + 2000); // 等待初始扫描完成后再检查
    }, delay);
  });

  // MutationObserver 监听DOM变化,动态更新问题列表
  const observerConfig = { childList: true, subtree: true };
  const observer = new MutationObserver((mutationsList) => {
    // 检查是否需要更新问题列表
    for (const mutation of mutationsList) {
      if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
        // 检查是否添加了新的消息元素
        const hasNewMessages = Array.from(mutation.addedNodes).some((node) => {
          if (node.nodeType === Node.ELEMENT_NODE) {
            return (
              (node.matches && node.matches(currentConfig.messageSelector)) ||
              (node.querySelector &&
                node.querySelector(currentConfig.messageSelector))
            );
          }
          return false;
        });

        if (hasNewMessages) {
          // 使用节流技术避免频繁更新
          if (!observer.updateTimeout) {
            observer.updateTimeout = setTimeout(() => {
              findAllQuestionsWithDeduplication();
              observer.updateTimeout = null;
            }, 500);
          }
          break;
        }
      }
    }
  });

  // 开始观察DOM变化
  setTimeout(() => {
    const chatContainer =
      document.querySelector(".chat-container, #chat, main, article") ||
      document.body;
    observer.observe(chatContainer, observerConfig);
  }, 1500);
})();