/*
// 功能：后台管理脚本文件
// 作者：启肯科技
// Q Q：328493711
// 微信：13738373177（同手机）
// 官网：http://www.qiken.com
// 说明：QKCMS-轻量级AI智能内容管理建站系统
// 版权：© 2025 温州启肯网络有限公司 保留所有权利，盗版必究。
*/

// 确保PHP在页面加载时定义了全局变量 DEFAULT_THUMBNAIL_PATH
// 如果全局变量未定义，提供一个默认值作为后备方案
if (typeof window.DEFAULT_THUMBNAIL_PATH === 'undefined') {
    window.DEFAULT_THUMBNAIL_PATH = '/assets/images/moren.jpg';
}

// 颜色工具函数
function hexToRgb(hex) {
    hex = hex.replace('#', '');
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    return { r, g, b };
}

function lightenColor(color, percent) {
    let r = parseInt(color.substring(1, 3), 16);
    let g = parseInt(color.substring(3, 5), 16);
    let b = parseInt(color.substring(5, 7), 16);
    r = Math.floor(r + (255 - r) * percent / 100);
    g = Math.floor(g + (255 - g) * percent / 100);
    b = Math.floor(b + (255 - b) * percent / 100);
    r = (r < 255) ? r : 255;
    g = (g < 255) ? g : 255;
    b = (b < 255) ? b : 255;
    r = Math.round(r);
    g = Math.round(g);
    b = Math.round(b);
    return "#" + (0x1000000 + r * 0x10000 + g * 0x100 + b).toString(16).slice(1);
}

function darkenColor(color, percent) {
    let r = parseInt(color.substring(1, 3), 16);
    let g = parseInt(color.substring(3, 5), 16);
    let b = parseInt(color.substring(5, 7), 16);
    r = Math.floor(r * (1 - percent / 100));
    g = Math.floor(g * (1 - percent / 100));
    b = Math.floor(b * (1 - percent / 100));
    r = (r > 0) ? r : 0;
    g = (g > 0) ? g : 0;
    b = (b > 0) ? b : 0;
    r = Math.round(r);
    g = Math.round(g);
    b = Math.round(b);
    return "#" + (0x1000000 + r * 0x10000 + g * 0x100 + b).toString(16).slice(1);
}



// 初始化评论编辑模态窗
// 存储当前编辑的图片列表
let currentEditImages = [];

function initCommentEditModal() {
    let modalContainer = document.getElementById('modal-container');
    if (!modalContainer) {
        modalContainer = document.createElement('div');
        modalContainer.id = 'modal-container';
        document.body.appendChild(modalContainer);
    }

    let commentEditModal = document.getElementById('commentEditModal');
    if (!commentEditModal) {
        commentEditModal = document.createElement('div');
        commentEditModal.id = 'commentEditModal';
        commentEditModal.className = 'modal';
        commentEditModal.style.display = 'none';
        commentEditModal.innerHTML = `
            <div class="modal-backdrop"></div>
            <div class="modal-content" style="max-width: 600px;">
                <div class="modal-header">
                    <h3 class="modal-title">编辑评论</h3>
                    <button type="button" class="modal-close" onclick="window.closeModal()">×</button>
                </div>
                <div class="modal-body">
                    <form id="commentEditForm">
                        <input type="hidden" id="editCommentId" name="comment_id" value="">
                        <div class="form-group">
                            <label>评论图片</label>
                            <div id="editCommentImages" class="comment-images-list" style="display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;"></div>
                        </div>
                        <div class="form-group">
                            <label>评论内容</label>
                            <textarea id="editCommentContent" name="content" class="form-control" rows="4" placeholder="请输入评论内容"></textarea>
                        </div>
                        <div class="form-group">
                            <label for="editCommentStatus">状态</label>
                            <select id="editCommentStatus" name="status" class="form-control">
                                <option value="1">已审核</option>
                                <option value="0">待审核</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <button type="button" id="submitCommentEdit" class="submit-button" style="background-color: var(--primary-color); width: 100%; padding: 10px 16px;">更新评论</button>
                        </div>
                    </form>
                </div>
            </div>
        `;
        document.body.appendChild(commentEditModal);

        const closeButton = commentEditModal.querySelector('.modal-close');
        if (closeButton) {
            closeButton.addEventListener('click', () => window.closeModal());
        }

        const submitButton = commentEditModal.querySelector('#submitCommentEdit');
        if (submitButton) {
            submitButton.addEventListener('click', window.submitCommentEdit);
        }
    }
}

// 渲染图片列表
function renderEditImages() {
    const container = document.getElementById('editCommentImages');
    if (!container) return;
    
    container.innerHTML = '';
    currentEditImages.forEach((imgSrc, index) => {
        const imgWrapper = document.createElement('div');
        imgWrapper.className = 'edit-image-item';
        imgWrapper.style.position = 'relative';
        imgWrapper.style.display = 'inline-block';
        
        const img = document.createElement('img');
        img.src = imgSrc;
        img.style.width = '80px';
        img.style.height = '80px';
        img.style.objectFit = 'cover';
        img.style.borderRadius = '8px';
        img.style.border = '1px solid #eee';
        
        const deleteBtn = document.createElement('button');
        deleteBtn.innerHTML = '×';
        deleteBtn.style.position = 'absolute';
        deleteBtn.style.top = '-5px';
        deleteBtn.style.right = '-5px';
        deleteBtn.style.width = '20px';
        deleteBtn.style.height = '20px';
        deleteBtn.style.borderRadius = '50%';
        deleteBtn.style.border = 'none';
        deleteBtn.style.backgroundColor = '#ff4444';
        deleteBtn.style.color = 'white';
        deleteBtn.style.fontSize = '14px';
        deleteBtn.style.cursor = 'pointer';
        deleteBtn.style.display = 'flex';
        deleteBtn.style.alignItems = 'center';
        deleteBtn.style.justifyContent = 'center';
        deleteBtn.onclick = function(e) {
            e.stopPropagation();
            currentEditImages.splice(index, 1);
            renderEditImages();
        };
        
        imgWrapper.appendChild(img);
        imgWrapper.appendChild(deleteBtn);
        container.appendChild(imgWrapper);
    });
}

// 从 HTML 中提取纯文本和图片
function parseCommentHtml(html) {
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = html || '';
    
    const images = [];
    const imgElements = tempDiv.querySelectorAll('img');
    imgElements.forEach(img => {
        if (img.src) {
            images.push(img.src);
        }
    });
    
    imgElements.forEach(img => img.remove());
    const text = tempDiv.textContent || tempDiv.innerText || '';
    
    return { text: text.trim(), images };
}

// 重新组装 HTML
function buildCommentHtml(text, images) {
    let html = text || '';
    if (images && images.length > 0) {
        if (html) html += '<br><br>';
        images.forEach(imgSrc => {
            html += `<img src="${imgSrc}" src="${imgSrc}">`;
        });
    }
    return html || '<p></p>';
}

window.openEditCommentModal = function (commentId, content, status) {
    try {
        initCommentEditModal();

        const modal = document.getElementById('commentEditModal');
        const commentIdInput = document.getElementById('editCommentId');
        const commentStatus = document.getElementById('editCommentStatus');
        const commentContent = document.getElementById('editCommentContent');

        if (!modal || !commentIdInput || !commentStatus || !commentContent) {
            console.error('未找到模态框或表单元素');
            return;
        }

        commentIdInput.value = commentId;
        commentStatus.value = status;

        const parsed = parseCommentHtml(content);
        commentContent.value = parsed.text;
        currentEditImages = parsed.images;
        renderEditImages();

        addModalStyles();

        modal.style.display = 'flex';
        setTimeout(() => {
            modal.classList.add('modal-visible');
            document.addEventListener('keydown', handleEscKey);
        }, 10);

    } catch (error) {
        console.error('打开评论编辑模态框时发生错误:', error);
        if (typeof showToast === 'function') {
            showToast('无法打开编辑窗口，请刷新页面重试', 'error');
        }
    }
};

window.submitCommentEdit = function () {
    try {
        const commentId = document.getElementById('editCommentId').value;
        const text = document.getElementById('editCommentContent').value;
        const status = document.getElementById('editCommentStatus').value;
        const content = buildCommentHtml(text, currentEditImages);

        if (!text.trim() && currentEditImages.length === 0) {
            showToast('评论内容不能为空', 'error');
            return;
        }

        const formData = new FormData();
        formData.append('comment_id', commentId);
        formData.append('content', content);
        formData.append('status', status);
        formData.append('edit_comment_submit', '1');

        const submitButton = document.getElementById('submitCommentEdit');
        const originalText = submitButton.innerHTML;
        submitButton.disabled = true;
        submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 更新中...';

        // 发送AJAX请求
        const xhr = new XMLHttpRequest();
        xhr.open('POST', '?tab=comments', true);

        // 设置请求完成的回调函数
        xhr.onload = function () {
            try {
                // 尝试解析JSON响应
                let responseData;
                try {
                    responseData = JSON.parse(xhr.responseText);
                } catch (jsonError) {
                    // 如果不是有效的JSON，可能是旧的响应格式
                    responseData = xhr.responseText;
                }

                // 检查请求是否成功
                if (xhr.status >= 200 && xhr.status < 300) {
                    // 处理响应数据
                    if (typeof responseData === 'object') {
                        if (responseData.success) {
                            showToast('评论更新成功', 'info');
                            window.closeModal();
                            if (typeof HeaderPagination !== 'undefined') {
                                HeaderPagination.load(); // 刷新列表
                            } else {
                                setTimeout(() => {
                                    window.location.reload();
                                }, 1500);
                            }
                        }
                    } else if (typeof responseData === 'string') {
                        if (responseData.includes('评论更新成功') || responseData.includes('success')) {
                            showToast('评论更新成功', 'info');
                            window.closeModal();
                            if (typeof HeaderPagination !== 'undefined') {
                                HeaderPagination.load(); // 刷新列表
                            } else {
                                setTimeout(() => {
                                    window.location.reload();
                                }, 1500);
                            }
                        } else {
                            showToast('评论更新失败，请重试', 'error');
                        }
                    }
                } else {
                    showToast('请求失败，状态码: ' + xhr.status, 'error');
                }
            } catch (error) {
                console.error('处理响应时出错:', error);
                showToast('处理响应时发生错误，请重试', 'error');
            } finally {
                // 恢复按钮状态
                submitButton.disabled = false;
                submitButton.innerHTML = originalText;
            }
        };

        // 设置错误回调函数
        xhr.onerror = function () {
            console.error('网络请求错误');
            showToast('更新失败，请检查网络连接', 'error');
            // 恢复按钮状态
            submitButton.disabled = false;
            submitButton.innerHTML = originalText;
        };

        // 发送请求
        xhr.send(formData);
    } catch (error) {
        console.error('提交评论编辑时发生错误:', error);
        showToast('提交失败，请重试', 'error');
    }
};

window.closeModal = function () {
    try {
        // 获取所有可能的模态框
        const modals = [
            document.getElementById('editUserModal'),
            document.getElementById('commentEditModal'),
            document.getElementById('navigationEditModal'),
            document.getElementById('modal-container')?.querySelector('.modal')
        ].filter(modal => modal);

        // 移除所有模态框的可见类
        modals.forEach(modal => {
            modal.classList.remove('modal-visible');
        });

        // 延迟处理 - 统一处理所有模态框
        setTimeout(() => {
            // 重置body样式
            // 只恢复overflow属性
            document.body.style.overflow = '';

            // 移除ESC键事件监听
            document.removeEventListener('keydown', handleEscKey);

            // 处理各个模态框
            modals.forEach(modal => {
                if (modal.id === 'modal-container') {
                    modal.innerHTML = '';
                } else if (modal.id === 'commentEditModal') {
                    modal.style.display = 'none';
                    const form = modal.querySelector('form');
                    if (form) form.reset();
                    // 清空 Quill 编辑器
                    if (commentQuillEditor) {
                        commentQuillEditor.root.innerHTML = '';
                    }
                } else {
                    modal.style.display = 'none';
                    const form = modal.querySelector('form');
                    if (form) form.reset();
                }
            });

            // 重置用户表单（如果函数存在）
            if (typeof resetUserForm === 'function') {
                resetUserForm();
            }
        }, 300);
    } catch (error) {
        console.error('关闭模态框时出错:', error);
    }
};

function handleEscKey(event) {
    if (event.key === 'Escape') window.closeModal();
}

document.addEventListener('DOMContentLoaded', function () {
    function applyThemeColor(color) {
        document.documentElement.style.setProperty('--primary', color);
        document.documentElement.style.setProperty('--primary-color', color);
        const lightColor = lightenColor(color, 10);
        const darkColor = darkenColor(color, 10);
        document.documentElement.style.setProperty('--primary-light', lightColor);
        document.documentElement.style.setProperty('--primary-dark', darkColor);
        document.documentElement.style.setProperty('--primary-color-light', lightColor);
        document.documentElement.style.setProperty('--primary-color-dark', darkColor);
        document.querySelectorAll('.color-option').forEach(option => {
            if (option.getAttribute('data-color') === color) option.classList.add('active');
            else option.classList.remove('active');
        });
        if (window.syncDropdownTriangleColors) window.syncDropdownTriangleColors();
    }

    // 获取主题色输入框（支持新旧ID）
    const primaryColorInput = document.getElementById('primary_color') || document.getElementById('theme_primary_color');
    const savedColor = primaryColorInput?.value;
    if (savedColor) applyThemeColor(savedColor);
    else {
        fetch('/admin/admin.php?action=get_theme_color')
            .then(response => response.json())
            .then(data => { if (data.primary_color) applyThemeColor(data.primary_color); })
            .catch(error => applyThemeColor('#7c3aed'));
    }

    document.querySelectorAll('.color-option').forEach(option => {
        option.addEventListener('click', function () {
            document.querySelectorAll('.color-option').forEach(opt => opt.classList.remove('active'));
            this.classList.add('active');
            const color = this.getAttribute('data-color');

            // 更新主题色输入框（支持新旧ID）
            const primaryColorInput = document.getElementById('primary_color') || document.getElementById('theme_primary_color');
            if (primaryColorInput) {
                primaryColorInput.value = color;
            }

            document.documentElement.style.setProperty('--primary', color);
            document.documentElement.style.setProperty('--primary-color', color);
            const lightColor = lightenColor(color, 10);
            const darkColor = darkenColor(color, 10);
            document.documentElement.style.setProperty('--primary-light', lightColor);
            document.documentElement.style.setProperty('--primary-dark', darkColor);
            document.documentElement.style.setProperty('--primary-color-light', lightColor);
            document.documentElement.style.setProperty('--primary-color-dark', darkColor);
        });
    });

    const circularProgresses = document.querySelectorAll('.circular-progress-container');
    if (circularProgresses.length > 0) {
        circularProgresses.forEach((progress, index) => {
            const circle = progress.querySelector('.progress-ring-circle');
            const countElement = progress.querySelector('.progress-number');
            const targetCount = parseInt(countElement.getAttribute('data-count'));
            const maxValue = parseInt(countElement.getAttribute('data-max')) || 100;
            const radius = 70;
            const circumference = 2 * Math.PI * radius;
            circle.style.strokeDasharray = `${circumference} ${circumference}`;
            circle.style.strokeDashoffset = circumference;

            function updateProgress(percent) {
                const offset = circumference - percent / 100 * circumference;
                circle.style.strokeDashoffset = offset;
            }

            let currentCount = 0;
            const duration = 1500;
            const frameDuration = 16;
            const totalFrames = Math.round(duration / frameDuration);
            let frame = 0;

            const calculatePercentage = (count, max) => Math.min(90, (count / (max || 1)) * 100);

            const animateCount = () => {
                frame++;
                const progress = frame / totalFrames;
                const current = Math.round(progress * targetCount);
                if (current > currentCount) {
                    currentCount = current;
                    countElement.textContent = currentCount;
                    const percentage = calculatePercentage(currentCount, maxValue);
                    updateProgress(percentage);
                }
                if (frame < totalFrames) requestAnimationFrame(animateCount);
            };
            animateCount();
        });
    }

    setTimeout(function () {
        const fileInput = document.getElementById('thumbnail');
        const uploadBtn = document.getElementById('thumbnail-upload-btn');
        const previewContainer = document.getElementById('thumbnail-preview');
        if (fileInput && uploadBtn && previewContainer) {
            fileInput.style.display = 'none';
            let lastClickTime = 0;
            const MIN_CLICK_INTERVAL = 200;
            const newUploadBtn = uploadBtn.cloneNode(true);
            uploadBtn.parentNode.replaceChild(newUploadBtn, uploadBtn);
            const updatedUploadBtn = document.getElementById('thumbnail-upload-btn');
            updatedUploadBtn.addEventListener('click', function (e) {
                e.preventDefault();
                const currentTime = new Date().getTime();
                if (currentTime - lastClickTime < MIN_CLICK_INTERVAL) return;
                lastClickTime = currentTime;
                try { fileInput.click(); } catch (err) { alert('选择文件时发生错误，请刷新页面重试'); }
            });
            previewContainer.style.pointerEvents = 'auto';
            fileInput.addEventListener('change', function (e) {
                const file = e.target.files[0];
                if (file) {
                    const existingPath = previewContainer.querySelector('.thumbnail-path[data-new="true"]');
                    if (existingPath) {
                        const codeElement = existingPath.querySelector('code');
                        if (codeElement) codeElement.textContent = file.name;
                    } else {
                        const placeholder = previewContainer.querySelector('.thumbnail-placeholder');
                        if (placeholder) placeholder.remove();
                        const newHtml = `<div class="thumbnail-path" data-new="true" style="display: flex; align-items: center; gap: 10px; flex: 1;"><div style="width: 255px; min-width: 0; overflow: hidden;"><code style="max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block;">${file.name}</code></div><img src="${fileUrl}" style="width: 80px; height: 38px; object-fit: cover; border-radius: 4px; background: none; flex-shrink: 0;"><input type="hidden" name="selected_thumbnail" value="${file.name}"></div>`;
                        previewContainer.insertAdjacentHTML('beforeend', newHtml);
                    }
                    updatedUploadBtn.textContent = '更换文件';
                } else updatedUploadBtn.textContent = '选择文件';
            });
        }
    }, 100);

    function fixArticlePropertySelection() {
        const allPropertySelects = document.querySelectorAll('select[name="article_property"]');
        if (allPropertySelects.length > 1) {
            // 只删除重复的下拉框，不修改值
            for (let i = 1; i < allPropertySelects.length; i++) {
                const parentDiv = allPropertySelects[i].closest('.form-group');
                if (parentDiv) parentDiv.remove();
                else allPropertySelects[i].remove();
            }
        }
        // 不再克隆替换元素，让其他代码可以正常添加事件监听器
    }
    fixArticlePropertySelection();

    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function (e) {
            const targetId = this.getAttribute('href');
            // 如果href为"#"，则不处理
            if (targetId === '#') {
                return;
            }
            e.preventDefault();
            const targetElement = document.querySelector(targetId);
            if (targetElement) targetElement.scrollIntoView({ behavior: 'smooth' });
        });
    });

    function handleResize() {
        const sidebar = document.querySelector('.admin-sidebar');
        const sidebarLinks = document.querySelectorAll('.admin-sidebar a');
        if (sidebar && sidebarLinks.length > 0) {
            if (window.innerWidth < 768) {
                sidebar.style.height = 'auto';
                sidebarLinks.forEach(link => link.style.display = 'inline-block');
            } else {
                sidebar.style.height = 'calc(100vh - 50px)';
                sidebarLinks.forEach(link => link.style.display = 'flex');
            }
        }
    }
    handleResize();
    window.addEventListener('resize', handleResize);

    function initSettingsFormAsyncSubmit() {
        const settingsForm = document.querySelector('form[method="post"]:has(button[name="save_settings"])');
        const saveButton = document.querySelector('button[name="save_settings"]');
        if (settingsForm && saveButton) {
            const logoInput = settingsForm.querySelector('#logo');
            const logoFileInput = settingsForm.querySelector('#logo_file');
            const uploadLogoBtn = settingsForm.querySelector('#upload-logo-btn');

            if (logoInput) {
                logoInput.addEventListener('input', function () {
                    if (logoInput.dataset && logoInput.dataset.tempPath) {
                        delete logoInput.dataset.tempPath;
                    }
                });
            }

            if (uploadLogoBtn && logoFileInput && logoInput) {
                uploadLogoBtn.addEventListener('click', function (e) {
                    e.preventDefault();
                    logoFileInput.click();
                });
                logoFileInput.addEventListener('change', function () {
                    const file = this.files && this.files[0] ? this.files[0] : null;
                    if (!file) return;
                    const uploadData = new FormData();
                    uploadData.append('upload_site_logo', '1');
                    uploadData.append('logo', file);
                    uploadLogoBtn.disabled = true;
                    fetch('/admin/ajaxx.php', {
                        method: 'POST',
                        body: uploadData,
                        credentials: 'same-origin',
                        headers: { 'X-Requested-With': 'XMLHttpRequest' }
                    }).then(response => response.text()).then(text => {
                        let data = null;
                        try {
                            data = JSON.parse(text);
                        } catch (e) {
                            const m = text.match(/\/uploads\/Temp\/logo_[^"'\\s<>]+/i);
                            if (m && m[0]) {
                                const tempPathFromText = m[0];
                                data = { success: true, logo_temp_path: tempPathFromText, logo_name: tempPathFromText.split('/').pop() };
                            } else {
                                data = null;
                            }
                        }
                        if (data && data.success) {
                            const payload = (data.data && typeof data.data === 'object') ? data.data : data;
                            let tempPath = '';
                            if (payload.logo_temp_path) {
                                tempPath = String(payload.logo_temp_path);
                            } else if (payload.logo_url && String(payload.logo_url).indexOf('/uploads/Temp/') !== -1) {
                                tempPath = String(payload.logo_url);
                            } else if (payload.logo_name) {
                                tempPath = '/uploads/Temp/' + String(payload.logo_name);
                            }
                            if (tempPath) {
                                logoInput.dataset.tempPath = tempPath;
                                logoInput.value = tempPath.split('/').pop();
                            }
                            if (tempPath) {
                                showToast('LOGO上传成功', 'success');
                            } else {
                                showToast('LOGO上传返回缺少临时路径', 'error');
                            }
                        } else {
                            showToast((data && (data.message || data.error)) ? (data.message || data.error) : 'LOGO上传失败', 'error');
                        }
                    }).catch(() => {
                        showToast('LOGO上传失败', 'error');
                    }).finally(() => {
                        uploadLogoBtn.disabled = false;
                        logoFileInput.value = '';
                    });
                });
            }

            settingsForm.addEventListener('submit', function (e) {
                e.preventDefault();
                e.stopPropagation();
            });
            saveButton.addEventListener('click', function (e) {
                e.preventDefault();
                e.stopPropagation();
                saveSettingsAsync();
            });

            function saveSettingsAsync() {
                const formData = new FormData(settingsForm);
                if (logoInput) {
                    const submitLogoValue = (logoInput.dataset && logoInput.dataset.tempPath)
                        ? String(logoInput.dataset.tempPath || '')
                        : String(logoInput.value || '');
                    formData.set('logo', submitLogoValue.trim());
                }
                formData.append('is_ajax', '1');
                formData.append('save_settings', '1');
                saveButton.disabled = true;
                saveButton.textContent = '保存中...';
                fetch('/admin/ajaxx.php', {
                    method: 'POST',
                    body: formData,
                    credentials: 'same-origin',
                    headers: { 'X-Requested-With': 'XMLHttpRequest' }
                })
                    .then(response => response.text())
                    .then(data => {
                        saveButton.disabled = false;
                        saveButton.textContent = '保存设置';
                        try {
                            const jsonResponse = JSON.parse(data);
                            if (jsonResponse.success) showToast('网站设置保存成功', 'info');
                            else showToast(jsonResponse.message || jsonResponse.error || '网站设置保存失败', 'error');
                        } catch (e) { }
                    })
                    .catch(error => {
                        saveButton.disabled = false;
                        saveButton.textContent = '保存设置';
                        showToast('保存设置时发生网络错误', 'error');
                    });
            }
        }
    }
    initSettingsFormAsyncSubmit();
    initAddCategoryFormAsyncSubmit();
    initEditCategoryFormAsyncSubmit();
    initPublishArticleFormAsyncSubmit();
    initEditArticleFormAsyncSubmit();
    initAddCategoryModal();
    if (typeof overrideConfirm === 'function') overrideConfirm();
});

function reloadAdcategoryListFromAdminJs(options = {}) {
    const resetToFirstPage = !!options.resetToFirstPage;
    if (typeof HeaderPagination !== 'undefined' && HeaderPagination.state) {
        if (resetToFirstPage) {
            HeaderPagination.state.page = 1;
        }
        HeaderPagination.cache = {};
    }
    if (typeof window.reloadAdcategoryList === 'function') {
        window.reloadAdcategoryList(options);
        return Promise.resolve({ success: true });
    }
    if (typeof HeaderPagination !== 'undefined' && typeof HeaderPagination.load === 'function') {
        HeaderPagination.load();
        return Promise.resolve({ success: true });
    }
    window.location.reload();
    return Promise.resolve({ success: true });
}

function addCategoryToFrontend(categoryData) {
    return reloadAdcategoryListFromAdminJs();
}

function updateCategoryRow(categoryData) {
    return reloadAdcategoryListFromAdminJs();
}

function syncTopCategoryCountAfterChildDelete(categoryId) {
    const childRow = document.querySelector('tr.tree-sub-row[data-category-id="' + categoryId + '"]');
    if (!childRow) return;
    const topId = parseInt(childRow.getAttribute('data-top-id') || '0', 10);
    if (topId <= 0) return;

    if (Array.isArray(window.allCatgroups)) {
        const group = window.allCatgroups.find(function(item) {
            return parseInt(item.id || 0, 10) === topId;
        });
        if (group) {
            group.category_count = Math.max(0, parseInt(group.category_count || 0, 10) - 1);
        }
    }

    const topRow = document.querySelector('tr.tree-top-row[data-top-id="' + topId + '"]');
    if (!topRow) return;
    const nameEl = topRow.querySelector('.tree-top-name');
    if (!nameEl) return;

    const currentText = String(nameEl.textContent || '').trim();
    const matched = currentText.match(/^(.*?)(?:（(\d+)）)?$/);
    if (!matched) return;
    const baseName = String(matched[1] || '').trim();
    const currentCount = Math.max(0, parseInt(matched[2] || '0', 10) - 1);
    nameEl.textContent = currentCount > 0 ? (baseName + '（' + currentCount + '）') : baseName;
}

function deleteCategoryConfirm(categoryId) {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', '/admin/admin.php?tab=adcategory&delete_category=' + categoryId + '&ajax=1', true);
    xhr.onload = function () {
        if (xhr.status >= 200 && xhr.status < 300) {
            try {
                const response = JSON.parse(xhr.responseText);
                if (response.success) {
                    syncTopCategoryCountAfterChildDelete(categoryId);
                    showToast('分类删除成功', 'success', 2000);
                    refreshCategoryList({ deltaTotal: -1, forceRender: true });
                } else {
                    showToast(response.message || '分类删除失败', 'error', 2000);
                }
            } catch (e) {
                showToast('分类删除失败：响应解析错误', 'error', 2000);
            }
        } else {
            showToast('网络请求失败，请重试', 'error', 2000);
        }
    };
    xhr.onerror = function () { showToast('网络连接错误，请检查您的网络', 'error', 2000); };
    xhr.send();
}



// 初始化添加分类表单的异步提交
function initAddCategoryFormAsyncSubmit(formElement) {
    // 如果传入了表单元素，直接使用它；否则查找页面上的表单
    const addCategoryForm = formElement || document.querySelector('form[method="post"]:has(input[name="add_category"])');
    if (addCategoryForm) {
        // 移除可能已存在的事件监听器，避免重复绑定
        addCategoryForm.removeEventListener('submit', addCategoryFormSubmitHandler);
        addCategoryForm.addEventListener('submit', addCategoryFormSubmitHandler);
    }
}

// 添加分类表单提交处理函数
function addCategoryFormSubmitHandler(e) {
    e.preventDefault();
    const addCategoryForm = this;
    let operationField = addCategoryForm.querySelector('input[name="add_category"]');
    if (!operationField) {
        operationField = document.createElement('input');
        operationField.type = 'hidden';
        operationField.name = 'add_category';
        operationField.value = '1';
        addCategoryForm.appendChild(operationField);
    } else operationField.value = '1';
    submitFormWithFileAsync(addCategoryForm, async function (response) {
        if (response.success) {
            showToast(response.message, 'success');
            addCategoryForm.reset();
            closeModal(); // 关闭模态框
            
            // 直接重新加载整个分类列表，确保表格结构完整
            if (typeof HeaderPagination !== 'undefined' && HeaderPagination.state) {
                HeaderPagination.cache = {};
                HeaderPagination.load();
            } else {
                window.location.reload();
            }
        } else showToast(response.message || '添加分类失败', 'error');
    });
}

// 初始化编辑分类表单的异步提交
function initEditCategoryFormAsyncSubmit(formElement) {
    // 如果传入了表单元素，直接使用它；否则查找页面上的表单
    const editCategoryForm = formElement || document.querySelector('form[method="post"]:has(input[name="edit_category"])');
    if (editCategoryForm) {
        // 移除可能已存在的事件监听器，避免重复绑定
        editCategoryForm.removeEventListener('submit', editCategoryFormSubmitHandler);
        editCategoryForm.addEventListener('submit', editCategoryFormSubmitHandler);
    }
}

// 编辑分类表单提交处理函数
function editCategoryFormSubmitHandler(e) {
    e.preventDefault();
    const editCategoryForm = this;
    let operationField = editCategoryForm.querySelector('input[name="edit_category"]');
    if (!operationField) {
        operationField = document.createElement('input');
        operationField.type = 'hidden';
        operationField.name = 'edit_category';
        operationField.value = '1';
        editCategoryForm.appendChild(operationField);
    } else operationField.value = '1';
    submitFormWithFileAsync(editCategoryForm, async function (response) {
        if (response.success) {
            showToast(response.message, 'success');
            closeModal(); // 关闭模态框
            
            // 直接重新加载整个分类列表，确保表格结构完整
            if (typeof HeaderPagination !== 'undefined' && HeaderPagination.state) {
                HeaderPagination.cache = {};
                HeaderPagination.load();
            } else {
                window.location.reload();
            }
        } else showToast(response.message || '编辑分类失败', 'error');
    });
}

let publishFormInitialized = false;
let editFormInitialized = false;

function initPublishArticleFormAsyncSubmit() {
    function enhancedExtractFirstImageFromContent(content) {
        try {
            if (!content || typeof content !== 'string') return null;
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = content;
            const images = tempDiv.querySelectorAll('img');
            if (images.length === 0) return null;
            for (let i = 0; i < images.length; i++) {
                const img = images[i];
                const src = img.getAttribute('src');
                if (!src) continue;
                if (src.startsWith('data:image/')) continue;
                try {
                    new URL(src, window.location.origin);
                    return src;
                } catch (urlError) { }
            }
            return null;
        } catch (error) { return null; }
    }
    const articleForm = document.getElementById('article-form');
    if (articleForm) {
        const formMode = document.getElementById('form_mode')?.value;
        if (formMode === 'add') {
            if (publishFormInitialized) return;
            publishFormInitialized = true;
            function handlePublishSubmit(e) {
                e.preventDefault();
                const submitButton = e.target.querySelector('button[type="submit"]');
                let existingThumbnailInput = e.target.querySelector('input[name="existing_thumbnail"]');
                if (!existingThumbnailInput) {
                    existingThumbnailInput = document.createElement('input');
                    existingThumbnailInput.type = 'hidden';
                    existingThumbnailInput.name = 'existing_thumbnail';
                    existingThumbnailInput.value = '';
                    e.target.appendChild(existingThumbnailInput);
                }
                let operationField = e.target.querySelector('input[name="publish_article"]');
                if (!operationField) {
                    operationField = document.createElement('input');
                    operationField.type = 'hidden';
                    operationField.name = 'publish_article';
                    operationField.value = '1';
                    e.target.appendChild(operationField);
                } else operationField.value = '1';
                const formDataSnapshot = new FormData(e.target);
                submitFormWithFileAsync(e.target, function (response) {
                    if (submitButton.disabled) {
                        submitButton.disabled = false;
                        submitButton.innerHTML = '发布文章';
                    }

                    if (response.success) {
                        showToast(response.message, 'success');

                        // 检查预览按钮是否存在
                        const previewButton = document.getElementById('preview-button');

                        // 检查article_id输入框是否存在
                        const articleIdInput = document.getElementById('article_id');

                        // 尝试多种方式获取新文章ID，确保能获取到
                        let newArticleId = null;
                        if (response.article_id) {
                            newArticleId = response.article_id;
                        } else if (response.data && response.data.article_id) {
                            newArticleId = response.data.article_id;
                        }

                        if (newArticleId) {
                            const formElement = e.target;
                            if (articleIdInput) {
                                articleIdInput.value = newArticleId;
                            }
                            const formModeInput = document.getElementById('form_mode');
                            if (formModeInput) {
                                formModeInput.value = 'edit';
                            }
                            window.isEditMode = true;
                            const submitBtn = document.getElementById('submit-button');
                            if (submitBtn) {
                                submitBtn.textContent = '更新文章';
                                submitBtn.name = 'edit_article';
                            }
                            const publishField = e.target.querySelector('input[name="publish_article"]');
                            if (publishField) {
                                publishField.remove();
                            }
                            let editField = e.target.querySelector('input[name="edit_article"]');
                            if (!editField) {
                                editField = document.createElement('input');
                                editField.type = 'hidden';
                                editField.name = 'edit_article';
                                editField.value = '1';
                                e.target.appendChild(editField);
                            } else {
                                editField.value = '1';
                            }
                            if (previewButton) {
                                previewButton.innerHTML = `预览`;
                            }
                            const newUrl = `${window.location.origin}/admin/?tab=articles&edit_id${newArticleId}`;
                            if (window.history && typeof window.history.replaceState === 'function') {
                                const categorySelect = document.getElementById('category_id');
                                const categoryId = categorySelect ? String(categorySelect.value || '').trim() : '';
                                window.history.replaceState({ articleId: newArticleId, mode: 'edit', publishedJustNow: true, categoryId: categoryId }, '', newUrl);
                            }
                            const cancelButton = document.getElementById('cancel-button');
                            const categorySelectForLabel = document.getElementById('category_id');
                            if (cancelButton && categorySelectForLabel && categorySelectForLabel.selectedIndex >= 0) {
                                const opt = categorySelectForLabel.options[categorySelectForLabel.selectedIndex];
                                const categoryName = opt ? String(opt.text || '').trim() : '';
                                if (categoryName) cancelButton.textContent = '返回' + categoryName;
                            }
                            const continuePublishButton = document.getElementById('continue-publish-button');
                            if (continuePublishButton) {
                                continuePublishButton.style.display = '';
                            }
                            formElement.removeEventListener('submit', handlePublishSubmit);
                            publishFormInitialized = false;
                            initEditArticleFormAsyncSubmit();
                        }
                    } else {
                        showToast(response.message || '发布文章失败', 'error');
                    }
                });
            }
            articleForm.addEventListener('submit', handlePublishSubmit);
        }
    }
}

function initEditArticleFormAsyncSubmit() {
    function enhancedExtractFirstImageFromContent(content) {
        if (!content || typeof content !== 'string') return null;
        try {
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = content;
            const images = tempDiv.querySelectorAll('img');
            if (!images || images.length === 0) return null;
            for (let i = 0; i < images.length; i++) {
                const img = images[i];
                const imgSrc = img.getAttribute('src');
                if (!imgSrc || !imgSrc.trim()) continue;
                if (imgSrc.startsWith('data:image/')) continue;
                if (/^https?:\/\/.+\.(jpg|jpeg|png|gif|bmp)$/i.test(imgSrc) || /^\/[^\/].+\.(jpg|jpeg|png|gif|bmp)$/i.test(imgSrc) || /^[^\/].+\.(jpg|jpeg|png|gif|bmp)$/i.test(imgSrc)) return imgSrc;
            }
            return null;
        } catch (error) { return null; }
    }
    const articleForm = document.getElementById('article-form');
    if (articleForm) {
        const formMode = document.getElementById('form_mode')?.value;
        if (formMode === 'edit') {
            if (editFormInitialized) return;
            editFormInitialized = true;
            function handleEditSubmit(e) {
                e.preventDefault();
                const submitButton = e.target.querySelector('button[type="submit"]');
                let existingThumbnailInput = e.target.querySelector('input[name="existing_thumbnail"]');
                if (!existingThumbnailInput) {
                    existingThumbnailInput = document.createElement('input');
                    existingThumbnailInput.type = 'hidden';
                    existingThumbnailInput.name = 'existing_thumbnail';
                    existingThumbnailInput.value = '';
                    e.target.appendChild(existingThumbnailInput);
                }

                let clearThumbnailInput = e.target.querySelector('input[name="clear_thumbnail"]');
                const clearThumbnailRequested = !!(clearThumbnailInput && clearThumbnailInput.value === '1');
                if (clearThumbnailRequested) {
                    existingThumbnailInput.value = '';
                }

                let operationField = e.target.querySelector('input[name="edit_article"]');
                if (!operationField) {
                    operationField = document.createElement('input');
                    operationField.type = 'hidden';
                    operationField.name = 'edit_article';
                    operationField.value = '1';
                    e.target.appendChild(operationField);
                } else operationField.value = '1';
                const formDataSnapshot = new FormData(e.target);
                submitFormWithFileAsync(e.target, function (response) {
                    if (submitButton.disabled) {
                        submitButton.disabled = false;
                        submitButton.innerHTML = '更新文章';
                    }
                    if (response.success) {
                        showToast(response.message, 'success');
                        // 更新成功后清除 clear_thumbnail 字段
                        const clearThumbnailInput = e.target.querySelector('input[name="clear_thumbnail"]');
                        if (clearThumbnailInput) {
                            clearThumbnailInput.remove();
                        }
                    }
                    else showToast(response.message || '更新文章失败', 'error');
                });
            }
            articleForm.addEventListener('submit', handleEditSubmit);
        }
    }
}

function escapeCategoryModalText(text) {
    return String(text == null ? '' : text)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
}

function getCategoryCatgroupList() {
    const modalGroups = Array.isArray(window.allCatgroupsForModal) ? window.allCatgroupsForModal : [];
    const pageGroups = Array.isArray(window.allCatgroups) ? window.allCatgroups : [];
    const groupMap = new Map();
    modalGroups.forEach(group => {
        groupMap.set(parseInt(group.id || 0, 10), group);
    });
    pageGroups.forEach(group => {
        groupMap.set(parseInt(group.id || 0, 10), group);
    });
    const groups = Array.from(groupMap.values()).filter(group => parseInt(group.id || 0, 10) > 0);
    groups.sort((a, b) => (parseInt(a.sort || 0, 10) - parseInt(b.sort || 0, 10)) || (parseInt(a.id || 0, 10) - parseInt(b.id || 0, 10)));
    groups.unshift({ id: 0, name: '默认分组', sort: 0 });
    return groups;
}

function getCategoryCatgroupDisplayText(archiveId) {
    const id = parseInt(archiveId || 0, 10);
    const groups = getCategoryCatgroupList();
    const target = groups.find(group => parseInt(group.id || 0, 10) === id);
    return target ? String(target.name || ('归档' + id)) : ('归档' + id);
}

function buildCategoryCatgroupDatalistOptions() {
    const groups = getCategoryCatgroupList();
    let html = '';
    groups.forEach(group => {
        const groupId = parseInt(group.id || 0, 10);
        const display = getCategoryCatgroupDisplayText(groupId);
        html += '<option value="' + escapeCategoryModalText(display) + '"></option>';
    });
    return html;
}

function initCategoryVirtualTopControls(modal, initialVirtualTop = 0, initialAnchor = 0) {
    const virtualTopEl = modal.querySelector('#edit_category_virtual_top');
    const anchorEl = modal.querySelector('#edit_category_virtual_anchor');
    const archiveTextEl = modal.querySelector('#edit_category_archiveid_text');
    if (!virtualTopEl || !anchorEl) return;
    const apply = () => {
        const vt = parseInt(virtualTopEl.value || '0', 10) === 1 ? 1 : 0;
        if (archiveTextEl) archiveTextEl.disabled = vt === 1;
        if (vt !== 1) {
            anchorEl.value = '0';
            return;
        }
        const rawAnchor = parseInt(anchorEl.value || '0', 10) || 0;
        if (rawAnchor === 0) {
            const archiveId = parseInt(modal.querySelector('#edit_category_archiveid')?.value || '0', 10) || 0;
            if (archiveId > 0) anchorEl.value = String(archiveId);
        }
    };
    virtualTopEl.value = String(parseInt(initialVirtualTop || 0, 10) === 1 ? 1 : 0);
    anchorEl.value = String(parseInt(initialAnchor || 0, 10) || 0);
    apply();
    virtualTopEl.addEventListener('change', apply);
}

function getCategoryArchiveMemoryKey() {
    return 'qk_adcategory_last_archiveid';
}

function getStoredCategoryArchiveId() {
    try {
        const val = localStorage.getItem(getCategoryArchiveMemoryKey());
        const id = parseInt(val || '0', 10);
        return Number.isFinite(id) && id >= 0 ? id : 0;
    } catch (e) {
        return 0;
    }
}

function setStoredCategoryArchiveId(archiveId) {
    try {
        const id = parseInt(archiveId || 0, 10);
        if (!Number.isFinite(id) || id < 0) return;
        localStorage.setItem(getCategoryArchiveMemoryKey(), String(id));
    } catch (e) {}
}

function initCategoryArchiveCombobox(modal, initialArchiveId = 0) {
    const textInput = modal.querySelector('#edit_category_archiveid_text');
    const hiddenInput = modal.querySelector('#edit_category_archiveid');
    const listEl = modal.querySelector('#edit_category_archiveid_list');
    if (!textInput || !hiddenInput || !listEl) return;
    listEl.innerHTML = buildCategoryCatgroupDatalistOptions();
    let selectedId = parseInt(initialArchiveId || 0, 10);
    const groups = getCategoryCatgroupList();
    const findByName = (name) => groups.find(group => String(group.name || '').trim() === String(name || '').trim());
    const setSelectedDisplay = () => {
        hiddenInput.value = String(selectedId);
        textInput.value = getCategoryCatgroupDisplayText(selectedId);
    };
    const normalizeArchiveFromText = () => {
        const text = String(textInput.value || '').trim();
        if (!text) {
            setSelectedDisplay();
            return;
        }
        const target = findByName(text);
        if (!target) {
            hiddenInput.value = '';
            return;
        }
        selectedId = parseInt(target.id || 0, 10);
        setSelectedDisplay();
        setStoredCategoryArchiveId(selectedId);
    };

    setSelectedDisplay();
    textInput.addEventListener('focus', function() {
        this.dataset.prevText = this.value || '';
        this.value = '';
    });
    textInput.addEventListener('input', function() {
        const target = findByName(this.value || '');
        hiddenInput.value = target ? String(parseInt(target.id || 0, 10)) : '';
    });
    textInput.addEventListener('blur', function() {
        normalizeArchiveFromText();
    });
    textInput.addEventListener('change', normalizeArchiveFromText);
}

function ensureCategoryDisplayControl(modal, initialDisplay = 1) {
    if (!modal) return;
    const nameInput = modal.querySelector('#edit_category_name');
    if (!nameInput) return;
    const rowGroup = nameInput.closest('.form-group');
    if (!rowGroup) return;
    const nameWrap = nameInput.closest('div');
    const archiveText = modal.querySelector('#edit_category_archiveid_text');
    const archiveWrap = archiveText ? archiveText.closest('div') : null;
    const sortInput = modal.querySelector('#edit_category_sort');
    const sortWrap = sortInput ? sortInput.closest('div') : null;
    if (nameWrap) nameWrap.style.flex = '0 0 calc(50% - 5px)';
    if (archiveWrap) archiveWrap.style.flex = '0 0 calc(50% - 5px)';
    if (sortWrap) sortWrap.style.flex = '0 0 calc(25% - 5px)';
    let displaySelect = modal.querySelector('#edit_category_display');
    let displayWrap = displaySelect ? displaySelect.closest('div') : null;
    if (!displaySelect) {
        displayWrap = document.createElement('div');
        displayWrap.style.flex = '0 0 calc(25% - 5px)';
        displayWrap.innerHTML = '<label for="edit_category_display">开关</label><select id="edit_category_display" name="display" class="form-control"><option value="1">启用</option><option value="0">关闭</option></select>';
        if (sortWrap && sortWrap.parentNode === rowGroup) rowGroup.insertBefore(displayWrap, sortWrap);
        else rowGroup.appendChild(displayWrap);
        displaySelect = displayWrap.querySelector('#edit_category_display');
    }
    if (displayWrap) {
        displayWrap.style.flex = '0 0 calc(25% - 5px)';
        if (sortWrap && sortWrap.parentNode === rowGroup) {
            rowGroup.insertBefore(displayWrap, sortWrap);
        }
    }
    if (displaySelect) {
        const val = parseInt(initialDisplay, 10);
        displaySelect.value = String(val === 0 ? 0 : 1);
    }
}

function optimizeCategoryModalLayout(modal) {
    if (!modal) return;
    const formSection = modal.querySelector('.form-section');
    if (!formSection) return;
    const thumbInput = modal.querySelector('#edit_category_thumbnail');
    const nameInput = modal.querySelector('#edit_category_name');
    if (!thumbInput || !nameInput) return;
    const nameWrap = nameInput.closest('div');
    const thumbRow = thumbInput.closest('.form-group');
    const baseRow = nameInput.closest('.form-group');
    if (!thumbRow || !baseRow) return;
    if (thumbRow !== baseRow && thumbRow.parentNode === formSection && baseRow.parentNode === formSection) {
        formSection.insertBefore(baseRow, thumbRow);
    }
    const archiveText = modal.querySelector('#edit_category_archiveid_text');
    const archiveWrap = archiveText ? archiveText.closest('div') : null;
    const virtualTopEl = modal.querySelector('#edit_category_virtual_top');
    const virtualWrap = virtualTopEl ? virtualTopEl.closest('div') : null;
    const displaySelect = modal.querySelector('#edit_category_display');
    const displayWrap = displaySelect ? displaySelect.closest('div') : null;
    const sortInput = modal.querySelector('#edit_category_sort');
    const sortWrap = sortInput ? sortInput.closest('div') : null;
    const sortRow = sortWrap ? sortWrap.closest('.form-group') : null;
    const displayRow = displayWrap ? displayWrap.closest('.form-group') : null;
    const thumbInputWrap = thumbInput.closest('div');
    baseRow.style.display = 'flex';
    baseRow.style.alignItems = 'end';
    baseRow.style.gap = '10px';
    if (nameWrap) nameWrap.style.flex = '0 0 calc(50% - 7px)';
    if (virtualWrap) virtualWrap.style.flex = '0 0 calc(25% - 7px)';
    if (archiveWrap) archiveWrap.style.flex = virtualWrap ? '0 0 calc(25% - 7px)' : '0 0 calc(50% - 7px)';
    if (nameWrap && nameWrap.parentNode !== baseRow) baseRow.appendChild(nameWrap);
    if (virtualWrap && virtualWrap.parentNode !== baseRow) baseRow.appendChild(virtualWrap);
    if (archiveWrap && archiveWrap.parentNode !== baseRow) baseRow.appendChild(archiveWrap);
    thumbRow.style.display = 'flex';
    thumbRow.style.alignItems = 'end';
    thumbRow.style.gap = '10px';
    if (thumbInputWrap) thumbInputWrap.style.flex = '0 0 calc(50% - 5px)';
    let rightRow = modal.querySelector('.category-second-row-right');
    if (!rightRow) {
        rightRow = document.createElement('div');
        rightRow.className = 'category-second-row-right';
        thumbRow.appendChild(rightRow);
    }
    rightRow.style.flex = '0 0 calc(50% - 5px)';
    rightRow.style.display = 'flex';
    rightRow.style.gap = '10px';
    rightRow.style.alignItems = 'end';
    if (displayWrap) {
        displayWrap.style.flex = '1 1 0';
        if (displayWrap.parentNode !== rightRow) rightRow.appendChild(displayWrap);
    }
    if (sortWrap) {
        sortWrap.style.flex = '1 1 0';
        if (sortWrap.parentNode !== rightRow) rightRow.appendChild(sortWrap);
    }

    if (sortRow && sortRow !== thumbRow && sortRow !== baseRow) {
        if (sortRow.querySelectorAll('.form-control').length === 0) sortRow.style.display = 'none';
    }
    if (displayRow && displayRow !== thumbRow && displayRow !== baseRow && displayRow !== sortRow) {
        if (displayRow.querySelectorAll('.form-control').length === 0) displayRow.style.display = 'none';
    }
    const uploadBtn = modal.querySelector('#thumbnail-upload-btn');
    const uploadIconSvg = '<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2" ry="2"></rect><circle cx="9" cy="10" r="1.4"></circle><path d="M21 16l-5.4-5.4a1.2 1.2 0 0 0-1.7 0L7 17"></path></svg>';
    if (uploadBtn) {
        uploadBtn.innerHTML = uploadIconSvg;
        uploadBtn.title = '上传缩略图';
        uploadBtn.setAttribute('aria-label', '上传缩略图');
        uploadBtn.style.width = '30px';
        uploadBtn.style.minWidth = '30px';
        uploadBtn.style.height = '30px';
        uploadBtn.style.padding = '0';
        uploadBtn.style.display = 'inline-flex';
        uploadBtn.style.alignItems = 'center';
        uploadBtn.style.justifyContent = 'center';
        uploadBtn.style.position = 'absolute';
        uploadBtn.style.right = '6px';
        uploadBtn.style.top = '50%';
        uploadBtn.style.transform = 'translateY(-50%)';
        uploadBtn.style.background = 'transparent';
        uploadBtn.style.color = '#6b7280';
        uploadBtn.style.border = 'none';
        uploadBtn.style.borderRadius = '6px';
        uploadBtn.style.transition = 'all .18s ease';
        uploadBtn.classList.add('qk-thumb-upload-inside-btn');
        let inputShell = modal.querySelector('.thumb-input-shell');
        if (!inputShell) {
            inputShell = document.createElement('div');
            inputShell.className = 'thumb-input-shell';
            inputShell.style.position = 'relative';
            thumbInput.parentNode.insertBefore(inputShell, thumbInput);
            inputShell.appendChild(thumbInput);
        }
        if (uploadBtn.parentNode !== inputShell) inputShell.appendChild(uploadBtn);
        thumbInput.style.paddingRight = '40px';
        ensureThumbUploadHoverStyles();
    }
}

function ensureThumbUploadHoverStyles() {
    if (document.getElementById('qk-thumb-upload-hover-style')) return;
    const style = document.createElement('style');
    style.id = 'qk-thumb-upload-hover-style';
    style.textContent = '.qk-thumb-upload-inside-btn:hover{color:#2563eb !important;background:rgba(37,99,235,.14) !important;box-shadow:0 0 0 1px rgba(37,99,235,.16) inset}.qk-thumb-upload-inside-btn:active{transform:translateY(-50%) scale(.96) !important}.qk-thumb-upload-inside-btn:disabled{opacity:.55 !important;cursor:not-allowed !important;background:transparent !important;color:#9ca3af !important}';
    document.head.appendChild(style);
}

function setThumbUploadButtonState(uploadBtn, loading) {
    if (!uploadBtn) return;
    const uploadIconSvg = '<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2" ry="2"></rect><circle cx="9" cy="10" r="1.4"></circle><path d="M21 16l-5.4-5.4a1.2 1.2 0 0 0-1.7 0L7 17"></path></svg>';
    if (loading) {
        uploadBtn.disabled = true;
        uploadBtn.innerHTML = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 2a10 10 0 1 0 10 10" /></svg>';
    } else {
        uploadBtn.disabled = false;
        uploadBtn.innerHTML = uploadIconSvg;
    }
}

window.openEditCategoryModal = function openEditCategoryModal(categoryId) {
    if (!categoryId || isNaN(parseInt(categoryId)) || parseInt(categoryId) <= 0) {
        if (typeof showToast === 'function') showToast('无效的分类ID', 'error');
        else alert('无效的分类ID');
        return;
    }
    let modalContainer = document.getElementById('modal-container');
    if (!modalContainer) {
        modalContainer = document.createElement('div');
        modalContainer.id = 'modal-container';
        document.body.appendChild(modalContainer);
    }
    modalContainer.innerHTML = '';
    const modal = document.createElement('div');
    modal.className = 'modal';
    const editCatgroupOptionsHtml = buildCategoryCatgroupDatalistOptions();
    modal.innerHTML = `
        <div class="modal-backdrop"></div>
        <div class="modal-content catgroup-modal-content">
            <div class="modal-header">
                <h3>编辑子栏目</h3>
                <button type="button" class="modal-close">×</button>
            </div>
            <div class="modal-body">
                <form id="edit-category-form" method="post">
                    <input type="hidden" name="edit_category" value="1">
                    <input type="hidden" name="category_id" value="${categoryId}">
                    <input type="hidden" id="edit_category_virtual_anchor" value="0">
                    <div class="form-section">
                        <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                            <div style="flex: 1;">
                                <label for="edit_category_thumbnail">缩略图地址</label>
                                <input type="text" id="edit_category_thumbnail" name="thumbnail_url" class="form-control" placeholder="请输入图片URL地址">
                            </div>
                            <button type="button" id="thumbnail-upload-btn" class="btn btn-default" style="background-color: #6b7280; color: #fff; height: 39px; padding: 0 15px; border: none; cursor: pointer; white-space: nowrap;">上传图片</button>
                        </div>
                        <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                            <div style="flex: 0 0 50%;">
                                <label for="edit_category_name">栏目名称</label>
                                <input type="text" id="edit_category_name" name="category_name" class="form-control" placeholder="请输入栏目名称" required>
                            </div>
                            <div style="flex: 0 0 calc(25% - 7px);">
                                <label for="edit_category_virtual_top">伪顶级</label>
                                <select id="edit_category_virtual_top" class="form-control">
                                    <option value="0">否</option>
                                    <option value="1">是</option>
                                </select>
                            </div>
                            <div style="flex: 0 0 calc(25% - 7px);">
                                <label for="edit_category_archiveid_text">顶级栏目</label>
                                <input type="hidden" id="edit_category_archiveid" name="archiveid" value="0">
                                <input type="text" id="edit_category_archiveid_text" class="form-control" list="edit_category_archiveid_list" placeholder="输入或选择顶级栏目" style="appearance:none;-webkit-appearance:none;background-image:none;padding-right:10px;">
                                <datalist id="edit_category_archiveid_list">${editCatgroupOptionsHtml}</datalist>
                            </div>
                        </div>
                        <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                            <div style="flex: 0 0 calc(25% - 7px);">
                                <label for="edit_category_sort">排序</label>
                                <input type="number" id="edit_category_sort" name="sort" class="form-control" min="1" value="1">
                            </div>
                            <div style="flex: 1;"></div>
                        </div>
                        <div class="form-group">
                            <label for="edit_category_seo_title">SEO标题</label>
                            <input type="text" id="edit_category_seo_title" name="category_seo_title" class="form-control" placeholder="请输入SEO标题，不填则前台回退栏目名称">
                        </div>
                        <div class="form-group">
                            <label for="edit_category_keywords">栏目关键词</label>
                            <input type="text" id="edit_category_keywords" name="category_keywords" class="form-control" placeholder="请输入栏目关键词，多个关键词用逗号分隔">
                        </div>
                        <div class="form-group">
                            <label for="edit_category_description">栏目描述</label>
                            <textarea id="edit_category_description" name="category_description" class="form-control" placeholder="请输入栏目描述" rows="3" style="min-height:82px;resize:vertical;"></textarea>
                        </div>
                    </div>
                    <div class="modal-actions">
                        <button type="submit" class="submit-button" style="background-color: var(--primary-color); width: 480px; margin: 0 auto; display: block; transition: opacity 0.2s ease;">立即保存</button>
                    </div>
                    <style>
                      .submit-button:hover{opacity:0.9;}
                      #edit_category_archiveid_text::-webkit-calendar-picker-indicator{display:none !important;}
                      .catgroup-modal-content{height:600px !important;max-height:600px !important;}
                      .catgroup-modal-content .modal-body{padding-top:20px !important;padding-bottom:20px !important;}
                      .catgroup-modal-content .form-section{gap:0 !important;min-width:0 !important;}
                      .catgroup-modal-content .form-section > .form-group + .form-group{margin-top:10px !important;}
                      .catgroup-modal-content .form-group{margin:0 !important;}
                      .catgroup-modal-content label{margin-bottom:6px !important;}
                      .catgroup-modal-content #edit_category_description{margin-bottom:16px !important;}
                      .catgroup-modal-content .modal-actions{margin-top:-5px !important;}
                    </style>
                </form>
            </div>
        </div>
        <input type="file" id="hidden-file-input" accept="image/*" style="display: none;">
    `;
    modalContainer.appendChild(modal);
    ensureCategoryDisplayControl(modal, 1);
    optimizeCategoryModalLayout(modal);
    addModalStyles();
    initCategoryArchiveCombobox(modal, 0);
    initCategoryVirtualTopControls(modal, 0, 0);
    // 显示模态框容器
    modal.style.display = 'flex';
    setTimeout(() => {
        modal.classList.add('modal-visible');
    }, 10);
    loadCategoryData(categoryId);
    const closeButtons = modal.querySelectorAll('.modal-close');
    closeButtons.forEach(button => button.addEventListener('click', () => closeModal()));
    const backdrop = modal.querySelector('.modal-backdrop');
    backdrop.addEventListener('click', () => closeModal());
    document.addEventListener('keydown', handleEscKey);

    // 添加上传按钮点击事件和文件上传功能
    const uploadBtn = modal.querySelector('#thumbnail-upload-btn');
    const hiddenFileInput = modal.querySelector('#hidden-file-input');
    const thumbnailInput = modal.querySelector('#edit_category_thumbnail');

    if (uploadBtn && hiddenFileInput) {
        uploadBtn.addEventListener('click', function () {
            hiddenFileInput.click();
        });

        hiddenFileInput.addEventListener('change', function () {
            const file = this.files[0];
            if (!file) return;

            // 检查文件类型
            const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
            if (!validTypes.includes(file.type)) {
                if (typeof showToast === 'function') showToast('只支持JPG、PNG、GIF、WebP格式图片', 'error');
                else alert('只支持JPG、PNG、GIF、WebP格式图片');
                this.value = '';
                return;
            }

            // 检查文件大小（2MB限制）
            if (file.size > 2 * 1024 * 1024) {
                if (typeof showToast === 'function') showToast('图片大小不能超过2MB', 'error');
                else alert('图片大小不能超过2MB');
                this.value = '';
                return;
            }

            // 真实上传实现：将文件发送到后端处理
            const formData = new FormData();
            formData.append('upload_category_thumbnail', '1');
            formData.append('thumbnail', file);

            // 显示上传中状态
            setThumbUploadButtonState(uploadBtn, true);

            // 图片上传不需要初始化表单异步提交功能，因为模态框中已经有了表单提交处理逻辑

            // 发送上传请求 - 添加X-Requested-With头部以通过AJAX验证
            fetch('/admin/ajaxx.php', {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            })
                .then(response => response.json())
                .then(data => {
                    setThumbUploadButtonState(uploadBtn, false);

                    // 确保数据格式正确
                    if (data && data.success && data.data && data.data.thumbnail_url) {
                        // 使用模态框中已定义的thumbnailInput变量
                        if (thumbnailInput) {
                            thumbnailInput.value = data.data.thumbnail_url;
                        }
                        if (typeof showToast === 'function') showToast('图片上传成功', 'success');
                    } else {
                        if (typeof showToast === 'function') showToast('图片上传失败，请重试', 'error');
                    }

                    // 重置文件输入
                    hiddenFileInput.value = '';
                })
                .catch(error => {
                    setThumbUploadButtonState(uploadBtn, false);
                    if (typeof showToast === 'function') showToast('上传请求失败', 'error');
                    else alert('上传请求失败');
                    hiddenFileInput.value = '';
                });
        });
    }

    // 表单提交处理
    const editCategoryForm = modal.querySelector('#edit-category-form');
    if (editCategoryForm) {
        const submitButton = editCategoryForm.querySelector('.submit-button');
        if (submitButton) submitButton.disabled = false;
        editCategoryForm.addEventListener('submit', function (e) {
            e.preventDefault();
            if (submitButton) {
                submitButton.disabled = true;
                submitButton.innerHTML = '保存中...';
            }
            const categoryName = document.getElementById('edit_category_name')?.value?.trim();
            const categorySort = parseInt(document.getElementById('edit_category_sort')?.value || '0', 10);
            if (!categoryName) {
                if (typeof showToast === 'function') showToast('栏目名称不能为空', 'error');
                else alert('栏目名称不能为空');
                if (submitButton) {
                    submitButton.disabled = false;
                    submitButton.innerHTML = '立即保存';
                }
                return;
            }
            if (!Number.isFinite(categorySort) || categorySort < 1) {
                if (typeof showToast === 'function') showToast('排序最小值为1', 'error');
                else alert('排序最小值为1');
                if (submitButton) {
                    submitButton.disabled = false;
                    submitButton.innerHTML = '立即保存';
                }
                return;
            }

            const archiveIdValue = String(document.getElementById('edit_category_archiveid')?.value || '').trim();
            if (archiveIdValue === '') {
                if (typeof showToast === 'function') showToast('请选择有效的顶级栏目', 'error');
                else alert('请选择有效的顶级栏目');
                if (submitButton) {
                    submitButton.disabled = false;
                    submitButton.innerHTML = '立即保存';
                }
                return;
            }

            // 创建FormData并设置表单数据
            const formData = new FormData();
            formData.append('edit_category', '1');
            formData.append('category_id', categoryId);
            formData.append('category_name', document.getElementById('edit_category_name')?.value?.trim() || '');
            formData.append('category_seo_title', document.getElementById('edit_category_seo_title')?.value?.trim() || '');
            formData.append('category_keywords', document.getElementById('edit_category_keywords')?.value?.trim() || '');
            formData.append('category_description', document.getElementById('edit_category_description')?.value?.trim() || '');
            const virtualTopValue = parseInt(document.getElementById('edit_category_virtual_top')?.value || '0', 10) === 1 ? 1 : 0;
            let virtualAnchorValue = parseInt(document.getElementById('edit_category_virtual_anchor')?.value || '0', 10) || 0;
            if (virtualTopValue === 1 && virtualAnchorValue === 0) {
                const archiveId = parseInt(archiveIdValue || '0', 10) || 0;
                if (archiveId > 0) virtualAnchorValue = archiveId;
            }
            formData.append('archiveid', String(virtualTopValue === 1 ? 0 : archiveIdValue));
            formData.append('display', String(parseInt(document.getElementById('edit_category_display')?.value || '1', 10) === 0 ? 0 : 1));
            formData.append('sort', String(categorySort));
            formData.append('virtual_top', String(virtualTopValue));
            formData.append('virtual_top_anchor', String(virtualTopValue === 1 ? virtualAnchorValue : 0));
            // 确保缩略图URL正确处理，为空时不发送空字符串
            const thumbnailUrl = document.getElementById('edit_category_thumbnail')?.value?.trim();
            if (thumbnailUrl) {
                formData.append('thumbnail_url', thumbnailUrl);
            } else {
                formData.append('thumbnail_url', '');
            }

            // 提交表单
            fetch('/admin/ajaxx.php', {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: { 'X-Requested-With': 'XMLHttpRequest' }
            })
                .then(response => response.json())
                .then(data => {
                    if (submitButton) {
                        submitButton.disabled = false;
                        submitButton.innerHTML = '立即保存';
                    }
                    if (data.success) {
                        if (typeof showToast === 'function') showToast(data.message, 'success');
                        else alert(data.message);
                        closeModal();
                        if (typeof reloadAdcategoryList === 'function') {
                            reloadAdcategoryList();
                        } else if (data.data && data.data.category) {
                            updateCategoryRow(data.data.category);
                        }
                    } else {
                        const errorMessage = data.message || '编辑栏目失败';
                        if (typeof showToast === 'function') showToast(errorMessage, 'error');
                        else alert(errorMessage);
                    }
                })
                .catch(error => {
                    if (submitButton) {
                        submitButton.disabled = false;
                        submitButton.innerHTML = '立即保存';
                    }
                    const errorMessage = '提交请求失败: ' + error.message;
                    if (typeof showToast === 'function') showToast(errorMessage, 'error');
                    else alert(errorMessage);
                });
        });
    }
}

function initEditCategoryModal() {
    // 初始化分类编辑模态框
    // 由于编辑按钮已改为直接调用openEditCategoryModal函数，此处无需额外的事件监听
    // 该函数保持存在是为了兼容可能的其他调用
    // 同时保留对传统链接的支持，确保兼容性
    const editCategoryLinks = document.querySelectorAll('a[href*="action=edit"][href*="categories"]');
    editCategoryLinks.forEach(link => {
        link.addEventListener('click', function (e) {
            e.preventDefault();
            const href = this.getAttribute('href');
            let categoryId = null;
            try {
                const urlParams = new URLSearchParams(href.split('?')[1]);
                categoryId = urlParams.get('id');
            } catch (error) { }
            if (!categoryId) {
                const idMatch = href.match(/id=(\d+)/);
                if (idMatch && idMatch[1]) categoryId = idMatch[1];
            }
            if (categoryId && !isNaN(parseInt(categoryId)) && parseInt(categoryId) > 0) {
                openEditCategoryModal(categoryId);
            } else {
                if (typeof showToast === 'function') showToast('无效的分类ID', 'error');
                else alert('无效的分类ID');
            }
        });
    });
}

function loadCategoryData(categoryId) {
    if (!categoryId || isNaN(parseInt(categoryId)) || parseInt(categoryId) <= 0) {
        if (typeof showToast === 'function') showToast('无效的分类ID，无法加载数据', 'error');
        else alert('无效的分类ID，无法加载数据');
        return;
    }
    fetch('/admin/ajaxx.php', {
        method: 'POST',
        credentials: 'same-origin',
        headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' },
        body: `action=get_category&id=${categoryId}`
    })
        .then(response => response.text())
        .then(text => {
            try {
                const response = JSON.parse(text);
                if (response.success && response.data) {
                    const categoryData = response.data;
                    const nameInput = document.getElementById('edit_category_name');
                    const seoTitleInput = document.getElementById('edit_category_seo_title');
                    const keywordsInput = document.getElementById('edit_category_keywords');
                    const descInput = document.getElementById('edit_category_description');
                    const thumbnailInput = document.getElementById('edit_category_thumbnail');
                    const archiveInput = document.getElementById('edit_category_archiveid');
                    const archiveTextInput = document.getElementById('edit_category_archiveid_text');
                    const sortInput = document.getElementById('edit_category_sort');
                    const displayInput = document.getElementById('edit_category_display');
                    const virtualTopInput = document.getElementById('edit_category_virtual_top');
                    const virtualAnchorInput = document.getElementById('edit_category_virtual_anchor');

                    if (nameInput) nameInput.value = categoryData.name || '';
                    if (seoTitleInput) seoTitleInput.value = categoryData.seo_title || '';
                    if (keywordsInput) keywordsInput.value = categoryData.keywords || '';
                    if (descInput) descInput.value = categoryData.description || '';
                    if (thumbnailInput) thumbnailInput.value = categoryData.thumbnail || '';
                    const vt = parseInt(categoryData.virtual_top || 0, 10) === 1 ? 1 : 0;
                    const va = parseInt(categoryData.virtual_top_anchor || 0, 10) || 0;
                    const selectedTopId = vt === 1 ? Math.abs(va) : parseInt(categoryData.archiveid || 0, 10);
                    if (archiveInput) archiveInput.value = String(selectedTopId);
                    if (archiveTextInput) archiveTextInput.value = getCategoryCatgroupDisplayText(selectedTopId);
                    if (sortInput) sortInput.value = String(Math.max(1, parseInt(categoryData.sort || 1, 10)));
                    if (displayInput) {
                        const rawDisplay = (categoryData && Object.prototype.hasOwnProperty.call(categoryData, 'display')) ? categoryData.display : 1;
                        displayInput.value = String(parseInt(rawDisplay, 10) === 0 ? 0 : 1);
                    }
                    if (virtualTopInput && virtualAnchorInput) {
                        virtualTopInput.value = String(vt);
                        virtualAnchorInput.value = String(va);
                        try {
                            virtualTopInput.dispatchEvent(new Event('change'));
                        } catch (e) {}
                    }
                } else {
                    const errorMsg = response.message || '加载分类数据失败';
                    if (typeof showToast === 'function') showToast(errorMsg, 'error');
                    else alert(errorMsg);
                }
            } catch (error) {
                if (typeof showToast === 'function') showToast('加载分类数据失败，请刷新页面重试', 'error');
                else alert('加载分类数据失败，请刷新页面重试');
            }
        })
        .catch(error => {
            if (typeof showToast === 'function') showToast('网络连接失败，请检查网络设置后重试', 'error');
            else alert('网络连接失败，请检查网络设置后重试');
        });
}

function initAddCategoryModal() {
    let addCategoryButton = document.getElementById('add-category-button');
    if (!addCategoryButton) addCategoryButton = document.querySelector('a.action-button[href="admin/admin.php?tab=adcategory&action=add"]');
    if (addCategoryButton) {
        addCategoryButton.addEventListener('click', function (e) {
            e.preventDefault();
            let modalContainer = document.getElementById('modal-container');
            if (!modalContainer) {
                modalContainer = document.createElement('div');
                modalContainer.id = 'modal-container';
                document.body.appendChild(modalContainer);
            }
            modalContainer.innerHTML = '';
            const modal = document.createElement('div');
            modal.className = 'modal';
            // 获取当前选中的archiveid
            const urlParams = new URLSearchParams(window.location.search);
            const archiveidFromUrl = parseInt(urlParams.get('archiveid') || '0', 10);
            const archiveidFromStore = getStoredCategoryArchiveId();
            const archiveid = archiveidFromStore > 0 ? archiveidFromStore : archiveidFromUrl;
            const addCatgroupOptionsHtml = buildCategoryCatgroupDatalistOptions();
            
            modal.innerHTML = `
                <div class="modal-backdrop"></div>
                <div class="modal-content catgroup-modal-content">
                    <div class="modal-header">
                        <h3>新增子栏目</h3>
                        <button type="button" class="modal-close">×</button>
                    </div>
                    <div class="modal-body">
                        <form id="add-category-form" method="post">
                            <input type="hidden" name="add_category" value="1">
                            <input type="hidden" id="edit_category_virtual_anchor" value="0">
                            <div class="form-section">
                                <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                                    <div style="flex: 1;">
                                        <label for="edit_category_thumbnail">缩略图地址</label>
                                        <input type="text" id="edit_category_thumbnail" name="thumbnail_url" class="form-control" placeholder="请输入图片URL地址">
                                    </div>
                                    <button type="button" id="thumbnail-upload-btn" class="btn btn-default" style="background-color: #6b7280; color: #fff; height: 39px; padding: 0 15px; border: none; cursor: pointer; white-space: nowrap;">上传图片</button>
                                </div>
                                <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                                    <div style="flex: 0 0 50%;">
                                        <label for="edit_category_name">栏目名称</label>
                                        <input type="text" id="edit_category_name" name="category_name" class="form-control" placeholder="请输入栏目名称" required>
                                    </div>
                                    <div style="flex: 0 0 calc(25% - 7px);">
                                        <label for="edit_category_virtual_top">伪顶级</label>
                                        <select id="edit_category_virtual_top" class="form-control">
                                            <option value="0">否</option>
                                            <option value="1">是</option>
                                        </select>
                                    </div>
                                    <div style="flex: 0 0 calc(25% - 7px);">
                                        <label for="edit_category_archiveid_text">顶级栏目</label>
                                        <input type="hidden" id="edit_category_archiveid" name="archiveid" value="0">
                                        <input type="text" id="edit_category_archiveid_text" class="form-control" list="edit_category_archiveid_list" placeholder="输入或选择顶级栏目" style="appearance:none;-webkit-appearance:none;background-image:none;padding-right:10px;">
                                        <datalist id="edit_category_archiveid_list">${addCatgroupOptionsHtml}</datalist>
                                    </div>
                                </div>
                                <div class="form-group" style="display: flex; align-items: end; gap: 10px;">
                                    <div style="flex: 0 0 calc(25% - 7px);">
                                        <label for="edit_category_sort">排序</label>
                                        <input type="number" id="edit_category_sort" name="sort" class="form-control" min="1" value="1">
                                    </div>
                                    <div style="flex: 1;"></div>
                                </div>
                                <div class="form-group">
                                    <label for="edit_category_seo_title">SEO标题</label>
                                    <input type="text" id="edit_category_seo_title" name="category_seo_title" class="form-control" placeholder="请输入SEO标题，不填则前台回退栏目名称">
                                </div>
                                <div class="form-group">
                                    <label for="edit_category_keywords">栏目关键词</label>
                                    <input type="text" id="edit_category_keywords" name="category_keywords" class="form-control" placeholder="请输入栏目关键词，多个关键词用逗号分隔">
                                </div>
                                <div class="form-group">
                                    <label for="edit_category_description">栏目描述</label>
                                    <textarea id="edit_category_description" name="category_description" class="form-control" placeholder="请输入栏目描述" rows="3" style="min-height:82px;resize:vertical;"></textarea>
                                </div>
                            </div>
                            <div class="modal-actions">
                                <button type="submit" class="submit-button" style="background-color: var(--primary-color); width: 480px; margin: 0 auto; display: block; transition: opacity 0.2s ease;">立即保存</button>
                            </div>
                            <style>
                              .submit-button:hover{opacity:0.9;}
                              #edit_category_archiveid_text::-webkit-calendar-picker-indicator{display:none !important;}
                              .catgroup-modal-content{height:600px !important;max-height:600px !important;}
                              .catgroup-modal-content .modal-body{padding-top:20px !important;padding-bottom:20px !important;}
                              .catgroup-modal-content .form-section{gap:0 !important;min-width:0 !important;}
                              .catgroup-modal-content .form-section > .form-group + .form-group{margin-top:10px !important;}
                              .catgroup-modal-content .form-group{margin:0 !important;}
                              .catgroup-modal-content label{margin-bottom:6px !important;}
                              .catgroup-modal-content #edit_category_description{margin-bottom:16px !important;}
                              .catgroup-modal-content .modal-actions{margin-top:-5px !important;}
                            </style>
                        </form>
                    </div>
                </div>
                <input type="file" id="hidden-file-input" accept="image/*" style="display: none;">
            `;
            modalContainer.appendChild(modal);
            ensureCategoryDisplayControl(modal, 1);
            optimizeCategoryModalLayout(modal);
            addModalStyles();
            initCategoryArchiveCombobox(modal, archiveid);
            initCategoryVirtualTopControls(modal, 0, 0);
            // 显示模态框容器
            modal.style.display = 'flex';
            setTimeout(() => {
                modal.classList.add('modal-visible');
            }, 10);
            const closeButtons = modal.querySelectorAll('.modal-close');
            closeButtons.forEach(button => button.addEventListener('click', () => closeModal()));
            const backdrop = modal.querySelector('.modal-backdrop');
            backdrop.addEventListener('click', () => closeModal());
            document.addEventListener('keydown', handleEscKey);

            // 添加上传按钮点击事件和文件上传功能
            const uploadBtn = modal.querySelector('#thumbnail-upload-btn');
            const hiddenFileInput = modal.querySelector('#hidden-file-input');
            const thumbnailInput = modal.querySelector('#edit_category_thumbnail');

            if (uploadBtn && hiddenFileInput) {
                uploadBtn.addEventListener('click', function () {
                    hiddenFileInput.click();
                });

                hiddenFileInput.addEventListener('change', function () {
                    const file = this.files[0];
                    if (!file) return;

                    // 检查文件类型
                    const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
                    if (!validTypes.includes(file.type)) {
                        if (typeof showToast === 'function') showToast('只支持JPG、PNG、GIF、WebP格式图片', 'error');
                        else alert('只支持JPG、PNG、GIF、WebP格式图片');
                        this.value = '';
                        return;
                    }

                    // 检查文件大小（2MB限制）
                    if (file.size > 2 * 1024 * 1024) {
                        if (typeof showToast === 'function') showToast('图片大小不能超过2MB', 'error');
                        else alert('图片大小不能超过2MB');
                        this.value = '';
                        return;
                    }

                    // 真实上传实现：将文件发送到后端处理
                    const formData = new FormData();
                    formData.append('upload_category_thumbnail', '1');
                    formData.append('thumbnail', file);

                    // 显示上传中状态
                    setThumbUploadButtonState(uploadBtn, true);

                    // 发送上传请求 - 添加X-Requested-With头部以通过AJAX验证

                    // 图片上传不需要初始化表单异步提交功能，因为模态框中已经有了表单提交处理逻辑
                    fetch('/admin/ajaxx.php', {
                        method: 'POST',
                        body: formData,
                        credentials: 'same-origin',
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest'
                        }
                    })
                        .then(response => response.json())
                        .then(data => {
                            setThumbUploadButtonState(uploadBtn, false);

                            // 确保数据格式正确
                            if (data && data.success && data.data && data.data.thumbnail_url) {
                                // 使用模态框中已定义的thumbnailInput变量
                                if (thumbnailInput) {
                                    thumbnailInput.value = data.data.thumbnail_url;
                                }
                                if (typeof showToast === 'function') showToast('图片上传成功', 'success');
                            } else {
                                if (typeof showToast === 'function') showToast('图片上传失败，请重试', 'error');
                            }

                            // 重置文件输入
                            hiddenFileInput.value = '';
                        })
                        .catch(error => {
                            setThumbUploadButtonState(uploadBtn, false);
                            if (typeof showToast === 'function') showToast('上传请求失败', 'error');
                            else alert('上传请求失败');
                            hiddenFileInput.value = '';
                        });
                });
            }

            // 表单提交处理
            const form = modal.querySelector('#add-category-form');
            if (form) {
                form.addEventListener('submit', function (e) {
                    e.preventDefault();
                    const submitButton = form.querySelector('.submit-button');
                    if (submitButton) {
                        submitButton.disabled = true;
                        submitButton.innerHTML = '保存中...';
                    }

                    const categorySort = parseInt(form.querySelector('#edit_category_sort')?.value || '0', 10);
                    if (!Number.isFinite(categorySort) || categorySort < 1) {
                        if (typeof showToast === 'function') showToast('排序最小值为1', 'error');
                        else alert('排序最小值为1');
                        if (submitButton) {
                            submitButton.disabled = false;
                            submitButton.innerHTML = '立即保存';
                        }
                        return;
                    }

                    const archiveIdValue = String(form.querySelector('#edit_category_archiveid')?.value || '').trim();
                    if (archiveIdValue === '') {
                        if (typeof showToast === 'function') showToast('请选择有效的顶级栏目', 'error');
                        else alert('请选择有效的顶级栏目');
                        if (submitButton) {
                            submitButton.disabled = false;
                            submitButton.innerHTML = '立即保存';
                        }
                        return;
                    }

                    const formData = new FormData(form);
                    const virtualTopValue = parseInt(form.querySelector('#edit_category_virtual_top')?.value || '0', 10) === 1 ? 1 : 0;
                    let virtualAnchorValue = parseInt(form.querySelector('#edit_category_virtual_anchor')?.value || '0', 10) || 0;
                    if (virtualTopValue === 1 && virtualAnchorValue === 0) {
                        const archiveId = parseInt(archiveIdValue || '0', 10) || 0;
                        if (archiveId > 0) virtualAnchorValue = archiveId;
                    }
                    formData.set('archiveid', String(virtualTopValue === 1 ? 0 : archiveIdValue));
                    formData.set('display', String(parseInt(form.querySelector('#edit_category_display')?.value || '1', 10) === 0 ? 0 : 1));
                    formData.set('sort', String(categorySort));
                    formData.set('virtual_top', String(virtualTopValue));
                    formData.set('virtual_top_anchor', String(virtualTopValue === 1 ? virtualAnchorValue : 0));
                    fetch('/admin/ajaxx.php', {
                        method: 'POST',
                        body: formData,
                        credentials: 'same-origin',
                        headers: {
                            'X-Requested-With': 'XMLHttpRequest'
                        }
                    })
                        .then(response => response.json())
                        .then(data => {
                            if (submitButton) {
                                submitButton.disabled = false;
                                submitButton.innerHTML = '立即保存';
                            }

                            if (data && data.success) {
                                if (typeof showToast === 'function') showToast(data.message || '栏目添加成功', 'success');
                                else alert(data.message || '栏目添加成功');
                                closeModal();
                                if (typeof reloadAdcategoryList === 'function') {
                                    reloadAdcategoryList();
                                } else if (data.data && data.data.category) {
                                    addCategoryToFrontend(data.data.category);
                                }
                            } else {
                                const errorMessage = data && data.message ? data.message : '添加栏目失败';
                                if (typeof showToast === 'function') showToast(errorMessage, 'error');
                                else alert(errorMessage);
                            }
                        })
                        .catch(error => {
                            if (submitButton) {
                                submitButton.disabled = false;
                                submitButton.innerHTML = '立即保存';
                            }
                            const errorMessage = '网络请求失败，请稍后重试';
                            if (typeof showToast === 'function') showToast(errorMessage, 'error');
                            else alert(errorMessage);
                        });
                });
            }
        });
    }
}

let isRefreshingCategoryList = false;
function refreshCategoryList(options = {}) {
    if (isRefreshingCategoryList) return Promise.resolve({ success: false, reason: '刷新已在进行中' });
    isRefreshingCategoryList = true;
    return reloadAdcategoryListFromAdminJs(options).finally(function() {
        isRefreshingCategoryList = false;
    });
}

function handleCategoryThumbnails() {
    Promise.resolve().then(() => {
        const categoryTable = document.querySelector('table.admin-table.category-manage');
        if (!categoryTable) return;
        const cells = categoryTable.querySelectorAll('td:nth-child(2)');
        if (cells.length === 0) return;
        let hasChanges = false;
        for (let cell of cells) {
            if (cell.textContent.trim() === '无' && !cell.querySelector('img')) {
                cell.innerHTML = `<img src=""+window.DEFAULT_THUMBNAIL_PATH+"" alt="默认缩略图" style="width: 60px; height: 45px; object-fit: cover; border-radius: 4px;">`;
                hasChanges = true;
            }
        }
    });
}

function addModalStyles() {
    if (!document.getElementById('modal-styles')) {
        const style = document.createElement('style');
        style.id = 'modal-styles';
        style.textContent = `.modal{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:2000;opacity:0;visibility:hidden;transition:opacity 0.3s ease,visibility 0.3s ease}.modal.modal-visible{opacity:1;visibility:visible}.modal-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.5);backdrop-filter:blur(2px);transition: opacity 0.3s ease}.modal-content{position:relative;background-color:white;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,0.2);width:100%;max-width:550px;max-height:650px;overflow-y:auto;transform:scale(0.95);opacity:0;transition:transform 0.3s ease, opacity 0.3s ease}.modal.modal-visible .modal-content{transform:scale(1);opacity:1}.modal-header{padding:16px 20px;border-bottom:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center}.modal-header h3{margin:0;font-size:18px;color:var(--text-primary)}.modal-close{background:none;border:none;font-size:24px;cursor:pointer;color:#666;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:0;transition:background-color 0.2s ease;margin-top:5px}.modal-close:hover{background-color:#f5f5f5}.thumbnail-upload-wrapper{display:flex;gap:10px}.thumbnail-url-input{flex:1}.upload-btn{padding:8px 16px;background-color:#2196F3;color:white;border:none;border-radius:4px;cursor:pointer;transition:background-color 0.2s ease}.upload-btn:hover{background-color:#1976D2}.modal-body{padding:20px 35px}.modal-layout{display:flex;gap:20px;margin-bottom:20px;align-items:flex-start}.upload-section{width:150px;display:flex;flex-direction:column;align-items:center;margin-top:29px}.form-section{flex:1;min-width:300px;display:flex;flex-direction:column;gap:10px}.description-aligned{margin-top:auto;display:flex;flex-direction:column}.upload-button{width:100%;padding:10px;background-color:#4a5568;color:white;border:none;border-radius:4px;cursor:pointer;font-size:14px;margin-bottom:10px;transition:background-color 0.2s ease}.upload-button:hover{background-color:#2d3748}.thumbnail-preview{width:100%;height:120px;border:2px dashed #e2e8f0;border-radius:4px;display:flex;align-items:center;justify-content:center;overflow:hidden;background-color:#f7fafc}.thumbnail-placeholder{color:#a0aec0;text-align:center;font-size:14px}.thumbnail-image img{max-width:100%;max-height:100%;object-fit:contain}.form-section{flex:1;display:flex;flex-direction:column;gap:0px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:5px;font-weight:500;color:#2d3748;font-size:14px}.form-control{width:100%;padding:8px 12px;border:1px solid #d1d5db;border-radius:4px;font-size:14px;transition:border-color 0.2s ease;box-sizing:border-box}textarea.form-control{resize:vertical;min-height:80px}.submit-button{width:100%;padding:12px;background-color: var(--primary-color);color:white;border:none;border-radius:4px;font-size:16px;font-weight:500;cursor:pointer;transition:background-color 0.2s ease}.submit-button:hover{filter:alpha(opacity:90); opacity:0.9;}`;
        document.head.appendChild(style);
        if (!document.getElementById('modal-override-styles')) {
            const override = document.createElement('style');
            override.id = 'modal-override-styles';
            override.textContent = `.modal-close{width:28px;height:28px;border:none;background:#dbdbdb;border-radius:50%;cursor:pointer;position:relative;transition:all .3s ease;color:transparent;font-size:0;padding:0;display:inline-flex;align-items:center;justify-content:center}.modal-close::before,.modal-close::after{content:'';position:absolute;top:50%;left:50%;width:12px;height:2px;background:#fff;transform:translate(-50%,-50%) rotate(45deg);transition:all .3s ease}.modal-close::after{transform:translate(-50%,-50%) rotate(-45deg)}.modal-close:hover{background:#ff5252;transform:rotate(90deg)}.modal-close:hover::before,.modal-close:hover::after{width:14px}`;
            document.head.appendChild(override);
        }
    }
}

function refreshArticleList() {
    return new Promise((resolve) => {
        let refreshSuccess = false;
        let failureReason = '';
        fetch('/admin/ajaxx.php', {
            method: 'POST',
            credentials: 'same-origin',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded' },
            body: 'action=get_article_list&is_ajax=1'
        })
            .then(response => response.text())
            .then(text => {
                try {
                    const jsonData = JSON.parse(text);
                    if (jsonData.success && jsonData.html) {
                        const updateMethods = [
                            function () {
                                const tableContainers = document.querySelectorAll('.table-container');
                                for (let i = 0; i < tableContainers.length; i++) {
                                    const articleTable = tableContainers[i].querySelector('table.admin-table:not(.category-manage)');
                                    if (articleTable) {
                                        tableContainers[i].innerHTML = jsonData.html;
                                        return true;
                                    }
                                }
                                return false;
                            },
                            function () {
                                const articleTables = document.querySelectorAll('table.admin-table');
                                for (let i = 0; i < articleTables.length; i++) {
                                    if (!articleTables[i].classList.contains('category-manage') && articleTables[i].parentElement) {
                                        articleTables[i].parentElement.innerHTML = jsonData.html;
                                        return true;
                                    }
                                }
                                return false;
                            },
                            function () {
                                const adminTables = document.querySelectorAll('table.admin-table');
                                for (let i = 0; i < adminTables.length; i++) {
                                    if (adminTables[i].closest('.table-container')) {
                                        adminTables[i].closest('.table-container').innerHTML = jsonData.html;
                                        return true;
                                    }
                                }
                                return false;
                            },
                            function () {
                                const allElements = document.querySelectorAll('*');
                                for (let i = 0; i < allElements.length; i++) {
                                    if (allElements[i].textContent.includes('文章管理') && allElements[i].querySelector('.table-container')) {
                                        const tableContainer = allElements[i].querySelector('.table-container');
                                        if (tableContainer) {
                                            tableContainer.innerHTML = jsonData.html;
                                            return true;
                                        }
                                    }
                                }
                                return false;
                            },
                            function () {
                                const tableContainers = document.querySelectorAll('.table-container');
                                if (tableContainers.length > 0) {
                                    tableContainers[0].innerHTML = jsonData.html;
                                    return true;
                                }
                                return false;
                            }
                        ];
                        let updated = false;
                        for (let i = 0; i < updateMethods.length; i++) {
                            if (updateMethods[i]()) {
                                updated = true;
                                break;
                            }
                        }
                        if (!updated) refreshSuccess = false;
                        else refreshSuccess = true;
                    } else {
                        setTimeout(() => window.location.reload(), 1000);
                    }
                } catch (e) {
                    if (text.includes('<table') && text.includes('</table>')) {
                        const htmlUpdateMethods = [
                            function () {
                                const articleTables = document.querySelectorAll('table.admin-table:not(.category-manage)');
                                for (let i = 0; i < articleTables.length; i++) {
                                    if (articleTables[i].parentElement) {
                                        articleTables[i].parentElement.innerHTML = text;
                                        return true;
                                    }
                                }
                                return false;
                            },
                            function () {
                                const tableContainers = document.querySelectorAll('.table-container');
                                for (let i = 0; i < tableContainers.length; i++) {
                                    if (!tableContainers[i].querySelector('.category-manage')) {
                                        tableContainers[i].innerHTML = text;
                                        return true;
                                    }
                                }
                                return false;
                            },
                            function () {
                                const allTables = document.querySelectorAll('table');
                                for (let i = 0; i < allTables.length; i++) {
                                    if (allTables[i].className.includes('admin-table') && !allTables[i].className.includes('category-manage')) {
                                        const parent = allTables[i].parentElement;
                                        if (parent) {
                                            parent.innerHTML = text;
                                            return true;
                                        }
                                    }
                                }
                                return false;
                            }
                        ];
                        let htmlUpdated = false;
                        for (let i = 0; i < htmlUpdateMethods.length; i++) {
                            if (htmlUpdateMethods[i]()) {
                                htmlUpdated = true;
                                break;
                            }
                        }
                        if (!htmlUpdated) refreshSuccess = false;
                        else refreshSuccess = true;
                    } else refreshSuccess = false;
                }
                resolve({ success: refreshSuccess, reason: failureReason });
            })
            .catch(error => {
                refreshSuccess = false;
                failureReason = '网络错误: ' + error.message;
                resolve({ success: refreshSuccess, reason: failureReason });
            });
    });
}

function submitFormWithFileAsync(formOrFormData, callback) {
    const formData = formOrFormData instanceof FormData ? formOrFormData : new FormData(formOrFormData);
    formData.append('is_ajax', '1');
    fetch('/admin/ajaxx.php', {
        method: 'POST',
        body: formData,
        credentials: 'same-origin',
        headers: { 'X-Requested-With': 'XMLHttpRequest' }
    })
        .then(response => {
            // 添加HTTP状态码检查
            if (!response.ok) {
                return response.text().then(text => {
                    return { success: false, message: `服务器返回了错误状态码: ${response.status}`, rawResponse: text };
                });
            }
            return response.text().then(text => {
                try {
                    const jsonData = JSON.parse(text);
                    if (typeof jsonData.success !== 'boolean') return { success: false, message: '服务器返回了格式不正确的JSON响应', rawResponse: text, parsedData: jsonData };
                    return jsonData;
                } catch (e) {
                    if (text.startsWith('<!DOCTYPE html>') || text.includes('<html') || text.includes('<head')) {
                        const errorMatch = text.match(/<title>(.*?)<\/title>/i);
                        const errorTitle = errorMatch ? errorMatch[1] : 'HTML错误页面';
                        return { success: false, message: `服务器返回了HTML错误页面: ${errorTitle}`, rawResponse: text, error: e.message };
                    }
                    return { success: false, message: '服务器返回了非预期的响应格式，无法解析为JSON', rawResponse: text, error: e.message };
                }
            });
        })
        .then(data => callback(data))
        .catch(error => callback({ success: false, message: `提交表单时发生网络错误: ${error.message}`, errorDetails: error.stack || error }));
}

document.addEventListener('DOMContentLoaded', function () {
    if (typeof initEditCategoryModal === 'function') initEditCategoryModal();
    if (typeof handleCategoryThumbnails === 'function') handleCategoryThumbnails();
    if (typeof initCommentSelection === 'function') initCommentSelection();
});

function initCommentSelection() {
    const selectAllCheckbox = document.getElementById('select-all-comments');
    const commentCheckboxes = document.querySelectorAll('.comment-checkbox');
    const batchCommentIds = document.getElementById('batch-comment-ids');
    if (!selectAllCheckbox || !commentCheckboxes.length) return;
    const newSelectAllCheckbox = selectAllCheckbox.cloneNode(true);
    selectAllCheckbox.parentNode.replaceChild(newSelectAllCheckbox, selectAllCheckbox);
    const freshSelectAllCheckbox = document.getElementById('select-all-comments');
    freshSelectAllCheckbox.addEventListener('change', function () { updateAllCommentsSelection(this.checked); });
    freshSelectAllCheckbox.addEventListener('click', function (e) {
        setTimeout(() => updateAllCommentsSelection(this.checked), 10);
    });
    commentCheckboxes.forEach(checkbox => {
        const newCheckbox = checkbox.cloneNode(true);
        checkbox.parentNode.replaceChild(newCheckbox, checkbox);
        newCheckbox.addEventListener('change', function () {
            updateBatchCommentIds();
            updateSelectAllStatus();
        });
    });
    function submitBatchOperation(batchForm) {
        const xhr = new XMLHttpRequest();
        xhr.open('POST', window.location.href, true);
        const formData = new FormData(batchForm);
        xhr.onload = function () {
            if (xhr.status >= 200 && xhr.status < 300) window.location.reload();
            else alert('操作失败，请重试');
        };
        xhr.send(formData);
    }
    const operationSelect = document.getElementById('batch-operation');
    if (operationSelect) {
        operationSelect.addEventListener('change', function () {
            const selectedIds = getSelectedCommentIds();
            const selectedAction = this.value;
            if (!selectedAction) return;
            if (selectedIds.length === 0) {
                alert('请至少选择一条评论');
                this.selectedIndex = 0;
                return;
            }
            if (batchCommentIds) batchCommentIds.value = selectedIds.join(',');
            const batchForm = document.getElementById('batch-operation-form');
            if (batchForm) {
                let actionInput = batchForm.querySelector('input[name="batch_action"]');
                if (!actionInput) {
                    actionInput = document.createElement('input');
                    actionInput.type = 'hidden';
                    actionInput.name = 'batch_action';
                    batchForm.appendChild(actionInput);
                }
                actionInput.value = selectedAction;
                let performInput = batchForm.querySelector('input[name="perform_batch_action"]');
                if (!performInput) {
                    performInput = document.createElement('input');
                    performInput.type = 'hidden';
                    performInput.name = 'perform_batch_action';
                    batchForm.appendChild(performInput);
                }
                performInput.value = '1';
                if (selectedAction === 'delete') {
                    window.confirmDialog('确定要删除选中的 ' + selectedIds.length + ' 条评论吗？', function () {
                        submitBatchOperation(batchForm);
                    }, function () { this.selectedIndex = 0; }.bind(this));
                } else submitBatchOperation(batchForm);
            }
        });
    }
    const batchForm = document.getElementById('batch-operation-form');
    if (batchForm) batchForm.addEventListener('submit', function (e) { });
    updateBatchCommentIds();
}

function updateAllCommentsSelection(checked) {
    const commentCheckboxes = document.querySelectorAll('.comment-checkbox');
    commentCheckboxes.forEach(checkbox => checkbox.checked = checked);
    updateBatchCommentIds();
}

function updateBatchCommentIds() {
    const batchCommentIds = document.getElementById('batch-comment-ids');
    if (batchCommentIds) {
        const selectedIds = getSelectedCommentIds();
        batchCommentIds.value = selectedIds.join(',');
    }
}

function updateSelectAllStatus() {
    const selectAllCheckbox = document.getElementById('select-all-comments');
    const commentCheckboxes = document.querySelectorAll('.comment-checkbox');
    if (selectAllCheckbox && commentCheckboxes.length > 0) {
        const checkedCheckboxes = document.querySelectorAll('.comment-checkbox:checked');
        selectAllCheckbox.checked = commentCheckboxes.length > 0 && checkedCheckboxes.length === commentCheckboxes.length;
    }
}

function getSelectedCommentIds() {
    const selectedIds = [];
    const checkedCheckboxes = document.querySelectorAll('.comment-checkbox:checked');
    checkedCheckboxes.forEach(checkbox => selectedIds.push(checkbox.value));
    return selectedIds;
}

window.testCommentSelection = function () {
    const selectAllCheckbox = document.getElementById('select-all-comments');
    const commentCheckboxes = document.querySelectorAll('.comment-checkbox');
    const batchCommentIds = document.getElementById('batch-comment-ids');
    const selectedIds = getSelectedCommentIds();
    if (selectAllCheckbox && commentCheckboxes.length > 0) {
        selectAllCheckbox.checked = !selectAllCheckbox.checked;
        const event = new Event('change', { bubbles: true });
        selectAllCheckbox.dispatchEvent(event);
        setTimeout(() => getSelectedCommentIds(), 100);
    }
    return '测试完成，请查看控制台输出';
};

function initNavigationModal() {
    if (window.qkcms_disable_adminjs_navigation_modal || window.qkcms_disable_adminjs_navigation_sorting) return;
    const navigationsContainer = document.getElementById('navigations-container');
    const addNavigationBtn = document.getElementById('add-navigation');
    if (!navigationsContainer || !addNavigationBtn) return;
    // 使用全局函数
    addNavigationBtn.addEventListener('click', function () { window.openNavigationModal(); });
    navigationsContainer.addEventListener('click', function (e) {
        if (e.target && e.target.classList.contains('edit-navigation')) {
            const navItem = e.target.closest('.navigation-item');
            if (navItem) {
                const id = navItem.dataset.id;
                const name = navItem.querySelector('.navigation-name')?.textContent || '';
                editNavigationItem(id, name);
            }
        }
    });
    initializeNavigationSorting();
    // 移除重复的keydown事件监听，使用全局的handleEscKey
}

function editNavigationItem(id, name) { window.openNavigationModal(id, name); }

// 编辑导航项函数 - 简化实现，避免冲突
window.openNavigationModal = function (navigationId = null, navigationName = null) {
    try {
        // 获取或创建模态框
        let modal = document.getElementById('navigationEditModal');

        // 避免重复创建，直接复用已有的模态框
        if (!modal) {
            // 创建模态框容器
            let modalContainer = document.getElementById('modal-container');
            if (!modalContainer) {
                modalContainer = document.createElement('div');
                modalContainer.id = 'modal-container';
                document.body.appendChild(modalContainer);
            }

            // 创建模态框
            modal = document.createElement('div');
            modal.id = 'navigationEditModal';
            modal.className = 'modal';

            // 设置模态框内容
            modal.innerHTML = `<div class="modal-backdrop"></div><div class="modal-content"><div class="modal-header"><h3 class="modal-title" id="navigationModalTitle">添加导航项</h3><button type="button" class="modal-close">×</button></div><div class="modal-body"><form id="navigation-form"><input type="hidden" id="navigation-id" name="id" value=""><div class="form-group"><label for="navigation-name">导航名称</label><input type="text" id="navigation-name" name="name" class="form-control" placeholder="请输入导航名称" required></div><div class="form-group"><label for="navigation-url">导航链接</label><input type="text" id="navigation-url" name="url" class="form-control" placeholder="请输入导航链接" required></div><div class="form-group"><label for="navigation-target">打开方式</label><select id="navigation-target" name="target" class="form-control"><option value="_self">当前窗口</option><option value="_blank">新窗口</option></select></div><div class="form-group"><label for="navigation-order">排序号</label><input type="number" id="navigation-order" name="display_order" class="form-control" placeholder="排序号" value="0" min="0"></div><div class="form-group"><label><input type="checkbox" id="navigation-status" name="status" value="1" checked>启用导航</label></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" onclick="window.closeModal()">取消</button><button type="button" class="btn btn-primary" onclick="saveSingleNavigationItem()">保存</button></div></div>`;
            modalContainer.appendChild(modal);

            // 只绑定一次事件，避免重复绑定
            const form = document.getElementById('navigation-form');
            if (form) form.addEventListener('submit', function (e) { e.preventDefault(); saveSingleNavigationItem(); });

            // 简化关闭事件绑定
            modal.addEventListener('click', function (e) {
                if (e.target === modal || e.target.classList.contains('modal-backdrop')) {
                    window.closeModal();
                }
            });

            // 绑定关闭按钮
            modal.querySelector('.modal-close').addEventListener('click', window.closeModal);
        }

        // 获取表单元素
        const modalTitle = document.getElementById('navigationModalTitle');
        const navigationIdInput = document.getElementById('navigation-id');
        const navigationNameInput = document.getElementById('navigation-name');
        const navigationUrlInput = document.getElementById('navigation-url');
        const navigationTargetSelect = document.getElementById('navigation-target');
        const navigationOrderInput = document.getElementById('navigation-order');
        const navigationStatusCheckbox = document.getElementById('navigation-status');

        // 重置表单
        navigationIdInput.value = '';
        navigationNameInput.value = '';
        navigationUrlInput.value = '';
        navigationTargetSelect.value = '_self';
        navigationOrderInput.value = document.querySelectorAll('.navigation-item').length;
        navigationStatusCheckbox.checked = true;

        // 设置标题和加载数据
        if (navigationId) {
            modalTitle.textContent = '编辑导航项';
            navigationIdInput.value = navigationId;
            loadNavigationData(navigationId, function (data) {
                if (data && data.navigation) {
                    const nav = data.navigation;
                    navigationNameInput.value = nav.name || '';
                    navigationUrlInput.value = nav.url || '';
                    navigationTargetSelect.value = nav.target || '_self';
                    navigationOrderInput.value = nav.display_order || 0;
                    navigationStatusCheckbox.checked = Number(nav.status) === 1;
                }
            });
        } else {
            modalTitle.textContent = '添加导航项';
        }

        // 关键修改：先计算滚动条宽度并设置body样式，避免抖动
        // 先移除之前可能存在的类
        modal.classList.remove('modal-visible');

        // 显示模态框
        modal.style.display = 'flex';

        // 确保只添加一次事件监听
        document.removeEventListener('keydown', handleEscKey);
        document.addEventListener('keydown', handleEscKey);

        // 使用setTimeout确保正确的时序和动画效果
        setTimeout(() => {
            // 添加可见类触发动画
            modal.classList.add('modal-visible');

            // 聚焦输入框
            navigationNameInput.focus();
        }, 50);
    } catch (error) {
        console.error('打开导航编辑窗口失败:', error);
        alert('无法打开导航编辑窗口，请刷新页面重试');
    }
}

// 将关闭导航模态框函数也设置为全局函数
window.closeNavigationModal = function () {
    // 直接调用全局的closeModal函数，确保滚动条和paddingRight正确重置
    window.closeModal();
}

function loadNavigationData(id, callback) {
    if (!id) { callback({ success: false, message: '导航项ID不能为空' }); return; }
    const url = `/admin/settings.php?action=get_navigation&id=${id}`;
    fetch(url)
        .then(response => response.json())
        .then(data => callback(data))
        .catch(error => callback({ success: false, message: error.message }));
}

function saveSingleNavigationItem() {
    const form = document.getElementById('navigation-form');
    const id = document.getElementById('navigation-id').value;
    const isNew = !id;
    const navigationData = {
        name: document.getElementById('navigation-name').value.trim(),
        url: document.getElementById('navigation-url').value.trim(),
        target: document.getElementById('navigation-target').value,
        display_order: parseInt(document.getElementById('navigation-order').value) || 0,
        status: document.getElementById('navigation-status').checked ? 1 : 0
    };
    if (!navigationData.name) { showToast('导航名称不能为空', 'error'); return; }
    if (!navigationData.url) { showToast('导航链接不能为空', 'error'); return; }
    const url = `/admin/settings.php?action=${isNew ? 'add_navigation' : 'update_navigation'}${isNew ? '' : '&id=' + id}`;
    fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(navigationData) })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                showToast(isNew ? '添加导航项成功' : '更新导航项成功', 'success');
                window.closeModal();
                setTimeout(() => window.location.reload(), 1000);
            } else showToast(data.message || (isNew ? '添加导航项失败' : '更新导航项失败'), 'error');
        })
        .catch(error => showToast((isNew ? '添加' : '更新') + '导航项失败，请重试', 'error'));
}

function deleteNavigationItem(id) {
    if (!id) { showToast('导航项ID不能为空', 'error'); return; }
    if (window.isDemoSettingsAccount) {
        showToast('演示账号无权限操作', 'error');
        return;
    }
    const url = `/admin/settings.php?action=delete_navigation&id=${id}&ajax=1`;
    fetch(url, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
        .then(response => response.text())
        .then(text => {
            try {
                return JSON.parse(text);
            } catch (e) {
                if (text.indexOf('演示账号无权限操作') !== -1) {
                    return { success: false, message: '演示账号无权限操作' };
                }
                throw e;
            }
        })
        .then(data => {
            if (data.success) {
                showToast('删除导航项成功', 'success');
                const navItem = document.querySelector(`.navigation-item[data-id="${id}"]`);
                if (navItem) {
                    navItem.style.transition = 'opacity 0.3s ease-out';
                    navItem.style.opacity = '0';
                    setTimeout(() => {
                        navItem.remove();
                        const remainingItems = document.querySelectorAll('.navigation-item');
                        const navigationsContainer = document.getElementById('navigations-container');
                        if (remainingItems.length === 0 && navigationsContainer) navigationsContainer.innerHTML = '<div class="empty-message">暂无导航项，请点击"添加导航项"按钮添加</div>';
                        updateNavigationIndices();
                    }, 300);
                }
            } else showToast(data.message || '删除导航项失败', 'error');
        })
        .catch(error => showToast('删除导航项失败，请重试', 'error'));
}

function initializeNavigationSorting() {
    if (window.qkcms_disable_adminjs_navigation_sorting) return;
    const navigationItems = document.querySelectorAll('.navigation-item');
    navigationItems.forEach(item => makeNavigationItemSortable(item));
}

function makeNavigationItemSortable(navItem) {
    if (!navItem) return;
    navItem.draggable = true;
    navItem.style.cursor = 'move';
    navItem.title = '拖拽调整顺序';
    navItem.addEventListener('dragstart', function (e) {
        e.dataTransfer.setData('text/plain', this.dataset.id);
        this.classList.add('dragging');
        e.dataTransfer.effectAllowed = 'move';
    });
    navItem.addEventListener('dragend', function () {
        this.classList.remove('dragging');
        document.querySelectorAll('.navigation-item.drag-over').forEach(item => item.classList.remove('drag-over'));
    });
    navItem.addEventListener('dragover', function (e) {
        e.preventDefault();
        if (this !== document.querySelector('.navigation-item.dragging')) {
            document.querySelectorAll('.navigation-item.drag-over').forEach(item => { if (item !== this) item.classList.remove('drag-over'); });
            this.classList.add('drag-over');
        }
    });
    navItem.addEventListener('dragleave', function () {
        setTimeout(() => { if (!this.contains(document.querySelector('.navigation-item.dragging'))) this.classList.remove('drag-over'); }, 10);
    });
    navItem.addEventListener('drop', function (e) {
        e.preventDefault();
        this.classList.remove('drag-over');
        const draggedId = e.dataTransfer.getData('text/plain');
        const draggedElement = document.querySelector(`.navigation-item[data-id="${draggedId}"]`);
        if (draggedElement && draggedElement !== this) {
            const container = document.getElementById('navigations-container');
            const rect = this.getBoundingClientRect();
            const y = e.clientY - rect.top;
            if (y < rect.height / 2) container.insertBefore(draggedElement, this);
            else container.insertBefore(draggedElement, this.nextSibling);
            updateNavigationIndices();
            saveNavigationOrder();
        }
    });
}

function updateNavigationIndices() {
    const items = document.querySelectorAll('.navigation-item');
    items.forEach((item, index) => {
        const indexElement = item.querySelector('.navigation-index');
        if (indexElement) indexElement.textContent = index + 1;
    });
}

function saveNavigationOrder() {
    const items = document.querySelectorAll('.navigation-item');
    const navigationData = Array.from(items).map((item, index) => ({ id: item.dataset.id, display_order: index }));
    const url = '/admin/settings.php?action=save_navigations';
    fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(navigationData) })
        .then(response => response.json())
        .then(data => {
            if (data.success) showToast('导航顺序保存成功', 'info');
            else showToast(data.message || '导航顺序保存失败', 'error');
        })
        .catch(error => showToast('保存导航顺序失败，请重试', 'error'));
}

function confirmDeleteNavigation(id, name) {
    if (!id) { showToast('导航项ID不能为空', 'error'); return; }
    if (window.isDemoSettingsAccount) {
        showToast('演示账号无权限操作', 'error');
        return;
    }
    if (window.deleteNavigationItem) {
        deleteNavigationItem(id);
        return;
    }
    showToast('删除功能不可用，请刷新页面重试', 'error');
}

document.addEventListener('DOMContentLoaded', function () {
    if (typeof initNavigationModal === 'function') initNavigationModal();
    // 初始化分类编辑功能
    if (typeof initEditCategoryModal === 'function') initEditCategoryModal();
    window.deleteNavigationItem = deleteNavigationItem;
    window.confirmDeleteNavigation = confirmDeleteNavigation;
    // 确保openEditCategoryModal函数全局可用
    if (typeof openEditCategoryModal === 'function') window.openEditCategoryModal = openEditCategoryModal;
    if (!window.closeModal) window.closeModal = function () { };
    const originalCloseModal = window.closeModal;
    window.closeModal = function () {
        originalCloseModal();
        const navigationModal = document.getElementById('navigationEditModal');
        if (navigationModal) {
            navigationModal.classList.remove('modal-visible');
            setTimeout(() => {
                navigationModal.style.display = 'none';
                // 只恢复overflow属性
                document.body.style.overflow = '';
            }, 300);
        }
    };
});

(function () {
    function getEl(id) { return document.getElementById(id); }

    function ensureCommonToolModal() {
        let modal = document.getElementById('commonToolModal');
        if (modal) return modal;

        modal = document.createElement('div');
        modal.id = 'commonToolModal';
        modal.className = 'modal';
        modal.style.display = 'none';
        modal.innerHTML = `
            <div class="modal-backdrop"></div>
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title" id="commonToolModalTitle">常用工具</h3>
                    <button type="button" class="modal-close" id="commonToolModalClose">×</button>
                </div>
                <div class="modal-body" id="commonToolModalBody"></div>
            </div>
        `;
        document.body.appendChild(modal);

        function close() {
            modal.classList.remove('modal-visible');
            modal.style.display = 'none';
            document.body.style.overflow = '';
            const body = getEl('commonToolModalBody');
            if (body) body.innerHTML = '';
        }

        const closeBtn = getEl('commonToolModalClose');
        const backdrop = modal.querySelector('.modal-backdrop');
        if (closeBtn) closeBtn.addEventListener('click', close);
        if (backdrop) backdrop.addEventListener('click', close);
        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && modal.style.display !== 'none') close();
        });

        modal.__close = close;
        return modal;
    }

    function setCommonToolModalSize(modal, width, height) {
        const modalContent = modal.querySelector('.modal-content');
        const modalBody = modal.querySelector('.modal-body');
        const modalHeader = modal.querySelector('.modal-header');
        if (!modalContent || !modalBody) return;

        const maxW = Math.max(320, window.innerWidth - 60);
        const maxH = Math.max(240, window.innerHeight - 60);

        let w = parseInt(width || '', 10);
        let h = parseInt(height || '', 10);

        if (!w || w <= 0) w = Math.min(980, maxW);
        if (!h || h <= 0) h = Math.min(720, maxH);
        w = Math.min(w, maxW);
        h = Math.min(h, maxH);

        modalContent.style.width = w + 'px';
        modalContent.style.height = h + 'px';

        const headerHeight = modalHeader ? modalHeader.offsetHeight : 64;
        const bodyHeight = Math.max(120, h - headerHeight);
        modalBody.style.height = bodyHeight + 'px';
        modalBody.style.overflow = 'hidden';
    }

    function openCommonToolPlugin(pluginIdentifier, pluginName, pluginType) {
        const modal = ensureCommonToolModal();
        const title = getEl('commonToolModalTitle');
        const body = getEl('commonToolModalBody');

        if (title) title.textContent = pluginName || '常用工具';
        if (body) body.innerHTML = '<div style="padding:20px;color:#64748b;">加载中...</div>';

        modal.style.display = 'flex';
        document.body.style.overflow = '';
        modal.classList.remove('modal-visible');

        const formData = new URLSearchParams();
        formData.set('action', 'render_tool_html');
        formData.set('plugin', pluginIdentifier);

        fetch('/admin/Plugin.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: formData.toString()
        })
            .then(r => r.text())
            .then(t => {
                try { return JSON.parse(t); } catch (e) { throw new Error('无效响应'); }
            })
            .then(data => {
                if (!data || !data.success) throw new Error((data && data.message) ? data.message : '加载失败');
                if (!body) return;

                const pluginCSS = '<style>#toast-container{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:9999;display:flex;flex-direction:column;gap:10px;align-items:center;}.toast{background-color:rgba(0,0,0,0.7);color:white;padding:12px 24px;border-radius:6px;font-size:14px;font-weight:500;max-width:420px;white-space:normal;text-align:center;line-height:1.5;opacity:0;transform:translateX(100%);transition:opacity 0.3s ease, transform 0.3s ease;box-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px-4px rgba(0,0,0,0.1);}.toast.toast-visible{opacity:1;transform:translateX(0);}.toast.toast-error{background-color:rgba(255,69,0,0.85);}#plugin-confirm-container{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,0.3);display:flex;align-items:center;justify-content:center;z-index:10000;}.plugin-confirm-dialog{background-color:white;border-radius:8px;padding:40px 50px;box-shadow:0 10px 25px rgba(0,0,0,0.2);opacity:0;transform:scale(0.9);transition:opacity 0.3s ease, transform 0.3s ease;}.plugin-confirm-dialog.plugin-confirm-visible{opacity:1;transform:scale(1);}.plugin-confirm-message{font-size:16px;color:#333;margin-bottom:20px;text-align:center;}.plugin-confirm-buttons{display:flex;gap:12px;justify-content:center;}.plugin-confirm-btn{padding:8px 20px;border:none;border-radius:4px;font-size:14px;cursor:pointer;transition:background-color 0.2s ease;}.plugin-cancel-btn{background-color:#f1f1f1;color:#333;}.plugin-cancel-btn:hover{background-color:#e0e0e0;}.plugin-confirm-btn.plugin-confirm-btn{background-color:#F03;color:white;}.plugin-confirm-btn.plugin-confirm-btn:hover{opacity:0.8;}</style>';
                const pluginScrollbarCSS = '<style id="qk-scrollbar-style">::-webkit-scrollbar{width:10px;height:10px;}::-webkit-scrollbar-track{background:#e2e8f0;border-radius:14px;}::-webkit-scrollbar-thumb{background:#94a3b8;border-radius:14px;}::-webkit-scrollbar-thumb:hover{background:#64748b;}</style>';

                const iframe = document.createElement('iframe');
                iframe.setAttribute('sandbox', 'allow-scripts allow-forms allow-same-origin allow-downloads allow-popups');
                iframe.style.border = 'none';
                iframe.style.display = 'block';
                iframe.style.width = '100%';
                iframe.style.height = '100%';
                iframe.style.overflow = 'hidden';

                const modalContent = modal.querySelector('.modal-content');
                const modalBody = modal.querySelector('.modal-body');
                if (modalContent && modalBody) {
                    if (data.width && data.height) {
                        const pluginWidth = parseInt(data.width);
                        const pluginHeight = parseInt(data.height);
                        iframe.style.width = '100%';
                        iframe.style.height = pluginHeight + 'px';
                        const modalWidth = pluginWidth + 30;
                        const modalHeight = pluginHeight + 130;
                        const maxWidth = window.innerWidth * 0.9;
                        const maxHeight = window.innerHeight * 0.9;
                        modalContent.style.width = Math.min(modalWidth, maxWidth) + 'px';
                        modalContent.style.height = Math.min(modalHeight, maxHeight) + 'px';
                    } else {
                        iframe.style.width = '100%';
                        iframe.style.height = 'auto';
                        modalContent.style.width = 'auto';
                    }
                    modalBody.style.overflow = 'hidden';
                }

                iframe.onload = function () {
                    try {
                        const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                        if (!iframeDoc) return;

                        const existingScrollbarStyle = iframeDoc.getElementById('qk-scrollbar-style');
                        if (!existingScrollbarStyle) {
                            const scrollbarStyle = iframeDoc.createElement('style');
                            scrollbarStyle.id = 'qk-scrollbar-style';
                            scrollbarStyle.textContent = '::-webkit-scrollbar{width:10px;height:10px;}::-webkit-scrollbar-track{background:#e2e8f0;border-radius:14px;}::-webkit-scrollbar-thumb{background:#94a3b8;border-radius:14px;}::-webkit-scrollbar-thumb:hover{background:#64748b;}';
                            const attachPoint = iframeDoc.head || iframeDoc.documentElement;
                            if (attachPoint) attachPoint.appendChild(scrollbarStyle);
                        }

                        const pluginContainer = iframeDoc.createElement('div');
                        pluginContainer.style.display = 'inline-block';
                        pluginContainer.style.textAlign = 'left';
                        pluginContainer.style.verticalAlign = 'top';

                        iframeDoc.body.style.margin = '0';
                        iframeDoc.body.style.padding = '15px';
                        iframeDoc.body.style.boxSizing = 'border-box';
                        iframeDoc.body.style.textAlign = 'center';
                        while (iframeDoc.body.firstChild) {
                            pluginContainer.appendChild(iframeDoc.body.firstChild);
                        }
                        iframeDoc.body.appendChild(pluginContainer);

                        let contentWidth;
                        let contentHeight;
                        if (data.width && data.height) {
                            contentWidth = parseInt(data.width, 10);
                            contentHeight = parseInt(data.height, 10);
                        } else {
                            contentWidth = pluginContainer.scrollWidth || pluginContainer.offsetWidth;
                            contentHeight = pluginContainer.scrollHeight || pluginContainer.offsetHeight;
                        }

                        const modalWidth = (contentWidth || 700) + 60;
                        const modalHeight = (contentHeight || 520) + 100;
                        const maxWidth = window.innerWidth * 0.9;
                        const maxHeight = window.innerHeight * 0.9;
                        if (modalContent && modalBody) {
                            modalContent.style.width = Math.min(modalWidth, maxWidth) + 'px';
                            modalContent.style.height = Math.min(modalHeight, maxHeight) + 'px';
                            modalBody.style.overflow = 'hidden';
                            iframe.style.width = '100%';
                            iframe.style.height = (contentHeight + 30) + 'px';
                            iframe.style.overflow = 'hidden';
                        }
                        modal.classList.add('modal-visible');
                    } catch (e) { }
                };
                iframe.srcdoc = pluginCSS + pluginScrollbarCSS + (data.html || '');
                body.innerHTML = '';
                body.appendChild(iframe);
            })
            .catch(err => {
                if (body) body.innerHTML = '<div style="padding:20px;color:#ef4444;">' + (err && err.message ? err.message : '加载失败') + '</div>';
                modal.classList.add('modal-visible');
                if (typeof showToast === 'function') showToast('加载失败', 'error');
            });
    }

    window.qkOpenCommonToolPlugin = openCommonToolPlugin;
    window.qkCloseCommonToolModal = function () {
        const modal = document.getElementById('commonToolModal');
        if (modal && typeof modal.__close === 'function') modal.__close();
    };

    function loadCommonTools() {
        return fetch('/admin/Plugin.php?action=get_favorite_tools', { method: 'GET' })
            .then(r => r.json())
            .then(data => {
                if (!data || !data.success || !Array.isArray(data.tools)) return [];
                return data.tools.map(p => ({
                    id: p['ID'] || p.ID || '',
                    name: p['名称'] || p.name || '',
                    type: '工具',
                    identifier: p['标识'] || p.identifier || ''
                })).filter(p => p.identifier && p.name);
            })
            .catch(() => []);
    }

    function renderCommonToolsMenu(menuEl, items) {
        menuEl.innerHTML = '';
        if (!items || items.length === 0) {
            const empty = document.createElement('div');
            empty.className = 'common-tools-empty';
            empty.textContent = '暂无工具';
            menuEl.appendChild(empty);
            return;
        }

        items.forEach(item => {
            const row = document.createElement('div');
            row.className = 'common-tools-item';
            row.dataset.plugin = item.identifier;
            row.dataset.name = item.name;
            row.dataset.type = item.type;

            const left = document.createElement('div');
            const idText = (item.id !== undefined && item.id !== null && String(item.id).trim() !== '') ? ('[' + String(item.id).trim() + '] ') : '';
            left.textContent = idText + item.name;
            left.style.overflow = 'hidden';
            left.style.textOverflow = 'ellipsis';

            row.appendChild(left);
            menuEl.appendChild(row);
        });
    }

    document.addEventListener('DOMContentLoaded', function () {
        const dropdown = getEl('commonToolsDropdown');
        const trigger = getEl('commonToolsTrigger');
        const menu = getEl('commonToolsMenu');
        if (!dropdown || !trigger || !menu) return;
        const isDemoCommonToolsAccount = trigger.getAttribute('data-demo-account') === '1';

        function openDropdown() {
            dropdown.classList.add('show');
            menu.innerHTML = '<div class="common-tools-empty">加载中...</div>';
            loadCommonTools().then(items => {
                renderCommonToolsMenu(menu, items);
            });
        }

        function closeDropdown() {
            dropdown.classList.remove('show');
        }

        trigger.addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (isDemoCommonToolsAccount) {
                if (typeof showToast === 'function') showToast('演示账号无权限操作', 'error', 1500);
                return;
            }
            if (dropdown.classList.contains('show')) {
                closeDropdown();
            } else {
                openDropdown();
            }
        });

        // 监听侧边栏切换事件，关闭下拉菜单
        document.addEventListener('sidebarToggled', function() {
            if (dropdown.classList.contains('show')) {
                closeDropdown();
            }
        });

        menu.addEventListener('click', function (e) {
            const item = e.target.closest('.common-tools-item');
            if (!item) return;
            if (isDemoCommonToolsAccount) {
                closeDropdown();
                if (typeof showToast === 'function') showToast('演示账号无权限操作', 'error', 1500);
                return;
            }
            const pluginIdentifier = item.dataset.plugin;
            const pluginName = item.dataset.name;
            const pluginType = item.dataset.type;
            closeDropdown();
            openCommonToolPlugin(pluginIdentifier, pluginName, pluginType);
        });

        document.addEventListener('click', function () {
            closeDropdown();
        });

        dropdown.addEventListener('click', function (e) {
            e.stopPropagation();
        });
    });
})();

(function () {
    function toElement(target) {
        if (!target) return null;
        if (typeof target === 'string') return document.querySelector(target);
        return target;
    }
    function clamp(value, min, max) { return Math.max(min, Math.min(value, max)); }
    function elementWidth(el) { return parseInt(window.getComputedStyle(el).width, 10) || el.offsetWidth || 0; }
    function initHorizontal(options) {
        options = options || {};
        var scrollContainer = toElement(options.scrollContainer || options.container);
        var scrollbarTrack = toElement(options.track);
        var scrollbarThumb = toElement(options.thumb);
        if (!scrollContainer || !scrollbarTrack || !scrollbarThumb) return null;
        var state = scrollContainer._qkHorizontalScrollbarState;
        if (state && typeof state.cleanup === 'function') state.cleanup();
        var dragState = { active: false, pendingClientX: 0, rafId: 0, trackRect: null, thumbWidth: 0, trackWidth: 0 };
        function updateScrollbarThumb() {
            var maxScrollLeft = Math.max(0, scrollContainer.scrollWidth - scrollContainer.clientWidth);
            if (maxScrollLeft <= 0) {
                scrollbarThumb.style.left = '0px';
                return;
            }
            var maxThumbPosition = Math.max(0, scrollbarTrack.offsetWidth - elementWidth(scrollbarThumb));
            scrollbarThumb.style.left = ((scrollContainer.scrollLeft / maxScrollLeft) * maxThumbPosition) + 'px';
        }
        function updateHorizontalByClientX(clientX) {
            var trackRect = dragState.trackRect || scrollbarTrack.getBoundingClientRect();
            var thumbWidth = dragState.thumbWidth || elementWidth(scrollbarThumb);
            var maxThumbPosition = Math.max(0, (dragState.trackWidth || scrollbarTrack.offsetWidth) - thumbWidth);
            var newLeft = clamp(clientX - trackRect.left - (thumbWidth / 2), 0, maxThumbPosition);
            var maxScrollLeft = Math.max(0, scrollContainer.scrollWidth - scrollContainer.clientWidth);
            scrollContainer.scrollLeft = (maxThumbPosition > 0 ? (newLeft / maxThumbPosition) : 0) * maxScrollLeft;
            scrollbarThumb.style.left = newLeft + 'px';
        }
        function queueHorizontalDragRender() {
            if (dragState.rafId) return;
            dragState.rafId = window.requestAnimationFrame(function () {
                dragState.rafId = 0;
                updateHorizontalByClientX(dragState.pendingClientX);
            });
        }
        function onMouseDown(e) {
            dragState.active = true;
            dragState.trackRect = scrollbarTrack.getBoundingClientRect();
            dragState.thumbWidth = elementWidth(scrollbarThumb);
            dragState.trackWidth = scrollbarTrack.offsetWidth;
            scrollbarThumb.classList.add('dragging');
            document.body.style.userSelect = 'none';
            e.preventDefault();
        }
        function onMouseMove(e) {
            if (!dragState.active) return;
            dragState.pendingClientX = e.clientX;
            queueHorizontalDragRender();
        }
        function onMouseUp() {
            if (!dragState.active) return;
            dragState.active = false;
            if (dragState.rafId) window.cancelAnimationFrame(dragState.rafId);
            dragState.rafId = 0;
            dragState.trackRect = null;
            dragState.thumbWidth = 0;
            dragState.trackWidth = 0;
            scrollbarThumb.classList.remove('dragging');
            document.body.style.userSelect = '';
        }
        function onTrackClick(e) { updateHorizontalByClientX(e.clientX); }
        scrollContainer.addEventListener('scroll', updateScrollbarThumb);
        scrollbarThumb.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
        scrollbarTrack.addEventListener('click', onTrackClick);
        scrollContainer[options.updateHookName || '_qkUpdateScrollbarThumb'] = updateScrollbarThumb;
        function cleanup() {
            if (dragState.rafId) window.cancelAnimationFrame(dragState.rafId);
            scrollContainer.removeEventListener('scroll', updateScrollbarThumb);
            scrollbarThumb.removeEventListener('mousedown', onMouseDown);
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
            scrollbarTrack.removeEventListener('click', onTrackClick);
        }
        scrollContainer._qkHorizontalScrollbarState = { cleanup: cleanup, update: updateScrollbarThumb };
        updateScrollbarThumb();
        window.requestAnimationFrame(updateScrollbarThumb);
        return scrollContainer._qkHorizontalScrollbarState;
    }
    function initVerticalMenu(options) {
        options = options || {};
        var menu = toElement(options.menu);
        if (!menu) return null;
        var content = menu.querySelector(options.contentSelector || '.qk-menu-scroll-content');
        var track = menu.querySelector(options.trackSelector || '.qk-menu-vscroll');
        var thumb = menu.querySelector(options.thumbSelector || '.qk-menu-vthumb');
        if (!content || !track || !thumb) return null;
        var state = menu._qkVerticalScrollbarState;
        if (state && typeof state.cleanup === 'function') state.cleanup();
        var thumbHeightConfig = parseInt(options.thumbHeight || 80, 10);
        if (!thumbHeightConfig || thumbHeightConfig < 24) thumbHeightConfig = 80;
        var scrollRafId = 0, dragRafId = 0, dragging = false, dragStartY = 0, dragStartTop = 0, pendingTop = 0;
        function setThumbTop(top) {
            thumb.setAttribute('data-top', String(top));
            thumb.style.transform = 'translateY(' + top + 'px)';
        }
        function update() {
            var maxScrollTop = content.scrollHeight - content.clientHeight;
            var trackHeight = track.clientHeight;
            if (trackHeight <= 0) {
                var style = window.getComputedStyle(track);
                var topGap = parseFloat(style.top) || 0;
                var bottomGap = parseFloat(style.bottom) || 0;
                trackHeight = Math.max(0, menu.clientHeight - topGap - bottomGap);
            }
            var hasOverflow = maxScrollTop > 1 && trackHeight > 0;
            if (!hasOverflow) {
                menu.classList.remove('qk-menu-has-scroll');
                menu.classList.remove('counter-menu-has-scroll');
                track.style.display = 'none';
                thumb.style.display = 'none';
                return;
            }
            menu.classList.add('qk-menu-has-scroll');
            menu.classList.add('counter-menu-has-scroll');
            track.style.display = 'block';
            thumb.style.display = 'block';
            trackHeight = track.clientHeight || trackHeight;
            var thumbHeight = Math.min(thumbHeightConfig, trackHeight);
            var maxThumbTop = Math.max(0, trackHeight - thumbHeight);
            var ratio = maxScrollTop > 0 ? (content.scrollTop / maxScrollTop) : 0;
            var thumbTop = ratio * maxThumbTop;
            if (thumbTop >= maxThumbTop - 0.5) thumbTop = maxThumbTop;
            if (thumbTop <= 0.5) thumbTop = 0;
            thumb.style.height = thumbHeight + 'px';
            setThumbTop(thumbTop);
        }
        function queueUpdate() {
            if (dragging) return;
            if (scrollRafId) return;
            scrollRafId = window.requestAnimationFrame(function () {
                scrollRafId = 0;
                update();
            });
        }
        function applyPendingTop() {
            var thumbHeight = thumb.offsetHeight;
            var maxThumbTop = Math.max(0, track.clientHeight - thumbHeight);
            var newTop = clamp(pendingTop, 0, maxThumbTop);
            var maxScrollTop = Math.max(0, content.scrollHeight - content.clientHeight);
            if (newTop >= maxThumbTop - 0.5) {
                newTop = maxThumbTop;
                content.scrollTop = maxScrollTop;
            } else if (newTop <= 0.5) {
                newTop = 0;
                content.scrollTop = 0;
            } else {
                content.scrollTop = (maxThumbTop > 0 ? (newTop / maxThumbTop) : 0) * maxScrollTop;
            }
            setThumbTop(newTop);
        }
        function queueDragRender() {
            if (dragRafId) return;
            dragRafId = window.requestAnimationFrame(function () {
                dragRafId = 0;
                applyPendingTop();
            });
        }
        function onThumbMouseDown(e) {
            dragging = true;
            dragStartY = e.clientY;
            dragStartTop = parseInt(thumb.getAttribute('data-top') || '0', 10) || 0;
            thumb.classList.add('dragging');
            document.body.style.userSelect = 'none';
            e.preventDefault();
            e.stopPropagation();
        }
        function onDocumentMouseMove(e) {
            if (!dragging) return;
            pendingTop = dragStartTop + (e.clientY - dragStartY);
            queueDragRender();
        }
        function onDocumentMouseUp() {
            if (!dragging) return;
            dragging = false;
            thumb.classList.remove('dragging');
            document.body.style.userSelect = '';
        }
        function onTrackClick(e) {
            if (e.target === thumb) return;
            var thumbHeight = thumb.offsetHeight;
            var maxThumbTop = Math.max(0, track.clientHeight - thumbHeight);
            var rect = track.getBoundingClientRect();
            var newTop = clamp(e.clientY - rect.top - (thumbHeight / 2), 0, maxThumbTop);
            var maxScrollTop = Math.max(0, content.scrollHeight - content.clientHeight);
            if (newTop >= maxThumbTop - 0.5) {
                newTop = maxThumbTop;
                content.scrollTop = maxScrollTop;
            } else if (newTop <= 0.5) {
                newTop = 0;
                content.scrollTop = 0;
            } else {
                content.scrollTop = (maxThumbTop > 0 ? (newTop / maxThumbTop) : 0) * maxScrollTop;
            }
            setThumbTop(newTop);
        }
        thumb.classList.remove('dragging');
        content.addEventListener('scroll', queueUpdate);
        thumb.addEventListener('mousedown', onThumbMouseDown);
        document.addEventListener('mousemove', onDocumentMouseMove);
        document.addEventListener('mouseup', onDocumentMouseUp);
        track.addEventListener('click', onTrackClick);
        menu[options.updateHookName || '_qkMenuScrollbarUpdate'] = update;
        function cleanup() {
            if (scrollRafId) window.cancelAnimationFrame(scrollRafId);
            if (dragRafId) window.cancelAnimationFrame(dragRafId);
            content.removeEventListener('scroll', queueUpdate);
            thumb.removeEventListener('mousedown', onThumbMouseDown);
            document.removeEventListener('mousemove', onDocumentMouseMove);
            document.removeEventListener('mouseup', onDocumentMouseUp);
            track.removeEventListener('click', onTrackClick);
        }
        menu._qkVerticalScrollbarState = { cleanup: cleanup, update: update };
        update();
        window.requestAnimationFrame(update);
        return menu._qkVerticalScrollbarState;
    }
    window.AdminScrollbar = window.AdminScrollbar || {};
    window.AdminScrollbar.initHorizontal = initHorizontal;
    window.AdminScrollbar.initVerticalMenu = initVerticalMenu;
})();

(function () {
    function ensureTip() {
        var tip = document.getElementById('qkHoverTip');
        if (tip) return tip;
        tip = document.createElement('div');
        tip.id = 'qkHoverTip';
        tip.className = 'qk-hover-tip';
        tip.style.setProperty('--qk-arrow-left', '50%');
        document.body.appendChild(tip);
        return tip;
    }

    function setArrow(tip, percent) {
        if (!tip) return;
        tip.style.setProperty('--qk-arrow-left', percent + '%');
    }

    function clamp(v, min, max) {
        return Math.max(min, Math.min(max, v));
    }

    function positionTip(tip, x, y) {
        if (!tip) return;
        var offsetX = 12;
        var offsetY = 14;
        var vw = document.documentElement.clientWidth || window.innerWidth || 0;
        var vh = document.documentElement.clientHeight || window.innerHeight || 0;
        var margin = 10;

        tip.style.left = '0px';
        tip.style.top = '0px';
        tip.classList.add('show');

        var rect = tip.getBoundingClientRect();
        var w = rect.width || 0;
        var h = rect.height || 0;

        var left = x - (w / 2);
        left = clamp(left, margin, Math.max(margin, vw - w - margin));

        var top = y - h - offsetY;
        var placeAbove = top >= margin;
        if (!placeAbove) {
            top = y + offsetY;
            if (top + h > vh - margin) {
                top = vh - h - margin;
            }
        } else {
        }
        tip.classList.toggle('dir-up', !placeAbove);
        tip.classList.toggle('dir-down', placeAbove);

        var arrowLeftPx = x - left;
        var arrowPercent = w > 0 ? (arrowLeftPx / w) * 100 : 50;
        setArrow(tip, clamp(arrowPercent, 12, 88));

        tip.style.left = Math.round(left) + 'px';
        tip.style.top = Math.round(top) + 'px';
    }

    function hideTip(tip) {
        if (!tip) return;
        tip.classList.remove('show');
    }

    function hasTipOverflow(el) {
        if (!el) return false;
        var text = String(el.textContent || '').trim();
        if (text.indexOf('...') !== -1) return true;
        if ((el.scrollWidth - el.clientWidth) > 1 || (el.scrollHeight - el.clientHeight) > 1) return true;
        var cell = el.closest ? el.closest('td,th') : null;
        if (cell && ((cell.scrollWidth - cell.clientWidth) > 1 || (cell.scrollHeight - cell.clientHeight) > 1)) {
            return true;
        }
        return false;
    }

    var activeEl = null;
    var activeText = '';
    var raf = 0;
    var lastX = 0;
    var lastY = 0;

    function scheduleMove(tip) {
        if (raf) return;
        raf = window.requestAnimationFrame(function () {
            raf = 0;
            if (!activeEl || !activeText) return;
            positionTip(tip, lastX, lastY);
        });
    }

    document.addEventListener('mouseover', function (e) {
        var t = e.target;
        if (!t || t === document || t === window) return;
        if (t.nodeType && t.nodeType !== 1) {
            t = t.parentElement;
        }
        var el = t && t.closest ? t.closest('[data-qk-tip]') : null;
        if (!el) return;
        var text = String(el.getAttribute('data-qk-tip') || '').trim();
        if (!text) return;
        if (!hasTipOverflow(el)) return;
        var tip = ensureTip();
        activeEl = el;
        activeText = text;
        tip.textContent = text;
        lastX = e.clientX;
        lastY = e.clientY;
        positionTip(tip, lastX, lastY);
    });

    document.addEventListener('mousemove', function (e) {
        if (!activeEl || !activeText) return;
        lastX = e.clientX;
        lastY = e.clientY;
        scheduleMove(ensureTip());
    });

    document.addEventListener('mouseout', function (e) {
        if (!activeEl) return;
        var related = e.relatedTarget;
        if (related && related.nodeType && related.nodeType !== 1) {
            related = related.parentElement;
        }
        if (related && activeEl.contains && activeEl.contains(related)) return;
        var tip = document.getElementById('qkHoverTip');
        hideTip(tip);
        activeEl = null;
        activeText = '';
    });

    document.addEventListener('scroll', function () {
        if (!activeEl) return;
        var tip = document.getElementById('qkHoverTip');
        hideTip(tip);
        activeEl = null;
        activeText = '';
    }, true);
})();
