Bilibili高级弹幕增强

开启你的B站弹幕职人之路!优化高级弹幕发送面板,增加多种高级弹幕样式

// ==UserScript==
// @name         Bilibili高级弹幕增强
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  开启你的B站弹幕职人之路!优化高级弹幕发送面板,增加多种高级弹幕样式
// @author       淡い光
// @license      MIT
// @match        *://*.bilibili.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==


/**
 * 添加新字体选项到弹幕字体选择列表
 */
function addNewFonts() {
    // 监听弹幕面板切换
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            if (mutation.target.classList &&
                mutation.target.classList.contains('bui-dropdown-name') &&
                mutation.target.textContent === '高级弹幕') {
                console.log("切换到高级弹幕面板");
                // 当切换到高级弹幕面板时
                setTimeout(setupFontSelector, 1);

                // setTimeout(setupEnhancedSendButton, 1);

            }
        });
    });

    // 开始观察文档变化,包含文本内容的变化
    observer.observe(document.body, {
        childList: true,
        subtree: true,
        characterData: true,
        characterDataOldValue: true
    });
}

/**
 * 设置字体选择器的事件监听
 */
function setupFontSelector() {
    const fontSelect = document.querySelector('.bpx-player-adv-danmaku-font-family-select');
    if (fontSelect && !fontSelect.dataset.enhanced) {
        fontSelect.dataset.enhanced = 'true';
        fontSelect.addEventListener('mouseenter', () => {
            insertFonts();
        }, { once: true }); // 只在第一次悬停时执行
    }
}

/**
 * 插入新字体到字体列表
 */
function insertFonts() {
    console.log("插入字体");
    const fontList = document.querySelector('.bpx-player-adv-danmaku-font-family ul.bui-select-list');
    if (!fontList) return;
    // 避免重复添加字体
    if (!document.querySelector('[data-value="KaiTi"]')) {
        const newFonts = [
            { value: 'KaiTi', text: '楷体' },
            { value: 'YouYuan', text: '幼圆' },
            { value: 'STCaiyun', text: '华文彩云' },
        ];

        newFonts.forEach(font => {
            const li = document.createElement('li');
            li.className = 'bui-select-item';
            li.setAttribute('data-value', font.value);
            li.textContent = font.text;

            // 插入到列表的最后
            fontList.appendChild(li);
        });

        // 添加点击事件处理
        fontList.addEventListener('click', (e) => {
            const item = e.target.closest('.bui-select-item');
            if (item) {
                // 更新选中状态
                fontList.querySelectorAll('.bui-select-item').forEach(el => {
                    el.classList.remove('bui-select-item-active');
                });
                item.classList.add('bui-select-item-active');

                // 更新显示的文本和字体选择器的状态
                const fontSelect = document.querySelector('.bpx-player-adv-danmaku-font-family-select');
                if (fontSelect) {
                    // 更新显示文本
                    const resultText = fontSelect.querySelector('.bui-select-result');
                    if (resultText) {
                        resultText.textContent = item.textContent;
                    }

                    // 触发字体选择事件
                    const event = new CustomEvent('fontChange', {
                        detail: {
                            value: item.getAttribute('data-value'),
                            text: item.textContent
                        }
                    });
                    fontSelect.dispatchEvent(event);
                }
            }
        });
    }
}

/**
 * 设置颜色选择器
 */
function setupColorPicker() {
    // 获取原面板的颜色选择器区域
    const colorPickerResult = document.querySelector('.bui-color-picker-result');
    if (!colorPickerResult || colorPickerResult.dataset.enhanced) return;
    colorPickerResult.dataset.enhanced = 'true';

    // 创建新的颜色选择器
    const colorInput = document.createElement('input');
    colorInput.type = 'color';
    colorInput.className = 'enhanced-color-picker';

    // 设置样式 - 完全隐藏但保持可用
    colorInput.style.cssText = `
            width: 0;
            height: 0;
            padding: 0;
            border: none;
            position: absolute;
            visibility: hidden;
        `;

    // 创建容器并添加颜色选择器
    const colorPickerContainer = document.createElement('div');
    colorPickerContainer.style.cssText = `
            position: absolute;
            left: 0;
            top: 105px;
            height: 1px;
            overflow: hidden;
            opacity: 0;
        `;
    colorPickerContainer.appendChild(colorInput);
    colorPickerResult.appendChild(colorPickerContainer);

    // 获取原有的颜色显示区域和输入框
    const originalDisplay = colorPickerResult.querySelector('.bui-color-picker-display');
    const colorTextInput = colorPickerResult.querySelector('.bui-color-picker-input input');

    if (originalDisplay) {
        // 确保鼠标样式显示为可点击
        originalDisplay.style.cursor = 'pointer';
        // 点击原有显示区域时触发颜色选择器
        originalDisplay.addEventListener('click', () => {
            // 在打开颜色选择器前,先同步当前颜色
            const currentColor = colorTextInput.value.toUpperCase();
            colorInput.value = currentColor;
            colorInput.click();
        });
    }

    // 监听颜色变化
    colorInput.addEventListener('input', (e) => {
        const hexColor = e.target.value.toUpperCase();
        if (colorTextInput) {
            colorTextInput.value = hexColor;
            // 触发原面板的颜色更新事件
            colorTextInput.dispatchEvent(new Event('input', { bubbles: true }));
        }
        // 更新原有显示区域的背景色
        if (originalDisplay) {
            originalDisplay.style.background = hexColor;
        }
    });
}

/**
 * 设置发送样式弹幕按钮和样式弹幕区域
 */
function setupEnhancedSendButton() {
    console.log("设置发送样式弹幕按钮和样式弹幕区域");
    // 检查是否已存在增强功能
    if (document.querySelector('.enhanced-danmaku-container')) return;

    // 添加隐藏的localDmFile元素
    const localDmFile = document.createElement('div');
    localDmFile.id = 'localDmFile';
    localDmFile.style.display = 'none';
    document.body.appendChild(localDmFile);



    // 添加数字输入框的上下箭头事件处理
    function setupNumberStepper(container) {
        // 获取原面板的按百分比复选框
        const getPercentCheckbox = () => document.querySelector('.bpx-player-adv-danmaku-pos-percent input');

        // 获取是否按百分比
        const getIsPercent = () => {
            const checkbox = getPercentCheckbox();
            return checkbox && checkbox.checked;
        };

        // 更新输入框的默认值
        function updateDefaultValues(isPercent) {
            const inputs = {
                'shadow-offset-x': { percent: '0.003', normal: '3' },
                'shadow-offset-y': { percent: '0.003', normal: '3' },
                'stroke-spacing': { percent: '0.002', normal: '2' }
            };

            Object.entries(inputs).forEach(([className, values]) => {
                const input = container.querySelector(`.${className}`);
                if (input) {
                    const currentValue = parseFloat(input.value);
                    // 只有当值等于另一个模式的默认值时才更新
                    if (currentValue === parseFloat(isPercent ? values.normal : values.percent)) {
                        input.value = isPercent ? values.percent : values.normal;
                    }
                }
            });
        }

        container.querySelectorAll('.bpx-player-adv-danmaku-spinner.bui-input').forEach(spinner => {
            const input = spinner.querySelector('input');
            const upArrow = spinner.querySelector('.bui-input-stepper-up');
            const downArrow = spinner.querySelector('.bui-input-stepper-down');

            // 获取步进值和范围限制
            const defaultStep = parseInt(spinner.dataset.step) || 1;
            const min = parseInt(spinner.dataset.min);
            const max = parseInt(spinner.dataset.max);

            // 点击上箭头
            upArrow.addEventListener('click', () => {
                const step = getIsPercent() ? 0.001 : defaultStep;
                let value = parseFloat(input.value) || 0;
                value = parseFloat((value + step).toFixed(3));
                if (!isNaN(max) && value > max) value = max;
                input.value = value;
                input.dispatchEvent(new Event('input', { bubbles: true }));
            });

            // 点击下箭头
            downArrow.addEventListener('click', () => {
                const step = getIsPercent() ? 0.001 : defaultStep;
                let value = parseFloat(input.value) || 0;
                value = parseFloat((value - step).toFixed(3));
                if (!isNaN(min) && value < min) value = min;
                input.value = value;
                input.dispatchEvent(new Event('input', { bubbles: true }));
            });
        });

        // 监听原面板按百分比复选框的变化
        const percentCheckbox = getPercentCheckbox();
        if (percentCheckbox) {
            // 监听复选框的change事件
            percentCheckbox.addEventListener('change', () => {
                const isPercent = getIsPercent();
                // 更新默认值
                updateDefaultValues(isPercent);
                // 更新所有输入框的值格式
                container.querySelectorAll('.bpx-player-adv-danmaku-spinner.bui-input input').forEach(input => {
                    const value = parseFloat(input.value) || 0;
                    input.value = isPercent ? value.toFixed(3) : Math.round(value);
                });
            });

            // 初始化时检查一次
            updateDefaultValues(getIsPercent());
        }
    }

    // 创建样式弹幕和参数区域的容器
    const enhancedContainer = document.createElement('div');
    enhancedContainer.className = 'bpx-player-adv-danmaku-group enhanced-danmaku-container';

    // 修改阴影参数区域的HTML,添加默认值
    enhancedContainer.innerHTML = `
            <div class="bpx-player-adv-danmaku-group-row">
                <span class="bpx-player-adv-danmaku-title">样式弹幕</span>
                <div class="enhanced-style-buttons">
                    <span class="bpx-player-adv-danmaku-btn bui bui-button active" data-style="shadow">
                        <div class="bui-area bui-button-small">立体阴影</div>
                    </span>
                    <span class="bpx-player-adv-danmaku-btn bui bui-button" data-style="stroke">
                        <div class="bui-area bui-button-small">颜色描边</div>
                    </span>
                    <span class="bpx-player-adv-danmaku-btn bui bui-button" data-style="background">
                        <div class="bui-area bui-button-small">文字背景</div>
                    </span>
                    <span class="bpx-player-adv-danmaku-btn bui bui-button" data-style="normal">
                        <div class="bui-area bui-button-small">无样式</div>
                    </span>
                    <span class="bpx-player-adv-danmaku-btn bui bui-button" data-style="ascii"style=" padding-top: 0px; margin-top: 8px;">
                        <div class="bui-area bui-button-small">字符画</div>
                    </span>
                </div>
            </div>

            <div class="enhanced-params-area">
                <div class="shadow-params" style="display: block;">
                    <div class="bpx-player-adv-danmaku-group-row" style="padding-top: 0px;">
                        <div class="bpx-player-adv-danmaku-group-item shadow-item">
                            <span class="bpx-player-adv-danmaku-title">阴影颜色</span>
                            <div class="bpx-player-adv-danmaku-color-picker bui bui-color-picker">
                                <div class="bui-area">
                                    <div class="bui-color-picker-wrap">
                                        <div class="bui-color-picker-result" style="!important; margin-bottom: 0px;">
                                            <span class="bui-color-picker-input bui bui-input">
                                                <div class="bui-area">
                                                    <div class="bui-input-wrap">
                                                        <input class="shadow-color bui-input-input" type="text" value="#222222">
                                                    </div>
                                                </div>
                                            </span>
                                            <span class="bui-color-picker-display" style="background: #222222"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="bpx-player-adv-danmaku-group-item shadow-item">
                            <span class="bpx-player-adv-danmaku-title">偏移X</span>
                            <span class="bpx-player-adv-danmaku-spinner bui bui-input" data-value="3" data-min="0" data-max="9999" data-step="1">
                                <div class="bui-area">
                                    <div class="bui-input-wrap">
                                        <input class="shadow-offset-x bui-input-input" type="number" value="3">
                                        <div class="bui-input-stepper">
                                            <div class="bui-input-stepper-half bui-input-stepper-up">
                                                <span class="bui-input-arrow bui-input-arrow-up"></span>
                                            </div>
                                            <div class="bui-input-stepper-half bui-input-stepper-down">
                                                <span class="bui-input-arrow bui-input-arrow-down"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </span>
                        </div>
                        <div class="bpx-player-adv-danmaku-group-item shadow-item">
                            <span class="bpx-player-adv-danmaku-title">偏移Y</span>
                            <span class="bpx-player-adv-danmaku-spinner bui bui-input" data-value="3" data-min="0" data-max="9999" data-step="1">
                                <div class="bui-area">
                                    <div class="bui-input-wrap">
                                        <input class="shadow-offset-y bui-input-input" type="number" value="3">
                                        <div class="bui-input-stepper">
                                            <div class="bui-input-stepper-half bui-input-stepper-up">
                                                <span class="bui-input-arrow bui-input-arrow-up"></span>
                                            </div>
                                            <div class="bui-input-stepper-half bui-input-stepper-down">
                                                <span class="bui-input-arrow bui-input-arrow-down"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </span>
                        </div>
                    </div>
                </div>
                <div class="stroke-params" style="display: none;">
                    <div class="bpx-player-adv-danmaku-group-row" style="padding-top: 0px;">
                        <div class="bpx-player-adv-danmaku-group-item stroke-item">
                            <span class="bpx-player-adv-danmaku-title">描边颜色</span>
                            <div class="bpx-player-adv-danmaku-color-picker bui bui-color-picker">
                                <div class="bui-area">
                                    <div class="bui-color-picker-wrap">
                                        <div class="bui-color-picker-result" style="!important; margin-bottom: 0px;">
                                            <span class="bui-color-picker-input bui bui-input">
                                                <div class="bui-area">
                                                    <div class="bui-input-wrap">
                                                        <input class="stroke-color bui-input-input" type="text" value="#00AEEC">
                                                    </div>
                                                </div>
                                            </span>
                                            <span class="bui-color-picker-display" style="background: #00AEEC"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="bpx-player-adv-danmaku-group-item stroke-item">
                            <span class="bpx-player-adv-danmaku-title">间距</span>
                            <span class="bpx-player-adv-danmaku-spinner bui bui-input" data-value="2" data-min="0" data-max="9999" data-step="1">
                                <div class="bui-area">
                                    <div class="bui-input-wrap">
                                        <input class="stroke-spacing bui-input-input" type="number" value="2">
                                        <div class="bui-input-stepper">
                                            <div class="bui-input-stepper-half bui-input-stepper-up">
                                                <span class="bui-input-arrow bui-input-arrow-up"></span>
                                            </div>
                                            <div class="bui-input-stepper-half bui-input-stepper-down">
                                                <span class="bui-input-arrow bui-input-arrow-down"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </span>
                        </div>
                    </div>
                </div>

                <div class="background-params" style="display: none;">
                    <div class="bpx-player-adv-danmaku-group-row" style="padding-top: 0px;">
                        <div class="bpx-player-adv-danmaku-group-item background-item">
                            <span class="bpx-player-adv-danmaku-title">背景颜色</span>
                            <div class="bpx-player-adv-danmaku-color-picker bui bui-color-picker">
                                <div class="bui-area">
                                    <div class="bui-color-picker-wrap">
                                        <div class="bui-color-picker-result" style="!important; margin-bottom: 0px;">
                                            <span class="bui-color-picker-input bui bui-input">
                                                <div class="bui-area">
                                                    <div class="bui-input-wrap">
                                                        <input class="background-color bui-input-input" type="text" value="#222222">
                                                    </div>
                                                </div>
                                            </span>
                                            <span class="bui-color-picker-display" style="background: #222222"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="bpx-player-adv-danmaku-group-item background-item">
                            <span class="bpx-player-adv-danmaku-title">背景字符</span>
                            <span class="bpx-player-adv-danmaku-spinner" style="width: 50px !important;">
                                <input type="text" class="background-char bui-input-input"  style="width: 50px !important;" value="█" maxlength="1">
                            </span>
                        </div>
                        <div class="bpx-player-adv-danmaku-group-item background-item">
                            <span class="bpx-player-adv-danmaku-checkbox bui bui-checkbox">
                                <div class="bui-area" style="padding-top: 26px;">
                                    <input class="bui-checkbox-input vertical-text" type="checkbox" aria-label="转竖列">
                                    <label class="bui-checkbox-label">
                                        <span class="bui-checkbox-icon bui-checkbox-icon-default">
                                            <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                                                <path d="M8 6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H8zm0-2h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                                            </svg>
                                        </span>
                                        <span class="bui-checkbox-icon bui-checkbox-icon-selected">
                                            <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                                                <path d="m13 18.25-1.8-1.8c-.6-.6-1.65-.6-2.25 0s-.6 1.5 0 2.25l2.85 2.85c.318.318.762.468 1.2.448.438.02.882-.13 1.2-.448l8.85-8.85c.6-.6.6-1.65 0-2.25s-1.65-.6-2.25 0l-7.8 7.8zM8 4h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                                            </svg>
                                        </span>
                                        <span class="bui-checkbox-name">转竖列</span>
                                    </label>
                                </div>
                            </span>
                        </div>
                    </div>
                </div>
                <div class="normal-params" style="display: none;">
                </div>
                <div class="ascii-params" style="display: none;">
                    <div class="bpx-player-adv-danmaku-group-row" style="padding-top: 0px;">
                        <div class="bpx-player-adv-danmaku-group-item" style="width: 100%; margin-bottom: 10px;">
                            <div class="bpx-player-adv-danmaku-text-input bui bui-input" style="width: calc(100%);">
                                <div class="bui-area">
                                    <div class="bui-input-wrap">
                                        <textarea class="ascii-content bui-input-input" type="text" placeholder="请输入字符画内容" style="min-height: 80px; font-family: '黑体', sans-serif; white-space: pre;!important;">    ◥◣    ◢◤    \n     ◥◣  ◢◤     \n ◢████████████◣\n◢██████████████◣\n██            ██\n██  ◢█    █◣  ██\n██ ◢█◤    ◥█◣ ██\n██ █◤      ◥█ ██\n██            ██\n██            ██\n██     ︶︶     ██\n██            ██\n◥██████████████◤\n ◥████████████◤ \n    ◥◤    ◥◤    </textarea>
                                        <span class="ascii-char-count" style="position: absolute; right: 18px; bottom: -10px; color: #99a2aa; font-size: 12px;">字数:0</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="bpx-player-adv-danmaku-group-row" style="padding-top: 0px;">
                        <div class="bpx-player-adv-danmaku-group-item" style="margin-right: 20px;">
                            <span class="bpx-player-adv-danmaku-title">发送方式</span>
                            <span class="ascii-send-mode-select bui bui-select" data-enhanced="true">
                                <div class="bui-area">
                                    <div class="bui-select-wrap">
                                        <div class="bui-select-border">
                                            <div class="bui-select-header">
                                                <span class="bui-select-result">更换Y坐标每行发送</span>
                                                <span class="bui-select-arrow">
                                                    <span class="bui-select-arrow-down"></span>
                                                </span>
                                            </div>
                                            <div class="bui-select-list-wrap" style="">
                                                <ul class="bui-select-list" style="height: 0px; border: none;">
                                                    <li class="bui-select-item bui-select-item-active" data-value="line">更换Y坐标每行发送</li>
                                                    <li class="bui-select-item" data-value="coord">相同坐标换行发送</li>
                                                </ul>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </span>
                        </div>
                        
                        <div class="bpx-player-adv-danmaku-group-item ascii-line-spacing" style="margin-right: 0px;">
                            <span class="bpx-player-adv-danmaku-title">每行间距</span>
                            <span class="bpx-player-adv-danmaku-spinner bui bui-input" data-value="30" data-min="0" data-max="999" data-step="1" style="width: 58px;">
                                <div class="bui-area">
                                    <div class="bui-input-wrap">
                                        <input class="line-spacing bui-input-input" type="number" value="36">
                                        <div class="bui-input-stepper">
                                            <div class="bui-input-stepper-half bui-input-stepper-up">
                                                <span class="bui-input-arrow bui-input-arrow-up"></span>
                                            </div>
                                            <div class="bui-input-stepper-half bui-input-stepper-down">
                                                <span class="bui-input-arrow bui-input-arrow-down"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </span>
                        </div>

                        <div class="bpx-player-adv-danmaku-group-item ascii-sync-font-size" style="margin-top: 24px;">
                            <span class="bpx-player-adv-danmaku-checkbox bui bui-checkbox sync-font-size"style="margin-left: 8px;>
                                <div class="bui-area">
                                    <input class="bui-checkbox-input" type="checkbox" aria-label="同步字号" checked>
                                    <label class="bui-checkbox-label">
                                        <span class="bui-checkbox-icon bui-checkbox-icon-default">
                                            <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                                                <path d="M8 6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H8zm0-2h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                                            </svg>
                                        </span>
                                        <span class="bui-checkbox-icon bui-checkbox-icon-selected">
                                            <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                                                <path d="m13 18.25-1.8-1.8c-.6-.6-1.65-.6-2.25 0s-.6 1.5 0 2.25l2.85 2.85c.318.318.762.468 1.2.448.438.02.882-.13 1.2-.448l8.85-8.85c.6-.6.6-1.65 0-2.25s-1.65-.6-2.25 0l-7.8 7.8zM8 4h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                                            </svg>
                                        </span>
                                        <span class="bui-checkbox-name">同步字号</span>
                                    </label>
                                </div>
                            </span>
                        </div>

                    </div>
                </div>
            </div>

            <div class="bpx-player-adv-danmaku-group-row bpx-player-adv-danmaku-send">
                <span class="bpx-player-adv-danmaku-btn bpx-player-adv-danmaku-send-test bui bui-button enhanced-send-btn">
                    <div class="bui-area bui-button-large">发送样式弹幕</div>
                </span>
       
            </div>
            <div class="bpx-player-adv-danmaku-group-row enhanced-send-status-row">
               <span class="enhanced-send-status"></span>
            </div>
        `;

    // 添加样式
    const style = document.createElement('style');
    style.textContent = `
            .enhanced-danmaku-container {
                margin-top: 0;
                padding: 20px 0;
                padding-top: 0px;
            }
            .enhanced-style-buttons {
                display: inline-block;
            }
            .enhanced-style-buttons .bpx-player-adv-danmaku-btn {
                margin-right: 8px;
            }
            .enhanced-style-buttons .active {
                background-color: #00a1d6;
                color: #fff;
            }
            .enhanced-params-area {
                margin: 8px 0;
            }
            .enhanced-params-area .bpx-player-adv-danmaku-group-item {
                margin-right: 16px;
            }
            .enhanced-params-area .bpx-player-adv-danmaku-spinner {
                display: inline-block;
                vertical-align: middle;
            }
            .enhanced-params-area input {
                width: 80px;
                height: 24px;
                padding: 0 8px;
                border: 1px solid #e3e5e7;
                border-radius: 2px;
                font-size: 12px;
            }
            .enhanced-send-btn.disabled {
                opacity: 0.5 !important;
                pointer-events: none !important;
                background-color: #e3e5e7 !important;
            }
            .enhanced-send-status {
                display: none;
                vertical-align: middle;
                margin-left: 10px;
                color: #666;
                font-size: 12px;
                line-height: 32px;
            }
            .enhanced-params-area .shadow-item,
            .enhanced-params-area .stroke-item {
                margin-right: 24px !important;
            }
            .enhanced-params-area .shadow-item:last-child,
            .enhanced-params-area .stroke-item:last-child {
                margin-right: 0 !important;
            }
            .enhanced-style-buttons .bpx-player-adv-danmaku-btn.active {
                background-color: #00a1d6 !important;
                color: #fff !important;
            }
            .preview-danmaku-btn {
                margin-top: 10px;
                text-align: center;
            }
            .preview-danmaku-btn .bui-area {
                background-color: #00a1d6;
                color: #fff;
                border-radius: 4px;
                cursor: pointer;
            }
            .preview-danmaku-btn .bui-area:hover {
                background-color: #00b5e5;
            }
        `;
    document.head.appendChild(style);

    // 组装并插入元素
    enhancedContainer.appendChild(style);

    // 监听高级弹幕面板的加载
    const observer = new MutationObserver((mutations, obs) => {
        const groupWrap = document.querySelector('.bpx-player-adv-danmaku-group-wrap');
        if (groupWrap) {
            obs.disconnect();
            // 找到最后一个group
            const lastGroup = groupWrap.querySelector('.bpx-player-adv-danmaku-group:last-child');
            if (lastGroup) {
                // 插入到最后一个group后面
                lastGroup.parentNode.insertBefore(enhancedContainer, lastGroup.nextSibling);

                // 样式弹幕添加事件监听
                setupStyleEventListeners(enhancedContainer);
                // 设置数字输入框的上下箭头事件
                setupNumberStepper(enhancedContainer);
                // 设置颜色选择器
                setupColorPicker();
                // 设置样式弹幕的颜色选择器
                setupStyleColorPickers(enhancedContainer);

                // 设置字符画按钮点击事件
                setupAsciiButton(enhancedContainer);

                // 设置同步字号
                setupSyncFontSize(document,enhancedContainer);
            }
        }
    });

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

    // 创建预览弹幕区域
    const previewArea = document.createElement('div');
    previewArea.className = 'bpx-player-adv-danmaku-group-row bpx-player-adv-danmaku-send';
    previewArea.innerHTML = `
        <span class="bpx-player-adv-danmaku-btn bpx-player-adv-danmaku-send-test bui bui-button upload-danmaku-btn">
            <div class="bui-area bui-button-large">上传弹幕文件</div>
            <input type="file" accept=".json,.xml" style="display: none;">
        </span>
        <span class="bpx-player-adv-danmaku-btn bpx-player-adv-danmaku-send-test bui bui-button preview-danmaku-btn disabled">
            <div class="bui-area bui-button-large">预览本地弹幕</div>
        </span>
        <span class="preview-danmaku-filename"></span>
    `;
    // enhancedContainer.appendChild(previewArea);

    // 添加预览区域样式
    if (!document.querySelector('#enhanced-danmaku-preview-style')) {
        const previewStyle = document.createElement('style');
        previewStyle.id = 'enhanced-danmaku-preview-style';
        previewStyle.textContent = `
            .preview-danmaku-btn,
            .upload-danmaku-btn {
                margin-right: 10px;
            }
            .preview-danmaku-btn .bui-area,
            .upload-danmaku-btn .bui-area {
                background-color: #00a1d6;
                color: #fff;
                border-radius: 4px;
                cursor: pointer;
            }
            .preview-danmaku-btn.disabled .bui-area {
                background-color: #b8b8b8;
                cursor: not-allowed;
            }
            .preview-danmaku-btn .bui-area:hover,
            .upload-danmaku-btn .bui-area:hover {
                background-color: #00b5e5;
            }
            .preview-danmaku-btn.disabled .bui-area:hover {
                background-color: #b8b8b8;
            }
            .preview-danmaku-filename {
                color: #666;
                font-size: 12px;
                line-height: 32px;
                margin-left: 10px;
                max-width: 200px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
        `;
        document.head.appendChild(previewStyle);
    }

    // 获取元素
    const fileInput = previewArea.querySelector('input[type="file"]');
    const previewBtn = previewArea.querySelector('.preview-danmaku-btn');
    const uploadBtn = previewArea.querySelector('.upload-danmaku-btn');
    const filenameSpan = previewArea.querySelector('.preview-danmaku-filename');
    let currentDanmakuList = null;

    // 监听文件选择
    fileInput.addEventListener('change', async (e) => {
        const file = e.target.files[0];
        if (!file) return;

        try {
            const content = await file.text();
            let danmakuList = [];

            if (file.name.endsWith('.xml')) {
                danmakuList = parseXMLDanmaku(content);
            } else if (file.name.endsWith('.json')) {
                danmakuList = parseJSONDanmaku(content);
            }

            if (danmakuList.length > 0) {
                currentDanmakuList = danmakuList;
                filenameSpan.textContent = `${file.name} (${danmakuList.length}条弹幕)`;
                previewBtn.classList.remove('disabled');
            }
        } catch (error) {
            console.error('加载弹幕文件失败:', error);
            alert('加载弹幕文件失败');
        }
    });

    // 上传按钮点击事件
    uploadBtn.addEventListener('click', () => {
        fileInput.click();
    });

    // 预览按钮点击事件
    previewBtn.addEventListener('click', () => {
        if (previewBtn.classList.contains('disabled')) return;

        // 预览弹幕
        previewDanmaku(currentDanmakuList);

    });

    // 创建测试样式按钮
    const testStyleBtn = document.createElement('span');
    testStyleBtn.className = 'bpx-player-adv-danmaku-btn bpx-player-adv-danmaku-send-test bui bui-button';
    testStyleBtn.innerHTML = '<div class="bui-area bui-button-large">测试样式效果</div>';

    // 将测试按钮插入到发送样式弹幕按钮前面
    const enhancedButton = enhancedContainer.querySelector('.enhanced-send-btn');
    enhancedButton.parentNode.insertBefore(testStyleBtn, enhancedButton);

    // 测试按钮点击事件
    testStyleBtn.addEventListener('click', async () => {
        // 获取当前选择的弹幕样式参数
        const baseParams = await getBaseDanmakuParams();
        const params = getAdvancedDanmakuParams();
        // 获取当前选中的样式按钮
        const buttonContainer = document.querySelector('.enhanced-style-buttons');
        const activeButton = buttonContainer.querySelector('.active');
        let currentStyle = activeButton.getAttribute('data-style');

        // 获取字符画发送方式
        const sendMode = document.querySelector('.ascii-send-mode-select .bui-select-item-active').getAttribute('data-value');

        if (currentStyle === 'shadow' || currentStyle === 'stroke' || currentStyle === 'background'  || currentStyle === 'normal') {
            if (!params.text) {
                alert('请输入弹幕内容');
                return;
            }
        }
        if (currentStyle === 'ascii') {
            if (sendMode === 'line') {
                currentStyle = 'ascii-line';
            } else if (sendMode === 'coord') {
                currentStyle = 'ascii-coord';
            }
        }
        let istest = true;
        testStyle(baseParams, params, currentStyle, istest, sendMode)

    });



    // 在Y轴翻转后面添加Z轴跟随移动角度复选框
    const zRotateFollowHtml = `
    <span class="bpx-player-adv-danmaku-checkbox bui bui-checkbox z-rotate-follow" style="margin-top: 25px;margin-left: 13px;>
        <div class="bui-area">
            <input class="bui-checkbox-input" type="checkbox" aria-label="Z轴跟随移动角度">
            <label class="bui-checkbox-label">
                <span class="bui-checkbox-icon bui-checkbox-icon-default">
                    <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                        <path d="M8 6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H8zm0-2h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                    </svg>
                </span>
                <span class="bui-checkbox-icon bui-checkbox-icon-selected">
                    <svg xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32">
                        <path d="m13 18.25-1.8-1.8c-.6-.6-1.65-.6-2.25 0s-.6 1.5 0 2.25l2.85 2.85c.318.318.762.468 1.2.448.438.02.882-.13 1.2-.448l8.85-8.85c.6-.6.6-1.65 0-2.25s-1.65-.6-2.25 0l-7.8 7.8zM8 4h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z"></path>
                    </svg>
                </span>
                <span class="bui-checkbox-name">Z轴跟随移动角度</span>
            </label>
        </div>
    </span>
    `;

    // 在setupEnhancedSendButton函数中添加以下代码
    setTimeout(() => {
        const rotateYContainer = document.querySelector('.bpx-player-adv-danmaku-rotateY');
        if (rotateYContainer) {
            rotateYContainer.insertAdjacentHTML('afterend', zRotateFollowHtml);

            // 添加坐标变化监听
            const zRotateFollow = document.querySelector('.z-rotate-follow input');
            const zRotateInput = document.querySelector('.bpx-player-adv-danmaku-rotateZ input');

            function updateZRotate() {
                if (!zRotateFollow.checked) return;

                const startX = parseFloat(document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="startX"] input').value) || 0;
                const startY = parseFloat(document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="startY"] input').value) || 0;
                const endX = parseFloat(document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="endX"] input').value) || 0;
                const endY = parseFloat(document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="endY"] input').value) || 0;

                // 计算角度
                let angle;
                if (startX >= 0 && startX <= 1 && startY >= 0 && startY <= 1 && endX >= 0 && endX <= 1 && endY >= 0 && endY <= 1) {
                    // 考虑屏幕比16:9,计算实际坐标
                    const screenWidth = 16;
                    const screenHeight = 9;
                    const actualStartX = startX * screenWidth;
                    const actualStartY = startY * screenHeight;
                    const actualEndX = endX * screenWidth;
                    const actualEndY = endY * screenHeight;

                    const dx = actualEndX - actualStartX;
                    const dy = actualEndY - actualStartY;
                    angle = Math.atan2(dy, dx) * (180 / Math.PI);
                } else {
                    const dx = endX - startX;
                    const dy = endY - startY;
                    angle = Math.atan2(dy, dx) * (180 / Math.PI);
                }

                // 将角度转换为0-360范围
                angle = (angle + 360) % 360;
                // if (angle > 0) {  
                //     angle = 360 - angle;
                // }
                // 更新Z轴翻转输入框并触发原本绑定的事件
                zRotateInput.value = Math.round(angle);
                // 创建并触发input事件以更新UI
                const event = new Event('input', { bubbles: true });
                zRotateInput.dispatchEvent(event);
                // 触发change事件以确保所有绑定的事件都被调用
                zRotateInput.dispatchEvent(new Event('change', { bubbles: true }));
            }

            // 监听坐标输入变化
            const coordInputs = [
                'startX', 'startY', 'endX', 'endY'
            ].forEach(key => {
                const input = document.querySelector(`.bpx-player-adv-danmaku-spinner[data-key="${key}"] input`);
                input.addEventListener('input', updateZRotate);
            });

            // 监听复选框状态变化
            zRotateFollow.addEventListener('change', updateZRotate);
        }
    }, 200);

}

/**
 * 更新字符数
 * @param {Element} enhancedContainer 
 */
function updateCharCount(enhancedContainer) {
    const contentTextarea = enhancedContainer.querySelector('.ascii-content');
    const charCountSpan = enhancedContainer.querySelector('.ascii-char-count');
    const content = contentTextarea.value;

    const charCount = [...content].length; // 使用扩展运算符正确计算Unicode字符
    charCountSpan.innerHTML = `字数:${charCount}`;

    // 更新title属性以显示完整内容
    contentTextarea.title = content;
}

/**
 * 设置同步字号
 * @param {Document} document 
 * @param {Element} enhancedContainer 
 */
function setupSyncFontSize(document,enhancedContainer) {
    // 处理发送方式选择
    const sendModeSelect = enhancedContainer.querySelector('.ascii-send-mode-select');
    const lineSpacingContainer = enhancedContainer.querySelector('.ascii-line-spacing');
    const syncFontSizeCheckbox = enhancedContainer.querySelector('.sync-font-size input');
    const fontSizeInput = document.querySelector('.bpx-player-adv-danmaku-font-size input');
    
    // 处理发送方式选择
    sendModeSelect.addEventListener('click', (e) => {
        const item = e.target.closest('.bui-select-item');
        if (item) {
            // 更新选中状态
            sendModeSelect.querySelectorAll('.bui-select-item').forEach(el => {
                el.classList.remove('bui-select-item-active');
            });
            item.classList.add('bui-select-item-active');
            
            // 更新显示的文本
            const resultText = sendModeSelect.querySelector('.bui-select-result');
            resultText.textContent = item.textContent;
            
            // 根据选择显示/隐藏行间距输入框
            lineSpacingContainer.style.display = 
                item.getAttribute('data-value') === 'line' ? '' : 'none';
        }
    });

    // 处理同步字号勾选框
    syncFontSizeCheckbox.addEventListener('change', () => {
        if (syncFontSizeCheckbox.checked) {
            // 同步字号
            const lineSpacingInput = document.querySelector('.line-spacing');
            lineSpacingInput.value = fontSizeInput.value;
        }
    });

    // 监听字体大小变化
    fontSizeInput.addEventListener('input', () => {
        if (syncFontSizeCheckbox.checked) {
            const lineSpacingInput = document.querySelector('.line-spacing');
            lineSpacingInput.value = fontSizeInput.value;
        }
    });

    // 监听每行间距变化
    const lineSpacingInput = document.querySelector('.line-spacing');
    lineSpacingInput.addEventListener('input', () => {
        if (syncFontSizeCheckbox.checked) {
            fontSizeInput.value = lineSpacingInput.value;
        }
    });
    
}



function setupAsciiButton(enhancedContainer) {
    // 处理发送方式选择
    const sendModeSelect = enhancedContainer.querySelector('.ascii-send-mode-select');
    const lineSpacingContainer = enhancedContainer.querySelector('.ascii-line-spacing');
    const syncFontSizeContainer = enhancedContainer.querySelector('.ascii-sync-font-size');

    // 同步字号勾选框
    const syncFontSizeCheckbox = document.querySelector('.sync-font-size input');

    // 处理下拉框的显示/隐藏
    const selectHeader = sendModeSelect.querySelector('.bui-select-header');
    const selectList = sendModeSelect.querySelector('.bui-select-list-wrap');
    const selectListUl = sendModeSelect.querySelector('.bui-select-list');


    // 处理字符画内容的字数统计和悬浮展示
    const contentTextarea = enhancedContainer.querySelector('.ascii-content');
    const charCountSpan = enhancedContainer.querySelector('.ascii-char-count');

    // const defaultAscii = ``;
    // contentTextarea.value = defaultAscii;

    // 监听输入事件
    contentTextarea.addEventListener('input', () => updateCharCount(enhancedContainer));
    // 初始化字数统计
    updateCharCount(enhancedContainer);


    selectHeader.addEventListener('click', () => {
        // 切换下拉列表的显示状态
        const isVisible = selectList.style.display === 'block';

        if (!isVisible) {
            // 显示下拉列表时设置正确的高度
            selectList.style.display = 'block';
            // 每个选项24px高,2个选项就是48px
            selectListUl.style.height = '48px';
            selectListUl.style.border = '1px solid #e3e5e7';
        } else {
            // 隐藏时重置样式
            selectList.style.display = 'none';
            selectListUl.style.height = '0px';
            selectListUl.style.border = 'none';
        }

        // 添加/移除active类
        sendModeSelect.classList.toggle('active');
    });

    // 处理选项点击
    selectList.addEventListener('click', (e) => {
        const item = e.target.closest('.bui-select-item');
        if (item) {
            // 更新选中状态
            sendModeSelect.querySelectorAll('.bui-select-item').forEach(el => {
                el.classList.remove('bui-select-item-active');
            });
            item.classList.add('bui-select-item-active');

            // 更新显示的文本
            const resultText = sendModeSelect.querySelector('.bui-select-result');
            resultText.textContent = item.textContent;

            // 隐藏下拉列表
            selectList.style.display = 'none';
            selectListUl.style.height = '0px';
            selectListUl.style.border = 'none';
            sendModeSelect.classList.remove('active');

            // 根据选择显示/隐藏行间距输入框
            lineSpacingContainer.style.display = item.getAttribute('data-value') === 'line' ? '' : 'none';

            syncFontSizeContainer.style.display  = item.getAttribute('data-value') === 'line' ? '' : 'none';
        }
    });

    // 点击外部关闭下拉列表
    document.addEventListener('click', (e) => {
        if (!sendModeSelect.contains(e.target)) {
            selectList.style.display = 'none';
            selectListUl.style.height = '0px';
            selectListUl.style.border = 'none';
            sendModeSelect.classList.remove('active');
        }
    });

    // 处理字符画按钮点击时也要重置下拉列表状态
    const asciiBtn = enhancedContainer.querySelector('[data-style="ascii"]');
    const asciiParams = enhancedContainer.querySelector('.ascii-params');

    asciiBtn.addEventListener('click', () => {
        // 隐藏其他参数区域
        enhancedContainer.querySelectorAll('.enhanced-params-area > div').forEach(div => {
            if (div !== asciiParams) {
                div.style.display = 'none';
            }
        });
        // 显示字符画参数区域
        asciiParams.style.display = 'block';

        // 重置下拉列表状态
        selectList.style.display = 'none';
        selectListUl.style.height = '0px';
        selectListUl.style.border = 'none';
        sendModeSelect.classList.remove('active');
    });

}

/**
 * 测试弹幕样式
 * @param {Object} baseParams 基础弹幕参数
 * @param {Object} params 高级弹幕参数
 * @param {string} currentStyle 当前选中的弹幕样式
 * @param {boolean} istest 是否是测试弹幕
 */
function testStyle(baseParams, params, currentStyle, istest) {

    const baseTime = istest ? Math.floor(window.player.getCurrentTime() * 1000) : parseFloat(baseParams.progress);
    // 转换为弹幕对象数组
    let testDanmakus = [];

    // 基础弹幕对象
    const baseDanmaku = {
        stime: baseTime,
        mode: 7,
        size: baseParams.fontSize,
        date: baseTime,
        pool: 0,
        uhash: '',
    };
    // 根据特效类型生成不同的弹幕组合
    switch (currentStyle) {
        case 'shadow':
            // 阴影效果:生成2条弹幕
            const shadowColor = document.querySelector('.shadow-color').value;
            const offsetX = parseFloat(document.querySelector('.shadow-offset-x').value);
            const offsetY = parseFloat(document.querySelector('.shadow-offset-y').value);

            const shadowParams = { ...params };
            shadowParams.startX = trimTrailingZeros((parseFloat(params.startX) + offsetX).toFixed(3));
            shadowParams.startY = trimTrailingZeros((parseFloat(params.startY) + offsetY).toFixed(3));
            shadowParams.endX = trimTrailingZeros((parseFloat(params.endX) + offsetX).toFixed(3));
            shadowParams.endY = trimTrailingZeros((parseFloat(params.endY) + offsetY).toFixed(3));
            shadowParams.color = shadowColor;

            testDanmakus = [
                {
                    ...baseDanmaku,
                    dmid: `test_shadow_bg_${baseTime}`,
                    color: convertColorToDecimal(shadowColor),
                    text: buildAdvancedDanmakuText(shadowParams)
                },
                {
                    ...baseDanmaku,
                    stime: baseDanmaku.stime + 0.001,
                    dmid: `test_shadow_main_${baseTime}`,
                    color: baseParams.color,
                    text: buildAdvancedDanmakuText(params)
                }
            ];
            break;
        case 'stroke':
            testDanmakus = [];

            const strokeColor = document.querySelector('.stroke-color').value;
            const spacing = document.querySelector('.stroke-spacing').value;
            if (!strokeColor || !spacing) {
                alert('请填写描边颜色和间距');
                return;
            }
            // 发送9条弹幕
            for (let i = 0; i < 9; i++) {
                const currentParams = { ...params };
                currentParams.stroke = 0;

                if (i < 8) {
                    // 前8条是描边,支持小数坐标
                    const positions = [
                        { x: -1, y: -1 }, // 左上
                        { x: 0, y: -1 },  // 中上
                        { x: 1, y: -1 },  // 右上
                        { x: -1, y: 0 },  // 左中
                        { x: 1, y: 0 },   // 右中
                        { x: -1, y: 1 },  // 左下
                        { x: 0, y: 1 },   // 中下
                        { x: 1, y: 1 }    // 右下
                    ];
                    const offsetX = parseFloat(spacing) * positions[i].x;
                    const offsetY = parseFloat(spacing) * positions[i].y;
                    currentParams.startX = trimTrailingZeros((parseFloat(params.startX) + offsetX).toFixed(3));
                    currentParams.startY = trimTrailingZeros((parseFloat(params.startY) + offsetY).toFixed(3));
                    currentParams.endX = trimTrailingZeros((parseFloat(params.endX) + offsetX).toFixed(3));
                    currentParams.endY = trimTrailingZeros((parseFloat(params.endY) + offsetY).toFixed(3));
                    testDanmakus.push({
                        ...baseDanmaku,
                        dmid: `test_stroke_${baseTime}_${i}`,
                        color: convertColorToDecimal(strokeColor),
                        text: buildAdvancedDanmakuText(currentParams)
                    });
                } else {
                    // 最后一条是原始弹幕,时间延迟0.001秒
                    testDanmakus.push({
                        ...baseDanmaku,
                        stime: baseDanmaku.stime + 0.001,
                        dmid: `test_stroke_${baseTime}_${i}`,
                        color: baseParams.color,
                        text: buildAdvancedDanmakuText(currentParams)
                    });
                }
            }

            break;
        case 'background':

            const backgroundColor = document.querySelector('.background-color').value;
            const backgroundChar = document.querySelector('.background-char').value;
            const isVertical = document.querySelector('.vertical-text').checked;

            if (!backgroundColor || !backgroundChar) {
                alert('请填写背景颜色和背景字符');
                return;
            }

            // 发送背景弹幕
            const backgroundParams = { ...params };
            let newText = params.text.replace(/\\n/g, ''); // 清除换行符获取文本长度
            let bgText = backgroundChar.repeat(newText.length);
            let originalText = params.text;

            // 如果勾选了转竖列,转换背景字符和原文本
            if (isVertical) {
                if (!bgText.includes('\\n')) {
                    bgText = convertToVertical(bgText);
                }
                console.log("originalText:", originalText);
                debugger;
                if (!originalText.includes('\\n')) {
                    originalText = convertToVertical(originalText);
                }
                params.text = originalText; // 使用可能转换后的文本
            }

            backgroundParams.text = bgText;
            backgroundParams.fontFamily = 'SimHei';
            backgroundParams.stroke = 0;

            // 背景效果:生成2条弹幕,一个文字一个背景
            testDanmakus = [
                {
                    ...baseDanmaku,
                    dmid: `test_bg_back_${baseTime}`,
                    color: convertColorToDecimal(backgroundColor), // 黑色背景
                    text: buildAdvancedDanmakuText(backgroundParams)
                },
                {
                    ...baseDanmaku,
                    stime: baseDanmaku.stime + 0.001,
                    dmid: `test_bg_text_${baseTime}`,
                    color: baseParams.color,
                    text: buildAdvancedDanmakuText(params)
                }
            ];
            break;
        case 'normal':
            testDanmakus = [
                {
                    ...baseDanmaku,
                    dmid: `test_normal_${baseTime}`,
                    color: baseParams.color,
                    text: buildAdvancedDanmakuText(params)
                }
            ];
            break;
        case 'ascii-line':
            testDanmakus = [];
            const asciiContent = document.querySelector('.ascii-content').value;
            // 分行处理
            const lines = asciiContent.split('\n').filter(line => line);
      
            // 更换Y坐标每行发送模式
            const lineSpacing = parseInt(document.querySelector('.line-spacing').value) || 36;
            let currentY = parseFloat(params.startY);
            let currentEndY = parseFloat(params.endY);

            // 逐行发送
            for (let i = 0; i < lines.length; i++) {
                const line = lines[i];
                if (!line) continue;

                const asciiParams = {
                    ...params,
                    text: line,
                    startY: currentY,
                    endY: currentEndY
                };

                // 更新Y坐标
                currentY += lineSpacing;
                currentEndY += lineSpacing;

                testDanmakus.push({
                    ...baseDanmaku,
                    dmid: `test_ascii_${baseTime}`,
                    color: baseParams.color,
                    text: buildAdvancedDanmakuText(asciiParams)
                });
            }

            break;
        case 'ascii-coord':
            testDanmakus = [];
            const coordAsciiContent = document.querySelector('.ascii-content').value;
            // 分行处理
            const coordLines = coordAsciiContent.split('\n');

            // 逐行发送
            for (let i = 0; i < coordLines.length; i++) {
                let line = coordLines[i];
                if (!line) continue;

                line = '\n'.repeat(i) + line;  // 将每行弹幕之间插入换行符

                const asciiParams = {
                    ...params,
                    text: line
                };

                testDanmakus.push({
                    ...baseDanmaku,
                    dmid: `test_ascii_coord_${baseTime}`,
                    color: baseParams.color,
                    text: buildAdvancedDanmakuText(asciiParams)
                });
            }

            break;
    }
    console.log(testDanmakus);

    // 预览这些测试弹幕
    previewDanmaku(testDanmakus);

    // if (istest) {
    //     console.log("测试弹幕持续时间:", params.duration);
    //     setTimeout(() => {
    //         console.log("删除测试弹幕");
    //         removePreviewDanmaku(testDanmakus);
    //     }, params.duration * 1000);
    // }
}


/**
 * 加载日期选择器
 */
function loadDatePicker() {
    // 用于存储查找元素的任务配置
    let task = {};

    /**
     * 查找指定选择器的元素并执行回调
     * @param {Object} param0 配置对象
     * @param {string} param0.selector CSS选择器
     * @param {Element} param0.context 查找上下文,默认为document
     * @param {Function} param0.callback 找到元素后的回调函数
     */
    function getElement({ selector, context = document, callback }) {
        const elem = context.querySelector(selector);
        if (elem) {
            callback(elem);
        }
    }

    // 创建MutationObserver用于监听DOM变化
    let ob = new MutationObserver(function (recode) {
        getElement(task);
    });

    // Promise链式调用,按顺序查找并操作各个元素
    return new Promise(resolve => {
        console.log("查找弹幕盒子");
        // 1. 查找弹幕盒子
        task.selector = "#danmukuBox";
        task.callback = resolve;
        getElement(task);
    }).then(danmukuBox => new Promise(resolve => {
        // 2. 监听弹幕盒子的变化,查找折叠面板
        ob.disconnect();
        ob.observe(danmukuBox, {
            "childList": true,
            "subtree": true
        });
        task.selector = "div.bui-collapse-wrap";
        task.context = danmukuBox;
        task.callback = resolve;
        getElement(task);
    })).then(collapseWrap => new Promise(resolve => {
        // 3. 如果面板折叠则展开,查找历史按钮
        if (collapseWrap.classList.contains("bui-collapse-wrap-folded")) {
            collapseWrap.querySelector("div.bui-collapse-header").click();
        }
        task.selector = "div.bpx-player-dm-btn-history";
        task.context = collapseWrap;
        task.callback = resolve;
        getElement(task);
    })).then(datePickerBtn => new Promise(resolve => {
        // 4. 监听历史按钮变化,点击显示日期选择器
        ob.disconnect();
        ob.observe(datePickerBtn, {
            "attributes": true,
            "childList": true,
            "subtree": true
        });

        // 修改这里:使用Promise确保点击事件完成后再继续
        return new Promise(clickResolve => {
            datePickerBtn.click();
            // 给一点时间让日期选择器显示出来
            setTimeout(() => {
                task.selector = "div.bpx-player-date-picker.bpx-player-show";
                task.context = datePickerBtn;
                task.callback = (elem) => {
                    clickResolve(elem);
                    resolve(elem);
                };
                getElement(task);
            }, 100);
        });
    })).then(datePicker => {
        console.log("关闭日期选择器", datePicker);
        // 确保日期选择器存在并且是显示状态
        if (datePicker && datePicker.classList.contains('bpx-player-show')) {
            const historyBtn = datePicker.closest("div.bpx-player-dm-btn-history");
            if (historyBtn) {
                historyBtn.click();
                console.log("日期选择器已关闭");
            } else {
                console.error("未找到历史按钮");
            }
        } else {
            console.error("日期选择器未处于显示状态");
        }
    }).finally(() => {
        ob.disconnect();
    });
}

/**
 * 注入弹幕到播放器
 */
function injectDanmaku(danmakuList) {
    // 将弹幕数据保存到隐藏元素中
    const localDmFile = document.getElementById('localDmFile');
    if (!localDmFile) {
        console.error('未找到本地弹幕容器');
        return;
    }
    // 使用原生方法保存数据
    localDmFile.setAttribute('data-decode-msg', JSON.stringify(danmakuList));

    // 先加载日期选择器,然后触发点击事件
    loadDatePicker().then(() => {
        // 模拟点击历史弹幕面板第一天的记录来触发加载
        const datePickerSelector = "#danmukuBox div.bpx-player-dm-btn-history div.bpx-player-date-picker";
        const datePicker = document.querySelector(datePickerSelector);
        if (!datePicker) return;

        const daySpan = datePicker.querySelector("div.bpx-player-date-picker-day-content span.bpx-player-date-picker-day");
        if (!daySpan) return;

        const fakeElement = daySpan.cloneNode(true);
        fakeElement.setAttribute('data-timestamp', String(new Date().setHours(0, 0, 0, 0) / 1e3));
        fakeElement.setAttribute('data-action', 'changeDay');

        const fakeEvent = new MouseEvent("click");
        Object.defineProperty(fakeEvent, "target", { value: fakeElement });
        datePicker.dispatchEvent(fakeEvent);

        // 延迟一下再自动播放,确保弹幕已经注入
        setTimeout(() => {
            autoPlayAfterPreview();
        }, 100);
    }).catch(error => {
        console.error('加载日期选择器失败:', error);
    });

}

/**
 * 劫持B站的弹幕历史记录加载功能
 */
function hookLoadHistory() {
    // 使用Object.defineProperty劫持全局对象的allHistory属性
    Object.defineProperty(Object.prototype, "allHistory", {
        set(v) {
            // 删除原有属性,防止递归调用
            delete Object.prototype.allHistory;
            let that = this;
            this.allHistory = v;
            // 使用Proxy代理allHistory,拦截获取操作
            this.allHistory = new Proxy(this.allHistory, {
                get(target, prop) {
                    // 清空高级弹幕列表
                    that.dmListStore.basList = [];
                    const basDanmaku = that.nodes.basDanmaku.querySelector('div.bas-danmaku');
                    if (basDanmaku) basDanmaku.innerHTML = "";

                    // 如果不是获取第一条历史记录,直接返回原值
                    if (prop !== "0") {
                        return target[prop];
                    } else {
                        // 获取本地弹幕数据
                        const localDmFile = document.getElementById('localDmFile');
                        const localRemoveDmFile = document.getElementById('localRemoveDmFile');
                        let decodeMsg = localDmFile ? localDmFile.getAttribute('data-decode-msg') : null;
                        let decodeRemoveMsg = localRemoveDmFile ? localRemoveDmFile.getAttribute('data-decode-msg') : null;

                        if (decodeMsg) {
                            // 如果是字符串则解析为对象
                            if (typeof decodeMsg === 'string') {
                                decodeMsg = JSON.parse(decodeMsg);
                            }
                            // 删除弹幕不为空则删除
                            // if (decodeRemoveMsg) {
                            //     debugger;
                            //     console.log("decodeRemoveMsg:", JSON.parse(decodeRemoveMsg));
                            //     if (typeof decodeRemoveMsg === 'string') {
                            //         decodeRemoveMsg = JSON.parse(decodeRemoveMsg);
                            //         for (let i = 0; i < decodeMsg.length; i++) {
                            //             for (let j = 0; j < decodeRemoveMsg.length; j++) {
                            //                 if (decodeRemoveMsg[j].dmid == decodeMsg[i].dmid) {
                            //                     let text = decodeMsg[i].text;
                            //                     console.log("decodeMsg[i].text:", text);
                            //                     let newText = text.split(",");
                            //                     // 将第五个参数值置为空字符串
                            //                     if (newText.length >= 5) {
                            //                         newText[4] = "\"\"";
                            //                     }
                            //                     decodeMsg[i].text = newText.join(","); // 更新text字段
                            //                     console.log("更新后的text:", decodeMsg[i].text);
                            //                 }
                            //             }
                            //         }
                            //     }
                            // }

                            // 合并本地弹幕和历史弹幕
                            return target[prop].then(originList => {
                                // 如果原始列表存在,则合并
                                if (Array.isArray(originList)) {
                                    let newList = [...decodeMsg, ...originList].sort((a, b) => a.stime - b.stime);
                                    return newList;
                                }

                                // 否则只返回本地弹幕
                                return decodeMsg;
                            });
                        } else {
                            // 否则返回原始历史记录
                            return target[prop];
                        }
                    }
                },
            });
        },
        get() {
            return this._allHistory;
        },
        configurable: true,
    });
}

/**
 * 注入弹幕到播放器
 */
function removePreviewDanmaku(danmakuList) {
    // 将弹幕数据保存到隐藏元素中
    const localRemoveDmFile = document.getElementById('localRemoveDmFile');
    if (!localRemoveDmFile) {
        console.error('未找到本地弹幕容器');
        return;
    }
    // 使用原生方法保存数据
    localRemoveDmFile.setAttribute('data-decode-msg', JSON.stringify(danmakuList));

    // 先加载日期选择器,然后触发点击事件
    loadDatePicker().then(() => {
        // 模拟点击历史弹幕面板第一天的记录来触发加载
        const datePickerSelector = "#danmukuBox div.bpx-player-dm-btn-history div.bpx-player-date-picker";
        const datePicker = document.querySelector(datePickerSelector);
        if (!datePicker) return;

        const daySpan = datePicker.querySelector("div.bpx-player-date-picker-day-content span.bpx-player-date-picker-day");
        if (!daySpan) return;

        const fakeElement = daySpan.cloneNode(true);
        fakeElement.setAttribute('data-timestamp', String(new Date().setHours(0, 0, 0, 0) / 1e3));
        fakeElement.setAttribute('data-action', 'changeDay');

        const fakeEvent = new MouseEvent("click");
        Object.defineProperty(fakeEvent, "target", { value: fakeElement });
        datePicker.dispatchEvent(fakeEvent);

        // 延迟一下再自动播放,确保弹幕已经注入
        setTimeout(() => {
            autoPlayAfterPreview();
        }, 100);
    }).catch(error => {
        console.error('加载日期选择器失败:', error);
    });

    // 刷新弹幕
    const player = window.player;
    if (player && player.reloadDanmaku) {
        player.reloadDanmaku();
    }

}

/**
 * 样式弹幕添加事件监听
 */
function setupStyleEventListeners(container) {
    // 默认选中阴影效果
    let currentStyle = 'shadow';

    // 样式切换事件
    const styleButtons = container.querySelector('.enhanced-style-buttons');
    styleButtons.addEventListener('click', (e) => {
        const button = e.target.closest('.bpx-player-adv-danmaku-btn');
        if (!button) return;

        // 更新按钮状态
        styleButtons.querySelectorAll('.bpx-player-adv-danmaku-btn').forEach(btn => {
            btn.classList.remove('active');
        });
        button.classList.add('active');
        currentStyle = button.dataset.style;

        // 显示对应的参数区域
        container.querySelector('.stroke-params').style.display = currentStyle === 'stroke' ? 'block' : 'none';
        container.querySelector('.shadow-params').style.display = currentStyle === 'shadow' ? 'block' : 'none';
        container.querySelector('.background-params').style.display = currentStyle === 'background' ? 'block' : 'none';
        container.querySelector('.normal-params').style.display = currentStyle === 'normal' ? 'block' : 'none';
        container.querySelector('.ascii-params').style.display = currentStyle === 'ascii' ? 'block' : 'none';
    });

    // 发送按钮事件
    const enhancedButton = container.querySelector('.enhanced-send-btn');
    enhancedButton.addEventListener('click', async () => {
        if (!currentStyle) {
            alert('请选择一个样式');
            return;
        }

        if (currentStyle === 'shadow') {
            await sendShadowDanmaku(currentStyle);
        } else if (currentStyle === 'stroke') {
            await sendStrokeDanmaku(currentStyle);
        } else if (currentStyle === 'background') {
            await sendBackgroundDanmaku(currentStyle);
        } else if (currentStyle === 'normal') {
            await sendNormalDanmaku(currentStyle);
        } else if (currentStyle === 'ascii') {
            await sendAsciiDanmaku(currentStyle);
        }

    });

}

/**
 * 发送字符画弹幕
 */
async function sendAsciiDanmaku(currentStyle) {
    // 获取字符画内容
    const container = document.querySelector('.enhanced-danmaku-container');
    const button = container.querySelector('.enhanced-send-btn');
    const status = container.querySelector('.enhanced-send-status');

    const asciiContent = document.querySelector('.ascii-content').value;
    if (!asciiContent.trim()) {
        alert('请输入字符画内容');
        return;
    }

    // 获取发送方式
    const sendMode = document.querySelector('.ascii-send-mode-select .bui-select-item-active').getAttribute('data-value');

    // 获取基础参数
    const baseParams = await getBaseDanmakuParams();
    if (!baseParams) return;
    const params = getAdvancedDanmakuParams();



    if (sendMode === 'line') {
        // 分行处理
        const lines = asciiContent.split('\n');

        // 更换Y坐标每行发送模式
        const lineSpacing = parseInt(document.querySelector('.line-spacing').value) || 36;
        let currentY = parseFloat(params.startY);
        let currentEndY = parseFloat(params.endY);

        let baseTime = 5 * (lines.length - 1); // 基础时间:1个间隔,5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共${lines.length}条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);

        let hasFailure = false;
        let failureCount = 0;

        // 逐行发送
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            if (!line) continue;
            const asciiParams = {
                ...params,
                text: line,
                startY: currentY,
                endY: currentEndY
            };

            // 更新Y坐标
            currentY += lineSpacing;
            currentEndY += lineSpacing;

            try {
                await sendDanmakuWithRetry(asciiParams, baseParams.color, baseParams.fontSize);
            } catch (error) {
                console.error('阴影弹幕发送失败:' + error.message);
                hasFailure = true;
                failureCount++;
                // 只在第一次失败时更新预计时间
                if (failureCount === 1) {
                    estimatedTime = baseTime + 21; // 增加一次重试的时间
                    await updateSendStatus(button, status, `共${lines.length}条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
                }
            }

            const waitTime = hasFailure ? 21000 : 5000;
            await new Promise(resolve => setTimeout(resolve, waitTime));
        }

        // 发送完成
        await updateSendStatus(button, status, `共${lines.length}条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);

        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, asciiParams, 'ascii-line', istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);

    } else if (sendMode === 'coord') {
        debugger;
        // 分行处理
        const coordLines = asciiContent.split('\n');

        let baseTime = 5 * (coordLines.length - 1); // 基础时间:1个间隔,5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共${coordLines.length}条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);

        let hasFailure = false;
        let failureCount = 0;

        // 逐行发送
        for (let i = 0; i < coordLines.length; i++) {
            let line = coordLines[i];
            if (!line) continue;

            line = '\\n'.repeat(i) + line;  // 将每行弹幕之间插入换行符
            if (!line) continue;
            const asciiParams = {
                ...params,
                text: line
            };

            try {
                await sendDanmakuWithRetry(asciiParams, baseParams.color, baseParams.fontSize);
            } catch (error) {
                console.error('阴影弹幕发送失败:' + error.message);
                hasFailure = true;
                failureCount++;
                // 只在第一次失败时更新预计时间
                if (failureCount === 1) {
                    estimatedTime = baseTime + 21; // 增加一次重试的时间
                    await updateSendStatus(button, status, `共${lines.length}条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
                }
            }

            const waitTime = hasFailure ? 21000 : 5000;
            await new Promise(resolve => setTimeout(resolve, waitTime));
        }

        // 发送完成
        await updateSendStatus(button, status, `共${coordLines.length}条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);

        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, asciiParams, 'ascii-coord', istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);
    } else if (sendMode === 'all') {
        // 整体发送模式
        const text = lines.join('');
        const params = {
            ...baseParams,
            text: text
        };

        try {
            await sendDanmaku(params);
            showMessage('字符画弹幕发送完成');
        } catch (error) {
            console.error('发送失败:', error);
            showMessage('发送失败,请重试');
        }
    }
}


// 辅助函数:更新发送进度
function updateSendingProgress(current) {
    const statusEl = document.querySelector('.enhanced-send-status');
    if (statusEl) {
        const total = parseInt(statusEl.textContent.split('/')[1]);
        statusEl.textContent = `发送进度:${current}/${total}`;
    }
}

/**
 * 获取基础弹幕参数
 */
async function getBaseDanmakuParams() {
    // 尝试多种方式获取 aid 和 cid
    let aid = null;
    let cid = null;

    // 方法1: 从 __INITIAL_STATE__ 获取
    if (window.__INITIAL_STATE__) {
        aid = window.__INITIAL_STATE__.aid;
        cid = window.__INITIAL_STATE__.epInfo?.cid || window.__INITIAL_STATE__.cid;
    }

    // 方法2: 从 URL 获取 BV号,然后查询视频信息获取aid和cid
    if (!aid || !cid) {
        try {
            // 从 URL 中提取 bvid
            const bvidMatch = window.location.pathname.match(/\/video\/(BV[\w]+)/);
            if (bvidMatch) {
                const bvid = bvidMatch[1];
                // 获取分P号,默认为1
                const urlParams = new URLSearchParams(window.location.search);
                const p = parseInt(urlParams.get('p')) || 1;

                // 调用API获取视频信息
                const response = await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`);
                const data = await response.json();
                if (data.code === 0) {
                    aid = data.data.aid;
                    // 根据分P获取对应的cid
                    if (data.data.pages && data.data.pages.length >= p) {
                        cid = data.data.pages[p - 1].cid;
                    }
                }
            }
        } catch (error) {
            console.error('获取视频信息失败:', error);
        }
    }

    if (!aid || !cid) {
        alert('获取视频信息失败,请刷新页面重试');
        return null;
    }

    const hexColor = document.querySelector('.bui-color-picker-input input').value;
    const color = convertColorToDecimal(hexColor);
    const fontSize = parseInt(document.querySelector('.bpx-player-adv-danmaku-font-size input').value);

    // 优先使用时间输入框的值
    const inputTime = parseTimeInput();
    const progress = inputTime !== null ? inputTime : Math.floor(window.player.getCurrentTime() * 1000);

    // 尝试多种方式获取 csrf token
    let csrf = document.cookie.match(/bili_jct=([^;]+)/)?.[1];
    if (!csrf) {
        // 尝试从页面全局变量获取
        csrf = window.bili_jct || window.CSRF_TOKEN;
    }

    if (!csrf) {
        alert('获取CSRF Token失败,请确保已登录');
        return null;
    }

    return { aid, cid, color, fontSize, progress, csrf };
}

/**
 * 获取高级弹幕参数
 */
function getAdvancedDanmakuParams() {
    // 获取所有参数
    const startX = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="startX"] input').value;
    const startY = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="startY"] input').value;
    const sOpacity = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="sOpacity"] input').value;
    const eOpacity = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="eOpacity"] input').value;
    const duration = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="duration"] input').value;
    const text = document.querySelector('.bpx-player-adv-danmaku-text-input textarea').value;
    const zRotate = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="zRotate"] input').value;
    const yRotate = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="yRotate"] input').value;
    const endX = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="endX"] input').value;
    const endY = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="endY"] input').value;
    const aTime = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="aTime"] input').value;
    const aDelay = document.querySelector('.bpx-player-adv-danmaku-spinner[data-key="aDelay"] input').value;
    const stroke = document.querySelector('.bpx-player-adv-danmaku-font-stroke input').checked ? 1 : 0;
    const family = document.querySelector('.bpx-player-adv-danmaku-font-family-select .bui-select-result').textContent;
    const linearSpeedUp = document.querySelector('.bpx-player-adv-danmaku-speedup input').checked ? 1 : 0;

    return {
        startX, startY, sOpacity, eOpacity, duration, text,
        zRotate, yRotate, endX, endY, aTime, aDelay,
        stroke, family, linearSpeedUp
    };
}

/**
 * 发送阴影效果弹幕
 */
async function sendShadowDanmaku(currentStyle) {
    const container = document.querySelector('.enhanced-danmaku-container');
    const button = container.querySelector('.enhanced-send-btn');
    const status = container.querySelector('.enhanced-send-status');

    try {
        const params = getAdvancedDanmakuParams();
        if (!params.text) {
            alert('请输入弹幕内容');
            return;
        }

        const shadowColor = document.querySelector('.shadow-color').value;
        const offsetX = parseFloat(document.querySelector('.shadow-offset-x').value);
        const offsetY = parseFloat(document.querySelector('.shadow-offset-y').value);

        if (!shadowColor || isNaN(offsetX) || isNaN(offsetY)) {
            alert('请填写阴影颜色和偏移值');
            return;
        }

        const baseParams = await getBaseDanmakuParams();
        if (!baseParams) return;

        // 更新发送状态,阴影效果共2条弹幕
        let baseTime = 5; // 基础时间:1个间隔,5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共2条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);

        let hasFailure = false;
        let failureCount = 0;

        // 发送阴影弹幕,支持小数坐标
        const shadowParams = { ...params };
        shadowParams.startX = trimTrailingZeros((parseFloat(params.startX) + offsetX).toFixed(3));
        shadowParams.startY = trimTrailingZeros((parseFloat(params.startY) + offsetY).toFixed(3));
        shadowParams.endX = trimTrailingZeros((parseFloat(params.endX) + offsetX).toFixed(3));
        shadowParams.endY = trimTrailingZeros((parseFloat(params.endY) + offsetY).toFixed(3));
        try {
            await sendDanmakuWithRetry(shadowParams, convertColorToDecimal(shadowColor), baseParams.fontSize);
        } catch (error) {
            console.error('阴影弹幕发送失败:' + error.message);
            hasFailure = true;
            failureCount++;
            // 只在第一次失败时更新预计时间
            if (failureCount === 1) {
                estimatedTime = baseTime + 21; // 增加一次重试的时间
                await updateSendStatus(button, status, `共2条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
            }
        }

        const waitTime = hasFailure ? 21000 : 5000;
        await new Promise(resolve => setTimeout(resolve, waitTime));

        // 发送原始弹幕
        const progress = baseParams.progress + 1;
        try {
            await sendDanmakuWithRetry(params, baseParams.color, baseParams.fontSize, progress);
        } catch (error) {
            console.error('原始弹幕发送失败:' + error.message);
            hasFailure = true;
            failureCount++;
        }

        // 发送完成
        await updateSendStatus(button, status, `共2条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);

        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, params, currentStyle, istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);

    } catch (error) {
        // 发送失败
        await updateSendStatus(button, status, '发送失败:' + error.message);
        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);
    }
}

/**
 * 发送描边效果弹幕
 */
async function sendStrokeDanmaku(currentStyle) {
    const container = document.querySelector('.enhanced-danmaku-container');
    const button = container.querySelector('.enhanced-send-btn');
    const status = container.querySelector('.enhanced-send-status');

    try {
        const params = getAdvancedDanmakuParams();
        if (!params.text) {
            alert('请输入弹幕内容');
            return;
        }

        const strokeColor = document.querySelector('.stroke-color').value;
        const spacing = document.querySelector('.stroke-spacing').value;
        if (!strokeColor || !spacing) {
            alert('请填写描边颜色和间距');
            return;
        }

        const baseParams = await getBaseDanmakuParams();
        if (!baseParams) return;

        // 更新发送状态,描边效果共9条弹幕
        let baseTime = 8 * 5; // 基础时间:8个间隔,每个5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共9条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);

        let hasFailure = false;
        let failureCount = 0;

        // 发送9条弹幕
        for (let i = 0; i < 9; i++) {
            const currentParams = { ...params };
            currentParams.stroke = 0;

            if (i < 8) {
                // 前8条是描边,支持小数坐标
                const positions = [
                    { x: -1, y: -1 }, // 左上
                    { x: 0, y: -1 },  // 中上
                    { x: 1, y: -1 },  // 右上
                    { x: -1, y: 0 },  // 左中
                    { x: 1, y: 0 },   // 右中
                    { x: -1, y: 1 },  // 左下
                    { x: 0, y: 1 },   // 中下
                    { x: 1, y: 1 }    // 右下
                ];
                const offsetX = parseFloat(spacing) * positions[i].x;
                const offsetY = parseFloat(spacing) * positions[i].y;
                currentParams.startX = trimTrailingZeros((parseFloat(params.startX) + offsetX).toFixed(3));
                currentParams.startY = trimTrailingZeros((parseFloat(params.startY) + offsetY).toFixed(3));
                currentParams.endX = trimTrailingZeros((parseFloat(params.endX) + offsetX).toFixed(3));
                currentParams.endY = trimTrailingZeros((parseFloat(params.endY) + offsetY).toFixed(3));
                try {
                    await sendDanmakuWithRetry(currentParams, convertColorToDecimal(strokeColor), baseParams.fontSize);
                } catch (error) {
                    console.error(`第${i + 1}条弹幕发送失败:${error.message}`);
                    hasFailure = true;
                    failureCount++;
                    // 只在第一次失败时更新预计时间
                    if (failureCount === 1) {
                        estimatedTime = baseTime + 21; // 增加一次重试的时间
                        await updateSendStatus(button, status, `共9条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
                    }
                    continue;
                }
            } else {
                // 最后一条是原始弹幕,时间延迟0.001秒
                const progress = baseParams.progress + 1;
                try {
                    await sendDanmakuWithRetry(currentParams, baseParams.color, baseParams.fontSize, progress);
                } catch (error) {
                    console.error(`最后一条弹幕发送失败:${error.message}`);
                    hasFailure = true;
                    failureCount++;
                }
            }

            if (i < 8) {
                const waitTime = hasFailure ? 21000 : 5000;
                await new Promise(resolve => setTimeout(resolve, waitTime));
            }
        }

        // 发送完成
        await updateSendStatus(button, status, `共9条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);

        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, params, currentStyle, istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);

    } catch (error) {
        // 发送失败
        await updateSendStatus(button, status, '发送失败:' + error.message);
        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);
    }
}

/**
 * 发送文字背景弹幕
 */
async function sendBackgroundDanmaku(currentStyle) {
    const container = document.querySelector('.enhanced-danmaku-container');
    const button = container.querySelector('.enhanced-send-btn');
    const status = container.querySelector('.enhanced-send-status');

    try {
        const params = getAdvancedDanmakuParams();
        if (!params.text) {
            alert('请输入弹幕内容');
            return;
        }

        const backgroundColor = document.querySelector('.background-color').value;
        const backgroundChar = document.querySelector('.background-char').value;
        const isVertical = document.querySelector('.vertical-text').checked;

        if (!backgroundColor || !backgroundChar) {
            alert('请填写背景颜色和背景字符');
            return;
        }

        const baseParams = await getBaseDanmakuParams();
        if (!baseParams) return;

        // 更新发送状态,文字背景效果共2条弹幕
        let baseTime = 5; // 基础时间:1个间隔,5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共2条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);

        let hasFailure = false;
        let failureCount = 0;

        // 发送背景弹幕
        const backgroundParams = { ...params };
        let bgText = backgroundChar.repeat(params.text.length);
        let originalText = params.text;

        // 如果勾选了转竖列,转换背景字符和原文本
        if (isVertical) {
            bgText = convertToVertical(bgText);
            originalText = convertToVertical(originalText);
        }

        backgroundParams.text = bgText;
        backgroundParams.fontFamily = 'SimHei';
        backgroundParams.stroke = 0;

        try {
            await sendDanmakuWithRetry(backgroundParams, convertColorToDecimal(backgroundColor), baseParams.fontSize);
        } catch (error) {
            console.error('背景弹幕发送失败:' + error.message);
            hasFailure = true;
            failureCount++;
            // 只在第一次失败时更新预计时间
            if (failureCount === 1) {
                estimatedTime = baseTime + 21; // 增加一次重试的时间
                await updateSendStatus(button, status, `共2条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
            }
        }

        const waitTime = hasFailure ? 21000 : 5000;
        await new Promise(resolve => setTimeout(resolve, waitTime));

        // 发送原始弹幕
        const progress = baseParams.progress + 1;
        params.text = originalText; // 使用可能转换后的文本
        try {
            await sendDanmakuWithRetry(params, baseParams.color, baseParams.fontSize, progress);
        } catch (error) {
            console.error('原始弹幕发送失败:' + error.message);
            hasFailure = true;
            failureCount++;
        }

        // 发送完成
        await updateSendStatus(button, status, `共2条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);


        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, params, currentStyle, istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);

    } catch (error) {
        // 发送失败
        await updateSendStatus(button, status, '发送失败:' + error.message);
        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);
    }
}

/**
 * 发送普通弹幕
 */
async function sendNormalDanmaku(currentStyle) {
    const container = document.querySelector('.enhanced-danmaku-container');
    const button = container.querySelector('.enhanced-send-btn');
    const status = container.querySelector('.enhanced-send-status');

    try {
        const params = getAdvancedDanmakuParams();
        if (!params.text) {
            alert('请输入弹幕内容');
            return;
        }

        const baseParams = await getBaseDanmakuParams();
        if (!baseParams) return;

        // 更新发送状态,文字背景效果共2条弹幕
        let baseTime = 5; // 基础时间:1个间隔,5秒
        let estimatedTime = baseTime;
        await updateSendStatus(button, status, `共1条弹幕,预计发送${estimatedTime}秒。正在发送中`, true);
        let hasFailure = false;

        // 发送原始弹幕
        try {
            await sendDanmakuWithRetry(params, baseParams.color, baseParams.fontSize);
        } catch (error) {
            console.error('原始弹幕发送失败:' + error.message);
            hasFailure = true;
        }

        // 发送完成
        await updateSendStatus(button, status, `共1条弹幕,已${hasFailure ? '部分' : '全部'}发送完成`);

        // 立即预览弹幕
        let istest = false;
        testStyle(baseParams, params, currentStyle, istest)

        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);

    } catch (error) {
        // 发送失败
        await updateSendStatus(button, status, '发送失败:' + error.message);
        setTimeout(() => {
            updateSendStatus(button, status, '');
        }, 3000);
    }

}

/**
 * 发送单条弹幕
 */
async function sendDanmaku(params, color, fontSize, progress = null) {
    const baseParams = await getBaseDanmakuParams();
    if (!baseParams) return;

    const formData = new URLSearchParams({
        type: 1,
        oid: baseParams.cid,
        msg: buildAdvancedDanmakuText(params, fontSize),
        aid: baseParams.aid,
        progress: progress || baseParams.progress,
        color: color,
        fontsize: fontSize,
        pool: 0,
        mode: 7,
        rnd: Math.floor(Date.now() / 1000),
        csrf: baseParams.csrf
    });
    // 打印当前弹幕发送时间
    console.log(`当前弹幕发送时间: ${new Date().toLocaleString()}`);
    const response = await fetch('https://api.bilibili.com/x/v2/dm/post', {
        method: 'POST',
        body: formData,
        credentials: 'include',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    });

    const result = await response.json();
    if (result.code !== 0) {
        throw new Error(result.message);
    }
}


/**
 * 发送单条弹幕(带重试)
 */
async function sendDanmakuWithRetry(params, color, fontSize, progress = null, retryCount = 1) {
    try {
        await sendDanmaku(params, color, fontSize, progress);
        return true;
    } catch (error) {
        if (retryCount > 0) {
            // 失败后等待21秒重试
            await new Promise(resolve => setTimeout(resolve, 21000));
            return sendDanmakuWithRetry(params, color, fontSize, progress, retryCount - 1);
        }
        throw error;
    }
}


/**
 * 更新发送状态显示
 */
async function updateSendStatus(button, status, text, isLoading = false) {
    // 更新按钮状态
    if (isLoading) {
        button.classList.add('disabled');
        button.style.pointerEvents = 'none';
    } else {
        button.classList.remove('disabled');
        button.style.pointerEvents = 'auto';
    }

    // 更新状态文本显示
    if (text) {
        status.style.display = 'inline-block';
        if (isLoading) {
            let dots = 0;
            const interval = setInterval(() => {
                status.textContent = text + '.'.repeat(dots + 1);
                dots = (dots + 1) % 3;
            }, 500);

            // 保存interval ID到status元素
            status.dataset.intervalId = interval;
        } else {
            // 清除现有的interval
            const intervalId = parseInt(status.dataset.intervalId);
            if (intervalId) {
                clearInterval(intervalId);
                delete status.dataset.intervalId;
            }
            status.textContent = text;
        }
    } else {
        status.style.display = 'none';
        status.textContent = '';
        // 清除interval
        const intervalId = parseInt(status.dataset.intervalId);
        if (intervalId) {
            clearInterval(intervalId);
            delete status.dataset.intervalId;
        }
    }
}

/**
 * 解析XML格式的弹幕文件
 */
function parseXMLDanmaku(content) {
    const parser = new DOMParser();
    const xml = parser.parseFromString(content, 'text/xml');
    const danmakuList = [];

    xml.querySelectorAll('d').forEach(d => {
        const p = d.getAttribute('p').split(',');
        danmakuList.push({
            stime: parseFloat(p[0]) * 1000,
            mode: parseInt(p[1]),
            size: parseInt(p[2]),
            color: parseInt(p[3]),
            date: parseInt(p[4]),
            pool: parseInt(p[5]),
            uhash: p[6],
            dmid: p[7],
            text: d.textContent
        });
    });

    return danmakuList;
}

/**
 * 解析JSON格式的弹幕文件
 */
function parseJSONDanmaku(content) {
    const data = JSON.parse(content);
    return data.map(item => ({
        stime: item.progress || item.stime * 1000,
        mode: item.mode,
        size: item.fontsize,
        color: item.color,
        date: item.ctime,
        pool: 0,
        uhash: '',
        dmid: item.dmid || '',
        text: item.text
    }));
}


/**
 * 解析时间输入框的值,转换为毫秒
 */
function parseTimeInput() {
    /*
    * 支持格式:
    * - 秒数(如:5)
    * - 时间格式:
    *   - M:SS(如:6:05)
    *   - H:MM:SS(如:1:00:01)
    *   - MM:SS(如:06:05)
    *   - HH:MM:SS(如:01:00:01)
    * - 带毫秒的时间格式:
    *   - M:SS.SSS
    *   - H:MM:SS.SSS
    *   - MM:SS.SSS
    *   - HH:MM:SS.SSS
    * 
    */
    const timeInput = document.querySelector('.bpx-player-adv-danmaku-showtime-input input');
    if (!timeInput || !timeInput.value.trim()) return null;

    const value = timeInput.value.trim();

    // 尝试解析时间格式
    if (value.includes(':')) {
        // 先处理可能存在的毫秒部分
        let mainPart = value;
        let milliseconds = 0;

        if (value.includes('.')) {
            const [timePart, msPart] = value.split('.');
            mainPart = timePart;
            // 将毫秒部分标准化为3位数
            milliseconds = parseInt((msPart + '000').slice(0, 3));
        }

        const parts = mainPart.split(':').map(Number);
        let totalMilliseconds = milliseconds;

        // 检查每个部分是否为有效数字
        if (parts.some(isNaN)) return null;

        if (parts.length === 2) {
            // M:SS 或 MM:SS 格式
            const [minutes, seconds] = parts;
            if (seconds >= 60) return null; // 秒数不能超过60
            totalMilliseconds += (minutes * 60 + seconds) * 1000;
            return totalMilliseconds;
        } else if (parts.length === 3) {
            // H:MM:SS 或 HH:MM:SS 格式
            const [hours, minutes, seconds] = parts;
            if (minutes >= 60 || seconds >= 60) return null; // 分秒不能超过60
            totalMilliseconds += (hours * 3600 + minutes * 60 + seconds) * 1000;
            return totalMilliseconds;
        }
    }

    // 尝试解析秒数(支持小数)
    const seconds = parseFloat(value);
    if (!isNaN(seconds)) {
        return Math.floor(seconds * 1000);
    }

    return null;
}


/**
 * 组装高级弹幕文本
 */
function buildAdvancedDanmakuText(params, fontSize) {
    const text = `[${params.startX},${params.startY},"${params.sOpacity}-${params.eOpacity}",${params.duration},"${params.text}",${params.zRotate},${params.yRotate},${params.endX},${params.endY},${params.aTime},${params.aDelay},${params.stroke},"${params.family}",${params.linearSpeedUp}]`;
    return text;
}

/**
 * 将文本转换为竖列格式
 * @param {string} text - 原始文本
 * @returns {string} - 转换后的竖列文本
 */
function convertToVertical(text) {
    return text.split('').join('\\n');
}

/**
 * 将16进制颜色代码转换为10进制
 * @param {string} hexColor - 16进制颜色代码,例如 "#FFFFFF"
 * @returns {number} 10进制颜色值
 */
function convertColorToDecimal(hexColor) {
    // 移除#号并转换为10进制
    return parseInt(hexColor.replace('#', ''), 16);
}


/**
 * 去除数字字符串末尾多余的0
 * @param {string} numStr - 数字字符串
 * @returns {string} - 处理后的数字字符串
 */
function trimTrailingZeros(numStr) {
    return numStr.replace(/\.?0+$/, '');
}

/**
 * 监听并修改弹幕发送时间
 */
function setupDanmakuTimeModifier() {
    // 使用 Proxy 拦截 XMLHttpRequest
    const XHRProxy = new Proxy(XMLHttpRequest, {
        construct(target) {
            const xhr = new target();

            // 保存原始的 open 方法
            const originalOpen = xhr.open;
            xhr.open = function (method, url, ...args) {
                // 标记弹幕发送请求
                if (url.includes('/x/v2/dm/post')) {
                    xhr._isDanmakuRequest = true;
                }
                return originalOpen.call(xhr, method, url, ...args);
            };

            // 保存原始的 send 方法
            const originalSend = xhr.send;
            xhr.send = function (body) {
                if (xhr._isDanmakuRequest && body) {
                    const timeInput = document.querySelector('.bpx-player-adv-danmaku-showtime-input input');
                    if (timeInput && timeInput.value && timeInput.value.includes('.')) {
                        console.log('检测到小数点时间:', timeInput.value);
                        const inputTime = parseTimeInput();
                        if (inputTime !== null) {
                            const formData = new URLSearchParams(body);
                            formData.set('progress', inputTime);
                            body = formData.toString();
                            console.log('出现时间修改后的请求参数:', body);
                        }
                    }
                    const durationInput = document.querySelector('.bpx-player-adv-danmaku-duration .bui-input-input');
                    if (durationInput) {
                        const durationValue = parseFloat(durationInput.value);
                        if (durationValue > 10) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[3] = durationValue; // 替换第四个值为新的持续时间
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                            console.log('生存时间修改后的请求参数:', body);
                        }
                    }
                    const animationTimeInput = document.querySelector('.bpx-player-adv-danmaku-animation-time input');
                    if (animationTimeInput) {
                        const animationTimeValue = parseFloat(animationTimeInput.value);
                        if (animationTimeValue > 10000) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[9] = animationTimeValue; // 替换第十个值为新的运动耗时
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                            console.log('运动耗时修改后的请求参数:', body);
                        }
                    }
                    const animationDelayInput = document.querySelector('.bpx-player-adv-danmaku-animation-delay input');
                    if (animationDelayInput) {
                        const animationDelayValue = parseFloat(animationDelayInput.value);
                        if (animationDelayValue > 10000) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[10] = animationDelayValue; // 替换第十一个值为新的延迟时间
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                            console.log('延迟时间修改后的请求参数:', body);
                        }
                    }
                    const startXInput = document.querySelector('.bpx-player-adv-danmaku-pos-start .bpx-player-adv-danmaku-spinner[data-key="startX"] input');
                    if (startXInput) {
                        const startXValue = parseFloat(startXInput.value);
                        if (startXValue < 0) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[0] = startXValue; // 替换第十二个值为新的起始X
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                        }
                    }
                    const startYInput = document.querySelector('.bpx-player-adv-danmaku-pos-start .bpx-player-adv-danmaku-spinner[data-key="startY"] input');
                    if (startYInput) {
                        const startYValue = parseFloat(startYInput.value);
                        if (startYValue < 0) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[1] = startYValue; // 替换第十三个值为新的起始Y
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                        }
                    }
                    const endXInput = document.querySelector('.bpx-player-adv-danmaku-pos-end .bpx-player-adv-danmaku-spinner[data-key="endX"] input');
                    if (endXInput) {
                        const endXValue = parseFloat(endXInput.value);
                        if (endXValue < 0) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[7] = endXValue; // 替换第七个值为新的结束X
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                        }
                    }
                    const endYInput = document.querySelector('.bpx-player-adv-danmaku-pos-end .bpx-player-adv-danmaku-spinner[data-key="endY"] input');
                    if (endYInput) {
                        const endYValue = parseFloat(endYInput.value);
                        if (endYValue < 0) {
                            const formData = new URLSearchParams(body);
                            const msgArray = JSON.parse(formData.get('msg'));
                            msgArray[8] = endYValue; // 替换第八个值为新的结束Y
                            formData.set('msg', JSON.stringify(msgArray));
                            body = formData.toString();
                            body = formData.toString();
                            console.log('结束Y修改后的请求参数:', body);
                            body = formData.toString();                        
                            console.log('结束Y修改后的请求参数:', body);
                        }
                    }

                }
                return originalSend.call(xhr, body);
            };

            return xhr;
        }
    });

    // 替换原始的 XMLHttpRequest
    window.XMLHttpRequest = XHRProxy;

    // 监听发送按钮以便调试
    const observer = new MutationObserver((mutations, obs) => {
        const sendButton = document.querySelector('.bpx-player-adv-danmaku-send-send .bui-area.bui-button-large');
        if (sendButton && !sendButton.dataset.enhanced) {
            sendButton.dataset.enhanced = 'true';
            sendButton.addEventListener('click', () => {
                const timeInput = document.querySelector('.bpx-player-adv-danmaku-showtime-input input');
                if (timeInput && timeInput.value) {
                    const inputTime = parseTimeInput();
                }
            }, true);
        }
    });

    // 开始观察文档变化
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
}

/**
 * 设置样式弹幕的颜色选择器
 */
function setupStyleColorPickers(container) {
    const colorPickers = {
        '.shadow-color': '.shadow-params',
        '.stroke-color': '.stroke-params',
        '.background-color': '.background-params',
    };

    // 添加自定义样式
    const style = document.createElement('style');
    style.textContent = `
            .enhanced-danmaku-container .bui-color-picker-input {
                width: 70px !important;
            }
            .enhanced-danmaku-container .bui-color-picker-input input {
                width: 100% !important;
            }
        `;
    document.head.appendChild(style);

    Object.entries(colorPickers).forEach(([inputSelector, paramsSelector]) => {
        const colorInput = container.querySelector(`${paramsSelector} ${inputSelector}`);
        const displayArea = colorInput.closest('.bui-color-picker-result').querySelector('.bui-color-picker-display');

        // 创建隐藏的颜色选择器
        const colorPicker = document.createElement('input');
        colorPicker.type = 'color';
        colorPicker.style.cssText = `
                width: 0;
                height: 0;
                padding: 0;
                border: none;
                position: absolute;
                visibility: hidden;
            `;
        displayArea.parentNode.appendChild(colorPicker);

        // 点击显示区域时触发颜色选择器
        displayArea.style.cursor = 'pointer';
        displayArea.addEventListener('click', () => {
            colorPicker.value = colorInput.value;
            colorPicker.click();
        });

        // 监听颜色变化
        colorPicker.addEventListener('input', (e) => {
            const hexColor = e.target.value.toUpperCase();
            colorInput.value = hexColor;
            displayArea.style.background = hexColor;
            colorInput.dispatchEvent(new Event('input', { bubbles: true }));
        });

        // 监听输入框变化
        colorInput.addEventListener('input', (e) => {
            const hexColor = e.target.value.toUpperCase();
            displayArea.style.background = hexColor;
        });
    });
}

// 在预览弹幕时自动播放
function autoPlayAfterPreview() {
    console.log("自动播放");

    // 获取播放按钮和音量按钮
    const playButton = document.querySelector('.bpx-player-ctrl-play');
    const volumeButton = document.querySelector('.bpx-player-ctrl-volume-icon');
    if (!playButton) {
        return;
    }

    // 检查当前音量状态
    const playerContainer = document.querySelector('.bpx-player-container');
    const isMuted = playerContainer.classList.contains('bpx-player-volume-0');
    let needRestoreVolume = false;

    // 如果当前有声音,则先静音并延迟播放
    if (!isMuted) {
        console.log("1.临时静音");
        volumeButton.click();
        needRestoreVolume = true;
        // 延迟执行后续操作,确保静音生效
        setTimeout(() => {
            playVideo();
        }, 100);
    } else {
        // 已经是静音状态,直接播放
        playVideo();
    }

    function playVideo() {
        // 如果当前是暂停状态,模拟点击播放按钮
        if (playerContainer.classList.contains('bpx-state-paused')) {
            console.log("2.点击播放按钮");
            playButton.click();

            // 确保弹幕容器也取消暂停状态
            const danmakuContainer = document.querySelector('.bpx-player-row-dm-wrap');
            if (danmakuContainer) {
                danmakuContainer.classList.remove('bili-danmaku-x-paused');
            }

            // 短暂延迟后暂停播放
            setTimeout(() => {
                console.log("3.暂停播放");
                playButton.click();

                // 如果之前有声音,恢复声音
                if (needRestoreVolume) {
                    console.log("4.恢复声音");
                    volumeButton.click();
                }

                // 保持弹幕继续显示
                if (danmakuContainer) {
                    danmakuContainer.classList.remove('bili-danmaku-x-paused');
                }
            }, 500);
        }
    }
}

// 修改预览弹幕的处理函数
function previewDanmaku(currentDanmakuList) {
    if (!currentDanmakuList) {
        return;
    }
    injectDanmaku(currentDanmakuList);
}

(function () {
    'use strict';

    // 初始化劫持弹幕历史记录功能
    hookLoadHistory();

    // 等待 DOM 加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    function init() {
        // 确保 document.body 存在
        if (!document.body) {
            setTimeout(init, 100);
            return;
        }

        // 添加隐藏的localDmFile元素
        const localDmFile = document.createElement('div');
        localDmFile.id = 'localDmFile';
        localDmFile.style.display = 'none';
        document.body.appendChild(localDmFile);

        const localRemoveDmFile = document.createElement('div');
        localRemoveDmFile.id = 'localRemoveDmFile';
        localRemoveDmFile.style.display = 'none';
        document.body.appendChild(localRemoveDmFile);

        console.log("启用高级弹幕加强功能");


        // 监听弹幕列表加载
        const listObserver = new MutationObserver((mutations, obs) => {
            const collapseWrap = document.querySelector('.bui-collapse-wrap');
            if (collapseWrap) {
                // 如果是折叠状态,点击展开
                if (collapseWrap.classList.contains('bui-collapse-wrap-folded')) {
                    const header = collapseWrap.querySelector('.bui-collapse-header');
                    if (header) {
                        header.click();
                    }
                }
                obs.disconnect();
            }
        });

        // 开始观察文档变化
        listObserver.observe(document.body, {
            childList: true,
            subtree: true
        });

        // addNewFonts();
        // 监听视频播放器加载
        const observer = new MutationObserver((mutations, obs) => {
            const dropdownName = document.querySelector('.bui-dropdown-name');
            if (dropdownName && dropdownName.textContent === '高级弹幕') {
                obs.disconnect();
                setupFontSelector();
                setupEnhancedSendButton();
                bypassDurationLimit();
            }
        });
        setupDanmakuTimeModifier();
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
})();

// 方案1: 移除输入限制
function removeInputLimit() {
    const durationInput = document.querySelector('.bpx-player-adv-danmaku-duration input');
    if (durationInput) {
        // 克隆并替换节点来移除所有事件监听器
        const newInput = durationInput.cloneNode(true);
        durationInput.parentNode.replaceChild(newInput, durationInput);

        // 移除max属性
        newInput.removeAttribute('max');
        // 更新dataset
        newInput.closest('.bpx-player-adv-danmaku-spinner').dataset.max = '99999';
    }
}

// 方案2: 监听并阻止值被重置
function bypassDurationLimit() {
    // 需要解除限制的输入框选择器列表
    const limitedInputs = [
        '.bpx-player-adv-danmaku-duration input',  // 生存时间
        '.bpx-player-adv-danmaku-animation-time input',  // 运动耗时
        '.bpx-player-adv-danmaku-animation-delay input',  // 延迟时间
        '.bpx-player-adv-danmaku-pos-start .bpx-player-adv-danmaku-spinner[data-key="startX"] input',  // 起始X
        '.bpx-player-adv-danmaku-pos-start .bpx-player-adv-danmaku-spinner[data-key="startY"] input',  // 起始Y
        '.bpx-player-adv-danmaku-pos-end .bpx-player-adv-danmaku-spinner[data-key="endX"] input',  // 结束X
        '.bpx-player-adv-danmaku-pos-end .bpx-player-adv-danmaku-spinner[data-key="endY"] input'  // 结束Y
    ];

    limitedInputs.forEach(selector => {
        const input = document.querySelector(selector);
        if (!input) return;

        let userValue = input.value;

        // 使用MutationObserver监听值的变化
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'value') {
                    if (input.value !== userValue) {
                        input.value = userValue;
                    }
                }
            });
        });

        // 监听value属性变化
        observer.observe(input, {
            attributes: true,
            attributeFilter: ['value']
        });

        // 监听用户输入
        input.addEventListener('input', (e) => {
            userValue = e.target.value;
        });

        // 监听失焦事件
        input.addEventListener('blur', () => {
            setTimeout(() => {
                if (input.value !== userValue) {
                    input.value = userValue;
                }
            }, 0);
        });
    });
}