Greasy Fork

Greasy Fork is available in English.

Coomer 佬友严选

OnlyFans 赛博菩萨,佬友严选,值得信赖!艺术家收藏、作品管理、视频播放

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Coomer 佬友严选
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  OnlyFans 赛博菩萨,佬友严选,值得信赖!艺术家收藏、作品管理、视频播放
// @author       urzeye
// @match        https://coomer.st/*
// @icon         https://thumbs.onlyfans.com/public/files/thumbs/c50/m/mk/mka/mkamcrf6rjmcwo0jj4zoavhmalzohe5a1640180203/avatar.jpg
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @grant        GM_setClipboard
// @grant        GM_getResourceText
// @grant        window.onurlchange
// @resource     videojs_css https://cdnjs.cloudflare.com/ajax/libs/video.js/8.16.1/video-js.min.css
// @require      https://cdnjs.cloudflare.com/ajax/libs/video.js/8.16.1/video.min.js
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // ============================================
    // 常量与配置
    // ============================================
    const STORAGE_KEYS = {
        ARTISTS: 'coomer_artists',
        POSTS: 'coomer_posts',
        SETTINGS: 'coomer_settings',
    };

    const DEFAULT_SETTINGS = {
        autoFullscreen: true,
        blockAds: true,
        panelPosition: 'bottom-right',
        fabPosition: { right: 20, bottom: 80 },
        presetCollapsed: false, // 预置分组是否折叠
        myCollectionCollapsed: false, // 我的收藏分组是否折叠
    };

    // 预置艺术家列表(佬友严选)
    const PRESET_ARTISTS = [
        {
            id: 'thedirectortong',
            nickname: 'thedirectortong',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/thedirectortong',
            avatar: 'https://img.coomer.st/icons/onlyfans/thedirectortong',
        },
        {
            id: '347914002094895104',
            nickname: 'Thelittlejuicer',
            platform: 'Fansly',
            homepageUrl: 'https://coomer.st/fansly/user/347914002094895104',
            avatar: 'https://img.coomer.st/icons/fansly/347914002094895104',
        },
        {
            id: 'thelittlejuicer',
            nickname: 'thelittlejuicer',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/thelittlejuicer',
            avatar: 'https://img.coomer.st/icons/onlyfans/thelittlejuicer',
        },
        {
            id: 'applecptv',
            nickname: 'applecptv',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/applecptv',
            avatar: 'https://img.coomer.st/icons/onlyfans/applecptv',
        },
        {
            id: 'kimchi.couple',
            nickname: 'kimchi.couple',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/kimchi.couple',
            avatar: 'https://img.coomer.st/icons/onlyfans/kimchi.couple',
        },
        {
            id: '531599132742135808',
            nickname: 'candy_factory',
            platform: 'Fansly',
            homepageUrl: 'https://coomer.st/fansly/user/531599132742135808',
            avatar: 'https://img.coomer.st/icons/fansly/531599132742135808',
        },
        {
            id: 'chocoletmilkk',
            nickname: 'chocoletmilkk',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/chocoletmilkk',
            avatar: 'https://img.coomer.st/icons/onlyfans/chocoletmilkk',
        },
        {
            id: '504758618625683456',
            nickname: 'demifairytw',
            platform: 'Fansly',
            homepageUrl: 'https://coomer.st/fansly/user/504758618625683456',
            avatar: 'https://img.coomer.st/icons/fansly/504758618625683456',
        },
        {
            id: 'skylar_blue',
            nickname: 'skylar_blue',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/skylar_blue',
            avatar: 'https://img.coomer.st/icons/onlyfans/skylar_blue',
        },
        {
            id: 'yui_xin_tw',
            nickname: 'yui_xin_tw',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/yui_xin_tw',
            avatar: 'https://img.coomer.st/icons/onlyfans/yui_xin_tw',
        },
        {
            id: 'yuyuhwa',
            nickname: 'yuyuhwa',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/yuyuhwa',
            avatar: 'https://img.coomer.st/icons/onlyfans/yuyuhwa',
        },
        {
            id: 'xxapple',
            nickname: 'xxapple',
            platform: 'OnlyFans',
            homepageUrl: 'https://coomer.st/onlyfans/user/xxapple',
            avatar: 'https://img.coomer.st/icons/onlyfans/xxapple',
        },
    ];

    const DOM_SELECTORS = {
        // 艺术家页面
        artistAvatar: '.user-header__avatar img',
        artistName: '.user-header__profile span:nth-child(2)',
        artistPlatform: '.user-header__profile span:nth-child(3)',
        // 作品页面
        postTitle: '.post__content',
        postAttachment: 'a.post__attachment-link',
        postThumbnail: '.post__thumbnail img',
        // 视频播放器
        videoWrapper: '.fluid_video_wrapper',
        videoElement: 'video',
    };

    // URL 匹配规则
    const URL_PATTERNS = {
        // userId 匹配任何非斜杠字符
        artistPage: /^\/(\w+)\/user\/([^/]+)\/?$/,
        postPage: /^\/(\w+)\/user\/([^/]+)\/post\/([^/]+)\/?$/,
    };

    // ============================================
    // StorageManager - 数据持久化
    // ============================================
    const StorageManager = {
        get(key, defaultValue = null) {
            try {
                const data = GM_getValue(key);
                return data !== undefined ? JSON.parse(data) : defaultValue;
            } catch {
                return defaultValue;
            }
        },

        set(key, value) {
            GM_setValue(key, JSON.stringify(value));
        },

        getArtists() {
            return this.get(STORAGE_KEYS.ARTISTS, {});
        },

        setArtists(artists) {
            this.set(STORAGE_KEYS.ARTISTS, artists);
        },

        getPosts() {
            return this.get(STORAGE_KEYS.POSTS, {});
        },

        setPosts(posts) {
            this.set(STORAGE_KEYS.POSTS, posts);
        },

        getSettings() {
            return { ...DEFAULT_SETTINGS, ...this.get(STORAGE_KEYS.SETTINGS, {}) };
        },

        setSettings(settings) {
            this.set(STORAGE_KEYS.SETTINGS, settings);
        },
    };

    // ============================================
    // PageParser - 页面数据解析
    // ============================================
    const PageParser = {
        getCurrentPageType() {
            const path = window.location.pathname;
            if (URL_PATTERNS.postPage.test(path)) return 'post';
            if (URL_PATTERNS.artistPage.test(path)) return 'artist';
            return 'other';
        },

        parseUrlInfo() {
            const path = window.location.pathname;
            let match;

            if ((match = URL_PATTERNS.postPage.exec(path))) {
                return { platform: match[1], userId: match[2], postId: match[3] };
            }
            if ((match = URL_PATTERNS.artistPage.exec(path))) {
                return { platform: match[1], userId: match[2] };
            }
            return null;
        },

        parseArtistInfo() {
            const urlInfo = this.parseUrlInfo();
            if (!urlInfo) return null;

            const pageType = this.getCurrentPageType();
            let avatar = '';
            let nickname = '';
            let platform = urlInfo.platform;

            if (pageType === 'post') {
                // 作品页面的选择器
                // 昵称: <a class="post__user-name">Thelittlejuicer</a>
                nickname = document.querySelector('a.post__user-name')?.textContent?.trim() || '';
                // 头像: <a class="post__user-profile"><picture><img src="//img.coomer.st/icons/..."></picture></a>
                const avatarImg = document.querySelector('a.post__user-profile img');
                if (avatarImg?.src) {
                    avatar = avatarImg.src.startsWith('//') ? 'https:' + avatarImg.src : avatarImg.src;
                }
            } else if (pageType === 'artist') {
                // 艺术家主页的选择器
                // 昵称: <span itemprop="name">thelittlejuicer</span>
                nickname =
                    document.querySelector('.user-header__profile span[itemprop="name"]')?.textContent?.trim() ||
                    document.querySelector('.user-header__profile span:nth-child(2)')?.textContent?.trim() ||
                    '';
                // 头像: <picture class="fancy-image__picture"><img src="//img.coomer.st/icons/..."></picture>
                const avatarImg = document.querySelector('.user-header__avatar img') || document.querySelector('.user-header picture img');
                if (avatarImg?.src) {
                    avatar = avatarImg.src.startsWith('//') ? 'https:' + avatarImg.src : avatarImg.src;
                }
                // 平台
                const platformEl = document.querySelector('.user-header__profile span:nth-child(1) img');
                if (platformEl?.src) {
                    // 从图片路径提取平台名 /static/onlyfans.svg -> onlyfans
                    const match = platformEl.src.match(/\/static\/(\w+)\.svg/);
                    if (match) platform = match[1];
                }
            }

            // 备用:如果没有获取到头像,根据 URL 构造一个
            if (!avatar && urlInfo.userId) {
                avatar = `https://img.coomer.st/icons/${urlInfo.platform}/${urlInfo.userId}`;
            }

            // 备用:如果没有获取到昵称,使用 userId
            if (!nickname) {
                nickname = urlInfo.userId;
            }

            // 构造正确的艺术家主页 URL
            const artistHomepageUrl = `https://coomer.st/${urlInfo.platform}/user/${urlInfo.userId}`;

            return {
                id: urlInfo.userId,
                nickname,
                avatar,
                platform: this.normalizePlatform(platform),
                homepageUrl: artistHomepageUrl,
                isPreset: false,
                addedAt: Date.now(),
            };
        },

        parsePostInfo() {
            const urlInfo = this.parseUrlInfo();
            if (!urlInfo || !urlInfo.postId) return null;

            const artistInfo = this.parseArtistInfo();
            const title = document.querySelector(DOM_SELECTORS.postTitle)?.textContent?.trim() || '';

            // 获取所有媒体下载链接
            const attachments = document.querySelectorAll(DOM_SELECTORS.postAttachment);
            let mediaUrls = Array.from(attachments)
                .map((a) => a.href)
                .filter(Boolean);

            // 如果没有找到附件链接,尝试从图片链接获取
            if (mediaUrls.length === 0) {
                // 获取 .fileThumb 大图链接
                const imageLinks = document.querySelectorAll('.post__files .fileThumb');
                mediaUrls = Array.from(imageLinks)
                    .map((a) => a.href)
                    .filter(Boolean);
            }

            // 获取缩略图:优先使用作品图片,如果没有则使用艺术家头像作为封面
            let thumb = document.querySelector(DOM_SELECTORS.postThumbnail)?.src || document.querySelector('.post__image img')?.src || document.querySelector('.fileThumb img')?.src || '';
            if (!thumb && artistInfo?.avatar) {
                thumb = artistInfo.avatar;
            }

            // 判断类型
            const hasVideo = mediaUrls.some((url) => /\.(mp4|webm|mov|m4v)/i.test(url));

            return {
                id: urlInfo.postId,
                title: title || `Post ${urlInfo.postId}`,
                artistId: urlInfo.userId,
                artistName: artistInfo?.nickname || '',
                platform: urlInfo.platform,
                thumb,
                mediaUrls,
                type: hasVideo ? 'video' : 'image',
                pageUrl: window.location.href.split('?')[0],
                addedAt: Date.now(),
            };
        },

        normalizePlatform(platform) {
            const map = {
                onlyfans: 'OnlyFans',
                fansly: 'Fansly',
                candfans: 'CandFans',
            };
            return map[platform.toLowerCase()] || platform;
        },
    };

    // ============================================
    // ArtistManager - 艺术家管理
    // ============================================
    const ArtistManager = {
        getAll() {
            return StorageManager.getArtists();
        },

        get(id) {
            return this.getAll()[id] || null;
        },

        add(artist) {
            const artists = this.getAll();
            artists[artist.id] = artist;
            StorageManager.setArtists(artists);
            return artist;
        },

        remove(id) {
            const artists = this.getAll();
            delete artists[id];
            StorageManager.setArtists(artists);
        },

        exists(id) {
            return !!this.getAll()[id];
        },

        count() {
            return Object.keys(this.getAll()).length;
        },

        // 切换置顶状态
        togglePin(id) {
            const artists = this.getAll();
            if (artists[id]) {
                artists[id].isPinned = !artists[id].isPinned;
                StorageManager.setArtists(artists);
                return artists[id].isPinned;
            }
            return false;
        },

        // 获取排序后的列表(置顶优先,然后按时间倒序)
        getSortedList() {
            return Object.values(this.getAll()).sort((a, b) => {
                // 置顶的排在前面
                if (a.isPinned && !b.isPinned) return -1;
                if (!a.isPinned && b.isPinned) return 1;
                // 同级别按时间倒序(最新的在前)
                return (b.addedAt || 0) - (a.addedAt || 0);
            });
        },

        // 收藏当前页面的艺术家
        collectCurrent() {
            const info = PageParser.parseArtistInfo();
            if (!info) return null;
            return this.add(info);
        },
    };

    // ============================================
    // PostManager - 作品管理
    // ============================================
    const PostManager = {
        getAll() {
            return StorageManager.getPosts();
        },

        get(id) {
            return this.getAll()[id] || null;
        },

        add(post) {
            const posts = this.getAll();
            posts[post.id] = post;
            StorageManager.setPosts(posts);
            return post;
        },

        remove(id) {
            const posts = this.getAll();
            delete posts[id];
            StorageManager.setPosts(posts);
        },

        exists(id) {
            return !!this.getAll()[id];
        },

        count() {
            return Object.keys(this.getAll()).length;
        },

        // 切换置顶状态
        togglePin(id) {
            const posts = this.getAll();
            if (posts[id]) {
                posts[id].isPinned = !posts[id].isPinned;
                StorageManager.setPosts(posts);
                return posts[id].isPinned;
            }
            return false;
        },

        // 获取排序后的列表(置顶优先,然后按时间倒序)
        getSortedList() {
            return Object.values(this.getAll()).sort((a, b) => {
                // 置顶的排在前面
                if (a.isPinned && !b.isPinned) return -1;
                if (!a.isPinned && b.isPinned) return 1;
                // 同级别按时间倒序(最新的在前)
                return (b.addedAt || 0) - (a.addedAt || 0);
            });
        },

        // 收藏当前页面的作品
        collectCurrent() {
            const info = PageParser.parsePostInfo();
            if (!info) return null;
            return this.add(info);
        },

        // 获取按艺术家分组的作品
        getByArtist(artistId) {
            const posts = this.getAll();
            return Object.values(posts).filter((p) => p.artistId === artistId);
        },
    };

    // ============================================
    // AdBlocker - 广告拦截
    // ============================================
    const AdBlocker = {
        init() {
            const settings = StorageManager.getSettings();
            if (!settings.blockAds) return;

            // Hook fluidPlayer 初始化,移除广告配置
            this.hookFluidPlayer();
        },

        hookFluidPlayer() {
            // 在 document-start 时执行,确保在 Fluid Player 加载前 hook
            const script = document.createElement('script');
            script.textContent = `
                (function() {
                    const originalDefineProperty = Object.defineProperty;
                    Object.defineProperty = function(obj, prop, descriptor) {
                        if (prop === 'fluidPlayer' && obj === window) {
                            const originalGetter = descriptor.get;
                            const originalValue = descriptor.value;
                            
                            const wrapper = function(...args) {
                                // 移除广告配置
                                if (args[1] && args[1].vastOptions) {
                                    delete args[1].vastOptions;
                                }
                                if (args[1] && args[1].adList) {
                                    args[1].adList = [];
                                }
                                const fn = originalGetter ? originalGetter() : originalValue;
                                return fn.apply(this, args);
                            };
                            
                            if (originalGetter) {
                                descriptor.get = () => wrapper;
                            } else {
                                descriptor.value = wrapper;
                            }
                        }
                        return originalDefineProperty.call(this, obj, prop, descriptor);
                    };
                })();
            `;
            document.documentElement.appendChild(script);
            script.remove();
        },
    };

    // ============================================
    // AutoFullscreen - 自动全屏
    // ============================================
    const AutoFullscreen = {
        init() {
            const settings = StorageManager.getSettings();
            if (!settings.autoFullscreen) return;

            // 等待 DOM 加载完成后监听视频
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', () => this.setup());
            } else {
                this.setup();
            }
        },

        setup() {
            // 使用 MutationObserver 检测视频元素
            const observer = new MutationObserver(() => {
                const video = document.querySelector('video');
                if (video && !video._autoFullscreenBound) {
                    video._autoFullscreenBound = true;
                    this.bindVideo(video);
                }
            });

            observer.observe(document.body, { childList: true, subtree: true });

            // 也检查已存在的视频
            const video = document.querySelector('video');
            if (video) this.bindVideo(video);
        },

        bindVideo(video) {
            video.addEventListener(
                'play',
                () => {
                    // 延迟执行,避免与广告冲突
                    setTimeout(() => {
                        if (!document.fullscreenElement && !video.paused) {
                            this.requestFullscreen(video);
                        }
                    }, 500);
                },
                { once: true },
            );
        },

        requestFullscreen(element) {
            if (element.requestFullscreen) {
                element.requestFullscreen().catch(() => {});
            } else if (element.webkitEnterFullscreen) {
                // iOS Safari
                element.webkitEnterFullscreen();
            } else if (element.webkitRequestFullscreen) {
                element.webkitRequestFullscreen();
            }
        },
    };

    // ============================================
    // UIPanel - 用户界面面板
    // ============================================
    const UIPanel = {
        container: null,
        panel: null,
        isOpen: false,
        activeTab: 'artists',

        // SPA 无刷新跳转
        navigateTo(url) {
            this.close(); // 先关闭面板

            // 策略:优先查找页面上已存在的精确链接进行点击(触发 SPA 路由)
            // 如果找不到,则回退到 window.location.href(硬跳转)
            // 移除不稳定的“链接劫持”逻辑,避免误跳到首页

            const targetPath = url.replace(window.location.origin, '');

            // 1. 优先找页面上已有的完全匹配的目标链接(且不是 _blank)
            const exactLink = document.querySelector(`a[href="${targetPath}"]:not([target="_blank"]), a[href="${url}"]:not([target="_blank"])`);
            if (exactLink) {
                exactLink.click();
                return;
            }

            // 2. 实在没办法,通过 location 跳转(会刷新,但最稳妥)
            window.location.href = url;
        },

        init() {
            this.injectStyles();
            this.createFloatingButton();
            this.createPanel();
            this.createQuickActions();
        },

        injectStyles() {
            // 注入 video.js CSS
            try {
                const videojsCss = GM_getResourceText('videojs_css');
                if (videojsCss) GM_addStyle(videojsCss);
            } catch (e) {
                console.warn('Failed to load video.js CSS:', e);
            }

            GM_addStyle(`
                :root {
                    --coomer-bg: #121212;
                    --coomer-surface: rgba(26, 26, 29, 0.95);
                    --coomer-card: #1E1E22;
                    --coomer-border: #333333;
                    --coomer-primary: #E0AA3E;
                    --coomer-primary-hover: #F2C94C;
                    --coomer-text: #E0E0E0;
                    --coomer-text-sec: #A0A0A0;
                    --coomer-danger: #ef4444;
                    --coomer-success: #10b981;
                    --coomer-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
                }

                /* 隐藏公告横幅 */
                #announcement-banner {
                    display: none !important;
                }

                /* 屏蔽广告元素 */
                .global-sidebar-entry-item[href*="tsyndicate.com"],
                #ts_ad_native_wxfxp,
                .ts-im-container {
                    display: none !important;
                }

                /* 悬浮按钮 - The Orb */
                .coomer-fab {
                    position: fixed;
                    width: 50px;
                    height: 50px;
                    border-radius: 50%;
                    background: #121212;
                    color: var(--coomer-primary);
                    border: 1px solid var(--coomer-primary);
                    cursor: pointer;
                    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
                    z-index: 99999;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    font-size: 20px;
                    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                    user-select: none;
                    touch-action: none;
                }
                .coomer-fab:hover {
                    width: 54px;
                    height: 54px;
                    background: var(--coomer-primary);
                    color: #121212;
                    box-shadow: 0 0 20px rgba(224, 170, 62, 0.4);
                }
                .coomer-fab.dragging {
                    cursor: grabbing;
                    transform: scale(0.95);
                    transition: none;
                }

                /* 面板容器 */
                .coomer-panel-overlay {
                    position: fixed;
                    top: 0;
                    bg-color: rgba(0, 0, 0, 0.6);
                    backdrop-filter: blur(4px);
                    z-index: 99998;
                    opacity: 0;
                    visibility: hidden;
                    transition: all 0.3s ease;
                }
                .coomer-panel-overlay.open {
                    opacity: 1;
                    visibility: visible;
                }

                /* 抽屉式面板 */
                .coomer-panel {
                    position: fixed;
                    bottom: 0;
                    left: 0;
                    right: 0;
                    max-height: 75vh;
                    background: var(--coomer-surface);
                    backdrop-filter: blur(12px);
                    border-radius: 20px 20px 0 0;
                    z-index: 99999;
                    transform: translateY(100%);
                    transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
                    display: flex;
                    flex-direction: column;
                    font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, sans-serif;
                    color: var(--coomer-text);
                    box-shadow: var(--coomer-shadow);
                    border: 1px solid rgba(255, 255, 255, 0.05);
                    border-bottom: none;
                }
                .coomer-panel.open {
                    transform: translateY(0);
                }

                /* PC 端样式 */
                @media (min-width: 768px) {
                    .coomer-panel {
                        left: auto;
                        right: 24px;
                        bottom: 96px;
                        width: 420px;
                        max-height: 600px;
                        border-radius: 16px;
                        border-bottom: 1px solid rgba(255, 255, 255, 0.05);
                    }
                }

                /* 面板头部 */
                .coomer-panel-header {
                    padding: 16px 20px;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    background: rgba(18, 18, 18, 0.8);
                    border-bottom: 1px solid var(--coomer-primary);
                    border-radius: 20px 20px 0 0;
                }
                @media (min-width: 768px) {
                    .coomer-panel-header {
                        border-radius: 16px 16px 0 0;
                    }
                }
                .coomer-panel-title {
                    font-size: 16px;
                    font-weight: 700;
                    color: var(--coomer-primary);
                    letter-spacing: 0.5px;
                    text-transform: uppercase;
                }
                .coomer-panel-header-actions {
                    display: flex;
                    align-items: center;
                    gap: 4px;
                }
                .coomer-panel-settings {
                    background: transparent;
                    border: none;
                    color: var(--coomer-text-sec);
                    font-size: 16px;
                    cursor: pointer;
                    padding: 8px;
                    line-height: 1;
                    border-radius: 8px;
                    transition: all 0.2s;
                }
                .coomer-panel-settings:hover {
                    color: var(--coomer-primary);
                    background: rgba(255, 255, 255, 0.05);
                }
                .coomer-panel-close {
                    background: transparent;
                    border: none;
                    color: var(--coomer-text-sec);
                    font-size: 20px;
                    cursor: pointer;
                    padding: 8px;
                    line-height: 1;
                    border-radius: 8px;
                    transition: all 0.2s;
                    z-index: 10;
                }
                .coomer-panel-close:hover {
                    color: var(--coomer-primary);
                    background: rgba(255, 255, 255, 0.05);
                }

                /* 标签栏 */
                .coomer-tabs {
                    display: flex;
                    background: #121212;
                    padding: 4px;
                    margin: 0;
                }
                .coomer-tab {
                    flex: 1;
                    padding: 10px;
                    background: transparent;
                    border: none;
                    color: var(--coomer-text-sec);
                    cursor: pointer;
                    font-size: 13px;
                    font-weight: 500;
                    transition: all 0.3s ease;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 6px;
                    position: relative;
                }
                .coomer-tab::after {
                    content: '';
                    position: absolute;
                    bottom: 0;
                    left: 50%;
                    width: 0;
                    height: 2px;
                    background: var(--coomer-primary);
                    transition: all 0.3s ease;
                    transform: translateX(-50%);
                }
                .coomer-tab:hover {
                    color: var(--coomer-text);
                }
                .coomer-tab.active {
                    color: var(--coomer-primary);
                }
                .coomer-tab.active::after {
                    width: 40%;
                }

                /* 面板内容 */
                .coomer-panel-content {
                    flex: 1;
                    overflow-y: auto;
                    padding: 16px;
                }
                /* 自定义滚动条 */
                .coomer-panel-content::-webkit-scrollbar {
                    width: 6px;
                    height: 6px;
                }
                .coomer-panel-content::-webkit-scrollbar-track {
                    background: transparent;
                }
                .coomer-panel-content::-webkit-scrollbar-thumb {
                    background: rgba(255, 255, 255, 0.15);
                    border-radius: 3px;
                    transition: background 0.2s;
                }
                .coomer-panel-content::-webkit-scrollbar-thumb:hover {
                    background: var(--coomer-primary);
                }

                /* 空状态 */
                .coomer-empty {
                    text-align: center;
                    padding: 40px 20px;
                    color: #666;
                }
                .coomer-empty-icon {
                    font-size: 48px;
                    margin-bottom: 12px;
                }

                /* 分组组件 */
                .coomer-group {
                    margin-bottom: 16px;
                    background: rgba(255, 255, 255, 0.02);
                    border-radius: 12px;
                    padding: 0 12px;
                }
                .coomer-group-header {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    padding: 12px 0;
                    cursor: pointer;
                    user-select: none;
                    position: sticky;
                    top: 0;
                    background: var(--coomer-surface);
                    z-index: 10;
                    margin: 0 -12px;
                    padding-left: 12px;
                    padding-right: 12px;
                    border-radius: 8px 8px 0 0;
                }
                .coomer-group-title {
                    font-size: 13px;
                    font-weight: 600;
                    color: var(--coomer-text-sec);
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    text-transform: uppercase;
                }
                .coomer-group-count {
                    font-size: 12px;
                    color: var(--coomer-text-sec);
                    opacity: 0.7;
                    font-weight: normal;
                }
                .coomer-group-toggle {
                    font-size: 12px;
                    color: var(--coomer-text-sec);
                    transition: transform 0.2s;
                }
                .coomer-group-toggle.collapsed {
                    transform: rotate(-90deg);
                }
                .coomer-group-content {
                    overflow: hidden;
                    transition: max-height 0.3s ease;
                }
                .coomer-group-content.collapsed {
                    max-height: 0 !important;
                }
                .coomer-badge {
                    display: inline-block;
                    padding: 2px 6px;
                    font-size: 10px;
                    border-radius: 4px;
                    background: var(--coomer-primary);
                    color: #000;
                    font-weight: 700;
                }
                .coomer-card .coomer-badge {
                    position: absolute;
                    top: 28px;
                    left: 4px;
                    z-index: 4;
                }

                /* 艺术家/作品卡片网格 */
                .coomer-grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
                    gap: 16px;
                    padding-bottom: 12px;
                }
                .coomer-card {
                    position: relative;
                    background: var(--coomer-card);
                    border: 1px solid rgba(255, 255, 255, 0.05);
                    border-radius: 12px;
                    overflow: hidden;
                    cursor: pointer;
                    transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                }
                .coomer-card:hover {
                    transform: translateY(-4px);
                    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
                    border-color: rgba(224, 170, 62, 0.3);
                }
                .coomer-card-img {
                    width: 100%;
                    aspect-ratio: 1;
                    object-fit: cover;
                    background: #121212;
                    filter: brightness(0.9);
                    transition: filter 0.3s;
                }
                .coomer-card:hover .coomer-card-img {
                    filter: brightness(1.1);
                }
                .coomer-card-info {
                    padding: 10px;
                }
                .coomer-card-name {
                    font-size: 12px;
                    font-weight: 600;
                    color: var(--coomer-text);
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                }
                .coomer-card-meta {
                    font-size: 10px;
                    color: var(--coomer-text-sec);
                    margin-top: 4px;
                    display: flex;
                    align-items: center;
                    gap: 4px;
                }
                .coomer-card-count {
                    position: absolute;
                    bottom: 48px;
                    right: 6px;
                    padding: 2px 6px;
                    font-size: 10px;
                    font-weight: 600;
                    border-radius: 4px;
                    background: rgba(0, 0, 0, 0.85);
                    color: var(--coomer-primary);
                    border: 1px solid rgba(224, 170, 62, 0.3);
                    z-index: 3;
                }
                .coomer-card-delete {
                    position: absolute;
                    top: 6px;
                    right: 6px;
                    width: 26px;
                    height: 26px;
                    border-radius: 50%;
                    background: rgba(20, 20, 20, 0.9);
                    color: var(--coomer-text);
                    border: 1px solid #333;
                    cursor: pointer;
                    font-size: 14px;
                    line-height: 1;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    opacity: 0;
                    transition: all 0.2s;
                    z-index: 5;
                }
                .coomer-card:hover .coomer-card-delete {
                    opacity: 1;
                }
                .coomer-card-delete:hover {
                    background: var(--coomer-danger);
                    border-color: var(--coomer-danger);
                    color: white;
                    transform: scale(1.1);
                }
                .coomer-card-pin {
                    position: absolute;
                    top: 6px;
                    left: 6px;
                    width: 26px;
                    height: 26px;
                    border-radius: 50%;
                    background: rgba(20, 20, 20, 0.9);
                    color: var(--coomer-text-sec);
                    border: 1px solid #333;
                    cursor: pointer;
                    font-size: 12px;
                    line-height: 1;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    opacity: 0;
                    transition: all 0.2s;
                    z-index: 5;
                }
                .coomer-card:hover .coomer-card-pin {
                    opacity: 1;
                }
                .coomer-card-pin.pinned {
                    opacity: 1;
                    border-color: var(--coomer-primary);
                    color: var(--coomer-primary);
                }
                .coomer-card-pin:hover {
                    color: var(--coomer-primary);
                    border-color: var(--coomer-primary);
                    transform: scale(1.1);
                }
                .coomer-card.pinned {
                    border: 1px solid var(--coomer-primary);
                    box-shadow: 0 0 10px rgba(224, 170, 62, 0.1);
                }

                /* 设置项 */
                .coomer-setting-item {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    padding: 12px 0;
                    border-bottom: 1px solid #2d2d44;
                }
                /* 视频播放列表 */
                .coomer-video-list {
                    display: flex;
                    flex-direction: column;
                    gap: 12px;
                    margin-bottom: 20px;
                }
                .coomer-video-item {
                    display: flex;
                    align-items: center;
                    gap: 16px;
                    padding: 16px;
                    background: var(--coomer-card);
                    border: 1px solid rgba(255, 255, 255, 0.05);
                    border-radius: 12px;
                    cursor: pointer;
                    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
                }
                .coomer-video-item:hover {
                    background: rgba(255, 255, 255, 0.05);
                    border-color: var(--coomer-primary);
                    transform: translateX(4px);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
                }
                .coomer-video-icon {
                    width: 32px;
                    height: 32px;
                    border-radius: 50%;
                    background: rgba(255, 255, 255, 0.1);
                    color: var(--coomer-primary);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    font-size: 14px;
                    flex-shrink: 0;
                    transition: all 0.2s;
                }
                .coomer-video-item:hover .coomer-video-icon {
                    background: var(--coomer-primary);
                    color: #000;
                    transform: scale(1.1);
                }
                .coomer-video-name {
                    font-size: 14px;
                    color: #e0e0e0;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    flex: 1;
                    font-weight: 500;
                }

                /* 视频播放器遮罩层 */
                .coomer-video-player-overlay {
                    position: fixed;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    background: rgba(0, 0, 0, 0.95);
                    backdrop-filter: blur(8px);
                    z-index: 100000;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                .coomer-video-player-wrapper {
                    position: relative;
                    width: 90%;
                    max-width: 1000px;
                    box-shadow: 0 20px 60px rgba(0,0,0,0.5);
                }
                .coomer-video-close {
                    position: absolute;
                    top: -50px;
                    right: 0;
                    width: 40px;
                    height: 40px;
                    border-radius: 50%;
                    background: rgba(255, 255, 255, 0.1);
                    color: white;
                    border: none;
                    cursor: pointer;
                    font-size: 24px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    transition: all 0.2s;
                }
                .coomer-video-close:hover {
                    background: var(--coomer-primary);
                    color: #000;
                    transform: rotate(90deg);
                }

                .coomer-setting-label {
                    font-size: 14px;
                    color: var(--coomer-text);
                }
                .coomer-toggle {
                    position: relative;
                    width: 44px;
                    height: 24px;
                    background: rgba(255, 255, 255, 0.1);
                    border-radius: 12px;
                    cursor: pointer;
                    transition: background 0.3s;
                }
                .coomer-toggle.active {
                    background: var(--coomer-primary);
                }
                .coomer-toggle::after {
                    content: '';
                    position: absolute;
                    top: 2px;
                    left: 2px;
                    width: 20px;
                    height: 20px;
                    background: white;
                    border-radius: 50%;
                    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
                    transition: transform 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
                }
                .coomer-toggle.active::after {
                    transform: translateX(20px);
                    background: #fff;
                }

                /* 快捷操作按钮 */
                .coomer-quick-actions {
                    position: fixed;
                    display: flex;
                    flex-direction: column;
                    gap: 12px;
                    z-index: 99997;
                    opacity: 0;
                    visibility: hidden;
                    transform: translateY(20px);
                    transition: all 0.3s;
                    pointer-events: none;
                }
                .coomer-quick-actions.show {
                    opacity: 1;
                    visibility: visible;
                    transform: translateY(0);
                    pointer-events: auto;
                }
                .coomer-quick-btn {
                    min-width: 80px;
                    height: 36px;
                    padding: 0 16px;
                    border-radius: 18px;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    cursor: pointer;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 6px;
                    font-size: 13px;
                    font-weight: 600;
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                    transition: all 0.2s;
                    white-space: nowrap;
                    background: rgba(18, 18, 18, 0.9);
                    color: var(--coomer-text);
                    backdrop-filter: blur(4px);
                }
                .coomer-quick-btn:hover {
                    transform: translateX(-4px);
                    border-color: var(--coomer-primary);
                    color: var(--coomer-primary);
                }
                .coomer-quick-btn.collect-artist {
                    border-color: rgba(255, 255, 255, 0.2);
                }
                .coomer-quick-btn.collect-post {
                    border-color: rgba(255, 255, 255, 0.2);
                }
                .coomer-quick-btn.collected {
                    background: var(--coomer-primary);
                    color: #000;
                    border-color: var(--coomer-primary);
                    font-weight: 700;
                    box-shadow: 0 0 15px rgba(224, 170, 62, 0.3);
                }
                /* 移动端隐藏悬浮快捷操作 */
                @media (max-width: 767px) {
                    .coomer-quick-actions {
                        display: none !important;
                    }
                }

                /* 面板上方收藏快捷操作(移动端显示,位置由JS动态计算) */
                .coomer-panel-quick-actions {
                    display: none;
                    position: fixed;
                    left: 0;
                    right: 0;
                    gap: 8px;
                    padding: 10px 16px;
                    background: rgba(18, 18, 18, 0.98);
                    backdrop-filter: blur(8px);
                    border-top: 1px solid var(--coomer-primary);
                    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
                    z-index: 100000;
                }
                @media (max-width: 767px) {
                    .coomer-panel-quick-actions.show {
                        display: flex;
                    }
                }
                .coomer-panel-quick-actions .coomer-quick-btn {
                    flex: 1;
                    justify-content: center;
                }

                /* Toast 提示 */
                .coomer-toast {
                    position: fixed;
                    bottom: 100px;
                    left: 50%;
                    transform: translateX(-50%) translateY(20px);
                    background: #333;
                    color: white;
                    padding: 12px 24px;
                    border-radius: 8px;
                    font-size: 14px;
                    z-index: 100000;
                    opacity: 0;
                    transition: all 0.3s;
                    pointer-events: none;
                }
                .coomer-toast.show {
                    opacity: 1;
                    transform: translateX(-50%) translateY(0);
                }
                .coomer-toast.success {
                    background: #4CAF50;
                }
                .coomer-toast.error {
                    background: #f44336;
                }

                /* 操作按钮组 */
                .coomer-btn-group {
                    display: flex;
                    gap: 12px;
                    margin-top: 20px;
                }
                .coomer-btn {
                    flex: 1;
                    padding: 12px 16px;
                    border: none;
                    border-radius: 8px;
                    cursor: pointer;
                    font-size: 13px;
                    font-weight: 600;
                    transition: all 0.2s;
                    text-transform: uppercase;
                    letter-spacing: 0.5px;
                }
                .coomer-btn:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                }
                .coomer-btn-primary {
                    background: var(--coomer-primary);
                    color: #000;
                }
                .coomer-btn-primary:hover {
                    background: var(--coomer-primary-hover);
                }
                .coomer-btn-danger {
                    background: transparent;
                    border: 1px solid var(--coomer-danger);
                    color: var(--coomer-danger);
                }
                .coomer-btn-danger:hover {
                    background: var(--coomer-danger);
                    color: white;
                }
                .coomer-btn-secondary {
                    background: rgba(255, 255, 255, 0.05);
                    color: var(--coomer-text);
                    border: 1px solid rgba(255, 255, 255, 0.05);
                }
                .coomer-btn-secondary:hover {
                    background: rgba(255, 255, 255, 0.1);
                    border-color: rgba(255, 255, 255, 0.1);
                }
            `);
        },

        createFloatingButton() {
            const fab = document.createElement('button');
            fab.className = 'coomer-fab';
            fab.innerHTML = '⭐';
            fab.title = 'Coomer 佬友严选 (可拖拽移动)';

            // 恢复保存的位置
            const settings = StorageManager.getSettings();
            const pos = settings.fabPosition || DEFAULT_SETTINGS.fabPosition;
            fab.style.right = pos.right + 'px';
            fab.style.bottom = pos.bottom + 'px';

            // 拖拽功能
            let isDragging = false;
            let hasMoved = false;
            let startX, startY, startRight, startBottom;

            const onStart = (e) => {
                isDragging = true;
                hasMoved = false;
                fab.classList.add('dragging');

                const touch = e.touches ? e.touches[0] : e;
                startX = touch.clientX;
                startY = touch.clientY;
                startRight = parseInt(fab.style.right) || pos.right;
                startBottom = parseInt(fab.style.bottom) || pos.bottom;

                e.preventDefault();
            };

            const onMove = (e) => {
                if (!isDragging) return;

                const touch = e.touches ? e.touches[0] : e;
                const deltaX = startX - touch.clientX;
                const deltaY = startY - touch.clientY;

                if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
                    hasMoved = true;
                }

                const newRight = Math.max(10, Math.min(window.innerWidth - 66, startRight + deltaX));
                const newBottom = Math.max(10, Math.min(window.innerHeight - 66, startBottom + deltaY));

                fab.style.right = newRight + 'px';
                fab.style.bottom = newBottom + 'px';

                e.preventDefault();
            };

            const onEnd = (e) => {
                if (!isDragging) return;
                isDragging = false;
                fab.classList.remove('dragging');

                // 保存位置
                const newSettings = StorageManager.getSettings();
                newSettings.fabPosition = {
                    right: parseInt(fab.style.right),
                    bottom: parseInt(fab.style.bottom),
                };
                StorageManager.setSettings(newSettings);

                // 更新快捷操作按钮位置
                if (this.updateQuickActionsPosition) {
                    this.updateQuickActionsPosition();
                }

                // 移动端:如果未拖拽,触发点击
                if (!hasMoved && e.type === 'touchend') {
                    this.toggle();
                }
            };

            // 鼠标事件
            fab.addEventListener('mousedown', onStart);
            document.addEventListener('mousemove', onMove);
            document.addEventListener('mouseup', onEnd);

            // 触摸事件
            fab.addEventListener('touchstart', onStart, { passive: false });
            document.addEventListener('touchmove', onMove, { passive: false });
            document.addEventListener('touchend', onEnd);

            // 点击事件(仅在未拖拽时触发)
            fab.addEventListener('click', (e) => {
                if (hasMoved) {
                    e.preventDefault();
                    e.stopPropagation();
                    return;
                }
                this.toggle();
            });

            document.body.appendChild(fab);
            this.fab = fab;
        },

        createPanel() {
            // 遮罩层
            const overlay = document.createElement('div');
            overlay.className = 'coomer-panel-overlay';
            overlay.addEventListener('click', () => this.close());
            document.body.appendChild(overlay);
            this.overlay = overlay;

            // 面板
            const panel = document.createElement('div');
            panel.className = 'coomer-panel';
            panel.innerHTML = `
                <div class="coomer-panel-header">
                    <span class="coomer-panel-title">👑 COOMER 臻选</span>
                    <div class="coomer-panel-header-actions">
                        <button class="coomer-panel-settings" title="设置">⚙️</button>
                        <button class="coomer-panel-close">×</button>
                    </div>
                </div>
                <div class="coomer-tabs">
                    <button class="coomer-tab active" data-tab="artists">👩‍🎨 艺术家</button>
                    <button class="coomer-tab" data-tab="posts">🎬 作品</button>
                </div>
                <div class="coomer-panel-content"></div>
            `;

            // 关闭按钮事件 - 使用更可靠的绑定方式
            const closeBtn = panel.querySelector('.coomer-panel-close');
            closeBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                this.close();
            });

            // 设置按钮事件
            const settingsBtn = panel.querySelector('.coomer-panel-settings');
            settingsBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                this.switchTab('settings');
            });

            // 标签页切换事件
            panel.querySelectorAll('.coomer-tab').forEach((tab) => {
                tab.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    this.switchTab(tab.dataset.tab);
                });
            });

            // 阻止面板内部点击冒泡到遮罩层
            panel.addEventListener('click', (e) => {
                e.stopPropagation();
            });

            document.body.appendChild(panel);
            this.panel = panel;
            this.contentArea = panel.querySelector('.coomer-panel-content');

            // 渲染初始内容
            this.renderTab('artists');
        },

        // SPA URL 变化时重新创建快捷操作按钮
        recreateQuickActions() {
            // 移除旧的快捷操作按钮
            if (this.quickActions) {
                this.quickActions.remove();
                this.quickActions = null;
                this.updateQuickActionsPosition = null;
            }
            // 延迟一点重新创建(等待页面渲染)
            setTimeout(() => {
                this.createQuickActions();
            }, 500);
        },

        createQuickActions() {
            const container = document.createElement('div');
            container.className = 'coomer-quick-actions';

            const pageType = PageParser.getCurrentPageType();
            const urlInfo = PageParser.parseUrlInfo();

            // 首先添加艺术家按钮(会显示在上方)
            if (pageType === 'artist' || pageType === 'post') {
                const isArtistCollected = urlInfo && ArtistManager.exists(urlInfo.userId);
                const collectArtistBtn = document.createElement('button');
                collectArtistBtn.className = `coomer-quick-btn collect-artist ${isArtistCollected ? 'collected' : ''}`;
                collectArtistBtn.innerHTML = isArtistCollected ? '✓ 已藏艺术家' : '👤 收藏艺术家';
                collectArtistBtn.title = isArtistCollected ? '点击取消收藏艺术家' : '收藏当前艺术家';
                collectArtistBtn.addEventListener('click', () => this.handleCollectArtist(collectArtistBtn));
                container.appendChild(collectArtistBtn);
            }

            // 然后添加作品按钮(会显示在下方,更靠近主按钮)
            if (pageType === 'post') {
                const isPostCollected = urlInfo && PostManager.exists(urlInfo.postId);
                const collectPostBtn = document.createElement('button');
                collectPostBtn.className = `coomer-quick-btn collect-post ${isPostCollected ? 'collected' : ''}`;
                collectPostBtn.innerHTML = isPostCollected ? '✓ 已藏作品' : '🎬 收藏作品';
                collectPostBtn.title = isPostCollected ? '点击取消收藏作品' : '收藏当前作品';
                collectPostBtn.addEventListener('click', () => this.handleCollectPost(collectPostBtn));
                container.appendChild(collectPostBtn);
            }

            if (container.children.length > 0) {
                document.body.appendChild(container);
                this.quickActions = container;

                // 更新快捷操作按钮位置
                const updateQuickActionsPosition = () => {
                    const fabRight = parseInt(this.fab.style.right) || 20;
                    const fabBottom = parseInt(this.fab.style.bottom) || 80;
                    container.style.right = fabRight + 'px';
                    container.style.bottom = fabBottom + 65 + 'px'; // 悬浮按钮高度 + 间距
                };

                // 初始化位置
                updateQuickActionsPosition();

                // 显示/隐藏快捷操作
                const showQuickActions = () => {
                    if (this.isOpen) return; // 面板打开时不显示
                    updateQuickActionsPosition();
                    container.classList.add('show');
                };

                const hideQuickActions = () => {
                    setTimeout(() => {
                        if (!container.matches(':hover') && !this.fab.matches(':hover')) {
                            container.classList.remove('show');
                        }
                    }, 150);
                };

                // 悬浮按钮悬停时显示快捷操作
                this.fab.addEventListener('mouseenter', showQuickActions);
                this.fab.addEventListener('mouseleave', hideQuickActions);
                container.addEventListener('mouseenter', () => container.classList.add('show'));
                container.addEventListener('mouseleave', hideQuickActions);

                // 保存位置更新函数供拖拽时调用
                this.updateQuickActionsPosition = updateQuickActionsPosition;
            }
        },

        // 更新快捷操作按钮的收藏状态
        updateQuickActionsState() {
            if (!this.quickActions) return;
            const urlInfo = PageParser.parseUrlInfo();
            if (!urlInfo) return;

            // 更新艺术家按钮状态
            const artistBtn = this.quickActions.querySelector('.collect-artist');
            if (artistBtn) {
                const isCollected = ArtistManager.exists(urlInfo.userId);
                artistBtn.classList.toggle('collected', isCollected);
                artistBtn.innerHTML = isCollected ? '✓ 已藏艺术家' : '👤 艺术家';
                artistBtn.title = isCollected ? '点击取消收藏艺术家' : '收藏当前艺术家';
            }

            // 更新作品按钮状态
            const postBtn = this.quickActions.querySelector('.collect-post');
            if (postBtn && urlInfo.postId) {
                const isCollected = PostManager.exists(urlInfo.postId);
                postBtn.classList.toggle('collected', isCollected);
                postBtn.innerHTML = isCollected ? '✓ 已藏作品' : '🎬 作品';
                postBtn.title = isCollected ? '点击取消收藏作品' : '收藏当前作品';
            }
        },

        handleCollectArtist(btn) {
            const urlInfo = PageParser.parseUrlInfo();
            if (!urlInfo) return;

            if (ArtistManager.exists(urlInfo.userId)) {
                ArtistManager.remove(urlInfo.userId);
                btn.classList.remove('collected');
                btn.innerHTML = '👤 收藏艺术家';
                btn.title = '收藏当前艺术家';
                this.showToast('已取消收藏', 'success');
            } else {
                const artist = ArtistManager.collectCurrent();
                if (artist) {
                    btn.classList.add('collected');
                    btn.innerHTML = '✓ 已藏艺术家';
                    btn.title = '点击取消收藏艺术家';
                    this.showToast(`已收藏 ${artist.nickname}`, 'success');
                } else {
                    this.showToast('收藏失败,请稍后重试', 'error');
                }
            }
            // 刷新面板内容
            if (this.isOpen && this.activeTab === 'artists') {
                this.renderTab('artists');
            }
        },

        handleCollectPost(btn) {
            const urlInfo = PageParser.parseUrlInfo();
            if (!urlInfo || !urlInfo.postId) return;

            if (PostManager.exists(urlInfo.postId)) {
                PostManager.remove(urlInfo.postId);
                btn.classList.remove('collected');
                btn.innerHTML = '🎬 收藏作品';
                btn.title = '收藏当前作品';
                this.showToast('已取消收藏', 'success');
            } else {
                const post = PostManager.collectCurrent();
                if (post) {
                    btn.classList.add('collected');
                    btn.innerHTML = '✓ 已藏作品';
                    btn.title = '点击取消收藏作品';
                    this.showToast('作品已收藏', 'success');
                } else {
                    this.showToast('收藏失败,请稍后重试', 'error');
                }
            }
            // 刷新面板内容
            if (this.isOpen && this.activeTab === 'posts') {
                this.renderTab('posts');
            }
        },

        // 更新面板上方快捷操作(移动端)
        updatePanelQuickActions() {
            // 获取或创建容器
            let container = document.querySelector('.coomer-panel-quick-actions');
            if (!container) {
                container = document.createElement('div');
                container.className = 'coomer-panel-quick-actions';
                document.body.appendChild(container);
            }

            const pageType = PageParser.getCurrentPageType();
            const urlInfo = PageParser.parseUrlInfo();

            // 清空容器
            container.innerHTML = '';
            container.classList.remove('show');
            container.style.top = '';

            // 如果不在艺术家或作品页面,不显示按钮
            if (pageType !== 'artist' && pageType !== 'post') {
                return;
            }

            // 艺术家收藏按钮
            if (pageType === 'artist' || pageType === 'post') {
                const isArtistCollected = urlInfo && ArtistManager.exists(urlInfo.userId);
                const artistBtn = document.createElement('button');
                artistBtn.className = `coomer-quick-btn collect-artist ${isArtistCollected ? 'collected' : ''}`;
                artistBtn.innerHTML = isArtistCollected ? '✓ 已藏艺术家' : '👤 艺术家';
                artistBtn.addEventListener('click', () => this.handleCollectArtist(artistBtn));
                container.appendChild(artistBtn);
            }

            // 作品收藏按钮
            if (pageType === 'post') {
                const isPostCollected = urlInfo && PostManager.exists(urlInfo.postId);
                const postBtn = document.createElement('button');
                postBtn.className = `coomer-quick-btn collect-post ${isPostCollected ? 'collected' : ''}`;
                postBtn.innerHTML = isPostCollected ? '✓ 已藏作品' : '🎬 作品';
                postBtn.addEventListener('click', () => this.handleCollectPost(postBtn));
                container.appendChild(postBtn);
            }

            // 显示并动态定位(紧贴面板顶部)
            if (container.children.length > 0) {
                // 计算面板高度,设置 bottom 值
                const panelHeight = this.panel.offsetHeight;
                container.style.bottom = panelHeight + 'px';
                container.classList.add('show');
            }
        },

        // 隐藏面板上方快捷操作
        hidePanelQuickActions() {
            const container = document.querySelector('.coomer-panel-quick-actions');
            if (container) {
                container.classList.remove('show');
            }
        },

        toggle() {
            this.isOpen ? this.close() : this.open();
        },

        open() {
            this.isOpen = true;
            this.overlay.classList.add('open');
            this.panel.classList.add('open');
            // 隐藏悬浮快捷操作按钮
            if (this.quickActions) {
                this.quickActions.style.display = 'none';
            }
            // 更新面板内快捷操作(移动端)
            this.updatePanelQuickActions();
            // 监听面板高度变化,动态更新收藏按钮位置
            this.startPanelResizeObserver();
            this.renderTab(this.activeTab);
        },

        close() {
            this.isOpen = false;
            this.overlay.classList.remove('open');
            this.panel.classList.remove('open');
            // 恢复悬浮快捷操作按钮
            if (this.quickActions) {
                this.quickActions.style.display = '';
            }
            // 隐藏面板上方快捷操作(移动端)
            this.hidePanelQuickActions();
            // 停止监听面板高度变化
            this.stopPanelResizeObserver();
        },

        // 开始监听面板高度变化
        startPanelResizeObserver() {
            if (this.panelResizeObserver) return;
            const container = document.querySelector('.coomer-panel-quick-actions');
            if (!container) return;

            this.panelResizeObserver = new ResizeObserver(() => {
                if (this.isOpen && container.classList.contains('show')) {
                    const panelHeight = this.panel.offsetHeight;
                    container.style.bottom = panelHeight + 'px';
                }
            });
            this.panelResizeObserver.observe(this.panel);
        },

        // 停止监听面板高度变化
        stopPanelResizeObserver() {
            if (this.panelResizeObserver) {
                this.panelResizeObserver.disconnect();
                this.panelResizeObserver = null;
            }
        },

        switchTab(tabName) {
            this.activeTab = tabName;
            this.panel.querySelectorAll('.coomer-tab').forEach((tab) => {
                tab.classList.toggle('active', tab.dataset.tab === tabName);
            });
            this.renderTab(tabName);
        },

        renderTab(tabName) {
            const content = this.contentArea;
            content.innerHTML = '';

            switch (tabName) {
                case 'artists':
                    this.renderArtistsTab(content);
                    break;
                case 'posts':
                    this.renderPostsTab(content);
                    break;
                case 'settings':
                    this.renderSettingsTab(content);
                    break;
            }
        },

        renderArtistsTab(container) {
            const myArtists = ArtistManager.getSortedList();
            const presetArtists = PRESET_ARTISTS;
            const settings = StorageManager.getSettings();

            // 如果都没有内容,显示空状态
            if (myArtists.length === 0 && presetArtists.length === 0) {
                container.innerHTML = `
                    <div class="coomer-empty">
                        <div class="coomer-empty-icon">📌</div>
                        <div>暂无收藏的艺术家</div>
                        <div style="font-size: 12px; margin-top: 8px;">访问艺术家主页并点击收藏按钮</div>
                    </div>
                `;
                return;
            }

            // 渲染预置艺术家分组(佬友严选)
            if (presetArtists.length > 0) {
                const presetGroup = this.createArtistGroup(
                    '📌 佬友严选',
                    presetArtists,
                    settings.presetCollapsed,
                    'preset',
                    true, // 是预置列表
                );
                container.appendChild(presetGroup);
            }

            // 渲染我的收藏分组
            if (myArtists.length > 0) {
                const myGroup = this.createArtistGroup(
                    '⭐ 我的收藏',
                    myArtists,
                    settings.myCollectionCollapsed,
                    'myCollection',
                    false, // 不是预置列表
                );
                container.appendChild(myGroup);
            } else if (presetArtists.length > 0) {
                // 有预置但没有自己收藏的,显示提示
                const emptyHint = document.createElement('div');
                emptyHint.style.cssText = 'text-align: center; color: #888; padding: 20px; font-size: 12px;';
                emptyHint.textContent = '点击艺术家卡片访问主页,或使用快捷按钮收藏';
                container.appendChild(emptyHint);
            }
        },

        // 创建艺术家分组
        createArtistGroup(title, artists, isCollapsed, settingKey, isPreset) {
            const group = document.createElement('div');
            group.className = 'coomer-group';

            // 分组标题
            const header = document.createElement('div');
            header.className = 'coomer-group-header';
            header.innerHTML = `
                <div class="coomer-group-title">
                    ${title}
                    <span class="coomer-group-count">(${artists.length})</span>
                </div>
                <span class="coomer-group-toggle ${isCollapsed ? 'collapsed' : ''}">▼</span>
            `;
            header.addEventListener('click', () => {
                const content = group.querySelector('.coomer-group-content');
                const toggle = header.querySelector('.coomer-group-toggle');
                const isCurrentlyCollapsed = content.classList.contains('collapsed');
                // 切换折叠状态
                content.classList.toggle('collapsed', !isCurrentlyCollapsed);
                toggle.classList.toggle('collapsed', !isCurrentlyCollapsed);
                // 设置 max-height
                content.style.maxHeight = isCurrentlyCollapsed ? content.scrollHeight + 'px' : '0';
                // 保存折叠状态
                const settings = StorageManager.getSettings();
                settings[settingKey + 'Collapsed'] = !isCurrentlyCollapsed;
                StorageManager.setSettings(settings);
            });
            group.appendChild(header);

            // 分组内容
            const content = document.createElement('div');
            content.className = `coomer-group-content ${isCollapsed ? 'collapsed' : ''}`;

            const grid = document.createElement('div');
            grid.className = 'coomer-grid';

            artists.forEach((artist) => {
                const card = this.createArtistCard(artist, isPreset);
                grid.appendChild(card);
            });

            content.appendChild(grid);
            group.appendChild(content);

            return group;
        },

        // 创建艺术家卡片
        createArtistCard(artist, isPreset = false) {
            const isInMyCollection = !isPreset && ArtistManager.exists(artist.id);
            const card = document.createElement('div');
            card.className = `coomer-card ${artist.isPinned ? 'pinned' : ''}`;

            if (isPreset) {
                // 预置艺术家卡片
                const isAlreadyCollected = ArtistManager.exists(artist.id);
                card.innerHTML = `
                    <img class="coomer-card-img" src="${artist.avatar || 'https://via.placeholder.com/100?text=No+Image'}" 
                         alt="${artist.nickname}" loading="lazy"
                         onerror="this.src='https://via.placeholder.com/100?text=Error'">
                    <div class="coomer-card-info">
                        <div class="coomer-card-name">${artist.nickname}</div>
                        <div class="coomer-card-meta">${artist.platform} ${isAlreadyCollected ? '✓' : ''}</div>
                    </div>
                `;
                // 点击预置卡片:跳转到主页
                card.addEventListener('click', () => {
                    this.navigateTo(artist.homepageUrl);
                });
                // 右键添加到收藏
                card.addEventListener('contextmenu', (e) => {
                    e.preventDefault();
                    if (!ArtistManager.exists(artist.id)) {
                        ArtistManager.add({
                            ...artist,
                            isPreset: false,
                            addedAt: Date.now(),
                        });
                        this.renderTab('artists');
                        this.showToast(`已添加 ${artist.nickname} 到我的收藏`, 'success');
                    } else {
                        this.showToast('该艺术家已在收藏中', 'error');
                    }
                });
                card.title = '点击访问主页,右键添加到收藏';
            } else {
                // 我的收藏卡片
                card.innerHTML = `
                    <button class="coomer-card-pin ${artist.isPinned ? 'pinned' : ''}" title="${artist.isPinned ? '取消置顶' : '置顶'}">📌</button>
                    <button class="coomer-card-delete" title="删除">×</button>
                    <img class="coomer-card-img" src="${artist.avatar || 'https://via.placeholder.com/100?text=No+Image'}" 
                         alt="${artist.nickname}" loading="lazy"
                         onerror="this.src='https://via.placeholder.com/100?text=Error'">
                    <div class="coomer-card-info">
                        <div class="coomer-card-name">${artist.nickname}</div>
                        <div class="coomer-card-meta">${artist.platform}</div>
                    </div>
                `;

                // 点击卡片跳转到艺术家主页
                card.addEventListener('click', (e) => {
                    if (e.target.classList.contains('coomer-card-delete') || e.target.classList.contains('coomer-card-pin')) return;
                    this.navigateTo(artist.homepageUrl);
                });

                // 置顶按钮
                card.querySelector('.coomer-card-pin').addEventListener('click', (e) => {
                    e.stopPropagation();
                    const isPinned = ArtistManager.togglePin(artist.id);
                    this.renderTab('artists');
                    this.showToast(isPinned ? '已置顶' : '已取消置顶', 'success');
                });

                // 删除按钮
                card.querySelector('.coomer-card-delete').addEventListener('click', (e) => {
                    e.stopPropagation();
                    if (confirm(`确定要删除 ${artist.nickname} 吗?`)) {
                        ArtistManager.remove(artist.id);
                        this.renderTab('artists');
                        this.updateQuickActionsState();
                        this.showToast('已删除', 'success');
                    }
                });
            }

            return card;
        },

        renderPostsTab(container) {
            const posts = PostManager.getSortedList(); // 使用排序后的列表

            if (posts.length === 0) {
                container.innerHTML = `
                    <div class="coomer-empty">
                        <div class="coomer-empty-icon">🎬</div>
                        <div>暂无收藏的作品</div>
                        <div style="font-size: 12px; margin-top: 8px;">访问作品页面并点击收藏按钮</div>
                    </div>
                `;
                return;
            }

            const grid = document.createElement('div');
            grid.className = 'coomer-grid';

            posts.forEach((post) => {
                const card = document.createElement('div');
                card.className = `coomer-card ${post.isPinned ? 'pinned' : ''}`;
                // 媒体数量角标
                const mediaCount = post.mediaUrls ? post.mediaUrls.length : 0;
                const countBadge = mediaCount > 0 ? `<span class="coomer-card-count">${post.type === 'video' ? '🎬' : '📷'} ${mediaCount}</span>` : '';
                card.innerHTML = `
                    <button class="coomer-card-pin ${post.isPinned ? 'pinned' : ''}" title="${post.isPinned ? '取消置顶' : '置顶'}">📌</button>
                    <button class="coomer-card-delete" title="删除">×</button>
                    ${countBadge}
                    <img class="coomer-card-img" src="${post.thumb || 'https://via.placeholder.com/100?text=' + (post.type === 'video' ? '🎬' : '📷')}" 
                         alt="${post.title}" loading="lazy"
                         onerror="this.src='https://via.placeholder.com/100?text=${post.type === 'video' ? '🎬' : '📷'}'">
                    <div class="coomer-card-info">
                        <div class="coomer-card-name">${post.title}</div>
                        <div class="coomer-card-meta">${post.type === 'video' ? '🎬' : '🖼️'} ${post.artistName}</div>
                    </div>
                `;

                // 点击卡片查看详情
                card.addEventListener('click', (e) => {
                    if (e.target.classList.contains('coomer-card-delete') || e.target.classList.contains('coomer-card-pin')) return;
                    this.showPostDetail(post);
                });

                // 置顶按钮
                card.querySelector('.coomer-card-pin').addEventListener('click', (e) => {
                    e.stopPropagation();
                    const isPinned = PostManager.togglePin(post.id);
                    this.renderTab('posts');
                    this.showToast(isPinned ? '已置顶' : '已取消置顶', 'success');
                });

                // 删除按钮
                card.querySelector('.coomer-card-delete').addEventListener('click', (e) => {
                    e.stopPropagation();
                    if (confirm(`确定要删除这个作品吗?`)) {
                        PostManager.remove(post.id);
                        this.renderTab('posts');
                        this.updateQuickActionsState();
                        this.showToast('已删除', 'success');
                    }
                });

                grid.appendChild(card);
            });

            container.appendChild(grid);
        },

        showPostDetail(post) {
            // 根据类型生成预览内容
            let previewContent = '';
            if (post.type === 'video' && post.mediaUrls && post.mediaUrls.length > 0) {
                // 视频作品:显示播放按钮列表
                const videoList = post.mediaUrls
                    .map((url, index) => {
                        // 单个视频显示"点击播放",多个视频显示"视频 1"、"视频 2"...
                        const displayName = post.mediaUrls.length === 1 ? '点击播放' : `视频 ${index + 1} 点击播放`;
                        return `
                        <div class="coomer-video-item" data-url="${url}">
                            <span class="coomer-video-icon">▶️</span>
                            <span class="coomer-video-name">${displayName}</span>
                        </div>
                    `;
                    })
                    .join('');
                previewContent = `
                    <div class="coomer-video-list">
                        ${videoList}
                    </div>
                `;
            } else if (post.thumb) {
                // 图片作品:显示缩略图
                previewContent = `<img class="coomer-card-img" src="${post.thumb}" style="width: 100%; border-radius: 8px; aspect-ratio: 16/9;">`;
            } else {
                // 无预览时显示占位符
                previewContent = `<div style="width: 100%; height: 120px; background: #252540; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 48px;">${
                    post.type === 'video' ? '🎬' : '📷'
                }</div>`;
            }

            this.contentArea.innerHTML = `
                <div style="margin-bottom: 16px;">
                    <button class="coomer-btn coomer-btn-secondary" id="back-btn">← 返回</button>
                </div>
                ${previewContent}
                <h3 style="margin: 12px 0 8px; font-size: 16px;">${post.title}</h3>
                <p style="color: #888; font-size: 14px;">艺术家: ${
                    post.platform ? `<a href="#" id="artist-link" style="color: var(--coomer-primary); text-decoration: none; cursor: pointer;">${post.artistName}</a>` : post.artistName
                }</p>
                
                <div class="coomer-btn-group">
                    <button class="coomer-btn coomer-btn-primary" id="open-btn">📖 打开页面</button>
                    <button class="coomer-btn coomer-btn-secondary" id="copy-btn">📋 复制下载链接 (${post.mediaUrls ? post.mediaUrls.length : 0})</button>
                </div>
                <div class="coomer-btn-group">
                    <button class="coomer-btn coomer-btn-danger" id="delete-btn">🗑️ 删除</button>
                </div>
            `;

            this.contentArea.querySelector('#back-btn').addEventListener('click', () => {
                this.renderTab('posts');
            });

            this.contentArea.querySelector('#open-btn').addEventListener('click', () => {
                this.navigateTo(post.pageUrl);
            });

            // 艺术家链接点击事件(仅在有 platform 数据时绑定)
            if (post.platform) {
                this.contentArea.querySelector('#artist-link').addEventListener('click', (e) => {
                    e.preventDefault();
                    const artistUrl = `https://coomer.st/${post.platform}/user/${post.artistId}`;
                    this.navigateTo(artistUrl);
                });
            }

            this.contentArea.querySelector('#copy-btn').addEventListener('click', () => {
                const links = post.mediaUrls.join('\n');
                GM_setClipboard(links);
                const count = post.mediaUrls.length;
                this.showToast(`已复制 ${count} 条下载链接`, 'success');
            });

            this.contentArea.querySelector('#delete-btn').addEventListener('click', () => {
                if (confirm('确定要删除这个作品吗?')) {
                    PostManager.remove(post.id);
                    this.renderTab('posts');
                    this.updateQuickActionsState();
                    this.showToast('已删除', 'success');
                }
            });

            // 视频播放按钮点击事件 - 使用 video.js 播放
            this.contentArea.querySelectorAll('.coomer-video-item').forEach((item) => {
                item.addEventListener('click', () => {
                    const url = item.dataset.url;
                    this.playVideo(url);
                });
            });
        },

        // 使用 video.js 播放视频
        playVideo(url) {
            // 注入 Video.js 自定义暗黑主题
            if (!document.getElementById('coomer-video-theme')) {
                const style = document.createElement('style');
                style.id = 'coomer-video-theme';
                style.textContent = `
                    .video-js .vjs-big-play-button {
                        left: 50%;
                        top: 50%;
                        transform: translate(-50%, -50%);
                        line-height: 2em;
                        height: 2em;
                        width: 2em;
                        border-radius: 50%;
                        background-color: rgba(224, 170, 62, 0.9);
                        border: none;
                        font-size: 3.5em;
                        box-shadow: 0 0 30px rgba(0,0,0,0.5);
                        backdrop-filter: blur(4px);
                    }
                    .video-js .vjs-big-play-button:hover {
                        background-color: #E0AA3E;
                        transform: translate(-50%, -50%) scale(1.1);
                    }
                    .video-js .vjs-control-bar {
                        background-color: rgba(0, 0, 0, 0.8);
                        border-radius: 8px;
                        margin: 12px;
                        width: calc(100% - 24px);
                        bottom: 0;
                        height: 48px;
                        display: flex;
                        align-items: center;
                    }
                    .video-js .vjs-button {
                        color: #E0E0E0;
                    }
                    .video-js .vjs-button:hover {
                        color: #E0AA3E;
                    }
                    .video-js .vjs-slider {
                        background-color: rgba(255, 255, 255, 0.2);
                    }
                    .video-js .vjs-play-progress {
                        background-color: #E0AA3E;
                    }
                    .video-js .vjs-play-progress:before {
                        color: #E0AA3E;
                    }
                    .video-js .vjs-load-progress {
                        background-color: rgba(255, 255, 255, 0.1);
                    }
                    .video-js .vjs-load-progress div {
                        background: rgba(255, 255, 255, 0.1);
                    }
                    /* 快进快退按钮图标适配 */
                    .video-js .vjs-skip-backward-15,
                    .video-js .vjs-skip-forward-15 {
                        font-family: FontAwesome, sans-serif; /* fallback */
                    }
                    .video-js .vjs-skip-backward-15:before {
                        content: "↺";
                        font-size: 1.5em; /* 调整图标大小 */
                        line-height: 1.8;
                    }
                    .video-js .vjs-skip-forward-15:before {
                        content: "↻";
                        font-size: 1.5em; /* 调整图标大小 */
                        line-height: 1.8;
                    }
                    /* 确保按钮在 hover 时变为金色 */
                    .video-js .vjs-skip-backward-15:hover,
                    .video-js .vjs-skip-forward-15:hover {
                         color: #E0AA3E;
                    }
                `;
                document.head.appendChild(style);
            }

            // 创建播放器容器
            const playerContainer = document.createElement('div');
            playerContainer.className = 'coomer-video-player-overlay';
            playerContainer.innerHTML = `
                <div class="coomer-video-player-wrapper">
                    <button class="coomer-video-close">×</button>
                    <video id="coomer-video-player" class="video-js vjs-big-play-centered vjs-fluid" controls preload="auto">
                        <source src="${url}" type="video/mp4">
                    </video>
                </div>
            `;
            document.body.appendChild(playerContainer);

            // 初始化 video.js 播放器
            const player = videojs('coomer-video-player', {
                fluid: true,
                autoplay: true,
                controls: true,
                playbackRates: [0.5, 1.0, 1.5, 2.0], // 倍速播放
                userActions: {
                    doubleClick: true, // 双击全屏
                    hotkeys: true, // 启用键盘热键
                },
                controlBar: {
                    children: [
                        'playToggle',
                        'skipBackward', // 后退 15s
                        'skipForward', // 快进 15s
                        'volumePanel',
                        'currentTimeDisplay',
                        'timeDivider',
                        'durationDisplay',
                        'progressControl',
                        'playbackRateMenuButton',
                        'pictureInPictureToggle',
                        'fullscreenToggle',
                    ],
                    skipButtons: {
                        forward: 15,
                        backward: 15,
                    },
                },
            });

            // 自动聚焦以便键盘控制
            player.ready(() => {
                player.focus();
            });

            const closePlayer = () => {
                if (player) {
                    player.dispose();
                }
                if (playerContainer && playerContainer.parentNode) {
                    playerContainer.parentNode.removeChild(playerContainer);
                }
                document.removeEventListener('keydown', escHandler);
            };

            // 关闭按钮
            playerContainer.querySelector('.coomer-video-close').addEventListener('click', closePlayer);

            // 点击遮罩关闭
            playerContainer.addEventListener('click', (e) => {
                if (e.target === playerContainer) {
                    closePlayer();
                }
            });

            // ESC 键关闭
            const escHandler = (e) => {
                if (e.key === 'Escape') {
                    closePlayer();
                }
            };
            document.addEventListener('keydown', escHandler);
        },

        renderSettingsTab(container) {
            const settings = StorageManager.getSettings();

            container.innerHTML = `
                <div class="coomer-setting-item">
                    <span class="coomer-setting-label">🚫 屏蔽广告</span>
                    <div class="coomer-toggle ${settings.blockAds ? 'active' : ''}" data-key="blockAds"></div>
                </div>
                <div class="coomer-setting-item">
                    <span class="coomer-setting-label">📺 自动全屏</span>
                    <div class="coomer-toggle ${settings.autoFullscreen ? 'active' : ''}" data-key="autoFullscreen"></div>
                </div>
                <div style="margin-top: 24px;">
                    <div class="coomer-btn-group">
                        <button class="coomer-btn coomer-btn-secondary" id="export-btn">📤 导出数据</button>
                        <button class="coomer-btn coomer-btn-secondary" id="import-btn">📥 导入数据</button>
                    </div>
                </div>
                <div style="margin-top: 16px; text-align: center; color: #666; font-size: 12px;">
                    <div>Coomer 佬友严选 v1.0.0</div>
                    <div style="margin-top: 4px;">艺术家: ${ArtistManager.count()} | 作品: ${PostManager.count()}</div>
                </div>
            `;

            // 绑定开关事件
            container.querySelectorAll('.coomer-toggle').forEach((toggle) => {
                toggle.addEventListener('click', () => {
                    const key = toggle.dataset.key;
                    const newSettings = StorageManager.getSettings();
                    newSettings[key] = !newSettings[key];
                    StorageManager.setSettings(newSettings);
                    toggle.classList.toggle('active');
                    this.showToast('设置已保存', 'success');
                });
            });

            // 导出数据
            container.querySelector('#export-btn').addEventListener('click', () => {
                const data = {
                    artists: ArtistManager.getAll(),
                    posts: PostManager.getAll(),
                    settings: StorageManager.getSettings(),
                    exportedAt: Date.now(),
                };
                const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `coomer-backup-${new Date().toISOString().split('T')[0]}.json`;
                a.click();
                URL.revokeObjectURL(url);
                this.showToast('数据已导出', 'success');
            });

            // 导入数据
            container.querySelector('#import-btn').addEventListener('click', () => {
                const input = document.createElement('input');
                input.type = 'file';
                input.accept = '.json';
                input.onchange = (e) => {
                    const file = e.target.files[0];
                    if (!file) return;
                    const reader = new FileReader();
                    reader.onload = (evt) => {
                        try {
                            const data = JSON.parse(evt.target.result);
                            if (data.artists) StorageManager.setArtists(data.artists);
                            if (data.posts) StorageManager.setPosts(data.posts);
                            if (data.settings) StorageManager.setSettings(data.settings);
                            this.showToast('数据已导入', 'success');
                            this.renderTab('settings');
                        } catch {
                            this.showToast('导入失败,文件格式错误', 'error');
                        }
                    };
                    reader.readAsText(file);
                };
                input.click();
            });
        },

        showToast(message, type = '') {
            // 移除已有的 toast
            document.querySelectorAll('.coomer-toast').forEach((t) => t.remove());

            const toast = document.createElement('div');
            toast.className = `coomer-toast ${type}`;
            toast.textContent = message;
            document.body.appendChild(toast);

            requestAnimationFrame(() => {
                toast.classList.add('show');
            });

            setTimeout(() => {
                toast.classList.remove('show');
                setTimeout(() => toast.remove(), 300);
            }, 2000);
        },
    };

    // ============================================
    // 初始化
    // ============================================
    function init() {
        // 广告拦截需要在 document-start 时执行
        AdBlocker.init();

        // 等待 DOM 加载完成后初始化其他功能
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initUI);
        } else {
            initUI();
        }
    }

    function initUI() {
        // 等待页面完全渲染(SPA 需要延迟)
        setTimeout(() => {
            UIPanel.init();
            AutoFullscreen.init();

            // 监听 SPA URL 变化
            if (window.onurlchange === null) {
                window.addEventListener('urlchange', (info) => {
                    // URL 变化时重新创建快捷操作按钮
                    UIPanel.recreateQuickActions();
                });
            }
        }, 1000);
    }

    init();
})();