源码安装
1090197965 / 【云】XMXMKB自动收藏功能

// ==UserScript==
// @name         【云】XMXMKB自动收藏功能
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  基于导入的收藏数据自动收藏匹配的列表项,支持JSON文件导入和自动收藏功能
// @author       You
// @match        https://www.xmxmkb.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
  'use strict';

  // 添加样式
  GM_addStyle(`
    .auto-favorite-btn {
      position: fixed;
      top: 20px;
      right: 520px;
      background: #28a745;
      color: white;
      border: none;
      padding: 8px 15px;
      border-radius: 4px;
      cursor: pointer;
      z-index: 9999;
      font-size: 13px;
      transition: all 0.3s;
    }
    
    .auto-favorite-btn:hover {
      background: #218838;
      transform: scale(1.05);
    }
    
    .auto-favorite-btn.loading {
      background: #ffc107;
      pointer-events: none;
    }
    
    .auto-favorite-btn.loading::after {
      content: '';
      display: inline-block;
      width: 12px;
      height: 12px;
      border: 2px solid transparent;
      border-top: 2px solid white;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin-left: 5px;
    }
    
    .auto-favorite-panel {
      position: fixed;
      top: 20px;
      right: 20px;
      width: 400px;
      max-height: 600px;
      background: white;
      border: 1px solid #ddd;
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.15);
      z-index: 10000;
      font-family: Arial, sans-serif;
      overflow: hidden;
      display: none;
    }
    
    .auto-favorite-header {
      background: #28a745;
      color: white;
      padding: 15px 20px;
      border-bottom: 1px solid #ddd;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    
    .auto-favorite-title {
      font-weight: bold;
      font-size: 16px;
    }
    
    .auto-favorite-close {
      background: none;
      border: none;
      font-size: 20px;
      cursor: pointer;
      color: white;
    }
    
    .auto-favorite-close:hover {
      color: #ccc;
    }
    
    .auto-favorite-content {
      padding: 20px;
      max-height: 400px;
      overflow-y: auto;
    }
    
    .import-section {
      margin-bottom: 20px;
    }
    
    .import-label {
      display: block;
      margin-bottom: 10px;
      font-weight: bold;
      color: #333;
    }
    
    .import-input {
      width: 100%;
      padding: 8px 12px;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 14px;
      box-sizing: border-box;
      margin-bottom: 10px;
    }
    
    .import-input:focus {
      outline: none;
      border-color: #28a745;
    }
    
    .import-btn {
      background: #28a745;
      color: white;
      border: none;
      padding: 8px 16px;
      border-radius: 4px;
      cursor: pointer;
      font-size: 14px;
      transition: all 0.3s;
    }
    
    .import-btn:hover {
      background: #218838;
    }
    
    .import-btn:disabled {
      background: #ccc;
      cursor: not-allowed;
    }
    
    .import-info {
      margin-top: 8px;
      padding: 8px 12px;
      background: #e8f5e8;
      border-radius: 4px;
      border: 1px solid #c3e6c3;
      font-size: 12px;
    }
    
    .ignore-section {
      margin-bottom: 20px;
      padding: 15px;
      background: #f8f9fa;
      border-radius: 4px;
      border: 1px solid #e9ecef;
    }
    
    .ignore-info {
      margin-top: 10px;
      padding: 8px 12px;
      background: white;
      border-radius: 4px;
      border: 1px solid #ddd;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    
    .contain-section {
      margin-bottom: 20px;
      padding: 15px;
      background: #f0f8ff;
      border-radius: 4px;
      border: 1px solid #b3d9ff;
    }
    
    .test-section {
      margin-bottom: 20px;
      padding: 15px;
      background: #fff3cd;
      border-radius: 4px;
      border: 1px solid #ffeaa7;
    }
    
    .status-section {
      margin-bottom: 20px;
    }
    
    .status-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 8px 0;
      border-bottom: 1px solid #eee;
    }
    
    .status-label {
      font-weight: bold;
      color: #333;
    }
    
    .status-value {
      color: #666;
    }
    
    .auto-favorite-actions {
      padding: 15px 20px;
      border-top: 1px solid #ddd;
      display: flex;
      gap: 10px;
    }
    
    .auto-favorite-action-btn {
      background: #28a745;
      color: white;
      border: none;
      padding: 8px 12px;
      border-radius: 4px;
      cursor: pointer;
      font-size: 12px;
      flex: 1;
      transition: all 0.3s;
    }
    
    .auto-favorite-action-btn:hover {
      background: #218838;
    }
    
    .auto-favorite-action-btn.danger {
      background: #dc3545;
    }
    
    .auto-favorite-action-btn.danger:hover {
      background: #c82333;
    }
    
    .auto-favorite-message {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      padding: 15px 20px;
      border-radius: 8px;
      color: white;
      font-size: 14px;
      font-weight: bold;
      z-index: 10001;
      box-shadow: 0 4px 12px rgba(0,0,0,0.3);
      animation: messageSlideIn 0.3s ease-out;
    }
    
    .auto-favorite-message-success {
      background: #28a745;
    }
    
    .auto-favorite-message-error {
      background: #dc3545;
    }
    
    .auto-favorite-message-info {
      background: #17a2b8;
    }
    
    @keyframes messageSlideIn {
      from {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.8);
      }
      to {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
      }
    }
    
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
  `);

  // 自动收藏管理器
  class AutoFavoriteManager {
    constructor() {
      this.importedFavorites = [];
      this.autoFavoriteEnabled = false;
      this.processedItems = new Set();
      this.ignoreChars = [];
      this.minMatchLength = 10;
      this.init();
    }

    init() {
      console.log('🚀 自动收藏管理器初始化开始...');
      this.loadImportedFavorites();
      this.loadIgnoreChars();
      this.loadMinMatchLength();
      this.createUI();
      
      // 如果有导入的收藏数据,自动启用收藏功能
      if (this.importedFavorites.length > 0) {
        this.autoFavoriteEnabled = true;
        console.log('🎯 检测到已导入收藏数据,自动启用收藏功能');
        this.updateStatus();
      }
      
      this.startAutoProcess();
      this.testNormalizeFunction();
      console.log('✅ 自动收藏管理器初始化完成');
    }

    // 测试标准化函数
    testNormalizeFunction() {
      console.log('🧪 测试字符串标准化功能...');
      
      const testCases = [
        'Hello World!',
        'Test, Title.',
        '【测试】标题',
        'Title (2023)',
        'Test-Title_123',
        '  Multiple   Spaces  ',
        'Mixed.Case,Title!'
      ];
      
      testCases.forEach(testCase => {
        const normalized = this.normalizeString(testCase);
        console.log(`   - "${testCase}" -> "${normalized}"`);
      });
      
      console.log('✅ 字符串标准化功能测试完成');
    }

    // 加载已导入的收藏数据
    loadImportedFavorites() {
      try {
        const data = localStorage.getItem('fav-list');
        if (data) {
          const parsedData = JSON.parse(data);
          // 检查数据格式,支持新的对象格式和旧的数组格式
          if (parsedData.favorites && Array.isArray(parsedData.favorites)) {
            this.importedFavorites = parsedData.favorites;
          } else if (Array.isArray(parsedData)) {
            this.importedFavorites = parsedData;
          } else {
            this.importedFavorites = [];
          }
        } else {
          this.importedFavorites = [];
        }
        
        console.log(`📂 已从localStorage加载导入的收藏数据: ${this.importedFavorites.length} 项`);
        
        if (this.importedFavorites.length > 0) {
          console.log('📋 导入的收藏标题列表:');
          this.importedFavorites.forEach((fav, index) => {
            console.log(`   ${index + 1}. "${fav.title}" (ID: ${fav.id})`);
          });
        } else {
          console.log('📭 暂无导入的收藏数据');
        }
      } catch (e) {
        console.error('❌ 加载导入数据失败:', e);
        this.importedFavorites = [];
      }
    }

    // 保存导入的收藏数据
    saveImportedFavorites() {
      try {
        const dataToSave = {
          favorites: this.importedFavorites,
          lastUpdated: Date.now(),
          version: '1.7'
        };
        localStorage.setItem('fav-list', JSON.stringify(dataToSave));
        console.log(`💾 已保存导入的收藏数据到localStorage: ${this.importedFavorites.length} 项`);
      } catch (e) {
        console.error('❌ 保存导入数据失败:', e);
      }
    }

    // 加载忽略字符设置
    loadIgnoreChars() {
      try {
        const data = localStorage.getItem('fav-list');
        if (data) {
          const parsedData = JSON.parse(data);
          this.ignoreChars = parsedData.ignoreChars || [];
        } else {
          this.ignoreChars = [];
        }
        
        console.log(`📂 已从localStorage加载忽略字符/字符串设置: ${this.ignoreChars.length} 个`);
        
        if (this.ignoreChars.length > 0) {
          console.log('🚫 忽略字符/字符串列表:');
          this.ignoreChars.forEach((chars, index) => {
            console.log(`   ${index + 1}. "${chars}" (长度: ${chars.length})`);
          });
        } else {
          console.log('📭 暂无忽略字符/字符串设置');
        }
      } catch (e) {
        console.error('❌ 加载忽略字符设置失败:', e);
        this.ignoreChars = [];
      }
    }

    // 保存忽略字符设置
    saveIgnoreChars() {
      try {
        const existingData = localStorage.getItem('fav-list');
        let dataToSave = existingData ? JSON.parse(existingData) : {};
        dataToSave.ignoreChars = this.ignoreChars;
        dataToSave.lastUpdated = Date.now();
        dataToSave.version = '1.7';
        localStorage.setItem('fav-list', JSON.stringify(dataToSave));
        console.log(`💾 已保存忽略字符/字符串设置到localStorage: ${this.ignoreChars.length} 个`);
      } catch (e) {
        console.error('❌ 保存忽略字符设置失败:', e);
      }
    }

    // 加载最小匹配长度设置
    loadMinMatchLength() {
      try {
        const data = localStorage.getItem('fav-list');
        if (data) {
          const parsedData = JSON.parse(data);
          this.minMatchLength = parsedData.minMatchLength || 10;
        } else {
          this.minMatchLength = 10;
        }
        console.log(`📂 已从localStorage加载最小匹配长度设置: ${this.minMatchLength}`);
      } catch (e) {
        console.error('❌ 加载最小匹配长度设置失败:', e);
        this.minMatchLength = 10;
      }
    }

    // 保存最小匹配长度设置
    saveMinMatchLength() {
      try {
        const existingData = localStorage.getItem('fav-list');
        let dataToSave = existingData ? JSON.parse(existingData) : {};
        dataToSave.minMatchLength = this.minMatchLength;
        dataToSave.lastUpdated = Date.now();
        dataToSave.version = '1.7';
        localStorage.setItem('fav-list', JSON.stringify(dataToSave));
        console.log(`💾 已保存最小匹配长度设置到localStorage: ${this.minMatchLength}`);
      } catch (e) {
        console.error('❌ 保存最小匹配长度设置失败:', e);
      }
    }

    // 创建用户界面
    createUI() {
      console.log('🎨 开始创建用户界面...');
      
      // 创建主按钮
      const mainBtn = document.createElement('button');
      mainBtn.className = 'auto-favorite-btn';
      mainBtn.textContent = '自动收藏';
      mainBtn.onclick = () => this.togglePanel();
      document.body.appendChild(mainBtn);
      console.log('✅ 主按钮已创建');

      // 创建面板
      const panel = document.createElement('div');
      panel.className = 'auto-favorite-panel';
      panel.innerHTML = `
        <div class="auto-favorite-header">
          <div class="auto-favorite-title">自动收藏管理</div>
          <button class="auto-favorite-close">×</button>
        </div>
        <div class="auto-favorite-content">
          <div class="import-section">
            <label class="import-label">导入收藏数据 (JSON格式):</label>
            <input type="file" class="import-input" accept=".json" id="importFile">
            <button class="import-btn" id="importBtn">导入数据</button>
            <div class="import-info">
              <span class="status-label">支持格式:</span>
              <span class="status-value">标准收藏格式、黑名单格式、自动去重追加</span>
            </div>
          </div>
          <div class="status-section">
            <div class="status-item">
              <span class="status-label">已导入收藏:</span>
              <span class="status-value" id="importedCount">${this.importedFavorites.length}</span>
            </div>
            <div class="status-item">
              <span class="status-label">自动收藏状态:</span>
              <span class="status-value" id="autoStatus">${this.autoFavoriteEnabled ? '已启用' : '已禁用'}</span>
            </div>
            <div class="status-item">
              <span class="status-label">已处理项目:</span>
              <span class="status-value" id="processedCount">${this.processedItems.size}</span>
            </div>
          </div>
          <div class="ignore-section">
            <label class="import-label">忽略字符/字符串设置:</label>
            <input type="text" class="import-input" id="ignoreChars" placeholder="输入要忽略的字符或字符串,用逗号分隔,如: 百度网盘,...,【】,(),[],{}">
            <button class="import-btn" id="saveIgnoreBtn">保存设置</button>
            <div class="ignore-info">
              <span class="status-label">当前忽略字符/字符串:</span>
              <span class="status-value" id="currentIgnoreChars">${this.ignoreChars.join(', ') || '无'}</span>
            </div>
          </div>
          <div class="contain-section">
            <label class="import-label">包含匹配设置:</label>
            <input type="number" class="import-input" id="minLength" placeholder="最小匹配长度" min="1" max="100" value="${this.minMatchLength}">
            <button class="import-btn" id="saveContainBtn">保存设置</button>
            <div class="ignore-info">
              <span class="status-label">当前最小长度:</span>
              <span class="status-value" id="currentMinLength">${this.minMatchLength}</span>
            </div>
          </div>
          <div class="test-section">
            <label class="import-label">自定义测试:</label>
            <input type="text" class="import-input" id="testString" placeholder="输入要测试的标题字符串">
            <button class="import-btn" id="testStringBtn">测试匹配</button>
          </div>
        </div>
        <div class="auto-favorite-actions">
          <button class="auto-favorite-action-btn" id="toggleAutoBtn">${this.autoFavoriteEnabled ? '禁用自动收藏' : '启用自动收藏'}</button>
          <button class="auto-favorite-action-btn" id="testMatchBtn">测试匹配</button>
          <button class="auto-favorite-action-btn danger" id="clearDataBtn">清空数据</button>
        </div>
      `;
      document.body.appendChild(panel);

      // 绑定事件
      this.bindEvents(panel);
      console.log('✅ 用户界面创建完成');
    }

    // 绑定事件
    bindEvents(panel) {
      // 关闭按钮
      panel.querySelector('.auto-favorite-close').onclick = () => this.hidePanel();

      // 文件导入
      const importFile = panel.querySelector('#importFile');
      const importBtn = panel.querySelector('#importBtn');
      
      importBtn.onclick = () => this.importData(importFile);

      // 保存忽略字符设置
      const saveIgnoreBtn = panel.querySelector('#saveIgnoreBtn');
      saveIgnoreBtn.onclick = () => this.saveIgnoreCharsSetting();

      // 保存包含匹配设置
      const saveContainBtn = panel.querySelector('#saveContainBtn');
      saveContainBtn.onclick = () => this.saveContainSetting();

      // 自定义字符串测试
      const testStringBtn = panel.querySelector('#testStringBtn');
      testStringBtn.onclick = () => this.testCustomString();

      // 切换自动收藏
      panel.querySelector('#toggleAutoBtn').onclick = () => this.toggleAutoFavorite();

      // 测试匹配
      panel.querySelector('#testMatchBtn').onclick = () => this.testMatching();

      // 清空数据
      panel.querySelector('#clearDataBtn').onclick = () => this.clearData();
    }

    // 显示/隐藏面板
    togglePanel() {
      const panel = document.querySelector('.auto-favorite-panel');
      panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
    }

    hidePanel() {
      const panel = document.querySelector('.auto-favorite-panel');
      panel.style.display = 'none';
    }

    // 导入数据
    importData(fileInput) {
      const file = fileInput.files[0];
      if (!file) {
        this.showMessage('请选择要导入的文件', 'error');
        return;
      }

      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const jsonData = JSON.parse(e.target.result);
          
          // 检测导入格式类型
          const importType = this.detectImportFormat(jsonData);
          console.log(`📋 检测到导入格式: ${importType}`);
          
          let newFavorites = [];
          let importMessage = '';
          
          if (importType === 'favorites') {
            // 标准收藏格式
            if (!jsonData.favorites || !Array.isArray(jsonData.favorites)) {
              this.showMessage('文件格式不正确,请确保包含favorites数组', 'error');
              return;
            }
            
            newFavorites = jsonData.favorites.map(fav => ({
              id: fav.id,
              title: fav.title,
              url: fav.url,
              images: fav.images || [],
              timestamp: fav.timestamp || Date.now(),
              superLiked: fav.superLiked || false,
              hasImages: fav.hasImages || (fav.images && fav.images.length > 0)
            }));
            
            importMessage = `成功导入 ${newFavorites.length} 个收藏项`;
            
          } else if (importType === 'blacklist') {
            // 黑名单格式
            if (!jsonData.blacklist || !Array.isArray(jsonData.blacklist)) {
              this.showMessage('黑名单格式不正确,请确保包含blacklist数组', 'error');
              return;
            }
            
            newFavorites = jsonData.blacklist.map((title, index) => ({
              id: `blacklist_${Date.now()}_${index}`,
              title: title,
              url: '',
              images: [],
              timestamp: Date.now(),
              superLiked: false,
              hasImages: false,
              source: 'blacklist' // 标记来源
            }));
            
            importMessage = `成功从黑名单导入 ${newFavorites.length} 个收藏项`;
            
          } else {
            this.showMessage('不支持的文件格式,请使用标准收藏格式或黑名单格式', 'error');
            return;
          }
          
          // 追加去重处理
          const result = this.appendAndDeduplicate(newFavorites);
          
          this.saveImportedFavorites();
          this.updateStatus();
          this.showMessage(`${importMessage},新增 ${result.added} 个,跳过重复 ${result.duplicates} 个`, 'success');
          
          // 清空文件输入
          fileInput.value = '';
          
        } catch (e) {
          console.error('导入失败:', e);
          this.showMessage('文件解析失败,请检查JSON格式', 'error');
        }
      };
      
      reader.readAsText(file);
    }

    // 检测导入格式类型
    detectImportFormat(jsonData) {
      console.log('🔍 开始检测导入格式...');
      console.log('📋 JSON数据结构:', Object.keys(jsonData));
      
      // 检查是否包含favorites数组
      if (jsonData.favorites && Array.isArray(jsonData.favorites)) {
        console.log('✅ 检测到标准收藏格式 (favorites)');
        return 'favorites';
      }
      
      // 检查是否包含blacklist数组
      if (jsonData.blacklist && Array.isArray(jsonData.blacklist)) {
        console.log('✅ 检测到黑名单格式 (blacklist)');
        return 'blacklist';
      }
      
      // 检查是否是直接的数组格式(兼容旧版本)
      if (Array.isArray(jsonData)) {
        console.log('✅ 检测到直接数组格式 (legacy)');
        return 'favorites';
      }
      
      console.log('❌ 未识别的格式');
      return 'unknown';
    }

    // 追加去重处理
    appendAndDeduplicate(newFavorites) {
      console.log('🔄 开始追加去重处理...');
      console.log(`📊 当前收藏数量: ${this.importedFavorites.length}`);
      console.log(`📊 新导入数量: ${newFavorites.length}`);
      
      let added = 0;
      let duplicates = 0;
      
      newFavorites.forEach(newFav => {
        // 检查是否已存在(基于标题进行去重)
        const exists = this.importedFavorites.some(existingFav => {
          const normalizedExisting = this.normalizeString(existingFav.title);
          const normalizedNew = this.normalizeString(newFav.title);
          return normalizedExisting === normalizedNew;
        });
        
        if (!exists) {
          this.importedFavorites.push(newFav);
          added++;
          console.log(`✅ 新增收藏: "${newFav.title}"`);
        } else {
          duplicates++;
          console.log(`⏭️ 跳过重复: "${newFav.title}"`);
        }
      });
      
      console.log(`📊 去重结果: 新增 ${added} 个,跳过重复 ${duplicates} 个`);
      console.log(`📊 最终收藏数量: ${this.importedFavorites.length}`);
      
      return { added, duplicates };
    }

    // 保存忽略字符设置
    saveIgnoreCharsSetting() {
      const input = document.querySelector('#ignoreChars');
      const inputValue = input.value.trim();
      
      if (!inputValue) {
        this.showMessage('请输入要忽略的字符或字符串', 'error');
        return;
      }
      
      try {
        // 解析输入的字符/字符串,支持逗号分隔
        const chars = inputValue.split(',').map(char => char.trim()).filter(char => char.length > 0);
        
        if (chars.length === 0) {
          this.showMessage('请输入有效的字符或字符串', 'error');
          return;
        }
        
        this.ignoreChars = chars;
        this.saveIgnoreChars();
        this.updateIgnoreCharsDisplay();
        
        console.log(`✅ 已保存忽略字符/字符串设置: ${chars.length} 个`);
        chars.forEach((char, index) => {
          console.log(`   ${index + 1}. "${char}" (长度: ${char.length})`);
        });
        
        this.showMessage(`已保存 ${chars.length} 个忽略字符/字符串设置`, 'success');
        
        // 清空输入框
        input.value = '';
        
      } catch (e) {
        console.error('❌ 保存忽略字符设置失败:', e);
        this.showMessage('保存设置失败', 'error');
      }
    }

    // 更新忽略字符显示
    updateIgnoreCharsDisplay() {
      const display = document.querySelector('#currentIgnoreChars');
      if (display) {
        display.textContent = this.ignoreChars.join(', ') || '无';
      }
    }

    // 保存包含匹配设置
    saveContainSetting() {
      const input = document.querySelector('#minLength');
      const inputValue = input.value.trim();
      
      if (!inputValue) {
        this.showMessage('请输入最小匹配长度', 'error');
        return;
      }
      
      const length = parseInt(inputValue);
      if (isNaN(length) || length < 1 || length > 100) {
        this.showMessage('请输入1-100之间的有效数字', 'error');
        return;
      }
      
      this.minMatchLength = length;
      this.saveMinMatchLength();
      this.updateMinLengthDisplay();
      
      console.log(`✅ 已保存最小匹配长度设置: ${length}`);
      this.showMessage(`已保存最小匹配长度: ${length}`, 'success');
    }

    // 更新最小长度显示
    updateMinLengthDisplay() {
      const display = document.querySelector('#currentMinLength');
      if (display) {
        display.textContent = this.minMatchLength;
      }
    }

    // 自定义字符串测试
    testCustomString() {
      const input = document.querySelector('#testString');
      const testString = input.value.trim();
      
      if (!testString) {
        this.showMessage('请输入要测试的字符串', 'error');
        return;
      }
      
      console.log('🧪 开始自定义字符串测试...');
      console.log(`📝 测试字符串: "${testString}"`);
      console.log(`📊 当前设置:`);
      console.log(`   - 导入收藏数量: ${this.importedFavorites.length}`);
      console.log(`   - 忽略字符/字符串: ${this.ignoreChars.length} 个`);
      console.log(`   - 最小匹配长度: ${this.minMatchLength}`);
      
      if (this.ignoreChars.length > 0) {
        console.log(`   - 忽略列表: ${this.ignoreChars.join(', ')}`);
      }
      
      if (this.importedFavorites.length === 0) {
        this.showMessage('请先导入收藏数据', 'error');
        console.log('❌ 测试失败:未导入收藏数据');
        return;
      }
      
      console.log(`\n🔍 开始详细匹配测试...`);
      
      // 测试各种匹配逻辑
      const matchResult = this.testSingleMatchDetailed(testString);
      
      if (matchResult) {
        console.log(`\n✅ 匹配成功!`);
        console.log(`   - 匹配类型: ${matchResult.type}`);
        console.log(`   - 匹配详情: ${matchResult.details}`);
        console.log(`   - 匹配的收藏ID: ${matchResult.matched.id}`);
        console.log(`   - 匹配的收藏标题: "${matchResult.matched.title}"`);
        this.showMessage(`匹配成功: ${matchResult.type}`, 'success');
      } else {
        console.log(`\n❌ 未找到匹配的收藏`);
        console.log(`\n📋 导入的收藏标题列表:`);
        this.importedFavorites.forEach((fav, index) => {
          console.log(`   ${index + 1}. "${fav.title}" (ID: ${fav.id})`);
        });
        this.showMessage('未找到匹配的收藏', 'error');
      }
      
      // 清空输入框
      input.value = '';
    }

    // 切换自动收藏状态
    toggleAutoFavorite() {
      this.autoFavoriteEnabled = !this.autoFavoriteEnabled;
      this.updateStatus();
      
      const btn = document.querySelector('#toggleAutoBtn');
      btn.textContent = this.autoFavoriteEnabled ? '禁用自动收藏' : '启用自动收藏';
      
      console.log(`🔄 自动收藏状态切换: ${this.autoFavoriteEnabled ? '已启用' : '已禁用'}`);
      console.log(`   - 导入收藏数量: ${this.importedFavorites.length}`);
      console.log(`   - 已处理项目: ${this.processedItems.size}`);
      
      this.showMessage(
        this.autoFavoriteEnabled ? '自动收藏已启用' : '自动收藏已禁用', 
        'info'
      );
    }

    // 测试匹配功能
    testMatching() {
      console.log('🧪 开始测试匹配功能...');
      
      if (this.importedFavorites.length === 0) {
        this.showMessage('请先导入收藏数据', 'error');
        console.log('❌ 测试失败:未导入收藏数据');
        return;
      }
      
      const items = document.querySelectorAll('.pbw');
      if (items.length === 0) {
        this.showMessage('当前页面没有找到列表项', 'error');
        console.log('❌ 测试失败:当前页面没有找到列表项');
        return;
      }
      
      console.log(`📋 开始测试 ${items.length} 个列表项的匹配情况...`);
      
      let testResults = {
        total: 0,
        matched: 0,
        matchTypes: {
          containMatch: 0
        }
      };
      
      items.forEach((item, index) => {
        const link = item.querySelector('a');
        if (!link) return;
        
        const title = link.textContent.trim();
        const id = item.id;
        
        if (!id) return;
        
        testResults.total++;
        console.log(`\n📝 测试第${index + 1}项: "${title}" (ID: ${id})`);
        
        // 测试各种匹配逻辑
        const matchResult = this.testSingleMatch(title);
        if (matchResult) {
          testResults.matched++;
          testResults.matchTypes[matchResult.type]++;
          console.log(`✅ 匹配成功 (${matchResult.type}): ${matchResult.details}`);
        } else {
          console.log(`❌ 未匹配`);
        }
      });
      
      // 输出测试结果统计
      console.log(`\n📊 测试结果统计:`);
      console.log(`   - 总测试项: ${testResults.total}`);
      console.log(`   - 匹配成功: ${testResults.matched}`);
      console.log(`   - 匹配率: ${((testResults.matched / testResults.total) * 100).toFixed(1)}%`);
      console.log(`   - 包含匹配: ${testResults.matchTypes.containMatch}`);
      
      this.showMessage(`测试完成: ${testResults.matched}/${testResults.total} 项匹配成功`, 'info');
    }
    
    // 测试单个标题的匹配情况
    testSingleMatch(title) {
      // 标准化当前标题
      const normalizedCurrentTitle = this.normalizeString(title);
      
      // 包含匹配逻辑:导入的收藏名称包含列表页标题
      const matched = this.importedFavorites.find(fav => {
        const normalizedFavTitle = this.normalizeString(fav.title);
        return normalizedFavTitle.includes(normalizedCurrentTitle);
      });
      
      if (matched) {
        return {
          type: 'containMatch',
          details: `包含匹配: "${title}" -> "${matched.title}" (标准化: "${this.normalizeString(matched.title)}" 包含 "${normalizedCurrentTitle}")`
        };
      }
      
      return null;
    }

    // 详细的单个匹配测试
    testSingleMatchDetailed(title) {
      console.log(`\n🔍 测试标题: "${title}"`);
      console.log(`📏 标题长度: ${title.length}`);
      
      // 标准化当前标题
      const normalizedCurrentTitle = this.normalizeString(title);
      console.log(`📝 当前标题标准化: "${normalizedCurrentTitle}"`);
      
      // 包含匹配逻辑:导入的收藏名称包含列表页标题
      console.log(`\n1️⃣ 测试包含匹配...`);
      const matched = this.importedFavorites.find(fav => {
        const normalizedFavTitle = this.normalizeString(fav.title);
        const isMatch = normalizedFavTitle.includes(normalizedCurrentTitle);
        console.log(`   - 导入标题: "${fav.title}"`);
        console.log(`   - 导入标题标准化: "${normalizedFavTitle}"`);
        console.log(`   - 包含检查: "${normalizedFavTitle}" 包含 "${normalizedCurrentTitle}" -> ${isMatch}`);
        return isMatch;
      });
      
      if (matched) {
        return {
          type: 'containMatch',
          details: `包含匹配: "${title}" -> "${matched.title}" (标准化包含匹配)`,
          matched: matched
        };
      }
      
      console.log(`\n❌ 包含匹配未成功`);
      return null;
    }

    // 清空数据
    clearData() {
      if (confirm('确定要清空所有导入的收藏数据吗?此操作不可恢复。')) {
        this.importedFavorites = [];
        this.processedItems.clear();
        this.saveImportedFavorites();
        this.updateStatus();
        this.showMessage('数据已从localStorage清空', 'info');
      }
    }

    // 更新状态显示
    updateStatus() {
      const importedCount = document.querySelector('#importedCount');
      const autoStatus = document.querySelector('#autoStatus');
      const processedCount = document.querySelector('#processedCount');
      
      if (importedCount) importedCount.textContent = this.importedFavorites.length;
      if (autoStatus) autoStatus.textContent = this.autoFavoriteEnabled ? '已启用' : '已禁用';
      if (processedCount) processedCount.textContent = this.processedItems.size;
      
      this.updateIgnoreCharsDisplay();
      this.updateMinLengthDisplay();
    }

    // 开始自动处理
    startAutoProcess() {
      console.log('🚀 自动收藏功能已启动,开始监控页面变化...');
      
      // 每3秒检查一次页面变化
      setInterval(() => {
        if (this.autoFavoriteEnabled && this.importedFavorites.length > 0) {
          this.processListPage();
        } else if (this.autoFavoriteEnabled && this.importedFavorites.length === 0) {
          console.log('⚠️ 自动收藏已启用但未导入收藏数据');
        }
      }, 3000);
      
      // 初始检查
      setTimeout(() => {
        if (this.autoFavoriteEnabled && this.importedFavorites.length > 0) {
          console.log('📋 执行初始页面扫描...');
          this.processListPage();
        }
      }, 1000);
    }

    // 处理列表页
    processListPage() {
      const items = document.querySelectorAll('.pbw');
      let processedCount = 0;
      let matchedCount = 0;
      let alreadyFavoritedCount = 0;
      let newItemsCount = 0;
      
      console.log(`🔍 开始扫描页面,发现 ${items.length} 个列表项`);
      
      items.forEach((item, index) => {
        const link = item.querySelector('a');
        if (!link) {
          console.log(`❌ 第${index + 1}项:未找到链接元素`);
          return;
        }

        const title = link.textContent.trim();
        const url = link.href;
        const id = item.id;
        
        if (!id) {
          console.log(`❌ 第${index + 1}项:未找到ID,标题: "${title}"`);
          return;
        }
        
        if (this.processedItems.has(id)) {
          console.log(`⏭️ 第${index + 1}项:已处理过,跳过 - "${title}"`);
          return;
        }

        newItemsCount++;
        console.log(`📝 第${index + 1}项:检查项目 - "${title}" (ID: ${id})`);

        // 检查是否匹配导入的收藏
        const matchedFavorite = this.findMatchingFavorite(title);
        if (matchedFavorite) {
          matchedCount++;
          console.log(`✅ 第${index + 1}项:找到匹配的收藏 - "${title}"`);
          
          // 检查是否已经收藏 - 查找 list-item-buttons 容器下的第一个按钮
          const buttonContainer = item.querySelector('.list-item-buttons');
          if (buttonContainer) {
            const favoriteBtn = buttonContainer.querySelector('button:first-child');
            if (favoriteBtn) {
              if (favoriteBtn.classList.contains('favorited')) {
                alreadyFavoritedCount++;
                console.log(`💚 第${index + 1}项:已经收藏,跳过 - "${title}"`);
              } else {
                console.log(`🎯 第${index + 1}项:准备自动收藏 - "${title}"`);
                // 自动点击收藏按钮
                this.autoClickFavorite(favoriteBtn, id, title, url);
                processedCount++;
              }
            } else {
              console.log(`❌ 第${index + 1}项:未找到收藏按钮 - "${title}"`);
            }
          } else {
            console.log(`❌ 第${index + 1}项:未找到按钮容器 - "${title}"`);
          }
        } else {
          console.log(`❌ 第${index + 1}项:未匹配到导入的收藏 - "${title}"`);
        }

        // 标记为已处理
        this.processedItems.add(id);
      });

      // 输出扫描结果统计
      console.log(`📊 扫描完成统计:`);
      console.log(`   - 总列表项: ${items.length}`);
      console.log(`   - 新项目: ${newItemsCount}`);
      console.log(`   - 匹配收藏: ${matchedCount}`);
      console.log(`   - 已收藏: ${alreadyFavoritedCount}`);
      console.log(`   - 新收藏: ${processedCount}`);
      console.log(`   - 已处理总数: ${this.processedItems.size}`);

      if (processedCount > 0) {
        console.log(`🎉 本次自动收藏了 ${processedCount} 个项目`);
        this.updateStatus();
      } else if (matchedCount > 0) {
        console.log(`ℹ️ 找到 ${matchedCount} 个匹配项,但都已收藏或无法操作`);
      } else {
        console.log(`ℹ️ 本次扫描未找到可自动收藏的项目`);
      }
    }

    // 查找匹配的收藏
    findMatchingFavorite(title) {
      console.log(`🔍 开始匹配标题: "${title}"`);
      
      // 标准化当前标题
      const normalizedCurrentTitle = this.normalizeString(title);
      
      // 包含匹配逻辑:导入的收藏名称包含列表页标题
      const matched = this.importedFavorites.find(fav => {
        const normalizedFavTitle = this.normalizeString(fav.title);
        // 检查导入的收藏标题是否包含当前标题
        return normalizedFavTitle.includes(normalizedCurrentTitle);
      });
      
      if (matched) {
        console.log(`✅ 匹配成功 (包含匹配): "${title}" -> 收藏ID: ${matched.id}`);
        console.log(`   - 当前标题标准化: "${normalizedCurrentTitle}"`);
        console.log(`   - 导入标题标准化: "${this.normalizeString(matched.title)}"`);
        console.log(`   - 包含关系: "${this.normalizeString(matched.title)}" 包含 "${normalizedCurrentTitle}"`);
        return matched;
      }
      
      console.log(`❌ 未找到匹配的收藏: "${title}"`);
      return null;
    }
    

    // 标准化字符串,用于匹配对比
    normalizeString(str) {
      if (!str || typeof str !== 'string') {
        return str;
      }
      
      let normalized = str;
      
      // 1. 去掉第一个空格前面的内容
      const spaceIndex = normalized.indexOf(' ');
      if (spaceIndex !== -1) {
        normalized = normalized.substring(spaceIndex + 1).trim();
      }
      
      // 2. 移除所有空格、制表符、换行符等空白字符
      normalized = normalized.replace(/\s+/g, '');
      
      // 3. 移除所有标点符号和特殊字符
      normalized = normalized.replace(/[.,;:!?()[\]{}"'`~@#$%^&*+=|\\/<>]/g, '');
      
      // 4. 转换为大写
      normalized = normalized.toUpperCase();
      
      // 5. 去掉"百度网盘"和"..."
      normalized = normalized.replace(/百度网盘/g, '');
      normalized = normalized.replace(/\.\.\./g, '');
      
      console.log(`🔄 字符串标准化: "${str}" -> "${normalized}"`);
      
      return normalized;
    }

    // 处理标题文本,应用忽略字符和标准化处理(保留原函数以兼容)
    processTitle(title) {
      return this.normalizeString(title);
    }


    // 自动点击收藏按钮
    autoClickFavorite(btn, id, title, url) {
      try {
        console.log(`🎯 开始自动收藏操作: "${title}" (ID: ${id})`);
        console.log(`   - 按钮状态: ${btn.className}`);
        console.log(`   - 按钮文本: ${btn.textContent}`);
        console.log(`   - 链接地址: ${url}`);
        
        // 检查是否存在修眉收藏功能脚本的页面处理器
        if (window.pageHandler && window.pageHandler.toggleFavorite) {
          console.log(`🔄 使用修眉收藏功能脚本的收藏方法`);
          // 使用修眉收藏功能脚本的收藏方法
          window.pageHandler.toggleFavorite(id, title, url, btn);
          console.log(`✅ 通过修眉收藏功能脚本收藏成功: "${title}" (ID: ${id})`);
        } else {
          console.log(`🔄 使用原生点击事件`);
          // 模拟点击事件 - 修复view属性问题,使用更兼容的方式
          try {
            // 方法1:尝试使用document.defaultView
            const event = new MouseEvent('click', {
              bubbles: true,
              cancelable: true,
              view: document.defaultView
            });
            btn.dispatchEvent(event);
            console.log(`✅ 通过原生点击事件收藏成功: "${title}" (ID: ${id})`);
          } catch (e) {
            console.log(`⚠️ 方法1失败,尝试方法2: ${e.message}`);
            try {
              // 方法2:不指定view属性
              const event = new MouseEvent('click', {
                bubbles: true,
                cancelable: true
              });
              btn.dispatchEvent(event);
              console.log(`✅ 通过原生点击事件收藏成功: "${title}" (ID: ${id})`);
            } catch (e2) {
              console.log(`⚠️ 方法2失败,尝试方法3: ${e2.message}`);
              // 方法3:直接调用click方法
              btn.click();
              console.log(`✅ 通过直接click方法收藏成功: "${title}" (ID: ${id})`);
            }
          }
        }
        
        // 显示成功消息
        this.showMessage(`自动收藏: ${title}`, 'success');
        
        // 延迟检查按钮状态变化
        setTimeout(() => {
          const newBtnState = btn.className;
          const newBtnText = btn.textContent;
          console.log(`🔄 收藏后按钮状态检查:`);
          console.log(`   - 新按钮状态: ${newBtnState}`);
          console.log(`   - 新按钮文本: ${newBtnText}`);
          
          if (newBtnState.includes('favorited') || newBtnText.includes('已收藏')) {
            console.log(`✅ 确认收藏状态已更新: "${title}"`);
          } else {
            console.log(`⚠️ 收藏状态可能未正确更新: "${title}"`);
          }
        }, 1000);
        
      } catch (e) {
        console.error(`❌ 自动收藏失败: "${title}"`, e);
        this.showMessage(`自动收藏失败: ${title}`, 'error');
      }
    }

    // 显示消息
    showMessage(message, type = 'info') {
      // 移除现有消息
      const existingMessage = document.querySelector('.auto-favorite-message');
      if (existingMessage) {
        existingMessage.remove();
      }

      // 创建新消息
      const messageEl = document.createElement('div');
      messageEl.className = `auto-favorite-message auto-favorite-message-${type}`;
      messageEl.textContent = message;
      document.body.appendChild(messageEl);

      // 3秒后自动移除
      setTimeout(() => {
        if (messageEl.parentNode) {
          messageEl.remove();
        }
      }, 3000);
    }
  }

  // 等待页面加载完成后初始化
  console.log('📄 页面加载状态:', document.readyState);
  console.log('🌐 当前页面URL:', window.location.href);
  
  // 检查localStorage中是否有收藏数据
  const hasFavData = localStorage.getItem('fav-list');
  if (hasFavData) {
    console.log('📂 检测到localStorage中有收藏数据,准备自动运行');
  } else {
    console.log('📭 localStorage中暂无收藏数据');
  }
  
  function initializeAutoFavorite() {
    console.log('✅ 开始初始化自动收藏管理器');
    new AutoFavoriteManager();
  }
  
  if (document.readyState === 'loading') {
    console.log('⏳ 等待页面加载完成...');
    document.addEventListener('DOMContentLoaded', initializeAutoFavorite);
  } else {
    console.log('✅ 页面已加载完成,立即初始化自动收藏管理器');
    initializeAutoFavorite();
  }
  
  // 监听页面变化,确保在单页应用中也能正常工作
  let lastUrl = location.href;
  new MutationObserver(() => {
    const url = location.href;
    if (url !== lastUrl) {
      lastUrl = url;
      console.log('🔄 检测到页面URL变化,重新初始化自动收藏管理器');
      setTimeout(initializeAutoFavorite, 1000); // 延迟1秒确保页面完全加载
    }
  }).observe(document, { subtree: true, childList: true });

})();