Greasy Fork

Greasy Fork is available in English.

(测试)隐藏/显示超星学习通作业答案

一键隐藏超星学习通作业页面中所有 div.mark_answer 答案块,支持单个控制和全局控制,支持为每道题添加笔记。

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

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

You will need to install an extension such as Tampermonkey to install this script.

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         (测试)隐藏/显示超星学习通作业答案
// @namespace    http://tampermonkey.net/
// @version      2.3.0
// @description  一键隐藏超星学习通作业页面中所有 div.mark_answer 答案块,支持单个控制和全局控制,支持为每道题添加笔记。
// @author       You
// @match        https://*.chaoxing.com/mooc-ans/mooc2/work/view*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chaoxing.com
// @grant        none
// @run-at       document-end
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // ===================== 配置管理模块 =====================
    class Config {
        static DEFAULT = {
            // ========== DOM 选择器配置 ==========
            selectors: {
                answerBlock: 'div.mark_answer',    // 答案块的选择器
                container: 'div.topicNumber',      // 题目容器的选择器
                questionItem: 'div.mark_item'      // 题目项的选择器
            },

            // ========== 延迟配置 ==========
            delays: {
                initialization: 800  // 脚本初始化延迟时间(毫秒),确保页面加载完成
            },

            // ========== 单个答案控制按钮配置 ==========
            answerButton: {
                // --- 按钮位置配置 ---
                position: {
                    marginLeft: '10px',      // 按钮左外边距
                    marginRight: '0px',      // 按钮右外边距
                    marginTop: '10px',       // 按钮上外边距
                    marginBottom: '0px',     // 按钮下外边距
                    verticalAlign: 'middle'  // 垂直对齐方式(top/middle/bottom)
                },
                // --- 按钮样式配置 ---
                style: {
                    fontSize: '12px',        // 字体大小
                    padding: '2px 8px',      // 内边距(上下 左右)
                    borderRadius: '3px',     // 圆角半径
                    border: 'none',          // 边框样式
                    fontWeight: 'normal',    // 字体粗细(normal/bold/100-900)
                    cursor: 'pointer',       // 鼠标样式
                    transition: 'background 0.2s'  // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    showBackground: '#4299e1',     // "显示答案"按钮背景色(蓝色)
                    hideBackground: '#9f7aea',     // "隐藏答案"按钮背景色(紫色)
                    textColor: 'white',            // 按钮文字颜色
                    hoverOpacity: '0.8'            // 鼠标悬停时的透明度
                },
                // --- 按钮文字配置 ---
                text: {
                    show: '显示答案',   // "显示答案"按钮文字
                    hide: '隐藏答案'    // "隐藏答案"按钮文字
                }
            },

            // ========== 笔记控制按钮配置 ==========
            noteButton: {
                // --- 按钮位置配置 ---
                position: {
                    marginLeft: '5px',       // 按钮左外边距(与答案按钮的间距)
                    marginRight: '0px',      // 按钮右外边距
                    marginTop: '10px',        // 按钮上外边距
                    marginBottom: '0px',     // 按钮下外边距
                    verticalAlign: 'middle'  // 垂直对齐方式
                },
                // --- 按钮样式配置 ---
                style: {
                    fontSize: '12px',        // 字体大小
                    padding: '2px 8px',      // 内边距(上下 左右)
                    borderRadius: '3px',     // 圆角半径
                    border: 'none',          // 边框样式
                    fontWeight: 'normal',    // 字体粗细
                    cursor: 'pointer',       // 鼠标样式
                    transition: 'background 0.2s'  // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    showBackground: '#48bb78',     // "显示笔记"按钮背景色(绿色)
                    hideBackground: '#9f7aea',     // "隐藏笔记"按钮背景色(紫色)
                    textColor: 'white',            // 按钮文字颜色
                    hoverOpacity: '0.8'            // 鼠标悬停时的透明度
                },
                // --- 按钮文字配置 ---
                text: {
                    show: '显示笔记',   // "显示笔记"按钮文字
                    hide: '隐藏笔记'    // "隐藏笔记"按钮文字
                }
            },

            // ========== 保存笔记按钮配置 ==========
            saveNoteButton: {
                // --- 按钮位置配置 ---
                position: {
                    marginLeft: '5px',       // 按钮左外边距(与笔记按钮的间距)
                    marginRight: '0px',      // 按钮右外边距
                    marginTop: '10px',        // 按钮上外边距
                    marginBottom: '0px',     // 按钮下外边距
                    verticalAlign: 'middle'  // 垂直对齐方式
                },
                // --- 按钮样式配置 ---
                style: {
                    fontSize: '12px',        // 字体大小
                    padding: '2px 8px',      // 内边距(上下 左右)
                    borderRadius: '3px',     // 圆角半径
                    border: 'none',          // 边框样式
                    fontWeight: 'normal',    // 字体粗细
                    cursor: 'pointer',       // 鼠标样式
                    transition: 'background 0.2s'  // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    background: '#38b2ac',   // 按钮背景色(青色)
                    textColor: 'white',      // 按钮文字颜色
                    hoverOpacity: '0.8'      // 鼠标悬停时的透明度
                },
                // --- 按钮文字配置 ---
                text: '💾 保存'           // 保存按钮文字
            },

            // ========== 全局控制按钮配置 ==========
            globalButton: {
                // --- 按钮位置配置 ---
                position: {
                    top: '8px',              // 距离容器顶部的距离
                    right: '8px',            // 距离容器右侧的距离
                    zIndex: '9999'           // 层级(确保在最上层)
                },
                // --- 按钮样式配置 ---
                style: {
                    fontSize: '12px',        // 字体大小
                    padding: '3px 10px',     // 内边距(上下 左右)
                    borderRadius: '4px',     // 圆角半径
                    border: 'none',          // 边框样式
                    fontWeight: 'normal',    // 字体粗细
                    cursor: 'pointer',       // 鼠标样式
                    transition: 'background 0.2s'  // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    showAllBackground: '#4299e1',  // "显示全部答案"按钮背景色(蓝色)
                    hideAllBackground: '#9f7aea',  // "隐藏全部答案"按钮背景色(紫色)
                    textColor: 'white',            // 按钮文字颜色
                    hoverOpacity: '0.8'            // 鼠标悬停时的透明度
                },
                // --- 按钮文字配置 ---
                text: {
                    showAll: '显示全部答案',   // "显示全部答案"按钮文字
                    hideAll: '隐藏全部答案'    // "隐藏全部答案"按钮文字
                }
            },

            // ========== 笔记编辑器配置 ==========
            noteEditor: {
                placeholder: '在这里记录你的笔记...',  // 编辑器占位符文字
                width: '110%',                          // 编辑器宽度
                minHeight: '60px',                      // 编辑器最小高度
                maxHeight: '400px',                     // 编辑器最大高度(超出滚动)
                fontSize: '14px',                       // 编辑器字体大小
                padding: '10px',                        // 编辑器内边距
                marginTop: '10px',                      // 编辑器上外边距
                marginBottom: '10px',                   // 编辑器下外边距
                borderRadius: '4px',                    // 编辑器圆角半径
                borderWidth: '1px',                     // 编辑器边框宽度
                borderStyle: 'solid',                   // 编辑器边框样式
                borderColor: '#cbd5e0',                 // 编辑器边框颜色(默认)
                focusBorderColor: '#4299e1',            // 编辑器获得焦点时的边框颜色
                backgroundColor: '#f7fafc',             // 编辑器背景颜色
                textColor: '#2d3748',                   // 编辑器文字颜色
                fontFamily: 'inherit',                  // 编辑器字体(继承父元素)
                resize: 'vertical'                      // 调整大小方式(none/vertical/horizontal/both)
            },

            // ========== 用户设置默认值 ==========
            settings: {
                autoSave: false,                        // 是否开启自动保存(默认关闭)
                autoSaveDelay: 5000                     // 自动保存延迟时间(毫秒)
            },

            // ========== 控制面板按钮配置 ==========
            manageButton: {
                // --- 按钮位置配置 ---
                position: {
                    top: '35px',             // 距离容器顶部的距离(在全局按钮下方)
                    right: '8px',            // 距离容器右侧的距离
                    zIndex: '9999'           // 层级(确保在最上层)
                },
                // --- 按钮样式配置 ---
                style: {
                    fontSize: '12px',        // 字体大小
                    padding: '3px 10px',     // 内边距(上下 左右)
                    borderRadius: '4px',     // 圆角半径
                    border: 'none',          // 边框样式
                    fontWeight: 'normal',    // 字体粗细
                    cursor: 'pointer',       // 鼠标样式
                    transition: 'background 0.2s'  // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    background: '#ed8936',   // 按钮背景色(橙色)
                    textColor: 'white',      // 按钮文字颜色
                    hoverOpacity: '0.8'      // 鼠标悬停时的透明度
                },
                // --- 按钮文字配置 ---
                text: '⚙️ 控制面板'    // 控制面板按钮文字
            },

            // ========== 控制面板保存按钮配置 ==========
            panelSaveButton: {
                // --- 按钮样式配置 ---
                style: {
                    padding: '10px 24px',       // 内边距(上下 左右)
                    borderRadius: '6px',        // 圆角半径
                    border: 'none',             // 边框样式
                    fontSize: '14px',           // 字体大小
                    fontWeight: '600',          // 字体粗细
                    cursor: 'pointer',          // 鼠标样式
                    transition: 'all 0.2s'      // 过渡动画
                },
                // --- 按钮颜色配置 ---
                colors: {
                    background: '#4299e1',          // 按钮背景色(蓝色)
                    hoverBackground: '#3182ce',     // 悬停时背景色
                    textColor: 'white',             // 按钮文字颜色
                    successBackground: '#48bb78',   // 保存成功背景色(绿色)
                    errorBackground: '#f56565',     // 保存失败背景色(红色)
                    boxShadow: '0 2px 4px rgba(66, 153, 225, 0.3)',           // 默认阴影
                    hoverBoxShadow: '0 4px 6px rgba(66, 153, 225, 0.4)'       // 悬停阴影
                },
                // --- 按钮文字配置 ---
                text: {
                    save: '💾 保存设置',      // 默认文字
                    success: '✅ 保存成功',   // 保存成功文字
                    error: '❌ 保存失败'      // 保存失败文字
                }
            },

            // ========== 数据库配置 ==========
            database: {
                name: 'ChaoxingNotesDB',     // IndexedDB 数据库名称
                version: 3,                   // 数据库版本号(v3:添加设置存储)
                stores: {
                    notes: 'notes',           // 笔记存储名称
                    attachments: 'attachments', // 附件存储名称
                    settings: 'settings'      // 用户设置存储名称
                }
            },

            // ========== 提示消息配置 ==========
            messages: {
                noAnswerBlocks: 'ℹ️ 未找到答案块(可能页面未完全加载,可刷新重试)',
                noContainer: 'ℹ️ 未找到容器模块,仅启用单个答案块隐藏功能',
                success: '✅ 超星作业答案块隐藏工具执行完成!',
                hiddenCount: (count) => `- 已隐藏 ${count} 个答案内容块,每个块已添加独立显示按钮`,
                globalButton: (hasContainer) => `- ${hasContainer ? '已在容器右上角添加全局控制按钮' : '未找到容器模块,未添加全局按钮'}`,
                noteSaved: '💾 笔记已自动保存',
                noteLoadError: '⚠️ 加载笔记失败'
            }
        };

        constructor(customConfig = {}) {
            this.config = this._deepMerge(Config.DEFAULT, customConfig);
        }

        get(path) {
            return path.split('.').reduce((obj, key) => obj?.[key], this.config);
        }

        _deepMerge(target, source) {
            const result = { ...target };
            for (const key in source) {
                if (source[key] instanceof Object && key in target) {
                    result[key] = this._deepMerge(target[key], source[key]);
                } else {
                    result[key] = source[key];
                }
            }
            return result;
        }
    }

    // ===================== 日志管理模块 =====================
    class Logger {
        static log(message, type = 'info') {
            const prefix = type === 'error' ? '❌' : type === 'warn' ? '⚠️' : 'ℹ️';
            console.log(`${prefix} ${message}`);
        }

        static success(message) {
            console.log(`✅ ${message}`);
        }

        static error(message, error) {
            console.error(`❌ ${message}`, error);
        }
    }

    // ===================== URL 解析器 =====================
    class URLParser {
        static parseWorkInfo() {
            const url = new URL(window.location.href);
            return {
                courseId: url.searchParams.get('courseId') || '',
                classId: url.searchParams.get('classId') || '',
                workId: url.searchParams.get('workId') || ''
            };
        }

        static getWorkKey() {
            const { courseId, classId, workId } = this.parseWorkInfo();
            return `${courseId}_${classId}_${workId}`;
        }
    }

    // ===================== IndexedDB 管理器 =====================
    class DatabaseManager {
        constructor(config) {
            this.config = config;
            this.db = null;
        }

        async init() {
            return new Promise((resolve, reject) => {
                const request = indexedDB.open(
                    this.config.get('database.name'),
                    this.config.get('database.version')
                );

                request.onerror = () => reject(request.error);
                request.onsuccess = () => {
                    this.db = request.result;
                    resolve(this.db);
                };

                request.onupgradeneeded = (event) => {
                    const db = event.target.result;
                    const oldVersion = event.oldVersion;
                    
                    // 创建或升级笔记存储
                    if (!db.objectStoreNames.contains(this.config.get('database.stores.notes'))) {
                        const notesStore = db.createObjectStore(
                            this.config.get('database.stores.notes'),
                            { keyPath: 'id' }
                        );
                        notesStore.createIndex('workKey', 'workKey', { unique: false });
                        notesStore.createIndex('questionId', 'questionId', { unique: false });
                        notesStore.createIndex('timestamp', 'timestamp', { unique: false });
                    }
                    
                    // v2: 创建附件存储(为未来图片等附件做准备)
                    if (oldVersion < 2 && !db.objectStoreNames.contains(this.config.get('database.stores.attachments'))) {
                        const attachmentsStore = db.createObjectStore(
                            this.config.get('database.stores.attachments'),
                            { keyPath: 'id' }
                        );
                        attachmentsStore.createIndex('noteId', 'noteId', { unique: false });
                        attachmentsStore.createIndex('workKey', 'workKey', { unique: false });
                        attachmentsStore.createIndex('type', 'type', { unique: false });
                        attachmentsStore.createIndex('timestamp', 'timestamp', { unique: false });
                    }

                    // v3: 创建设置存储
                    if (oldVersion < 3 && !db.objectStoreNames.contains(this.config.get('database.stores.settings'))) {
                        db.createObjectStore(
                            this.config.get('database.stores.settings'),
                            { keyPath: 'key' }
                        );
                    }
                };
            });
        }

        async saveNote(workKey, questionId, content) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readwrite'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                
                const id = `${workKey}_${questionId}`;
                const data = {
                    id,
                    workKey,
                    questionId,
                    content,
                    contentType: 'text',  // 内容类型:text, html等
                    hasAttachments: false, // 是否有附件
                    attachmentCount: 0,    // 附件数量
                    timestamp: Date.now(),
                    updatedAt: Date.now()
                };

                const request = objectStore.put(data);
                request.onsuccess = () => resolve(data);
                request.onerror = () => reject(request.error);
            });
        }        async getNote(workKey, questionId) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                
                const id = `${workKey}_${questionId}`;
                const request = objectStore.get(id);

                request.onsuccess = () => resolve(request.result?.content || '');
                request.onerror = () => reject(request.error);
            });
        }        async getAllNotes(workKey) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                const index = objectStore.index('workKey');
                const request = index.getAll(workKey);

                request.onsuccess = () => resolve(request.result);
                request.onerror = () => reject(request.error);
            });
        }

        /**
         * 获取整个域名下的所有笔记
         */
        async getAllDomainNotes() {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                const request = objectStore.getAll();

                request.onsuccess = () => resolve(request.result);
                request.onerror = () => reject(request.error);
            });
        }

        async deleteNote(workKey, questionId) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readwrite'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                
                const id = `${workKey}_${questionId}`;
                const request = objectStore.delete(id);

                request.onsuccess = () => resolve();
                request.onerror = () => reject(request.error);
            });
        }

        /**
         * 批量删除笔记
         * @param {Array<string>} noteIds - 笔记ID数组
         */
        async deleteNotes(noteIds) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readwrite'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                
                let completedCount = 0;
                const totalCount = noteIds.length;

                if (totalCount === 0) {
                    resolve(0);
                    return;
                }

                noteIds.forEach(id => {
                    const request = objectStore.delete(id);
                    request.onsuccess = () => {
                        completedCount++;
                        if (completedCount === totalCount) {
                            resolve(completedCount);
                        }
                    };
                    request.onerror = () => {
                        Logger.error(`删除笔记失败: ${id}`, request.error);
                        completedCount++;
                        if (completedCount === totalCount) {
                            resolve(completedCount);
                        }
                    };
                });
            });
        }

        /**
         * 获取数据库统计信息
         */
        async getStatistics() {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.notes')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.notes'));
                const countRequest = objectStore.count();

                countRequest.onsuccess = () => {
                    resolve({
                        totalNotes: countRequest.result,
                        databaseName: this.config.get('database.name'),
                        version: this.config.get('database.version')
                    });
                };
                countRequest.onerror = () => reject(countRequest.error);
            });
        }

        /**
         * 保存设置
         * @param {string} key - 设置键
         * @param {any} value - 设置值
         */
        async saveSetting(key, value) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.settings')],
                    'readwrite'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.settings'));
                
                const data = { key, value, updatedAt: Date.now() };
                const request = objectStore.put(data);

                request.onsuccess = () => resolve(data);
                request.onerror = () => reject(request.error);
            });
        }

        /**
         * 获取设置
         * @param {string} key - 设置键
         * @param {any} defaultValue - 默认值
         */
        async getSetting(key, defaultValue = null) {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.settings')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.settings'));
                const request = objectStore.get(key);

                request.onsuccess = () => {
                    const result = request.result;
                    resolve(result ? result.value : defaultValue);
                };
                request.onerror = () => reject(request.error);
            });
        }

        /**
         * 获取所有设置
         */
        async getAllSettings() {
            if (!this.db) await this.init();

            return new Promise((resolve, reject) => {
                const transaction = this.db.transaction(
                    [this.config.get('database.stores.settings')],
                    'readonly'
                );
                const objectStore = transaction.objectStore(this.config.get('database.stores.settings'));
                const request = objectStore.getAll();

                request.onsuccess = () => {
                    const settings = {};
                    request.result.forEach(item => {
                        settings[item.key] = item.value;
                    });
                    resolve(settings);
                };
                request.onerror = () => reject(request.error);
            });
        }
    }

    // ===================== 笔记编辑器组件 =====================
    class NoteEditor {
        constructor(questionId, workKey, dbManager, config, styleGenerator) {
            this.questionId = questionId;
            this.workKey = workKey;
            this.dbManager = dbManager;
            this.config = config;
            this.styleGenerator = styleGenerator;
            this.editor = null;
            this.saveTimer = null;
            this.isVisible = false;
        }

        async create() {
            const noteConfig = this.config.get('noteEditor');

            this.editor = DOMHelper.createElement('textarea', {
                placeholder: noteConfig.placeholder,
                style: this.styleGenerator.getNoteEditorStyle()
            });

            // 加载已保存的笔记
            try {
                const savedContent = await this.dbManager.getNote(this.workKey, this.questionId);
                if (savedContent) {
                    this.editor.value = savedContent;
                    this._adjustHeight();
                }
            } catch (error) {
                Logger.error(this.config.get('messages.noteLoadError'), error);
            }

            // 监听输入事件,自动调整高度和保存
            this.editor.addEventListener('input', () => {
                this._adjustHeight();
                this._scheduleAutoSave();
            });

            // 获得焦点时改变边框颜色
            this.editor.addEventListener('focus', () => {
                this.editor.style.borderColor = this.config.get('noteEditor.focusBorderColor');
            });

            this.editor.addEventListener('blur', () => {
                this.editor.style.borderColor = this.config.get('noteEditor.borderColor');
            });

            return this.editor;
        }

        _adjustHeight() {
            // 重置高度以获取正确的 scrollHeight
            this.editor.style.height = 'auto';
            const noteConfig = this.config.get('noteEditor');
            const minHeight = parseInt(noteConfig.minHeight);
            const maxHeight = parseInt(noteConfig.maxHeight);
            const newHeight = Math.min(Math.max(this.editor.scrollHeight, minHeight), maxHeight);
            this.editor.style.height = `${newHeight}px`;
        }

        _scheduleAutoSave() {
            // 检查自动保存是否启用
            this.dbManager.getSetting('autoSave', this.config.get('settings.autoSave'))
                .then(autoSaveEnabled => {
                    if (!autoSaveEnabled) return;

                    if (this.saveTimer) {
                        clearTimeout(this.saveTimer);
                    }

                    this.dbManager.getSetting('autoSaveDelay', this.config.get('settings.autoSaveDelay'))
                        .then(delay => {
                            this.saveTimer = setTimeout(async () => {
                                await this.save();
                            }, delay);
                        });
                });
        }

        async save() {
            try {
                const content = this.editor.value.trim();
                await this.dbManager.saveNote(this.workKey, this.questionId, content);
            } catch (error) {
                Logger.error('保存笔记失败', error);
            }
        }

        show() {
            this.editor.style.display = 'block';
            this.isVisible = true;
            this._adjustHeight();
        }

        hide() {
            this.editor.style.display = 'none';
            this.isVisible = false;
        }

        toggle() {
            if (this.isVisible) {
                this.hide();
            } else {
                this.show();
            }
        }

        getElement() {
            return this.editor;
        }
    }

    // ===================== 控制面板UI组件 =====================
    class ControlPanelUI {
        constructor(dbManager, workKey, config) {
            this.dbManager = dbManager;
            this.workKey = workKey;
            this.config = config;
            this.modal = null;
            this.notesList = [];
            this.selectedNotes = new Set();
            this.notesScope = 'current'; // 'current', 'course', 'class', 'domain'
            this.currentTab = 'settings'; // 'settings', 'notes', 'styles'
            this.settings = {};
            this.notesMenuExpanded = false; // 管理笔记子菜单是否展开
            
            // 解析 workKey 获取 courseId, classId, workId
            const parts = workKey.split('_');
            this.courseId = parts[0] || '';
            this.classId = parts[1] || '';
            this.workId = parts[2] || '';
        }

        /**
         * 显示控制面板
         */
        async show() {
            await this._loadSettings();
            await this._loadNotes();
            this._createModal();
            this._renderContent();
        }

        /**
         * 加载用户设置
         */
        async _loadSettings() {
            try {
                this.settings = await this.dbManager.getAllSettings();
                // 填充默认值
                if (!('autoSave' in this.settings)) {
                    this.settings.autoSave = this.config.get('settings.autoSave');
                }
                if (!('autoSaveDelay' in this.settings)) {
                    this.settings.autoSaveDelay = this.config.get('settings.autoSaveDelay');
                }
            } catch (error) {
                Logger.error('加载设置失败', error);
                this.settings = {
                    autoSave: this.config.get('settings.autoSave'),
                    autoSaveDelay: this.config.get('settings.autoSaveDelay')
                };
            }
        }

        /**
         * 加载笔记数据
         */
        async _loadNotes() {
            try {
                const allNotes = await this.dbManager.getAllDomainNotes();
                
                switch (this.notesScope) {
                    case 'current':
                        // 当前页面:完全匹配 workKey
                        this.notesList = allNotes.filter(note => note.workKey === this.workKey);
                        break;
                    case 'course':
                        // 当前课程:courseId 相同
                        this.notesList = allNotes.filter(note => {
                            const parts = note.workKey.split('_');
                            return parts[0] === this.courseId;
                        });
                        break;
                    case 'class':
                        // 当前班级:courseId 和 classId 都相同
                        this.notesList = allNotes.filter(note => {
                            const parts = note.workKey.split('_');
                            return parts[0] === this.courseId && parts[1] === this.classId;
                        });
                        break;
                    case 'domain':
                        // 整个域名:所有笔记
                        this.notesList = allNotes;
                        break;
                    default:
                        this.notesList = allNotes.filter(note => note.workKey === this.workKey);
                }
                
                this.notesList.sort((a, b) => b.timestamp - a.timestamp);
            } catch (error) {
                Logger.error('加载笔记失败', error);
                this.notesList = [];
            }
        }

        /**
         * 创建模态框
         */
        _createModal() {
            // 创建遮罩层
            const overlay = DOMHelper.createElement('div', {
                style: {
                    position: 'fixed',
                    top: '0',
                    left: '0',
                    width: '100%',
                    height: '100%',
                    backgroundColor: 'rgba(0, 0, 0, 0.5)',
                    zIndex: '99999',
                    display: 'flex',
                    justifyContent: 'center',
                    alignItems: 'center'
                }
            });

            // 创建主容器
            const mainContainer = DOMHelper.createElement('div', {
                style: {
                    backgroundColor: 'white',
                    borderRadius: '12px',
                    width: '90%',
                    maxWidth: '900px',
                    height: '85vh',
                    display: 'flex',
                    boxShadow: '0 10px 40px rgba(0, 0, 0, 0.2)',
                    overflow: 'hidden'
                }
            });

            // 创建左侧边栏
            const sidebar = this._createSidebar();
            mainContainer.appendChild(sidebar);

            // 创建右侧内容区
            const contentArea = DOMHelper.createElement('div', {
                id: 'panel-content-area',
                style: {
                    flex: '1',
                    display: 'flex',
                    flexDirection: 'column',
                    backgroundColor: '#f7fafc'
                }
            });

            // 创建内容区标题栏
            const contentHeader = DOMHelper.createElement('div', {
                id: 'panel-content-header',
                style: {
                    padding: '20px 30px',
                    borderBottom: '1px solid #e2e8f0',
                    backgroundColor: 'white',
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center'
                }
            });

            const headerTitle = DOMHelper.createElement('h2', {
                id: 'panel-header-title',
                innerText: '⚙️ 设置',
                style: {
                    margin: '0',
                    fontSize: '20px',
                    fontWeight: 'bold',
                    color: '#2d3748'
                }
            });

            const closeBtn = DOMHelper.createElement('button', {
                innerText: '✕',
                style: {
                    background: 'none',
                    border: 'none',
                    fontSize: '24px',
                    cursor: 'pointer',
                    color: '#718096',
                    padding: '0',
                    width: '30px',
                    height: '30px',
                    lineHeight: '30px',
                    textAlign: 'center',
                    borderRadius: '50%',
                    transition: 'background 0.2s'
                }
            });

            closeBtn.addEventListener('mouseenter', () => {
                closeBtn.style.backgroundColor = '#e2e8f0';
            });

            closeBtn.addEventListener('mouseleave', () => {
                closeBtn.style.backgroundColor = 'transparent';
            });

            closeBtn.addEventListener('click', () => this._close());

            contentHeader.appendChild(headerTitle);
            contentHeader.appendChild(closeBtn);
            contentArea.appendChild(contentHeader);

            // 创建内容主体
            const contentBody = DOMHelper.createElement('div', {
                id: 'panel-content-body',
                style: {
                    flex: '1',
                    overflow: 'auto',
                    padding: '30px'
                }
            });

            contentArea.appendChild(contentBody);
            mainContainer.appendChild(contentArea);
            overlay.appendChild(mainContainer);

            // 点击遮罩层关闭
            overlay.addEventListener('click', (e) => {
                if (e.target === overlay) {
                    this._close();
                }
            });

            this.modal = overlay;
            document.body.appendChild(overlay);
        }

        /**
         * 创建左侧边栏
         */
        _createSidebar() {
            const sidebar = DOMHelper.createElement('div', {
                style: {
                    width: '220px',
                    backgroundColor: '#2d3748',
                    display: 'flex',
                    flexDirection: 'column',
                    padding: '20px 0'
                }
            });

            // 标题
            const title = DOMHelper.createElement('div', {
                innerText: '控制面板',
                style: {
                    padding: '0 20px 20px',
                    fontSize: '18px',
                    fontWeight: 'bold',
                    color: 'white',
                    borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
                    marginBottom: '10px'
                }
            });

            sidebar.appendChild(title);

            // 菜单项
            const menuItems = [
                { id: 'settings', icon: '⚙️', text: '设置' },
                { 
                    id: 'notes', 
                    icon: '📝', 
                    text: '管理笔记',
                    hasSubmenu: true,
                    submenu: [
                        { id: 'notes-current', icon: '📄', text: '当前页面', scope: 'current' },
                        { id: 'notes-course', icon: '📚', text: '当前课程', scope: 'course' },
                        { id: 'notes-class', icon: '👥', text: '当前班级', scope: 'class' },
                        { id: 'notes-domain', icon: '🌐', text: '整个域名', scope: 'domain' }
                    ]
                },
                { id: 'styles', icon: '🎨', text: '样式管理' }
            ];

            menuItems.forEach(item => {
                const menuItem = this._createMenuItem(item);
                sidebar.appendChild(menuItem);
            });

            return sidebar;
        }

        /**
         * 创建菜单项(支持子菜单)
         */
        _createMenuItem(item) {
            const container = DOMHelper.createElement('div');
            
            // 主菜单项
            const menuItem = DOMHelper.createElement('div', {
                dataset: { tab: item.id },
                style: {
                    padding: '12px 20px',
                    cursor: 'pointer',
                    color: this.currentTab === item.id ? 'white' : '#a0aec0',
                    backgroundColor: this.currentTab === item.id ? '#4a5568' : 'transparent',
                    borderLeft: this.currentTab === item.id ? '3px solid #4299e1' : '3px solid transparent',
                    fontWeight: this.currentTab === item.id ? 'bold' : 'normal',
                    transition: 'all 0.2s',
                    display: 'flex',
                    alignItems: 'center',
                    gap: '10px',
                    justifyContent: 'space-between'
                }
            });

            const leftContent = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    alignItems: 'center',
                    gap: '10px'
                }
            });

            const iconSpan = DOMHelper.createElement('span', {
                innerText: item.icon,
                style: {
                    fontSize: '16px'
                }
            });

            const textSpan = DOMHelper.createElement('span', {
                innerText: item.text,
                style: {
                    fontSize: '14px'
                }
            });

            leftContent.appendChild(iconSpan);
            leftContent.appendChild(textSpan);
            menuItem.appendChild(leftContent);

            // 如果有子菜单,添加展开图标
            if (item.hasSubmenu) {
                const expandIcon = DOMHelper.createElement('span', {
                    innerText: '▼',
                    style: {
                        fontSize: '10px',
                        transition: 'transform 0.2s',
                        transform: this.notesMenuExpanded ? 'rotate(0deg)' : 'rotate(-90deg)'
                    }
                });
                menuItem.appendChild(expandIcon);

                // 创建子菜单容器
                const submenuContainer = DOMHelper.createElement('div', {
                    style: {
                        display: this.notesMenuExpanded ? 'block' : 'none',
                        backgroundColor: '#1a202c'
                    }
                });

                item.submenu.forEach(subItem => {
                    const subMenuItem = this._createSubMenuItem(subItem);
                    submenuContainer.appendChild(subMenuItem);
                });

                menuItem.addEventListener('click', () => {
                    this.notesMenuExpanded = !this.notesMenuExpanded;
                    expandIcon.style.transform = this.notesMenuExpanded ? 'rotate(0deg)' : 'rotate(-90deg)';
                    submenuContainer.style.display = this.notesMenuExpanded ? 'block' : 'none';
                });

                container.appendChild(menuItem);
                container.appendChild(submenuContainer);
            } else {
                // 无子菜单的普通菜单项
                menuItem.addEventListener('mouseenter', () => {
                    if (this.currentTab !== item.id) {
                        menuItem.style.backgroundColor = '#4a5568';
                        menuItem.style.color = '#e2e8f0';
                    }
                });

                menuItem.addEventListener('mouseleave', () => {
                    if (this.currentTab !== item.id) {
                        menuItem.style.backgroundColor = 'transparent';
                        menuItem.style.color = '#a0aec0';
                    }
                });

                menuItem.addEventListener('click', () => {
                    this.currentTab = item.id;
                    this._updateSidebarState();
                    this._renderContent();
                });

                container.appendChild(menuItem);
            }

            return container;
        }

        /**
         * 创建子菜单项
         */
        _createSubMenuItem(subItem) {
            const isActive = this.currentTab === 'notes' && this.notesScope === subItem.scope;
            
            const subMenuItem = DOMHelper.createElement('div', {
                dataset: { scope: subItem.scope },
                style: {
                    padding: '10px 20px 10px 50px',
                    cursor: 'pointer',
                    color: isActive ? '#4299e1' : '#718096',
                    backgroundColor: isActive ? '#2d3748' : 'transparent',
                    fontSize: '13px',
                    transition: 'all 0.2s',
                    display: 'flex',
                    alignItems: 'center',
                    gap: '8px'
                }
            });

            const icon = DOMHelper.createElement('span', {
                innerText: subItem.icon,
                style: {
                    fontSize: '14px'
                }
            });

            const text = DOMHelper.createElement('span', {
                innerText: subItem.text
            });

            subMenuItem.appendChild(icon);
            subMenuItem.appendChild(text);

            subMenuItem.addEventListener('mouseenter', () => {
                if (!(this.currentTab === 'notes' && this.notesScope === subItem.scope)) {
                    subMenuItem.style.backgroundColor = '#2d3748';
                    subMenuItem.style.color = '#a0aec0';
                }
            });

            subMenuItem.addEventListener('mouseleave', () => {
                if (!(this.currentTab === 'notes' && this.notesScope === subItem.scope)) {
                    subMenuItem.style.backgroundColor = 'transparent';
                    subMenuItem.style.color = '#718096';
                }
            });

            subMenuItem.addEventListener('click', async () => {
                this.currentTab = 'notes';
                this.notesScope = subItem.scope;
                this.selectedNotes.clear();
                await this._loadNotes();
                this._updateSidebarState();
                this._renderContent();
            });

            return subMenuItem;
        }

        /**
         * 更新侧边栏状态
         */
        _updateSidebarState() {
            const menuItems = this.modal.querySelectorAll('[data-tab]');
            menuItems.forEach(item => {
                const isActive = item.dataset.tab === this.currentTab;
                item.style.color = isActive ? 'white' : '#a0aec0';
                item.style.backgroundColor = isActive ? '#4a5568' : 'transparent';
                item.style.borderLeft = isActive ? '3px solid #4299e1' : '3px solid transparent';
                item.style.fontWeight = isActive ? 'bold' : 'normal';
            });
        }

        /**
         * 渲染内容区
         */
        _renderContent() {
            const headerTitle = document.getElementById('panel-header-title');
            const contentBody = document.getElementById('panel-content-body');

            if (this.currentTab === 'settings') {
                headerTitle.innerText = '⚙️ 设置';
                this._renderSettingsPanel(contentBody);
            } else if (this.currentTab === 'notes') {
                headerTitle.innerText = '📝 管理笔记';
                this._renderNotesPanel(contentBody);
            } else if (this.currentTab === 'styles') {
                headerTitle.innerText = '🎨 样式管理';
                this._renderStylesPanel(contentBody);
            }
        }

        /**
         * 渲染设置面板
         */
        _renderSettingsPanel(container) {
            container.innerHTML = '';

            const settingsContainer = DOMHelper.createElement('div', {
                style: {
                    backgroundColor: 'white',
                    borderRadius: '8px',
                    padding: '24px',
                    boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
                    marginBottom: '20px'
                }
            });

            // 自动保存开关
            const autoSaveSection = this._createSettingItem(
                '自动保存',
                '开启后会在输入停止一段时间后自动保存笔记',
                'checkbox',
                'autoSave',
                this.settings.autoSave
            );

            settingsContainer.appendChild(autoSaveSection);

            // 自动保存延迟时间
            const delaySection = this._createSettingItem(
                '自动保存延迟',
                '输入停止后多久开始保存(毫秒)',
                'number',
                'autoSaveDelay',
                this.settings.autoSaveDelay
            );

            settingsContainer.appendChild(delaySection);

            container.appendChild(settingsContainer);

            // 添加保存按钮
            const saveButtonContainer = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    justifyContent: 'flex-end',
                    gap: '10px'
                }
            });

            const buttonConfig = this.config.get('panelSaveButton');
            const saveButton = DOMHelper.createElement('button', {
                innerText: buttonConfig.text.save,
                style: {
                    padding: buttonConfig.style.padding,
                    border: buttonConfig.style.border,
                    borderRadius: buttonConfig.style.borderRadius,
                    backgroundColor: buttonConfig.colors.background,
                    color: buttonConfig.colors.textColor,
                    fontSize: buttonConfig.style.fontSize,
                    fontWeight: buttonConfig.style.fontWeight,
                    cursor: buttonConfig.style.cursor,
                    transition: buttonConfig.style.transition,
                    boxShadow: buttonConfig.colors.boxShadow
                }
            });

            saveButton.addEventListener('mouseenter', () => {
                saveButton.style.backgroundColor = buttonConfig.colors.hoverBackground;
                saveButton.style.transform = 'translateY(-1px)';
                saveButton.style.boxShadow = buttonConfig.colors.hoverBoxShadow;
            });

            saveButton.addEventListener('mouseleave', () => {
                if (saveButton.innerText === buttonConfig.text.save) {
                    saveButton.style.backgroundColor = buttonConfig.colors.background;
                    saveButton.style.transform = 'translateY(0)';
                    saveButton.style.boxShadow = buttonConfig.colors.boxShadow;
                }
            });

            saveButton.addEventListener('click', async () => {
                try {
                    // 保存所有设置
                    await this.dbManager.saveSetting('autoSave', this.settings.autoSave);
                    await this.dbManager.saveSetting('autoSaveDelay', this.settings.autoSaveDelay);
                    
                    // 显示成功提示
                    saveButton.innerText = buttonConfig.text.success;
                    saveButton.style.backgroundColor = buttonConfig.colors.successBackground;
                    
                    setTimeout(() => {
                        saveButton.innerText = buttonConfig.text.save;
                        saveButton.style.backgroundColor = buttonConfig.colors.background;
                    }, 2000);
                    
                    Logger.success('设置已保存');
                } catch (error) {
                    Logger.error('保存设置失败', error);
                    saveButton.innerText = buttonConfig.text.error;
                    saveButton.style.backgroundColor = buttonConfig.colors.errorBackground;
                    
                    setTimeout(() => {
                        saveButton.innerText = buttonConfig.text.save;
                        saveButton.style.backgroundColor = buttonConfig.colors.background;
                    }, 2000);
                }
            });

            saveButtonContainer.appendChild(saveButton);
            container.appendChild(saveButtonContainer);
        }

        /**
         * 创建设置项
         */
        _createSettingItem(label, description, type, key, value) {
            const item = DOMHelper.createElement('div', {
                style: {
                    marginBottom: '24px',
                    paddingBottom: '24px',
                    borderBottom: '1px solid #e2e8f0'
                }
            });

            const labelEl = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                    marginBottom: '8px'
                }
            });

            const labelText = DOMHelper.createElement('span', {
                innerText: label,
                style: {
                    fontSize: '16px',
                    fontWeight: '600',
                    color: '#2d3748'
                }
            });

            let input;
            if (type === 'checkbox') {
                input = DOMHelper.createElement('input', {
                    type: 'checkbox',
                    checked: value,
                    style: {
                        width: '20px',
                        height: '20px',
                        cursor: 'pointer'
                    }
                });

                input.addEventListener('change', () => {
                    this.settings[key] = input.checked;
                });
            } else if (type === 'number') {
                input = DOMHelper.createElement('input', {
                    type: 'number',
                    value: value,
                    style: {
                        width: '120px',
                        padding: '6px 12px',
                        border: '1px solid #cbd5e0',
                        borderRadius: '4px',
                        fontSize: '14px'
                    }
                });

                input.addEventListener('change', () => {
                    const numValue = parseInt(input.value);
                    if (numValue > 0) {
                        this.settings[key] = numValue;
                    }
                });
            }

            labelEl.appendChild(labelText);
            labelEl.appendChild(input);

            const desc = DOMHelper.createElement('div', {
                innerText: description,
                style: {
                    fontSize: '13px',
                    color: '#718096',
                    marginTop: '4px'
                }
            });

            item.appendChild(labelEl);
            item.appendChild(desc);

            return item;
        }

        /**
         * 渲染笔记管理面板
         */
        _renderNotesPanel(container) {
            container.innerHTML = '';
            container.style.padding = '0';

            if (this.notesList.length === 0) {
                const emptyMsg = DOMHelper.createElement('div', {
                    innerText: '📭 暂无笔记',
                    style: {
                        textAlign: 'center',
                        color: '#a0aec0',
                        padding: '60px 20px',
                        fontSize: '16px'
                    }
                });
                container.appendChild(emptyMsg);
                return;
            }

            // 操作栏
            const toolbar = DOMHelper.createElement('div', {
                style: {
                    padding: '15px 30px',
                    backgroundColor: 'white',
                    borderBottom: '1px solid #e2e8f0',
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center'
                }
            });

            const info = DOMHelper.createElement('span', {
                id: 'notes-info-text',
                innerText: `共 ${this.notesList.length} 条笔记`,
                style: {
                    fontSize: '14px',
                    color: '#718096'
                }
            });

            const actions = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    gap: '10px'
                }
            });

            const selectAllBtn = DOMHelper.createElement('button', {
                innerText: '全选',
                style: {
                    padding: '6px 14px',
                    border: '1px solid #cbd5e0',
                    borderRadius: '4px',
                    backgroundColor: 'white',
                    cursor: 'pointer',
                    fontSize: '13px',
                    fontWeight: '500',
                    transition: 'all 0.2s'
                }
            });

            const deleteBtn = DOMHelper.createElement('button', {
                innerText: '删除选中',
                style: {
                    padding: '6px 14px',
                    border: 'none',
                    borderRadius: '4px',
                    backgroundColor: '#f56565',
                    color: 'white',
                    cursor: 'pointer',
                    fontSize: '13px',
                    fontWeight: '500',
                    transition: 'all 0.2s'
                }
            });

            selectAllBtn.addEventListener('click', () => this._toggleSelectAll());
            deleteBtn.addEventListener('click', () => this._deleteSelected());

            actions.appendChild(selectAllBtn);
            actions.appendChild(deleteBtn);
            toolbar.appendChild(info);
            toolbar.appendChild(actions);

            // 笔记列表
            const notesList = DOMHelper.createElement('div', {
                id: 'notes-list-content',
                style: {
                    padding: '20px 30px',
                    overflow: 'auto',
                    flex: '1'
                }
            });

            if (this.notesScope === 'current') {
                // 当前页面:直接显示笔记列表
                this.notesList.forEach(note => {
                    const noteItem = this._createNoteItem(note);
                    notesList.appendChild(noteItem);
                });
            } else {
                // 其他范围:按 workKey 分组显示
                const groupedNotes = this._groupNotesByWorkKey(this.notesList);
                Object.entries(groupedNotes).forEach(([workKey, notes]) => {
                    const group = this._createNotesGroup(workKey, notes);
                    notesList.appendChild(group);
                });
            }

            container.appendChild(toolbar);
            container.appendChild(notesList);
        }

        /**
         * 创建笔记项
         */
        _createNoteItem(note) {
            const item = DOMHelper.createElement('div', {
                style: {
                    padding: '16px',
                    marginBottom: '12px',
                    border: '1px solid #e2e8f0',
                    borderRadius: '8px',
                    backgroundColor: this.selectedNotes.has(note.id) ? '#ebf8ff' : 'white',
                    cursor: 'pointer',
                    transition: 'all 0.2s'
                }
            });

            item.addEventListener('mouseenter', () => {
                if (!this.selectedNotes.has(note.id)) {
                    item.style.backgroundColor = '#f7fafc';
                }
            });

            item.addEventListener('mouseleave', () => {
                if (!this.selectedNotes.has(note.id)) {
                    item.style.backgroundColor = 'white';
                }
            });

            const header = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    alignItems: 'center',
                    marginBottom: '10px',
                    gap: '10px'
                }
            });

            const checkbox = DOMHelper.createElement('input', {
                type: 'checkbox',
                checked: this.selectedNotes.has(note.id),
                style: {
                    width: '16px',
                    height: '16px',
                    cursor: 'pointer'
                }
            });

            checkbox.addEventListener('change', (e) => {
                e.stopPropagation();
                if (checkbox.checked) {
                    this.selectedNotes.add(note.id);
                    item.style.backgroundColor = '#ebf8ff';
                } else {
                    this.selectedNotes.delete(note.id);
                    item.style.backgroundColor = 'white';
                }
                this._updateNotesInfo();
            });

            const questionId = DOMHelper.createElement('span', {
                innerText: note.questionId,
                style: {
                    fontSize: '14px',
                    fontWeight: '600',
                    color: '#4299e1',
                    flex: '1'
                }
            });

            const time = DOMHelper.createElement('span', {
                innerText: new Date(note.timestamp).toLocaleString('zh-CN'),
                style: {
                    fontSize: '12px',
                    color: '#a0aec0'
                }
            });

            header.appendChild(checkbox);
            header.appendChild(questionId);
            header.appendChild(time);

            const content = DOMHelper.createElement('div', {
                innerText: note.content || '(空笔记)',
                style: {
                    fontSize: '14px',
                    color: note.content ? '#2d3748' : '#a0aec0',
                    lineHeight: '1.6',
                    maxHeight: '80px',
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    whiteSpace: 'pre-wrap'
                }
            });

            item.appendChild(header);
            item.appendChild(content);

            item.addEventListener('click', (e) => {
                if (e.target !== checkbox) {
                    checkbox.checked = !checkbox.checked;
                    checkbox.dispatchEvent(new Event('change'));
                }
            });

            return item;
        }

        /**
         * 切换全选
         */
        _toggleSelectAll() {
            if (this.selectedNotes.size === this.notesList.length) {
                this.selectedNotes.clear();
            } else {
                this.notesList.forEach(note => this.selectedNotes.add(note.id));
            }
            this._renderContent();
        }

        /**
         * 删除选中的笔记
         */
        async _deleteSelected() {
            if (this.selectedNotes.size === 0) {
                alert('请先选择要删除的笔记');
                return;
            }

            if (!confirm(`确定要删除选中的 ${this.selectedNotes.size} 条笔记吗?\n此操作不可恢复!`)) {
                return;
            }

            try {
                const noteIds = Array.from(this.selectedNotes);
                await this.dbManager.deleteNotes(noteIds);
                Logger.success(`已删除 ${noteIds.length} 条笔记`);

                this.selectedNotes.clear();
                await this._loadNotes();
                this._renderContent();
            } catch (error) {
                Logger.error('删除笔记失败', error);
                alert('删除笔记失败,请查看控制台了解详情');
            }
        }

        /**
         * 更新笔记信息
         */
        _updateNotesInfo() {
            const info = document.getElementById('notes-info-text');
            if (info) {
                const selectedText = this.selectedNotes.size > 0 ? `,已选中 ${this.selectedNotes.size} 条` : '';
                info.innerText = `共 ${this.notesList.length} 条笔记${selectedText}`;
            }
        }

        /**
         * 按 workKey 分组笔记
         */
        _groupNotesByWorkKey(notes) {
            const groups = {};
            notes.forEach(note => {
                if (!groups[note.workKey]) {
                    groups[note.workKey] = [];
                }
                groups[note.workKey].push(note);
            });
            // 按时间戳排序每个组
            Object.keys(groups).forEach(key => {
                groups[key].sort((a, b) => b.timestamp - a.timestamp);
            });
            return groups;
        }

        /**
         * 创建笔记组(用于域名模式)
         */
        _createNotesGroup(workKey, notes) {
            const group = DOMHelper.createElement('div', {
                style: {
                    marginBottom: '30px'
                }
            });

            // 组标题
            const groupHeader = DOMHelper.createElement('div', {
                style: {
                    padding: '12px 16px',
                    backgroundColor: '#e3f2fd',
                    borderRadius: '8px',
                    marginBottom: '12px',
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                    cursor: 'pointer',
                    transition: 'all 0.2s'
                }
            });

            const headerLeft = DOMHelper.createElement('div', {
                style: {
                    display: 'flex',
                    alignItems: 'center',
                    gap: '10px'
                }
            });

            const collapseIcon = DOMHelper.createElement('span', {
                innerText: '▼',
                style: {
                    fontSize: '12px',
                    color: '#1976d2',
                    transition: 'transform 0.2s'
                }
            });

            const groupTitle = DOMHelper.createElement('span', {
                innerText: `📄 ${workKey}`,
                style: {
                    fontSize: '14px',
                    fontWeight: '600',
                    color: '#1976d2'
                }
            });

            const groupCount = DOMHelper.createElement('span', {
                innerText: `(${notes.length} 条)`,
                style: {
                    fontSize: '13px',
                    color: '#64b5f6',
                    marginLeft: '8px'
                }
            });

            headerLeft.appendChild(collapseIcon);
            headerLeft.appendChild(groupTitle);
            headerLeft.appendChild(groupCount);

            // 全选此组的按钮
            const selectGroupBtn = DOMHelper.createElement('button', {
                innerText: '全选',
                style: {
                    padding: '4px 10px',
                    border: '1px solid #2196f3',
                    borderRadius: '4px',
                    backgroundColor: 'white',
                    color: '#2196f3',
                    cursor: 'pointer',
                    fontSize: '12px',
                    fontWeight: '500',
                    transition: 'all 0.2s'
                }
            });

            selectGroupBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                const allSelected = notes.every(note => this.selectedNotes.has(note.id));
                if (allSelected) {
                    notes.forEach(note => this.selectedNotes.delete(note.id));
                    selectGroupBtn.innerText = '全选';
                } else {
                    notes.forEach(note => this.selectedNotes.add(note.id));
                    selectGroupBtn.innerText = '取消';
                }
                this._renderContent();
            });

            groupHeader.appendChild(headerLeft);
            groupHeader.appendChild(selectGroupBtn);

            // 笔记列表容器
            const notesContainer = DOMHelper.createElement('div', {
                style: {
                    display: 'block',
                    paddingLeft: '20px'
                }
            });

            notes.forEach(note => {
                const noteItem = this._createNoteItem(note);
                notesContainer.appendChild(noteItem);
            });

            // 折叠/展开功能
            let isCollapsed = false;
            groupHeader.addEventListener('click', (e) => {
                if (e.target === selectGroupBtn) return;
                isCollapsed = !isCollapsed;
                notesContainer.style.display = isCollapsed ? 'none' : 'block';
                collapseIcon.style.transform = isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)';
            });

            group.appendChild(groupHeader);
            group.appendChild(notesContainer);

            return group;
        }

        /**
         * 渲染样式管理面板
         */
        async _renderStylesPanel(container) {
            container.innerHTML = '';

            // 样式配置的分类
            const styleCategories = [
                {
                    title: '答案按钮样式',
                    key: 'answerButton',
                    fields: [
                        { name: 'fontSize', label: '字体大小', type: 'text', path: 'style.fontSize' },
                        { name: 'padding', label: '内边距', type: 'text', path: 'style.padding' },
                        { name: 'borderRadius', label: '圆角半径', type: 'text', path: 'style.borderRadius' },
                        { name: 'showBackground', label: '显示按钮背景色', type: 'color', path: 'colors.showBackground' },
                        { name: 'hideBackground', label: '隐藏按钮背景色', type: 'color', path: 'colors.hideBackground' }
                    ]
                },
                {
                    title: '笔记按钮样式',
                    key: 'noteButton',
                    fields: [
                        { name: 'fontSize', label: '字体大小', type: 'text', path: 'style.fontSize' },
                        { name: 'padding', label: '内边距', type: 'text', path: 'style.padding' },
                        { name: 'showBackground', label: '显示按钮背景色', type: 'color', path: 'colors.showBackground' },
                        { name: 'hideBackground', label: '隐藏按钮背景色', type: 'color', path: 'colors.hideBackground' }
                    ]
                },
                {
                    title: '保存笔记按钮样式',
                    key: 'saveNoteButton',
                    fields: [
                        { name: 'fontSize', label: '字体大小', type: 'text', path: 'style.fontSize' },
                        { name: 'padding', label: '内边距', type: 'text', path: 'style.padding' },
                        { name: 'background', label: '背景色', type: 'color', path: 'colors.background' }
                    ]
                },
                {
                    title: '笔记编辑器样式',
                    key: 'noteEditor',
                    fields: [
                        { name: 'width', label: '宽度', type: 'text', path: 'width' },
                        { name: 'minHeight', label: '最小高度', type: 'text', path: 'minHeight' },
                        { name: 'maxHeight', label: '最大高度', type: 'text', path: 'maxHeight' },
                        { name: 'fontSize', label: '字体大小', type: 'text', path: 'fontSize' },
                        { name: 'backgroundColor', label: '背景色', type: 'color', path: 'backgroundColor' },
                        { name: 'borderColor', label: '边框颜色', type: 'color', path: 'borderColor' }
                    ]
                }
            ];

            // 加载已保存的样式配置
            const savedStyles = await this.dbManager.getSetting('customStyles', {});

            // 创建滚动容器
            const scrollContainer = DOMHelper.createElement('div', {
                style: {
                    overflow: 'auto',
                    padding: '20px'
                }
            });

            // 为每个分类创建配置区块
            styleCategories.forEach(category => {
                const section = this._createStyleSection(category, savedStyles);
                scrollContainer.appendChild(section);
            });

            container.appendChild(scrollContainer);

            // 添加保存和重置按钮
            const buttonContainer = DOMHelper.createElement('div', {
                style: {
                    padding: '20px',
                    borderTop: '1px solid #e2e8f0',
                    display: 'flex',
                    justifyContent: 'space-between',
                    backgroundColor: 'white'
                }
            });

            const resetButton = DOMHelper.createElement('button', {
                innerText: '🔄 重置为默认',
                style: {
                    padding: '10px 20px',
                    border: '1px solid #cbd5e0',
                    borderRadius: '6px',
                    backgroundColor: 'white',
                    color: '#718096',
                    fontSize: '14px',
                    fontWeight: '600',
                    cursor: 'pointer',
                    transition: 'all 0.2s'
                }
            });

            resetButton.addEventListener('click', async () => {
                if (confirm('确定要重置所有样式为默认值吗?')) {
                    await this.dbManager.saveSetting('customStyles', {});
                    Logger.success('样式已重置');
                    this._renderStylesPanel(container);
                }
            });

            const buttonConfig = this.config.get('panelSaveButton');
            const saveButton = DOMHelper.createElement('button', {
                innerText: buttonConfig.text.save,
                style: {
                    padding: buttonConfig.style.padding,
                    border: buttonConfig.style.border,
                    borderRadius: buttonConfig.style.borderRadius,
                    backgroundColor: buttonConfig.colors.background,
                    color: buttonConfig.colors.textColor,
                    fontSize: buttonConfig.style.fontSize,
                    fontWeight: buttonConfig.style.fontWeight,
                    cursor: buttonConfig.style.cursor,
                    transition: buttonConfig.style.transition,
                    boxShadow: buttonConfig.colors.boxShadow
                }
            });

            saveButton.addEventListener('click', async () => {
                try {
                    const customStyles = {};
                    
                    // 收集所有表单数据
                    styleCategories.forEach(category => {
                        category.fields.forEach(field => {
                            const input = document.getElementById(`style-${category.key}-${field.name}`);
                            if (input && input.value) {
                                if (!customStyles[category.key]) {
                                    customStyles[category.key] = {};
                                }
                                // 设置嵌套属性
                                const pathParts = field.path.split('.');
                                let target = customStyles[category.key];
                                for (let i = 0; i < pathParts.length - 1; i++) {
                                    if (!target[pathParts[i]]) {
                                        target[pathParts[i]] = {};
                                    }
                                    target = target[pathParts[i]];
                                }
                                target[pathParts[pathParts.length - 1]] = input.value;
                            }
                        });
                    });

                    await this.dbManager.saveSetting('customStyles', customStyles);
                    
                    saveButton.innerText = buttonConfig.text.success;
                    saveButton.style.backgroundColor = buttonConfig.colors.successBackground;
                    
                    setTimeout(() => {
                        saveButton.innerText = buttonConfig.text.save;
                        saveButton.style.backgroundColor = buttonConfig.colors.background;
                    }, 2000);
                    
                    Logger.success('样式已保存,刷新页面后生效');
                    
                } catch (error) {
                    Logger.error('保存样式失败', error);
                    saveButton.innerText = buttonConfig.text.error;
                    saveButton.style.backgroundColor = buttonConfig.colors.errorBackground;
                    
                    setTimeout(() => {
                        saveButton.innerText = buttonConfig.text.save;
                        saveButton.style.backgroundColor = buttonConfig.colors.background;
                    }, 2000);
                }
            });

            buttonContainer.appendChild(resetButton);
            buttonContainer.appendChild(saveButton);
            container.appendChild(buttonContainer);
        }

        /**
         * 创建样式配置区块
         */
        _createStyleSection(category, savedStyles) {
            const section = DOMHelper.createElement('div', {
                style: {
                    backgroundColor: 'white',
                    borderRadius: '8px',
                    padding: '20px',
                    marginBottom: '20px',
                    boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)'
                }
            });

            const title = DOMHelper.createElement('h3', {
                innerText: category.title,
                style: {
                    margin: '0 0 16px 0',
                    fontSize: '16px',
                    fontWeight: '600',
                    color: '#2d3748',
                    borderBottom: '2px solid #4299e1',
                    paddingBottom: '8px'
                }
            });

            section.appendChild(title);

            category.fields.forEach(field => {
                const fieldGroup = DOMHelper.createElement('div', {
                    style: {
                        marginBottom: '16px',
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'space-between'
                    }
                });

                const label = DOMHelper.createElement('label', {
                    innerText: field.label,
                    style: {
                        fontSize: '14px',
                        color: '#4a5568',
                        fontWeight: '500',
                        flex: '1'
                    }
                });

                // 获取当前值(优先使用保存的值,否则使用默认配置值)
                let currentValue;
                if (savedStyles[category.key]) {
                    const pathParts = field.path.split('.');
                    let value = savedStyles[category.key];
                    for (let part of pathParts) {
                        value = value?.[part];
                    }
                    currentValue = value;
                }
                
                if (!currentValue) {
                    const pathParts = field.path.split('.');
                    let value = this.config.get(category.key);
                    for (let part of pathParts) {
                        value = value?.[part];
                    }
                    currentValue = value || '';
                }

                const input = DOMHelper.createElement('input', {
                    type: field.type,
                    value: currentValue,
                    id: `style-${category.key}-${field.name}`,
                    style: {
                        width: field.type === 'color' ? '60px' : '150px',
                        padding: '6px 10px',
                        border: '1px solid #cbd5e0',
                        borderRadius: '4px',
                        fontSize: '13px'
                    }
                });

                fieldGroup.appendChild(label);
                fieldGroup.appendChild(input);
                section.appendChild(fieldGroup);
            });

            return section;
        }

        /**
         * 关闭模态框
         */
        _close() {
            if (this.modal && this.modal.parentNode) {
                document.body.removeChild(this.modal);
                this.modal = null;
            }
        }
    }

    // ===================== DOM 工具类 =====================
    class DOMHelper {
        static createElement(tag, attributes = {}) {
            const element = document.createElement(tag);
            Object.entries(attributes).forEach(([key, value]) => {
                if (key === 'style' && typeof value === 'object') {
                    Object.assign(element.style, value);
                } else if (key === 'dataset' && typeof value === 'object') {
                    Object.entries(value).forEach(([dataKey, dataValue]) => {
                        element.dataset[dataKey] = dataValue;
                    });
                } else {
                    element[key] = value;
                }
            });
            return element;
        }

        static insertElement(element, parent, nextSibling = null) {
            if (nextSibling) {
                parent.insertBefore(element, nextSibling);
            } else {
                parent.appendChild(element);
            }
        }

        static removeElement(element) {
            element?.parentNode?.removeChild(element);
        }

        static ensureRelativePosition(element) {
            if (getComputedStyle(element).position === 'static') {
                element.style.position = 'relative';
            }
        }
    }

    // ===================== 样式生成器 =====================
    class StyleGenerator {
        constructor(config) {
            this.config = config;
        }

        /**
         * 获取单个答案按钮的样式
         * @param {boolean} isHidden - 是否为隐藏状态
         * @returns {Object} 样式对象
         */
        getAnswerButtonStyle(isHidden = true) {
            const position = this.config.get('answerButton.position');
            const style = this.config.get('answerButton.style');
            const colors = this.config.get('answerButton.colors');

            return {
                marginLeft: position.marginLeft,
                marginRight: position.marginRight,
                marginTop: position.marginTop,
                marginBottom: position.marginBottom,
                verticalAlign: position.verticalAlign,
                padding: style.padding,
                border: style.border,
                borderRadius: style.borderRadius,
                background: isHidden ? colors.showBackground : colors.hideBackground,
                color: colors.textColor,
                fontSize: style.fontSize,
                fontWeight: style.fontWeight,
                cursor: style.cursor,
                transition: style.transition,
                display: 'inline-block'
            };
        }

        /**
         * 获取笔记按钮的样式
         * @param {boolean} isVisible - 笔记是否可见
         * @returns {Object} 样式对象
         */
        getNoteButtonStyle(isVisible = false) {
            const position = this.config.get('noteButton.position');
            const style = this.config.get('noteButton.style');
            const colors = this.config.get('noteButton.colors');

            return {
                marginLeft: position.marginLeft,
                marginRight: position.marginRight,
                marginTop: position.marginTop,
                marginBottom: position.marginBottom,
                verticalAlign: position.verticalAlign,
                padding: style.padding,
                border: style.border,
                borderRadius: style.borderRadius,
                background: isVisible ? colors.hideBackground : colors.showBackground,
                color: colors.textColor,
                fontSize: style.fontSize,
                fontWeight: style.fontWeight,
                cursor: style.cursor,
                transition: style.transition,
                display: 'inline-block'
            };
        }

        /**
         * 获取保存笔记按钮的样式
         * @returns {Object} 样式对象
         */
        getSaveNoteButtonStyle() {
            const position = this.config.get('saveNoteButton.position');
            const style = this.config.get('saveNoteButton.style');
            const colors = this.config.get('saveNoteButton.colors');

            return {
                marginLeft: position.marginLeft,
                marginRight: position.marginRight,
                marginTop: position.marginTop,
                marginBottom: position.marginBottom,
                verticalAlign: position.verticalAlign,
                padding: style.padding,
                border: style.border,
                borderRadius: style.borderRadius,
                background: colors.background,
                color: colors.textColor,
                fontSize: style.fontSize,
                fontWeight: style.fontWeight,
                cursor: style.cursor,
                transition: style.transition,
                display: 'inline-block'
            };
        }

        /**
         * 获取全局按钮的样式
         * @param {boolean} isHidden - 是否为全部隐藏状态
         * @returns {Object} 样式对象
         */
        getGlobalButtonStyle(isHidden = true) {
            const position = this.config.get('globalButton.position');
            const style = this.config.get('globalButton.style');
            const colors = this.config.get('globalButton.colors');

            return {
                position: 'absolute',
                top: position.top,
                right: position.right,
                zIndex: position.zIndex,
                border: style.border,
                borderRadius: style.borderRadius,
                padding: style.padding,
                fontSize: style.fontSize,
                fontWeight: style.fontWeight,
                color: colors.textColor,
                cursor: style.cursor,
                transition: style.transition,
                background: isHidden ? colors.showAllBackground : colors.hideAllBackground
            };
        }

        /**
         * 获取笔记编辑器的样式
         * @returns {Object} 样式对象
         */
        getNoteEditorStyle() {
            const noteConfig = this.config.get('noteEditor');

            return {
                width: noteConfig.width || '100%',
                minHeight: noteConfig.minHeight,
                maxHeight: noteConfig.maxHeight,
                padding: noteConfig.padding,
                marginTop: noteConfig.marginTop,
                marginBottom: noteConfig.marginBottom,
                fontSize: noteConfig.fontSize,
                border: `${noteConfig.borderWidth} ${noteConfig.borderStyle} ${noteConfig.borderColor}`,
                borderRadius: noteConfig.borderRadius,
                backgroundColor: noteConfig.backgroundColor,
                color: noteConfig.textColor,
                resize: noteConfig.resize,
                fontFamily: noteConfig.fontFamily,
                outline: 'none',
                display: 'none',
                transition: 'border-color 0.2s',
                boxSizing: 'border-box'
            };
        }

        /**
         * 获取管理按钮的样式
         * @returns {Object} 样式对象
         */
        getManageButtonStyle() {
            const position = this.config.get('manageButton.position');
            const style = this.config.get('manageButton.style');
            const colors = this.config.get('manageButton.colors');

            return {
                position: 'absolute',
                top: position.top,
                right: position.right,
                zIndex: position.zIndex,
                border: style.border,
                borderRadius: style.borderRadius,
                padding: style.padding,
                fontSize: style.fontSize,
                fontWeight: style.fontWeight,
                color: colors.textColor,
                cursor: style.cursor,
                transition: style.transition,
                background: colors.background
            };
        }
    }

    // ===================== 答案块控制器 =====================
    class AnswerBlockController {
        constructor(block, config, styleGenerator, dbManager, workKey) {
            this.block = block;
            this.config = config;
            this.styleGenerator = styleGenerator;
            this.dbManager = dbManager;
            this.workKey = workKey;
            this.parent = block.parentNode;
            this.nextSibling = block.nextSibling;
            this.originalHTML = block.outerHTML;
            this.toggleButton = null;
            this.noteButton = null;
            this.saveNoteButton = null;
            this.noteEditor = null;
            this.buttonContainer = null;
            this.currentAnswerBlock = null;  // 跟踪当前显示的答案块
            this.isHidden = false;
            this.questionId = this._extractQuestionId();
        }

        _extractQuestionId() {
            // 从父元素中查找包含 question 的 id
            let element = this.block;
            while (element && element !== document.body) {
                if (element.id && element.id.startsWith('question')) {
                    return element.id;
                }
                element = element.parentElement;
            }
            // 如果没找到,生成一个唯一标识
            return `question_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
        }

        async initialize() {
            this._hideBlockInitial();
            await this._createButtons();
            await this._createNoteEditor();
            return this.buttonContainer;
        }

        _hideBlockInitial() {
            // 初始化时删除原始答案块
            DOMHelper.removeElement(this.block);
            this.currentAnswerBlock = null;
            this.isHidden = true;
        }

        async _createButtons() {
            // 创建按钮容器
            this.buttonContainer = DOMHelper.createElement('div', {
                style: {
                    display: 'inline-block',
                    marginLeft: this.config.get('answerButton.position.marginLeft'),
                    marginTop: this.config.get('answerButton.position.marginTop'),
                    verticalAlign: this.config.get('answerButton.position.verticalAlign')
                }
            });

            // 创建答案切换按钮
            this._createAnswerToggleButton();

            // 创建笔记切换按钮
            this._createNoteToggleButton();

            // 创建保存笔记按钮
            this._createSaveNoteButton();

            // 插入按钮容器
            DOMHelper.insertElement(this.buttonContainer, this.parent, this.nextSibling);
        }

        _createAnswerToggleButton() {
            const buttonText = this.config.get('answerButton.text');
            this.toggleButton = DOMHelper.createElement('button', {
                innerText: buttonText.show,
                style: this.styleGenerator.getAnswerButtonStyle(true),
                title: '点击显示/隐藏当前答案块',
                dataset: {
                    isHidden: 'true',
                    originalHTML: this.originalHTML
                }
            });

            this.toggleButton.addEventListener('click', () => this._handleAnswerToggle());
            this.buttonContainer.appendChild(this.toggleButton);
        }

        _createNoteToggleButton() {
            const buttonText = this.config.get('noteButton.text');
            this.noteButton = DOMHelper.createElement('button', {
                innerText: buttonText.show,
                style: this.styleGenerator.getNoteButtonStyle(false),
                title: '点击显示/隐藏笔记编辑器',
                dataset: {
                    isVisible: 'false'
                }
            });

            this.noteButton.addEventListener('click', () => this._handleNoteToggle());
            this.buttonContainer.appendChild(this.noteButton);
        }

        _createSaveNoteButton() {
            const buttonText = this.config.get('saveNoteButton.text');
            this.saveNoteButton = DOMHelper.createElement('button', {
                innerText: buttonText,
                style: this.styleGenerator.getSaveNoteButtonStyle(),
                title: '手动保存当前笔记'
            });

            this.saveNoteButton.addEventListener('click', async () => {
                await this.noteEditor.save();
                Logger.success('💾 笔记已保存');
            });
            this.buttonContainer.appendChild(this.saveNoteButton);
        }

        async _createNoteEditor() {
            this.noteEditor = new NoteEditor(
                this.questionId,
                this.workKey,
                this.dbManager,
                this.config,
                this.styleGenerator
            );

            const editorElement = await this.noteEditor.create();

            // 将编辑器插入到按钮容器之后
            DOMHelper.insertElement(editorElement, this.parent, this.buttonContainer.nextSibling);
        }

        _handleAnswerToggle() {
            if (this.isHidden) {
                this._showBlock();
            } else {
                this._hideBlock();
            }
            this._updateAnswerButtonState();
        }

        _showBlock() {
            // 如果已经有显示的答案块,先删除它(防止重复)
            if (this.currentAnswerBlock && this.currentAnswerBlock.parentNode) {
                DOMHelper.removeElement(this.currentAnswerBlock);
            }

            const tempContainer = document.createElement('div');
            tempContainer.innerHTML = this.originalHTML;
            const restoredBlock = tempContainer.firstChild;

            // 保存对新创建的答案块的引用
            this.currentAnswerBlock = restoredBlock;

            // 插入到笔记编辑器之后(如果可见)或按钮容器之后
            const insertAfter = this.noteEditor.isVisible ?
                this.noteEditor.getElement().nextSibling :
                this.buttonContainer.nextSibling;
            DOMHelper.insertElement(restoredBlock, this.parent, insertAfter);
            this.isHidden = false;
        }

        _hideBlock() {
            // 删除当前显示的答案块
            if (this.currentAnswerBlock && this.currentAnswerBlock.parentNode) {
                DOMHelper.removeElement(this.currentAnswerBlock);
                this.currentAnswerBlock = null;
            }
            this.isHidden = true;
        }

        _updateAnswerButtonState() {
            const buttonText = this.config.get('answerButton.text');
            const colors = this.config.get('answerButton.colors');

            this.toggleButton.innerText = this.isHidden ? buttonText.show : buttonText.hide;
            this.toggleButton.style.background = this.isHidden ? colors.showBackground : colors.hideBackground;
            this.toggleButton.dataset.isHidden = String(this.isHidden);
        }

        _handleNoteToggle() {
            this.noteEditor.toggle();
            this._updateNoteButtonState();
        }

        _updateNoteButtonState() {
            const buttonText = this.config.get('noteButton.text');
            const colors = this.config.get('noteButton.colors');

            this.noteButton.innerText = this.noteEditor.isVisible ? buttonText.hide : buttonText.show;
            this.noteButton.style.background = this.noteEditor.isVisible ? colors.hideBackground : colors.showBackground;
            this.noteButton.dataset.isVisible = String(this.noteEditor.isVisible);
        }

        toggle() {
            this._handleAnswerToggle();
        }

        getState() {
            return this.isHidden;
        }
    }

    // ===================== 全局控制器 =====================
    class GlobalController {
        constructor(container, controllers, config, styleGenerator, dbManager, workKey) {
            this.container = container;
            this.controllers = controllers;
            this.config = config;
            this.styleGenerator = styleGenerator;
            this.dbManager = dbManager;
            this.workKey = workKey;
            this.globalButton = null;
            this.manageButton = null;
        }

        initialize() {
            if (!this.container) return null;

            DOMHelper.ensureRelativePosition(this.container);
            this._createGlobalButton();
            this._createManageButton();
            return this.globalButton;
        }

        _createGlobalButton() {
            const buttonText = this.config.get('globalButton.text');
            this.globalButton = DOMHelper.createElement('button', {
                innerText: buttonText.showAll,
                style: this.styleGenerator.getGlobalButtonStyle(true),
                title: '点击一键显示/隐藏所有答案块'
            });

            this.globalButton.addEventListener('click', () => this._handleGlobalToggle());
            this.container.appendChild(this.globalButton);
        }

        _createManageButton() {
            const buttonText = this.config.get('manageButton.text');
            this.manageButton = DOMHelper.createElement('button', {
                innerText: buttonText,
                style: this.styleGenerator.getManageButtonStyle(),
                title: '打开控制面板:设置和笔记管理'
            });

            this.manageButton.addEventListener('click', () => this._handleManageClick());
            this.container.appendChild(this.manageButton);
        }

        _handleManageClick() {
            const controlPanel = new ControlPanelUI(this.dbManager, this.workKey, this.config);
            controlPanel.show();
        }

        _handleGlobalToggle() {
            const allHidden = this.controllers.every(ctrl => ctrl.getState());

            this.controllers.forEach(controller => {
                const shouldToggle = allHidden ? controller.getState() : !controller.getState();
                if (shouldToggle) {
                    controller.toggle();
                }
            });

            this._updateGlobalButtonState(!allHidden);
        }

        _updateGlobalButtonState(allHidden) {
            const buttonText = this.config.get('globalButton.text');
            const colors = this.config.get('globalButton.colors');

            this.globalButton.innerText = allHidden ? buttonText.showAll : buttonText.hideAll;
            this.globalButton.style.background = allHidden ? colors.showAllBackground : colors.hideAllBackground;
        }
    }

    // ===================== 主应用类 =====================
    class ChaoxingAnswerHider {
        constructor(customConfig = {}) {
            this.config = new Config(customConfig);
            this.styleGenerator = new StyleGenerator(this.config);
            this.dbManager = new DatabaseManager(this.config);
            this.answerControllers = [];
            this.globalController = null;
            this.workKey = URLParser.getWorkKey();
        }

        async initialize() {
            try {
                // 初始化数据库
                await this.dbManager.init();
                Logger.success('数据库初始化成功');

                // 加载自定义样式配置
                await this._loadCustomStyles();

                await this._waitForPageLoad();
                const elements = this._findElements();

                if (!this._validateElements(elements)) {
                    return;
                }

                await this._initializeAnswerBlocks(elements.answerBlocks);
                this._initializeGlobalControl(elements.container);
                this._logSuccess(elements.answerBlocks.length, !!elements.container);
            } catch (error) {
                Logger.error('初始化失败', error);
            }
        }

        async _loadCustomStyles() {
            try {
                const customStyles = await this.dbManager.getSetting('customStyles', {});
                if (customStyles && Object.keys(customStyles).length > 0) {
                    // 将自定义样式合并到配置中
                    this.config = new Config(this.config._deepMerge(this.config.config, customStyles));
                    this.styleGenerator = new StyleGenerator(this.config);
                    Logger.log('✨ 已加载自定义样式配置');
                }
            } catch (error) {
                Logger.error('加载自定义样式失败', error);
            }
        }

        _waitForPageLoad() {
            const delay = this.config.get('delays.initialization');
            return new Promise(resolve => setTimeout(resolve, delay));
        }

        _findElements() {
            return {
                container: document.querySelector(this.config.get('selectors.container')),
                answerBlocks: document.querySelectorAll(this.config.get('selectors.answerBlock'))
            };
        }

        _validateElements({ container, answerBlocks }) {
            if (answerBlocks.length === 0) {
                Logger.log(this.config.get('messages.noAnswerBlocks'));
                return false;
            }

            if (!container) {
                Logger.log(this.config.get('messages.noContainer'), 'warn');
            }

            return true;
        }

        async _initializeAnswerBlocks(blocks) {
            for (const block of blocks) {
                const controller = new AnswerBlockController(
                    block,
                    this.config,
                    this.styleGenerator,
                    this.dbManager,
                    this.workKey
                );
                await controller.initialize();
                this.answerControllers.push(controller);
            }
        }

        _initializeGlobalControl(container) {
            this.globalController = new GlobalController(
                container,
                this.answerControllers,
                this.config,
                this.styleGenerator,
                this.dbManager,
                this.workKey
            );
            this.globalController.initialize();
        }

        _logSuccess(count, hasContainer) {
            Logger.success(this.config.get('messages.success'));
            Logger.log(this.config.get('messages.hiddenCount')(count));
            Logger.log(this.config.get('messages.globalButton')(hasContainer));
            Logger.log(`📝 笔记功能已启用,数据存储标识: ${this.workKey}`);
        }
    }

    // ===================== 启动应用 =====================
    const app = new ChaoxingAnswerHider();
    app.initialize();
})();