<?php
// 功能：包含图像处理 网站设置 栏目管理 文章管理 安全验证等
// 作者：启肯科技
// Q Q：328493711
// 微信：13738373177（同手机）
// 官网：http://www.qiken.com
// 说明：QKCMS-轻量级AI智能内容管理建站系统
// 版权：© 2025 温州启肯网络有限公司 保留所有权利，盗版必究。

require_once '../common.php';

// 权限验证 - 只有已登录的管理员才能访问后台接口
if (!isLoggedIn() || !isAdmin()) {
    header('Content-Type: application/json');
    echo json_encode(['success' => false, 'message' => '权限不足，请先登录']);
    exit;
}

// 确保上传目录存在
ensureUploadDirectories();

function qk_download_remote_images_to_temp_by_ext($content, $maxImages = 30, $maxBytes = 4194304)
{
    if (!$content || !is_string($content)) {
        return array('content' => $content, 'found' => 0, 'downloaded' => 0);
    }
    if (!function_exists('curl_init')) {
        return array('content' => $content, 'found' => 0, 'downloaded' => 0);
    }

    $allowedExts = array('jpg', 'jpeg', 'png', 'gif', 'webp');
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
    $currentHost = $host !== '' ? strtolower($host) : '';

    $found = 0;
    $downloaded = 0;
    $seen = array();

    $updated = preg_replace_callback('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', function ($m) use (&$found, &$downloaded, &$seen, $maxImages, $maxBytes, $allowedExts, $protocol, $host, $currentHost) {
        if ($downloaded >= $maxImages) {
            return $m[0];
        }

        $imgTag = $m[0];
        $src = trim(html_entity_decode((string)$m[1], ENT_QUOTES | ENT_HTML5, 'UTF-8'));
        if ($src === '' || strpos($src, 'data:image/') === 0 || strpos($src, 'blob:') === 0) {
            return $imgTag;
        }

        $url = $src;
        if (strpos($url, '//') === 0) $url = 'https:' . $url;
        if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) {
            return $imgTag;
        }
        if (isset($seen[$url])) {
            $cached = $seen[$url];
            if ($cached !== '') {
                return str_replace($m[1], $cached, $imgTag);
            }
            return $imgTag;
        }

        $p = @parse_url($url);
        if (!$p || empty($p['host'])) {
            $seen[$url] = '';
            return $imgTag;
        }
        $h = strtolower((string)$p['host']);
        $path = isset($p['path']) ? (string)$p['path'] : '';
        if ($currentHost !== '' && $h === $currentHost) {
            if (strpos($path, '/uploads/') === 0 || strpos($path, '/assets/') === 0) {
                $seen[$url] = $src;
                return $imgTag;
            }
        }

        $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
        if ($ext === 'jpeg') $ext = 'jpg';
        if ($ext === '' || !in_array($ext, $allowedExts, true)) {
            $seen[$url] = '';
            return $imgTag;
        }

        $found++;
        $tmpName = 'article_' . uniqid('', true) . '.tmp';
        $tmpPath = UPLOAD_DIR . $tmpName;
        $fp = @fopen($tmpPath, 'wb');
        if (!$fp) {
            $seen[$url] = '';
            return $imgTag;
        }

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
        curl_setopt($ch, CURLOPT_TIMEOUT, 25);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8'));
        curl_setopt($ch, CURLOPT_FILE, $fp);
        curl_setopt($ch, CURLOPT_BUFFERSIZE, 16384);
        curl_setopt($ch, CURLOPT_NOPROGRESS, false);
        curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function ($resource, $downloadSize, $downloadedBytes, $uploadSize, $uploaded) use ($maxBytes) {
            if (is_numeric($downloadedBytes) && $downloadedBytes > $maxBytes) return 1;
            return 0;
        });
        $ok = curl_exec($ch);
        $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        fclose($fp);

        if ($ok === false || $httpCode < 200 || $httpCode >= 300) {
            @unlink($tmpPath);
            $seen[$url] = '';
            return $imgTag;
        }

        $size = @filesize($tmpPath);
        if (!$size || $size <= 0 || $size > $maxBytes) {
            @unlink($tmpPath);
            $seen[$url] = '';
            return $imgTag;
        }

        $info = @getimagesize($tmpPath);
        if (!$info || empty($info['mime'])) {
            @unlink($tmpPath);
            $seen[$url] = '';
            return $imgTag;
        }

        $mimeToExt = array(
            'image/jpeg' => 'jpg',
            'image/jpg' => 'jpg',
            'image/png' => 'png',
            'image/gif' => 'gif',
            'image/webp' => 'webp',
        );
        $mime = strtolower((string)$info['mime']);
        if (!isset($mimeToExt[$mime])) {
            @unlink($tmpPath);
            $seen[$url] = '';
            return $imgTag;
        }

        $finalExt = $mimeToExt[$mime];
        $fileName = 'article_' . uniqid('', true) . '.' . $finalExt;
        $destPath = UPLOAD_DIR . $fileName;
        if (!@rename($tmpPath, $destPath)) {
            if (!@copy($tmpPath, $destPath)) {
                @unlink($tmpPath);
                $seen[$url] = '';
                return $imgTag;
            }
            @unlink($tmpPath);
        }

        $newUrl = '/uploads/' . $fileName;
        $downloaded++;
        $seen[$url] = $newUrl;
        return str_replace($m[1], $newUrl, $imgTag);
    }, $content);

    return array('content' => $updated, 'found' => $found, 'downloaded' => $downloaded);
}
// 允许这些GET操作无需XMLHttpRequest头
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && in_array($_GET['action'], array('get_categories', 'get_categories_simple', 'get_articles', 'get_article', 'get_comments', 'get_reports', 'get_tags', 'get_searches', 'get_orders', 'get_publish', 'get_publish_detail', 'get_users', 'get_goods', 'get_counter'))) {
    // 允许这些GET请求
    session_start();
    require_once '../common.php';
    get_db_connection();
} else if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && in_array($_GET['action'], array('get_categories', 'get_categories_simple', 'get_articles', 'get_article', 'get_comments', 'get_reports', 'get_tags', 'get_searches', 'get_orders', 'get_publish', 'get_publish_detail', 'get_users', 'get_goods', 'get_counter'))) {
    // 允许这些GET请求
    session_start();
    require_once '../common.php';
    get_db_connection();
} else if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    return_json(false, '无效的请求方式');
}
// 移除POST请求的XMLHttpRequest头检查，允许所有POST请求
session_start();
require_once '../common.php';
// 初始化数据库连接
$conn = get_db_connection();
// 分类缩略图上传函数 - 使用category_前缀
if (isset($_POST['upload_category_thumbnail']) && isset($_FILES['thumbnail'])) {
    ensureUploadDirectories();
    $file = $_FILES['thumbnail'];
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileError = $file['error'];
    $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
    if ($fileError !== UPLOAD_ERR_OK) {
        return_json(false, '文件上传失败');
    }
    if (!in_array($fileExt, $allowedExts)) {
        return_json(false, '不支持的文件类型');
    }
    if ($fileSize > 2 * 1024 * 1024) {
        return_json(false, '文件大小超过2MB限制');
    }
    $newFileName = 'category_' . uniqid('', true) . '.' . $fileExt;
    $destination = TEMP_UPLOAD_DIR . $newFileName;
    if (move_uploaded_file($fileTmpName, $destination)) {
        $thumbnailUrl = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
        return_json(true, '分类缩略图上传成功', ['thumbnail_url' => $thumbnailUrl]);
    } else {
        return_json(false, '文件保存失败');
    }
}
if (isset($_POST['upload_site_logo']) && isset($_FILES['logo'])) {
    ensureUploadDirectories();
    $file = $_FILES['logo'];
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileError = $file['error'];
    $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg', 'ico'];
    if ($fileError !== UPLOAD_ERR_OK) {
        return_json(false, '文件上传失败');
    }
    if (!in_array($fileExt, $allowedExts)) {
        return_json(false, '不支持的文件类型');
    }
    if ($fileSize > 2 * 1024 * 1024) {
        return_json(false, '文件大小超过2MB限制');
    }
    $newFileName = 'logo_' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT) . '.' . $fileExt;
    $destination = TEMP_UPLOAD_DIR . $newFileName;
    if (move_uploaded_file($fileTmpName, $destination)) {
        $logoTempPath = '/uploads/Temp/' . $newFileName;
        return_json(true, 'LOGO上传成功', ['logo_url' => $logoTempPath, 'logo_name' => $newFileName, 'logo_temp_path' => $logoTempPath]);
    } else {
        return_json(false, '文件保存失败');
    }
}
if (!isset($GLOBALS['conn']) || $GLOBALS['conn']->connect_error) {
    return_json(false, '数据库连接失败');
}
$conn = $GLOBALS['conn'];
qk_ensure_posts_extra_columns();
if (isset($_POST['check_comment_check_status'])) {
    try {
        $commentCheckValue = 0;
        $result = execute_query($conn, "SELECT comment_check FROM settings WHERE id = 1");
        if ($result && $row = $result->fetch_assoc()) {
            $commentCheckValue = isset($row['comment_check']) ? $row['comment_check'] : 0;
        }
        return_json(true, '查询成功', array(
            'comment_check' => $commentCheckValue
        ));
    } catch (Exception $e) {
        return_json(false, '查询设置状态时发生系统错误');
    }
}
if (isset($_POST['save_comment_check'])) {
    $comment_check = isset($_POST['comment_check']) ? intval($_POST['comment_check']) : 0;
    try {
        $result = execute_query($conn, "SELECT COUNT(*) AS count FROM settings");
        $row = $result->fetch_assoc();
        $count = $row['count'];

        if ($count > 0) {
            $sql = "UPDATE settings SET comment_check = ? WHERE id = 1";
            $result = execute_non_query($conn, $sql, array($comment_check));
            if ($result !== false) {
                return_json(true, '评论审核设置保存成功');
            } else {
                return_json(false, '设置更新失败');
            }
        } else {
            $sql = "INSERT INTO settings (site_title, comment_check) VALUES (?, ?)";
            $result = execute_non_query($conn, $sql, array('网站标题', $comment_check));
            if ($result !== false) {
                return_json(true, '评论审核设置保存成功');
            } else {
                return_json(false, '设置保存失败');
            }
        }
    } catch (Exception $e) {
        return_json(false, '保存设置时发生系统错误');
    }
}
if (isset($_POST['save_settings'])) {
    $site_title = isset($_POST['site_title']) ? trim($_POST['site_title']) : '';
    $site_name = isset($_POST['site_name']) ? trim($_POST['site_name']) : '';
    $logo = isset($_POST['logo']) ? trim($_POST['logo']) : '';
    $site_description = isset($_POST['site_description']) ? trim($_POST['site_description']) : '';
    $site_keywords = isset($_POST['site_keywords']) ? trim($_POST['site_keywords']) : '';
    $site_copyright = isset($_POST['site_copyright']) ? trim($_POST['site_copyright']) : '';
    $comment_check = isset($_POST['comment_check']) ? intval($_POST['comment_check']) : 0;
    $status = isset($_POST['status']) ? intval($_POST['status']) : 0;
    $close_reason = isset($_POST['close_reason']) ? trim($_POST['close_reason']) : '';
    $Prohw = isset($_POST['Prohw']) ? trim($_POST['Prohw']) : '';
    if (empty($site_title)) {
        return_json(false, '网站标题不能为空');
    }

    if ($logo !== '') {
        $logoPath = parse_url($logo, PHP_URL_PATH);
        if (!is_string($logoPath) || $logoPath === '') {
            $logoPath = $logo;
        }
        if (strpos($logoPath, '/uploads/Temp/') !== false) {
            $movedLogo = moveImageFromTemp($logo, false);
            $movedLogoPath = parse_url($movedLogo, PHP_URL_PATH);
            if (!is_string($movedLogoPath) || $movedLogoPath === '') {
                $movedLogoPath = $movedLogo;
            }
            if (strpos($movedLogoPath, '/uploads/Temp/') !== false) {
                return_json(false, 'LOGO移动到正式目录失败');
            }
            if (strpos($movedLogoPath, '/uploads/') === false) {
                return_json(false, 'LOGO移动路径无效');
            }
            $logo = $movedLogoPath;
        }
    }

    $conn->begin_transaction();
    try {
        $result = $conn->query("SELECT COUNT(*) AS count FROM settings");
        $row = $result->fetch_assoc();
        $count = $row['count'];
        $result->close();
        if ($count > 0) {
            $sql = "UPDATE settings SET site_title = ?, site_name = ?, logo = ?, site_keywords = ?, site_description = ?, site_copyright = ?, comment_check = ?, status = ?, close_reason = ?, Prohw = ? WHERE id = 1";
            if ($stmt = $conn->prepare($sql)) {
                $stmt->bind_param("ssssssiiss", $site_title, $site_name, $logo, $site_keywords, $site_description, $site_copyright, $comment_check, $status, $close_reason, $Prohw);
                if (!$stmt->execute()) {
                    $stmt->close();
                    $conn->rollback();
                    return_json(false, '设置更新失败');
                }
                $stmt->close();
            } else {
                $conn->rollback();
                return_json(false, '系统错误：准备更新语句失败');
            }
        } else {
            $sql = "INSERT INTO settings (site_title, site_name, logo, site_keywords, site_description, site_copyright, comment_check, status, close_reason, Prohw) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            if ($stmt = $conn->prepare($sql)) {
                $stmt->bind_param("ssssssiiss", $site_title, $site_name, $logo, $site_keywords, $site_description, $site_copyright, $comment_check, $status, $close_reason, $Prohw);
                if (!$stmt->execute()) {
                    $stmt->close();
                    $conn->rollback();
                    return_json(false, '设置保存失败');
                }
                $stmt->close();
            } else {
                $conn->rollback();
                return_json(false, '系统错误：准备插入语句失败');
            }
        }
        $conn->commit();
        return_json(true, '设置保存成功', array('settings_saved' => true));
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '保存设置时发生系统错误');
    }
}

if (isset($_POST['save_theme'])) {
    $primary_color = isset($_POST['primary_color']) ? trim($_POST['primary_color']) : '';
    $home_template = isset($_POST['home_template']) ? trim($_POST['home_template']) : '';

    if (empty($primary_color)) {
        return_json(false, '主题颜色不能为空');
    }

    $conn->begin_transaction();
    try {
        $result = $conn->query("SELECT COUNT(*) AS count FROM settings");
        $row = $result->fetch_assoc();
        $count = $row['count'];
        $result->close();
        if ($count > 0) {
            $sql = "UPDATE settings SET primary_color = ?, home_template = ? WHERE id = 1";
            if ($stmt = $conn->prepare($sql)) {
                $stmt->bind_param("ss", $primary_color, $home_template);
                if (!$stmt->execute()) {
                    $stmt->close();
                    $conn->rollback();
                    return_json(false, '主题设置更新失败');
                }
                $stmt->close();
            } else {
                $conn->rollback();
                return_json(false, '系统错误：准备更新语句失败');
            }
        } else {
            $sql = "INSERT INTO settings (primary_color, home_template) VALUES (?, ?)";
            if ($stmt = $conn->prepare($sql)) {
                $stmt->bind_param("ss", $primary_color, $home_template);
                if (!$stmt->execute()) {
                    $stmt->close();
                    $conn->rollback();
                    return_json(false, '主题设置保存失败');
                }
                $stmt->close();
            } else {
                $conn->rollback();
                return_json(false, '系统错误：准备插入语句失败');
            }
        }
        $conn->commit();
        return_json(true, '主题设置保存成功', array('theme_saved' => true));
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '保存主题设置时发生系统错误');
    }
}

if (isset($_POST['add_category'])) {
    if (function_exists('ensureCategorySortColumn')) ensureCategorySortColumn();
    if (function_exists('ensureCategorySeoTitleColumn')) ensureCategorySeoTitleColumn();
    $category_name = isset($_POST['category_name']) ? trim($_POST['category_name']) : '';
    $category_seo_title = isset($_POST['category_seo_title']) ? trim($_POST['category_seo_title']) : '';
    $category_description = isset($_POST['category_description']) ? trim($_POST['category_description']) : '';
    $category_keywords = isset($_POST['category_keywords']) ? trim($_POST['category_keywords']) : '';
    $archiveid = isset($_POST['archiveid']) ? intval($_POST['archiveid']) : 0;
    $virtual_top = isset($_POST['virtual_top']) ? intval($_POST['virtual_top']) : 0;
    $virtual_top = $virtual_top === 1 ? 1 : 0;
    $virtual_top_anchor = isset($_POST['virtual_top_anchor']) ? intval($_POST['virtual_top_anchor']) : 0;
    $sort = isset($_POST['sort']) ? intval($_POST['sort']) : 0;
    $display = isset($_POST['display']) ? intval($_POST['display']) : 1;
    $display = $display === 0 ? 0 : 1;
    $thumbnail = '';
    if (empty($category_name)) {
        return_json(false, '请输入分类名称');
    }
    if ($sort < 1) {
        return_json(false, '排序最小值为1');
    }
    $categories = getCategories();
    $name_exists = false;
    foreach ($categories as $category) {
        if ($category['name'] == $category_name) {
            $name_exists = true;
            break;
        }
    }
    if ($name_exists) {
        return_json(false, '该分类名称已存在');
    }
    if (isset($_POST['thumbnail_url']) && !empty($_POST['thumbnail_url'])) {
        $thumbnail = trim($_POST['thumbnail_url']);
    } else if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] === UPLOAD_ERR_OK) {
        $uploadDir = UPLOAD_DIR;
        $file = $_FILES['thumbnail'];
        $fileName = $file['name'];
        $fileTmpName = $file['tmp_name'];
        $fileSize = $file['size'];
        $fileError = $file['error'];
        $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        if (in_array($fileExt, $allowedExts)) {
            if ($fileSize <= 2 * 1024 * 1024) {
                $newFileName = uniqid('category_', true) . '.' . $fileExt;
                $destination = $uploadDir . $newFileName;
                if (move_uploaded_file($fileTmpName, $destination)) {
                    $thumbnail = qk_build_relative_upload_path($newFileName);
                }
            }
        }
    }

    // 将临时目录中的图片移动到正式目录
    $thumbnail = processTempThumbnail($thumbnail);

    $conn->begin_transaction();
    try {
        $newCategoryId = addCategory($category_name, $category_description, $thumbnail, $category_keywords, $archiveid, $sort, $display, $category_seo_title);
        if ($newCategoryId) {
            if ($virtual_top !== 0 || $virtual_top_anchor !== 0) {
                $rt = execute_non_query($conn, "UPDATE categories SET virtual_top = ?, virtual_top_anchor = ? WHERE id = ?", array($virtual_top, $virtual_top_anchor, intval($newCategoryId)));
                if ($rt === false) {
                    $rt2 = execute_non_query($conn, "UPDATE categories SET virtual_top_anchor = ? WHERE id = ?", array($virtual_top_anchor, intval($newCategoryId)));
                    if ($rt2 === false) {
                        execute_non_query($conn, "UPDATE categories SET virtual_top = ? WHERE id = ?", array($virtual_top, intval($newCategoryId)));
                    }
                }
            }
            $conn->commit();
            
            // 获取新添加的分类数据
            $newCategory = get_single_row($conn, 
                "SELECT c.*, g.color as archive_color FROM categories c 
                 LEFT JOIN catgroup g ON c.archiveid = g.id 
                 WHERE c.id = ?", 
                array($newCategoryId)
            );
            
            return_json(true, '分类已成功添加', ['category' => $newCategory]);
        } else {
            $conn->rollback();
            return_json(false, '分类添加失败');
        }
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '系统错误：' . $e->getMessage());
    }
}
if (isset($_POST['edit_category'])) {
    if (function_exists('ensureCategorySortColumn')) ensureCategorySortColumn();
    if (function_exists('ensureCategorySeoTitleColumn')) ensureCategorySeoTitleColumn();
    $category_id = intval($_POST['category_id']);
    $category_name = isset($_POST['category_name']) ? trim($_POST['category_name']) : '';
    $category_seo_title = isset($_POST['category_seo_title']) ? trim($_POST['category_seo_title']) : '';
    $category_description = isset($_POST['category_description']) ? trim($_POST['category_description']) : '';
    $category_keywords = isset($_POST['category_keywords']) ? trim($_POST['category_keywords']) : '';
    $archiveid = isset($_POST['archiveid']) ? intval($_POST['archiveid']) : 0;
    $virtual_top = isset($_POST['virtual_top']) ? intval($_POST['virtual_top']) : 0;
    $virtual_top = $virtual_top === 1 ? 1 : 0;
    $virtual_top_anchor = isset($_POST['virtual_top_anchor']) ? intval($_POST['virtual_top_anchor']) : 0;
    $sort = isset($_POST['sort']) ? intval($_POST['sort']) : 0;
    $display = isset($_POST['display']) ? intval($_POST['display']) : 1;
    $display = $display === 0 ? 0 : 1;
    $thumbnail = isset($_POST['thumbnail_url']) ? trim($_POST['thumbnail_url']) : '';
    $old_thumbnail = $thumbnail;
    if (empty($category_name)) {
        return_json(false, '请输入分类名称');
    }
    if ($sort < 1) {
        return_json(false, '排序最小值为1');
    }
    $categories = getCategories();
    $name_exists = false;
    foreach ($categories as $category) {
        if ($category['id'] != $category_id && $category['name'] == $category_name) {
            $name_exists = true;
            break;
        }
    }
    if ($name_exists) {
        return_json(false, '该分类名称已存在');
    }
    $hasNewThumbnail = false;
    if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] === UPLOAD_ERR_OK) {
        $uploadDir = '../uploads/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        $file = $_FILES['thumbnail'];
        $fileName = $file['name'];
        $fileTmpName = $file['tmp_name'];
        $fileSize = $file['size'];
        $fileError = $file['error'];
        $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        $allowedExts = ['jpg', 'jpeg', 'png', 'gif'];
        if (in_array($fileExt, $allowedExts)) {
            if ($fileSize <= 2 * 1024 * 1024) {
                $newFileName = uniqid('category_', true) . '.' . $fileExt;
                $destination = $uploadDir . $newFileName;
                if (move_uploaded_file($fileTmpName, $destination)) {
                    $thumbnail = qk_build_relative_upload_path($newFileName);
                    $hasNewThumbnail = true;
                }
            }
        }
    }

    // 将临时目录中的图片移动到正式目录
    $thumbnail = processTempThumbnail($thumbnail);

    $conn->begin_transaction();
    try {
        if ($thumbnail === '') {
            $thumbnail = defined('DEFAULT_THUMBNAIL_PATH') ? DEFAULT_THUMBNAIL_PATH : $thumbnail;
        }

        $base_rt = execute_non_query(
            $conn,
            "UPDATE categories SET name = ?, seo_title = ?, description = ?, thumbnail = ?, display = ?, keywords = ?, archiveid = ?, sort = ? WHERE id = ?",
            array($category_name, $category_seo_title, $category_description, $thumbnail, $display, $category_keywords, $archiveid, $sort, $category_id)
        );
        if ($base_rt === false) {
            $conn->rollback();
            return_json(false, '分类更新失败');
        }

        $virtual_changed = false;
        $rt = execute_non_query($conn, "UPDATE categories SET virtual_top = ?, virtual_top_anchor = ? WHERE id = ?", array($virtual_top, $virtual_top_anchor, $category_id));
        if ($rt !== false) {
            $virtual_changed = intval($rt['affected_rows'] ?? 0) > 0;
        } else {
            $rt2 = execute_non_query($conn, "UPDATE categories SET virtual_top_anchor = ? WHERE id = ?", array($virtual_top_anchor, $category_id));
            if ($rt2 !== false) {
                $virtual_changed = intval($rt2['affected_rows'] ?? 0) > 0;
            } else {
                $rt3 = execute_non_query($conn, "UPDATE categories SET virtual_top = ? WHERE id = ?", array($virtual_top, $category_id));
                if ($rt3 === false) {
                    $conn->rollback();
                    return_json(false, '分类更新失败');
                }
                $virtual_changed = intval($rt3['affected_rows'] ?? 0) > 0;
            }
        }

        if ((intval($base_rt['affected_rows'] ?? 0) > 0) || $virtual_changed) {
            if (function_exists('clear_cache')) {
                clear_cache();
            }
        }

            if ($hasNewThumbnail && !empty($old_thumbnail) && strpos($old_thumbnail, '/uploads/') !== false) {
                $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
                $host = $_SERVER['HTTP_HOST'];
                $oldThumbnailPath = str_replace($protocol . '://' . $host, '.', $old_thumbnail);
                if (file_exists($oldThumbnailPath)) {
                    unlink($oldThumbnailPath);
                }
            }
            $conn->commit();
            
            // 获取更新后的分类数据
            $updatedCategory = get_single_row($conn, 
                "SELECT c.*, g.color as archive_color FROM categories c 
                 LEFT JOIN catgroup g ON c.archiveid = g.id 
                 WHERE c.id = ?", 
                array($category_id)
            );

            qk_clear_page_cache();
            return_json(true, '分类已成功更新', ['category' => $updatedCategory]);
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '系统错误：' . $e->getMessage());
    }
}
if (isset($_POST['publish_article'])) {
    $title = isset($_POST['title']) ? trim($_POST['title']) : '';
    $content = isset($_POST['content']) ? trim($_POST['content']) : '';
    $status = isset($_POST['status']) ? (int)$_POST['status'] : 1;
    $categoryId = isset($_POST['category_id']) ? (int)$_POST['category_id'] : 1;
    $thumbnail = '';
    $keywords = isset($_POST['keywords']) ? trim($_POST['keywords']) : '';
    $description = isset($_POST['description']) ? trim($_POST['description']) : '';
    $property = isset($_POST['article_property']) ? (int)$_POST['article_property'] : 0;
    $viewCount = isset($_POST['views']) && $_POST['views'] !== '' ? (int)$_POST['views'] : 0;
    $points = isset($_POST['article_points']) && $_POST['article_points'] !== '' ? (int)$_POST['article_points'] : 0;
    $mp4url = isset($_POST['mp4url']) ? trim($_POST['mp4url']) : '';
    $template = isset($_POST['template']) ? trim($_POST['template']) : 'post.php';
    $customUrl = isset($_POST['custom_url']) ? trim($_POST['custom_url']) : '';
    $bindDomain = isset($_POST['bind_domain']) ? trim($_POST['bind_domain']) : '';
    $accessPassword = isset($_POST['access_password']) ? trim($_POST['access_password']) : '';
    $toolUrl = isset($_POST['tool_url']) ? trim($_POST['tool_url']) : '';
    $redirectUrl = isset($_POST['redirect_url']) ? trim($_POST['redirect_url']) : '';
    $customField1 = isset($_POST['custom_field_1']) ? trim($_POST['custom_field_1']) : '';
    $customField2 = isset($_POST['custom_field_2']) ? trim($_POST['custom_field_2']) : '';
    $customField3 = isset($_POST['custom_field_3']) ? trim($_POST['custom_field_3']) : '';
    $price = isset($_POST['price']) && $_POST['price'] !== '' ? (int)$_POST['price'] : 0;
    $statusSwitch = isset($_POST['status_switch']) ? (int)$_POST['status_switch'] : 0;
    $functionType = isset($_POST['function_type']) ? trim($_POST['function_type']) : 'tool';
    $topType = isset($_POST['top_type']) ? (int)$_POST['top_type'] : 0;
    $autoCropThumbnail = isset($_POST['auto_crop_thumbnail']) && (string)$_POST['auto_crop_thumbnail'] === '1';
    if ($topType < 0 || $topType > 2) $topType = 0;
    if (empty($title) || empty($content)) {
        return_json(false, '标题和内容不能为空');
    }
    // 验证属性ID是否合法
    $validProperties = getArticleProperties();
    if (!isset($validProperties[$property])) {
        return_json(false, '无效的文章属性');
    }
    // 验证属性ID是否合法
    $validProperties = getArticleProperties();
    if (!isset($validProperties[$property])) {
        return_json(false, '无效的文章属性');
    }
    if (checkArticleTitleExists($title)) {
        return_json(false, '标题已存在请更换');
    }
    if (!empty($customUrl) && checkArticleCustomUrlExists($customUrl)) {
        return_json(false, '自定义URL已存在请更换');
    }
    // 检查违禁词
    if (has_forbidden_words($title)) {
        return_json(false, '标题包含违禁词');
    }
    if (has_forbidden_words($content)) {
        return_json(false, '内容包含违禁词');
    }
    if (!empty($description) && has_forbidden_words($description)) {
        return_json(false, '描述包含违禁词');
    }
    if (!empty($keywords) && has_forbidden_words($keywords)) {
        return_json(false, '关键词包含违禁词');
    }
    // 处理 Base64 图片
    $processedContent = processBase64ImagesInContent($content);
    if ($processedContent) {
        $content = $processedContent;
    }

    if (isset($_POST['download_remote_images']) && (string)$_POST['download_remote_images'] === '1') {
        $dl = qk_download_remote_images_to_temp_by_ext($content);
        if (isset($dl['content']) && is_string($dl['content']) && $dl['content'] !== '') {
            $content = $dl['content'];
        }
    }

    // 提取第一张图片（此时图片在临时目录，无水印）
    $extractedThumbnail = '';
    if (!empty($content)) {
        $extractedThumbnail = extractFirstImageFromContent($content);
    }

    // 处理缩略图上传
    $thumbnail = '';
    if (isset($_POST['existing_thumbnail']) && !empty(trim($_POST['existing_thumbnail']))) {
        // 优先使用已上传的缩略图URL
        $thumbnail = trim($_POST['existing_thumbnail']);
        $thumbnail = qk_normalize_media_path($thumbnail);
    } else if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] === UPLOAD_ERR_OK) {
        // 只有当没有已上传的缩略图时，才处理新上传的文件
        $file = $_FILES['thumbnail'];
        $fileName = $file['name'];
        $fileTmpName = $file['tmp_name'];
        $fileSize = $file['size'];
        $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

        if (in_array($fileExt, $allowedExts) && $fileSize <= 2 * 1024 * 1024) {
            $newFileName = 'thumbnail_' . uniqid('', true) . '.' . $fileExt;
            $destination = TEMP_UPLOAD_DIR . $newFileName;

            if (move_uploaded_file($fileTmpName, $destination)) {
                if ($autoCropThumbnail) {
                    $thumbnailResized = resizeThumbnail($destination, true);
                    if ($thumbnailResized) {
                        $thumbnail = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
                    }
                } else {
                    $thumbnail = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
                }
            }
        }
    }

    // 1. 先移动临时图片到正式目录（此时还不打水印）
    $content = processTempImagesInContent($content, false);

    // 2. 如果缩略图为空，则从正文第一张图片生成或继承缩略图
    if (empty($thumbnail) && !empty($extractedThumbnail)) {
        $template = isset($_POST['template']) ? trim($_POST['template']) : 'post.php';
        $thumbnail = resolveThumbnailFromContentImage($extractedThumbnail, $template, $autoCropThumbnail);
    }

    // 3. 给正式目录的图片添加水印
    addWatermarkToContentImages($content);

    // 处理临时缩略图
    $thumbnail = processTempThumbnail($thumbnail);

    $conn->begin_transaction();
    try {
        $userId = $_SESSION['user_id'];
        $article_id = publishArticle($title, $content, $userId, $status, $categoryId, $thumbnail, $keywords, $description, $property, $viewCount, $points, $mp4url, $template, $customUrl, $toolUrl, $redirectUrl, $price, $statusSwitch, $functionType, $customField1, $customField2, $customField3, $bindDomain, $topType, $accessPassword);
        if ($article_id) {
            $conn->commit();

            return_json(true, '文章发布成功', array('article_id' => $article_id));
        } else {
            $conn->rollback();
            return_json(false, '文章发布失败');
        }
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '系统错误：' . $e->getMessage());
    }
}
if (isset($_POST['edit_article'])) {
    $article_id = (int)$_POST['article_id'];
    $title = isset($_POST['title']) ? trim($_POST['title']) : '';
    $content = isset($_POST['content']) ? trim($_POST['content']) : '';
    $status = isset($_POST['status']) ? (int)$_POST['status'] : 1;
    $categoryId = isset($_POST['category_id']) ? (int)$_POST['category_id'] : 1;
    $thumbnail = isset($_POST['existing_thumbnail']) ? trim($_POST['existing_thumbnail']) : '';
    $hasNewThumbnail = false;

    // 获取文章原本的缩略图
    global $conn;
    $old_thumbnail = '';
    if ($article_id > 0) {
        $sql = "SELECT thumbnail FROM posts WHERE id = ?";
        $stmt = $conn->prepare($sql);
        if ($stmt) {
            $stmt->bind_param('i', $article_id);
            $stmt->execute();
            $result = $stmt->get_result();
            if ($result && $row = $result->fetch_assoc()) {
                $old_thumbnail = $row['thumbnail'];
            }
            $stmt->close();
        }
    }
    $keywords = isset($_POST['keywords']) ? trim($_POST['keywords']) : '';
    $description = isset($_POST['description']) ? trim($_POST['description']) : '';
    $property = isset($_POST['article_property']) ? (int)$_POST['article_property'] : 0;
    $viewCount = isset($_POST['views']) && $_POST['views'] !== '' ? (int)$_POST['views'] : 0;
    $points = isset($_POST['article_points']) && $_POST['article_points'] !== '' ? (int)$_POST['article_points'] : 0;
    $mp4url = isset($_POST['mp4url']) ? trim($_POST['mp4url']) : '';
    $template = isset($_POST['template']) ? trim($_POST['template']) : 'post.php';
    $customUrl = isset($_POST['custom_url']) ? trim($_POST['custom_url']) : '';
    $bindDomain = isset($_POST['bind_domain']) ? trim($_POST['bind_domain']) : '';
    $accessPassword = isset($_POST['access_password']) ? trim($_POST['access_password']) : '';
    $toolUrl = isset($_POST['tool_url']) ? trim($_POST['tool_url']) : '';
    $redirectUrl = isset($_POST['redirect_url']) ? trim($_POST['redirect_url']) : '';
    $customField1 = isset($_POST['custom_field_1']) ? trim($_POST['custom_field_1']) : '';
    $customField2 = isset($_POST['custom_field_2']) ? trim($_POST['custom_field_2']) : '';
    $customField3 = isset($_POST['custom_field_3']) ? trim($_POST['custom_field_3']) : '';
    $price = isset($_POST['price']) && $_POST['price'] !== '' ? (int)$_POST['price'] : 0;
    $statusSwitch = isset($_POST['status_switch']) ? (int)$_POST['status_switch'] : 0;
    $functionType = isset($_POST['function_type']) ? trim($_POST['function_type']) : 'tool';
    $topType = isset($_POST['top_type']) ? (int)$_POST['top_type'] : 0;
    $autoCropThumbnail = isset($_POST['auto_crop_thumbnail']) && (string)$_POST['auto_crop_thumbnail'] === '1';
    if ($topType < 0 || $topType > 2) $topType = 0;
    if (empty($title) || empty($content)) {
        return_json(false, '标题和内容不能为空');
    }
    if (checkArticleTitleExists($title, $article_id)) {
        return_json(false, '标题已存在请更换');
    }
    if (!empty($customUrl) && checkArticleCustomUrlExists($customUrl, $article_id)) {
        return_json(false, '自定义URL已存在请更换');
    }
    // 检查违禁词
    if (has_forbidden_words($title)) {
        return_json(false, '标题包含违禁词');
    }
    if (has_forbidden_words($content)) {
        return_json(false, '内容包含违禁词');
    }
    if (!empty($description) && has_forbidden_words($description)) {
        return_json(false, '描述包含违禁词');
    }
    if (!empty($keywords) && has_forbidden_words($keywords)) {
        return_json(false, '关键词包含违禁词');
    }
    // 处理 Base64 图片
    $processedContent = processBase64ImagesInContent($content);
    if ($processedContent) {
        $content = $processedContent;
    }

    if (isset($_POST['download_remote_images']) && (string)$_POST['download_remote_images'] === '1') {
        $dl = qk_download_remote_images_to_temp_by_ext($content);
        if (isset($dl['content']) && is_string($dl['content']) && $dl['content'] !== '') {
            $content = $dl['content'];
        }
    }

    // 提取第一张图片（此时图片在临时目录，无水印）
    $extractedThumbnail = '';
    if (!empty($content)) {
        $extractedThumbnail = extractFirstImageFromContent($content);
    }

    // 处理缩略图上传
    $thumbnail = isset($_POST['existing_thumbnail']) ? trim($_POST['existing_thumbnail']) : '';
    $hasNewThumbnail = false;

    $clearThumbnail = isset($_POST['clear_thumbnail']) && $_POST['clear_thumbnail'] === '1';

    // 如果用户明确删除了缩略图，清空缩略图值
    if ($clearThumbnail) {
        $thumbnail = '';
        $hasNewThumbnail = trim((string)$old_thumbnail) !== '';
    }

    if (!$clearThumbnail && isset($_POST['existing_thumbnail']) && !empty(trim($_POST['existing_thumbnail']))) {
        // 优先使用已上传的缩略图URL
        $thumbnail = trim($_POST['existing_thumbnail']);
        $thumbnail = qk_normalize_media_path($thumbnail);
        $hasNewThumbnail = ($thumbnail !== $old_thumbnail);
    } else if (!$clearThumbnail && isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] === UPLOAD_ERR_OK) {
        // 只有当没有已上传的缩略图时，才处理新上传的文件
        $file = $_FILES['thumbnail'];
        $fileName = $file['name'];
        $fileTmpName = $file['tmp_name'];
        $fileSize = $file['size'];
        $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

        if (in_array($fileExt, $allowedExts) && $fileSize <= 2 * 1024 * 1024) {
            $newFileName = 'thumbnail_' . uniqid('', true) . '.' . $fileExt;
            $destination = TEMP_UPLOAD_DIR . $newFileName;

            if (move_uploaded_file($fileTmpName, $destination)) {
                if ($autoCropThumbnail) {
                    $thumbnailResized = resizeThumbnail($destination, true);
                    if ($thumbnailResized) {
                        $thumbnail = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
                        $hasNewThumbnail = true;
                    }
                } else {
                    $thumbnail = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
                    $hasNewThumbnail = true;
                }
            }
        }
    }

    // 1. 先移动临时图片到正式目录（此时还不打水印）
    $content = processTempImagesInContent($content, false);

    // 2. 如果缩略图为空，则从正文第一张图片生成或继承缩略图
    if (!$clearThumbnail && empty($thumbnail) && !empty($extractedThumbnail)) {
        $template = isset($_POST['template']) ? trim($_POST['template']) : 'post.php';
        $thumbnail = resolveThumbnailFromContentImage($extractedThumbnail, $template, $autoCropThumbnail);
        $hasNewThumbnail = true;
    }

    // 3. 给正式目录的图片添加水印
    addWatermarkToContentImages($content);

    // 处理临时缩略图
    if (!$clearThumbnail) {
        $thumbnail = processTempThumbnail($thumbnail);
    } else {
        $thumbnail = '';
    }

    $conn->begin_transaction();
    try {
        if (updateArticle($article_id, $title, $content, $status, $categoryId, $thumbnail, $keywords, $description, $property, $viewCount, $points, $mp4url, $template, $customUrl, $toolUrl, $redirectUrl, $price, $statusSwitch, $functionType, $customField1, $customField2, $customField3, $bindDomain, $topType, $accessPassword)) {
            if (($clearThumbnail || $hasNewThumbnail) && !empty($old_thumbnail) && strpos($old_thumbnail, '/uploads/') !== false && trim((string)$old_thumbnail) !== trim((string)$thumbnail)) {
                deleteUploadFile($old_thumbnail);
            }
            $conn->commit();

            return_json(true, '文章更新成功', array('article_id' => $article_id));
        } else {
            $conn->rollback();
            return_json(false, '文章更新失败');
        }
    } catch (Exception $e) {
        $conn->rollback();
        return_json(false, '系统错误：' . $e->getMessage());
    }
}
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'get_categories') {
    $conn = $GLOBALS['conn'];
    try {
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
        $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
        $search = isset($_GET['search']) ? trim($_GET['search']) : '';
        $archiveid = isset($_GET['archiveid']) ? intval($_GET['archiveid']) : 0;

        if ($page < 1) $page = 1;
        if ($page_size < 1) $page_size = 30;
        if ($page_size > 1000) $page_size = 1000;

        // 确定 catgroup 表名
        $catgroup_table = 'catgroup';
        $check_qk = $conn->query("SHOW TABLES LIKE 'qkcms_catgroup'");
        if ($check_qk && $check_qk->num_rows > 0) {
            $catgroup_table = 'qkcms_catgroup';
        }
        if ($check_qk) $check_qk->close();

        $all_categories = getCategories('');
        if (!is_array($all_categories)) $all_categories = array();

        if ($archiveid > 0) {
            $all_categories = array_values(array_filter($all_categories, function ($cat) use ($archiveid) {
                return intval($cat['archiveid'] ?? 0) === $archiveid;
            }));
        } else {
            $all_categories = array_values($all_categories);
        }

        $matched_group_ids = array();
        $visible_group_ids = array();
        if ($search !== '') {
            $like = '%' . $conn->real_escape_string($search) . '%';
            $group_result = $conn->query("SELECT id FROM `{$catgroup_table}` WHERE name LIKE '{$like}'");
            if ($group_result) {
                while ($gr = $group_result->fetch_assoc()) {
                    $gid = intval($gr['id']);
                    if ($archiveid > 0 && $gid !== $archiveid) continue;
                    $matched_group_ids[] = $gid;
                }
                $group_result->close();

                $all_categories = array_values(array_filter($all_categories, function ($cat) use ($search, $matched_group_ids, &$visible_group_ids) {
                    $aid = intval($cat['archiveid'] ?? 0);
                    $name = (string)($cat['name'] ?? '');
                    $category_matched = function_exists('mb_stripos')
                        ? mb_stripos($name, $search, 0, 'UTF-8') !== false
                        : stripos($name, $search) !== false;
                    $group_matched = $aid > 0 && in_array($aid, $matched_group_ids, true);

                    if ($category_matched && $aid > 0 && !in_array($aid, $visible_group_ids, true)) {
                        $visible_group_ids[] = $aid;
                    }
                    if ($group_matched && !in_array($aid, $visible_group_ids, true)) {
                        $visible_group_ids[] = $aid;
                    }

                    return $category_matched || $group_matched;
                }));

                foreach ($matched_group_ids as $gid) {
                    if (!in_array($gid, $visible_group_ids, true)) {
                        $visible_group_ids[] = $gid;
                    }
                }
            }
        }

        $archive_category_counts = array(0 => 0);
        $archive_post_counts = array(0 => 0);
        $categories_by_group = array(0 => array());
        foreach ($all_categories as $cat) {
            $aid = isset($cat['archiveid']) ? intval($cat['archiveid']) : 0;
            if (!isset($archive_category_counts[$aid])) $archive_category_counts[$aid] = 0;
            if (!isset($archive_post_counts[$aid])) $archive_post_counts[$aid] = 0;
            if (!isset($categories_by_group[$aid])) $categories_by_group[$aid] = array();
            $archive_category_counts[$aid]++;
            $archive_post_counts[$aid] += intval($cat['post_count'] ?? 0);
            $archive_post_counts[0] += intval($cat['post_count'] ?? 0);
            $categories_by_group[$aid][] = $cat;
        }

        // 顶级栏目：搜索时显示命中的顶级栏目，以及命中子栏目的父级栏目
        $groups_sql = "SELECT * FROM `{$catgroup_table}`";
        if ($search !== '') {
            if (!empty($visible_group_ids)) {
                $ids_str = implode(',', array_map('intval', $visible_group_ids));
                $groups_sql .= " WHERE id IN ({$ids_str})";
            } else {
                $groups_sql .= " WHERE 1=0";
            }
        } else if ($archiveid > 0) {
            $groups_sql .= " WHERE id = " . intval($archiveid);
        }
        $groups_sql .= " ORDER BY sort ASC, id ASC";
        $groups = array();
        $result = $conn->query($groups_sql);
        if ($result) {
            while ($row = $result->fetch_assoc()) {
                $gid = intval($row['id']);
                $row['category_count'] = isset($archive_category_counts[$gid]) ? intval($archive_category_counts[$gid]) : 0;
                $row['post_count_total'] = isset($archive_post_counts[$gid]) ? intval($archive_post_counts[$gid]) : 0;
                if (empty($row['color']) || !preg_match('/^#[0-9a-fA-F]{6}$/', trim((string)$row['color']))) {
                    $row['color'] = '#64748b';
                }
                $groups[] = $row;
            }
            $result->close();
        }

        // 获取分类模板列表
        $template_files = array('list.html' => 'list.html（默认）');
        $dirs = array('../templates/skin', '../templates');
        foreach ($dirs as $dir) {
            if (!is_dir($dir)) continue;
            foreach (scandir($dir) as $file) {
                if (strpos($file, 'list') !== 0) continue;
                $ext = pathinfo($file, PATHINFO_EXTENSION);
                if ($ext !== 'html' && $ext !== 'php') continue;
                $path = (strpos($dir, 'skin') !== false ? 'skin/' : '') . $file;
                if (!isset($template_files[$path])) $template_files[$path] = $file;
            }
        }

        // 获取顶级栏目模板列表
        $catgroup_templates = array('catgroup.html' => 'catgroup.html（默认）');
        foreach ($dirs as $dir) {
            if (!is_dir($dir)) continue;
            foreach (scandir($dir) as $file) {
                $ext = pathinfo($file, PATHINFO_EXTENSION);
                if (($ext !== 'html' && $ext !== 'php') || strpos($file, 'catgroup') !== 0) continue;
                $path = (strpos($dir, 'skin') !== false ? 'skin/' : '') . $file;
                if (!isset($catgroup_templates[$path])) $catgroup_templates[$path] = $file;
            }
        }

        $ordered_page_group_ids = array();
        if (!empty($categories_by_group[0])) {
            $ordered_page_group_ids[] = 0;
        }
        foreach ($groups as $group) {
            $gid = intval($group['id']);
            if (!isset($categories_by_group[$gid])) $categories_by_group[$gid] = array();
            $ordered_page_group_ids[] = $gid;
        }

        $group_pages = array();
        $current_group_page = array();
        $current_group_units = 0;
        foreach ($ordered_page_group_ids as $gid) {
            $group_units = 1;
            if (!empty($current_group_page) && ($current_group_units + $group_units) > $page_size) {
                $group_pages[] = $current_group_page;
                $current_group_page = array();
                $current_group_units = 0;
            }
            $current_group_page[] = $gid;
            $current_group_units += $group_units;
        }
        if (!empty($current_group_page)) {
            $group_pages[] = $current_group_page;
        }
        if (empty($group_pages)) {
            $group_pages[] = array();
        }

        $total = count($ordered_page_group_ids);
        $total_pages = count($group_pages);
        if ($page > $total_pages) $page = $total_pages;
        $page_group_ids = $group_pages[$page - 1] ?? array();
        $page_group_lookup = array();
        foreach ($page_group_ids as $gid) {
            $page_group_lookup[intval($gid)] = true;
        }

        $page_categories = array_values(array_filter($all_categories, function ($cat) use ($page_group_lookup) {
            $aid = isset($cat['archiveid']) ? intval($cat['archiveid']) : 0;
            return isset($page_group_lookup[$aid]);
        }));
        $groups = array_values(array_filter($groups, function ($group) use ($page_group_lookup) {
            return isset($page_group_lookup[intval($group['id'] ?? 0)]);
        }));

        return_json(true, '获取分类列表成功', array(
            'categories' => $page_categories,
            'catgroups' => $groups,
            'templates' => $template_files,
            'catgroup_templates' => $catgroup_templates,
            'total' => $total,
            'total_pages' => $total_pages,
            'current_page' => $page,
            'page_size' => $page_size
        ));
    } catch (Exception $e) {
        return_json(false, '获取分类列表时发生系统错误');
    }
}
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'get_categories_simple') {
    $conn = $GLOBALS['conn'];
    try {
        $sql = "SELECT c.*, COUNT(p.id) as post_count FROM categories c LEFT JOIN posts p ON c.id = p.category_id GROUP BY c.id ORDER BY c.id DESC";
        $result = $conn->query($sql);
        if ($result === false) {
            return_json(false, '获取分类列表失败');
        }
        // 优先查找自定义模板目录 templates/skin/
        $skin_dir = $_SERVER['DOCUMENT_ROOT'] . '/templates/skin';
        $template_files = array();
        if (is_dir($skin_dir)) {
            $files = scandir($skin_dir);
            foreach ($files as $file) {
                // 只显示list开头的文件作为列表模板
                if (strpos($file, 'list') === 0 && (pathinfo($file, PATHINFO_EXTENSION) === 'html' || pathinfo($file, PATHINFO_EXTENSION) === 'php')) {
                    $templatePath = 'skin/' . $file;
                    $templateName = $file;

                    // 尝试读取模板文件中的中文名称标记
                    $filePath = $skin_dir . '/' . $file;
                    if (file_exists($filePath)) {
                        $content = file_get_contents($filePath);
                        // 新规则：获取第一行注释中"——"符号后面的文字
                        if (preg_match('/^\/\/.*?——(.*)$/m', $content, $matches)) {
                            $templateName = $file . '（' . trim($matches[1]) . '）';
                        }
                    }

                    $template_files[$templatePath] = $templateName;
                }
            }
        }
        // 确保list.html在第一个，并标记为默认
        $default_template = 'list.html（默认）';
        // 移除可能存在的list.html条目
        unset($template_files['list.html']);
        // 创建新数组，将list.html（默认）放在第一个位置
        $new_template_files = array('list.html' => $default_template);
        // 合并其他模板文件
        $template_files = $new_template_files + $template_files;
        $html = '<table class="admin-table category-manage">
                  <thead>
                    <tr>
                      <th>ID</th>
                      <th>缩略图</th>
                      <th>分类名称</th>
                      <th>列表模板</th>
                      <th>URL（双击编辑）</th>
                      <th>文章数</th>
                      <th style="text-align: center;">开关</th>
                      <th>操作</th>
                    </tr>
                  </thead>
                  <tbody>';
        while ($category = $result->fetch_assoc()) {
            $html .= '<tr>
                      <td>' . $category['id'] . '</td>
                      <td>';
            // 处理分类缩略图，检查本地文件是否存在
            $thumbnail_url = $category['thumbnail'];
            if (!empty($thumbnail_url)) {
                // 获取相对路径
                $relative_path = $thumbnail_url;
                if (strpos($thumbnail_url, '://') !== false) {
                    $path_parts = parse_url($thumbnail_url);
                    $relative_path = isset($path_parts['path']) ? $path_parts['path'] : '';
                }

                // 构建本地路径并获取上传时间
                $local_path = $_SERVER['DOCUMENT_ROOT'] . $relative_path;
                $upload_time = '';
                if (file_exists($local_path)) {
                    $ts = @filemtime($local_path);
                    if ($ts) {
                        $upload_time = date('Y-m-d H:i:s', $ts);
                    }
                }
                $title_attr = $upload_time !== '' ? ' title="上传时间：' . escape($upload_time) . '"' : '';
                $data_time_attr = $upload_time !== '' ? ' data-upload-time="' . escape($upload_time) . '"' : '';
                $html .= '<img src="' . escape($thumbnail_url) . '" alt="' . escape($category['name']) . '" style="width: 60px; height: 45px; object-fit: cover; border-radius: 4px; cursor: pointer;" onclick="replaceCategoryThumbnail(' . $category['id'] . ', this);"' . $title_attr . $data_time_attr . '>';
            } else {
                $html .= '<span class="text-muted" style="cursor: pointer;" onclick="replaceCategoryThumbnail(' . $category['id'] . ', this);">点击上传</span>';
            }
            $html .= '</td>
                      <td><a href="/admin?tab=articles&category_id=' . $category['id'] . '" class="category-name-link" title="查看该分类下的文章">' . escape($category['name']) . '</a></td>
                      <td>
                        <select class="form-control" onchange="updateCategoryTemplate(' . $category['id'] . ', this.value)">
                        ';
            foreach ($template_files as $templatePath => $templateName) {
                $selected = isset($category['template']) && $category['template'] == $templatePath ? 'selected' : '';
                $html .= '<option value="' . $templatePath . '" ' . $selected . '>' . $templateName . '</option>';
            }
            $html .= '</select>
                      </td>
                      <td class="category-custom-url-cell" data-category-id="' . $category['id'] . '">
                        <span class="custom-url-display" data-original-url="' . escape($category['custom_url']) . '" data-default-url="list_id' . $category['id'] . '.html">' . (empty($category['custom_url']) ? 'list_id' . $category['id'] . '.html' : escape($category['custom_url'])) . '</span>
                        <input type="text" class="custom-url-input form-control" value="' . (empty($category['custom_url']) ? 'list_id' . $category['id'] . '.html' : escape($category['custom_url'])) . '" style="display: none; width: 200px; margin: 0;" onblur="saveCategoryCustomUrl(' . $category['id'] . ', this)" onkeypress="if(event.key === \'Enter\') saveCategoryCustomUrl(' . $category['id'] . ', this); if(event.key === \'Escape\') cancelEditCategoryCustomUrl(' . $category['id'] . ');" ondblclick="editCategoryCustomUrl(' . $category['id'] . ')">
                      </td>
                      <td>' . $category['post_count'] . '</td>
                      <td style="text-align: center; vertical-align: middle; height: 100%;">
                        <form method="post" class="inline-form" style="display: flex; align-items: center; justify-content: center; margin: 0; height: 100%;">
                          <input type="hidden" name="update_display" value="1">
                          <input type="hidden" name="category_id" value="' . $category['id'] . '">
                          <label class="theme-switch" style="margin: 0; display: flex; align-items: center;">
                            <input type="checkbox" name="display" value="1" ' . (isset($category['display']) && $category['display'] == 1 ? 'checked' : '') . ' onchange="submitCategoryDisplayForm(this)">
                            <span class="slider round"></span> </label>
                        </form>
                      </td>
                      <td><button type="button" onclick="previewCategory(' . $category['id'] . ')" class="btn btn-sm btn-secondary">预览</button> <button type="button" onclick="openEditCategoryModal(' . $category['id'] . ');" class="btn btn-sm btn-primary">编辑</button> <button type="button" onclick="deleteCategoryConfirm(' . $category['id'] . ');" class="btn btn-sm btn-danger">删除</button></td>
                    </tr>';
        }
        $html .= '</tbody>
                </table>';
        $result->close();
        return_json(true, '获取分类列表成功', array('html' => $html));
    } catch (Exception $e) {
        return_json(false, '获取分类列表时发生系统错误');
    }
}
if (isset($_POST['action']) && $_POST['action'] === 'get_category') {
    if (function_exists('ensureCategorySortColumn')) ensureCategorySortColumn();
    if (function_exists('ensureCategorySeoTitleColumn')) ensureCategorySeoTitleColumn();
    $conn = $GLOBALS['conn'];
    $category_id = isset($_POST['id']) ? intval($_POST['id']) : 0;
    if ($category_id <= 0) {
        return_json(false, '无效的分类ID');
    }
    try {
        $sql = "SELECT * FROM categories WHERE id = ?";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("i", $category_id);
            if ($stmt->execute()) {
                $result = $stmt->get_result();
                if ($category = $result->fetch_assoc()) {
                    return_json(true, '获取分类数据成功', $category);
                } else {
                    return_json(false, '未找到该分类');
                }
                $stmt->close();
            } else {
                return_json(false, '获取分类数据失败');
            }
        } else {
            return_json(false, '系统错误：准备查询语句失败');
        }
    } catch (Exception $e) {
        return_json(false, '获取分类数据时发生系统错误');
    }
}

// 获取文章列表接口 - 优化版本
if (isset($_GET['action']) && $_GET['action'] === 'get_articles') {
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 15;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';
    $category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
    $property_id = isset($_GET['property_id']) ? intval($_GET['property_id']) : 0;
    $template = isset($_GET['template']) ? trim($_GET['template']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 15;
    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }

    try {
        // 构建WHERE条件
        $where_conditions = [];
        $params = [];
        $types = '';

        if (!empty($search)) {
            $where_conditions[] = 'p.title LIKE ?';
            $params[] = '%' . $search . '%';
            $types .= 's';
        }

        if ($category_id > 0) {
            $where_conditions[] = 'p.category_id = ?';
            $params[] = $category_id;
            $types .= 'i';
        }

        if ($property_id > 0) {
            $where_conditions[] = 'p.property = ?';
            $params[] = $property_id;
            $types .= 'i';
        }

        if ($template !== '') {
            $where_conditions[] = 'p.template = ?';
            $params[] = $template;
            $types .= 's';
        }

        $where_clause = !empty($where_conditions) ? 'WHERE ' . implode(' AND ', $where_conditions) : '';

        $sql = "SELECT p.id, p.title, p.thumbnail, p.created_at, p.updated_at, 
               p.category_id, p.user_id, p.property, p.template, p.views, p.points, p.mp4url, p.keywords, p.description, p.status, p.custom_url,
               c.name as category_name
               FROM posts p 
               LEFT JOIN categories c ON p.category_id = c.id 
               {$where_clause}
               ORDER BY p.id DESC 
               LIMIT ?, ?";

        $params[] = $offset;
        $params[] = $page_size;
        $types .= 'ii';

        $stmt = $conn->prepare($sql);
        if (!$stmt) {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }

        if (!empty($params)) {
            $stmt->bind_param($types, ...$params);
        }

        // 计算总文章数
        $count_sql = 'SELECT COUNT(*) as count FROM posts p ' . $where_clause;
        $count_stmt = $conn->prepare($count_sql);
        $total_count = 0;

        if ($count_stmt) {
            // 构建计数查询的参数绑定
            $count_params = [];
            $count_types = '';

            if (!empty($search)) {
                $count_params[] = '%' . $search . '%';
                $count_types .= 's';
            }
            if ($category_id > 0) {
                $count_params[] = $category_id;
                $count_types .= 'i';
            }
            if ($property_id > 0) {
                $count_params[] = $property_id;
                $count_types .= 'i';
            }
            if ($template !== '') {
                $count_params[] = $template;
                $count_types .= 's';
            }

            if (!empty($count_params)) {
                $count_stmt->bind_param($count_types, ...$count_params);
            }
            $count_stmt->execute();
            $count_result = $count_stmt->get_result();
            if ($count_row = $count_result->fetch_assoc()) {
                $total_count = $count_row['count'];
            }
            $count_stmt->close();
        }

        $total_pages = ceil($total_count / $page_size);

        // 执行主查询
        $stmt->execute();
        $result = $stmt->get_result();
        $articles = [];
        $article_ids = [];
        while ($row = $result->fetch_assoc()) {
            $row['comment_count'] = 0;
            $articles[] = $row;
            if (isset($row['id'])) $article_ids[] = intval($row['id']);
        }
        $stmt->close();

        if (!empty($article_ids)) {
            $comment_count_map = [];
            $placeholders = implode(',', array_fill(0, count($article_ids), '?'));
            $count_comments_sql = "SELECT post_id, COUNT(*) as cnt FROM comments WHERE post_id IN ($placeholders) GROUP BY post_id";
            $count_comments_stmt = $conn->prepare($count_comments_sql);
            if ($count_comments_stmt) {
                $comment_types = str_repeat('i', count($article_ids));
                $count_comments_stmt->bind_param($comment_types, ...$article_ids);
                if ($count_comments_stmt->execute()) {
                    $count_comments_result = $count_comments_stmt->get_result();
                    while ($cc_row = $count_comments_result->fetch_assoc()) {
                        $comment_count_map[intval($cc_row['post_id'])] = intval($cc_row['cnt']);
                    }
                }
                $count_comments_stmt->close();
            }

            foreach ($articles as &$article) {
                $aid = intval($article['id'] ?? 0);
                $article['comment_count'] = $comment_count_map[$aid] ?? 0;
            }
            unset($article);
        }

        // 使用静态缓存减少重复查询
        static $categories_cache = null;
        static $properties_cache = null;

        if ($categories_cache === null) {
            $categories_cache = [];
            $category_sql = 'SELECT id, name FROM categories ORDER BY id ASC';
            if ($category_result = $conn->query($category_sql)) {
                while ($category_row = $category_result->fetch_assoc()) {
                    $categories_cache[] = $category_row;
                }
                $category_result->close();
            }
        }

        if ($properties_cache === null) {
            $properties_cache = [];
            $property_sql = 'SELECT id, name FROM properties WHERE is_enabled = 1 ORDER BY sort_order ASC, id ASC';
            if ($property_result = $conn->query($property_sql)) {
                while ($property_row = $property_result->fetch_assoc()) {
                    $properties_cache[] = $property_row;
                }
                $property_result->close();
            }
        }

        return_json(true, '获取文章列表成功', [
            'articles' => $articles,
            'categories' => $categories_cache,
            'properties' => $properties_cache,
            'current_page' => $page,
            'page_size' => $page_size,
            'total_count' => $total_count,
            'total_pages' => $total_pages
        ]);
    } catch (Exception $e) {
        return_json(false, '获取文章列表时发生系统错误：' . $e->getMessage());
    }
}

// 获取评论列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_comments') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $status = isset($_GET['status']) ? $_GET['status'] : 'all';
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询评论列表，支持状态过滤和搜索
        $sql = "SELECT c.id, c.content, c.post_id as article_id, p.title as article_title, u.username, c.created_at, c.status FROM comments c LEFT JOIN users u ON c.user_id = u.id LEFT JOIN posts p ON c.post_id = p.id ";
        $where_conditions = array();
        $params = array();

        if ($status != 'all') {
            $status_value = is_numeric($status) ? intval($status) : ($status == 'approved' ? 1 : 0);
            $where_conditions[] = "c.status = ?";
            $params[] = $status_value;
        }

        if (!empty($search)) {
            $where_conditions[] = "(c.content LIKE ? OR u.username LIKE ? OR p.title LIKE ?)";
            $searchPattern = '%' . $search . '%';
            $params[] = $searchPattern;
            $params[] = $searchPattern;
            $params[] = $searchPattern;
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY c.id DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $comments = array();
                while ($row = $result->fetch_assoc()) {
                    // 保存完整的HTML内容用于编辑，同时也保存纯文本用于显示
                    $row['full_content'] = $row['content'];
                    $comments[] = $row;
                }
                $stmt->close();

                // 计算总评论数和总页数
                $count_sql = "SELECT COUNT(*) as total FROM comments c LEFT JOIN users u ON c.user_id = u.id LEFT JOIN posts p ON c.post_id = p.id ";
                if (!empty($where_conditions)) $count_sql .= " WHERE " . implode(" AND ", $where_conditions);

                $count_stmt = $conn->prepare($count_sql);
                if ($count_stmt) {
                    // 绑定参数（排除LIMIT和OFFSET参数）
                    $count_params = array_slice($params, 0, count($params) - 2);
                    if (count($count_params) > 0) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }

                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        $count_row = $count_result->fetch_assoc();
                        $total_count = $count_row['total'];
                        $total_pages = ceil($total_count / $page_size);
                        $count_stmt->close();
                    } else {
                        $total_count = 0;
                        $total_pages = 1;
                    }
                } else {
                    $total_count = 0;
                    $total_pages = 1;
                }

                return_json(true, '获取评论列表成功', array(
                    'comments' => $comments,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取评论列表时发生系统错误：' . $e->getMessage());
    }
}

// 获取单篇文章详情接口
if (isset($_GET['action']) && $_GET['action'] === 'get_article') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $article_id = isset($_GET['id']) ? intval($_GET['id']) : 0;
    if ($article_id <= 0) {
        return_json(false, '无效的文章ID');
    }
    try {
        $sql = "SELECT * FROM posts WHERE id = ?";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("i", $article_id);
            if ($stmt->execute()) {
                $result = $stmt->get_result();
                if ($article = $result->fetch_assoc()) {
                    return_json(true, '获取文章详情成功', $article);
                } else {
                    return_json(false, '未找到该文章');
                }
                $stmt->close();
            } else {
                return_json(false, '获取文章详情失败');
            }
        } else {
            return_json(false, '系统错误：准备查询语句失败');
        }
    } catch (Exception $e) {
        return_json(false, '获取文章详情时发生系统错误');
    }
}

// 获取举报列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_reports') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $status = isset($_GET['status']) ? $_GET['status'] : 'all';
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询举报列表，支持状态过滤和搜索
        $sql = "SELECT r.id, r.content_id as reported_id, r.content_type as reported_type, r.reason, r.user_id as reported_by, u.username as reporter_username, r.created_at, r.status FROM reports r LEFT JOIN users u ON r.user_id = u.id ";
        $where_conditions = array();
        $params = array();

        if ($status != 'all') {
            $status_value = is_numeric($status) ? intval($status) : ($status == 'processed' ? 1 : 0);
            $where_conditions[] = "r.status = ?";
            $params[] = $status_value;
        }

        if (!empty($search)) {
            $where_conditions[] = "(r.reason LIKE ? OR u.username LIKE ?)";
            $searchPattern = '%' . $search . '%';
            $params[] = $searchPattern;
            $params[] = $searchPattern;
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY r.created_at DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $reports = array();
                $post_ids = array();
                $comment_ids = array();
                $user_ids = array();

                // 先收集所有ID，批量查询
                while ($row = $result->fetch_assoc()) {
                    if ($row['reported_type'] == 'post') {
                        $post_ids[] = $row['reported_id'];
                    } elseif ($row['reported_type'] == 'comment') {
                        $comment_ids[] = $row['reported_id'];
                    } elseif ($row['reported_type'] == 'user') {
                        $user_ids[] = $row['reported_id'];
                    }
                    $reports[] = $row;
                }
                $stmt->close();

                // 批量获取文章标题
                $post_titles = array();
                if (!empty($post_ids)) {
                    $post_id_str = implode(',', array_map('intval', $post_ids));
                    $post_result = $conn->query("SELECT id, title FROM posts WHERE id IN ($post_id_str)");
                    if ($post_result) {
                        while ($post_row = $post_result->fetch_assoc()) {
                            $post_titles[$post_row['id']] = $post_row['title'];
                        }
                        $post_result->close();
                    }
                }

                // 批量获取评论内容
                $comment_contents = array();
                if (!empty($comment_ids)) {
                    $comment_id_str = implode(',', array_map('intval', $comment_ids));
                    $comment_result = $conn->query("SELECT id, content FROM comments WHERE id IN ($comment_id_str)");
                    if ($comment_result) {
                        while ($comment_row = $comment_result->fetch_assoc()) {
                            $content = $comment_row['content'];
                            $comment_contents[$comment_row['id']] = (mb_strlen($content, 'UTF-8') > 20 ? mb_substr($content, 0, 20, 'UTF-8') . '...' : $content);
                        }
                        $comment_result->close();
                    }
                }

                // 批量获取用户名
                $user_names = array();
                if (!empty($user_ids)) {
                    $user_id_str = implode(',', array_map('intval', $user_ids));
                    $user_result = $conn->query("SELECT id, username FROM users WHERE id IN ($user_id_str)");
                    if ($user_result) {
                        while ($user_row = $user_result->fetch_assoc()) {
                            $user_names[$user_row['id']] = $user_row['username'];
                        }
                        $user_result->close();
                    }
                }

                // 填充reported_title
                foreach ($reports as &$report) {
                    if ($report['reported_type'] == 'post') {
                        $report['reported_title'] = isset($post_titles[$report['reported_id']]) ? $post_titles[$report['reported_id']] : '已删除的文章';
                    } elseif ($report['reported_type'] == 'comment') {
                        $report['reported_title'] = isset($comment_contents[$report['reported_id']]) ? $comment_contents[$report['reported_id']] : '已删除的评论';
                    } elseif ($report['reported_type'] == 'user') {
                        $report['reported_title'] = isset($user_names[$report['reported_id']]) ? $user_names[$report['reported_id']] : '已删除的用户';
                    }
                }
                unset($report);

                // 计算总举报数
                $total_count = 0;
                $count_sql = "SELECT COUNT(*) as count FROM reports r LEFT JOIN users u ON r.user_id = u.id";
                $count_where_conditions = array();
                $count_params = array();

                if ($status != 'all') {
                    $status_value = is_numeric($status) ? intval($status) : ($status == 'processed' ? 1 : 0);
                    $count_where_conditions[] = "r.status = ?";
                    $count_params[] = $status_value;
                }

                if (!empty($search)) {
                    $count_where_conditions[] = "(r.reason LIKE ? OR u.username LIKE ?)";
                    $searchPattern = '%' . $search . '%';
                    $count_params[] = $searchPattern;
                    $count_params[] = $searchPattern;
                }

                if (!empty($count_where_conditions)) $count_sql .= " WHERE " . implode(" AND ", $count_where_conditions);

                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = $count_row['count'];
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = ceil($total_count / $page_size);

                return_json(true, '获取举报列表成功', array(
                    'reports' => $reports,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取举报列表时发生系统错误：' . $e->getMessage());
    }
}

// 获取商品列表接口（用于商品管理分页/搜索）
if (isset($_GET['action']) && $_GET['action'] === 'get_goods') {
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';
    $category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;
    if ($page_size > 1000) $page_size = 1000;
    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        $where = array();
        $params = array();
        $types = '';

        if (!empty($search)) {
            $where[] = "g.title LIKE ?";
            $params[] = '%' . $search . '%';
            $types .= 's';
        }
        if ($category_id > 0) {
            $where[] = "g.category_id = ?";
            $params[] = $category_id;
            $types .= 'i';
        }

        $base_sql = "FROM goods g";
        if (!empty($where)) {
            $base_sql .= " WHERE " . implode(" AND ", $where);
        }

        $count_sql = "SELECT COUNT(*) as count " . $base_sql;
        $total_count = 0;
        if ($count_stmt = $conn->prepare($count_sql)) {
            if (!empty($params)) {
                $count_stmt->bind_param($types, ...$params);
            }
            if ($count_stmt->execute()) {
                $count_result = $count_stmt->get_result();
                if ($count_row = $count_result->fetch_assoc()) {
                    $total_count = intval($count_row['count']);
                }
            }
            $count_stmt->close();
        }

        $sql = "SELECT g.id, g.title, g.image, g.price, g.stock, g.sales, g.status, g.category_id, g.create_time " . $base_sql . " ORDER BY g.id DESC LIMIT ?, ?";
        $list_params = $params;
        $list_types = $types . 'ii';
        $list_params[] = $offset;
        $list_params[] = $page_size;

        $goods = array();
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param($list_types, ...$list_params);
            if ($stmt->execute()) {
                $result = $stmt->get_result();
                while ($row = $result->fetch_assoc()) {
                    if (!isset($row['sales'])) $row['sales'] = 0;
                    $goods[] = $row;
                }
            }
            $stmt->close();
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }

        $categories = array();
        $cat_result = $conn->query("SELECT id, name FROM categories ORDER BY id DESC");
        if ($cat_result) {
            while ($cat = $cat_result->fetch_assoc()) {
                $categories[] = $cat;
            }
            $cat_result->close();
        }

        $total_pages = $total_count > 0 ? ceil($total_count / $page_size) : 1;
        return_json(true, '获取商品列表成功', array(
            'goods' => $goods,
            'categories' => $categories,
            'current_page' => $page,
            'page_size' => $page_size,
            'total_count' => $total_count,
            'total_pages' => $total_pages
        ));
    } catch (Exception $e) {
        return_json(false, '获取商品列表时发生系统错误：' . $e->getMessage());
    }
}

// 获取TAG列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_tags') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询TAG列表，支持搜索
        $sql = "SELECT id, keywords FROM posts WHERE keywords != ''";
        $where_conditions = array();
        $params = array();

        if (!empty($search)) {
            $where_conditions[] = "keywords LIKE ?";
            $params[] = '%' . $search . '%';
        }

        if (!empty($where_conditions)) $sql .= " AND " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY id DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $tags = array();
                while ($row = $result->fetch_assoc()) {
                    $tags[] = $row;
                }
                $stmt->close();

                // 计算总TAG数和总页数
                $total_count = 0;
                $count_sql = "SELECT COUNT(*) as count FROM posts WHERE keywords != ''";
                $count_where_conditions = array();
                $count_params = array();

                if (!empty($search)) {
                    $count_where_conditions[] = "keywords LIKE ?";
                    $count_params[] = '%' . $search . '%';
                }

                if (!empty($count_where_conditions)) $count_sql .= " WHERE " . implode(" AND ", $count_where_conditions);

                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = $count_row['count'];
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = ceil($total_count / $page_size);

                return_json(true, '获取TAG列表成功', array(
                    'tags' => $tags,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取TAG列表时发生系统错误：' . $e->getMessage());
    }
}

// 获取搜索词列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_searches') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询搜索词列表，支持搜索
        $sql = "SELECT id, username, search_term, search_time FROM search";
        $where_conditions = array();
        $params = array();

        if (!empty($search)) {
            $where_conditions[] = "search_term LIKE ?";
            $params[] = '%' . $search . '%';
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY search_time DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $searches = array();
                while ($row = $result->fetch_assoc()) {
                    $searches[] = $row;
                }
                $stmt->close();

                // 计算总搜索词数和总页数
                $total_count = 0;
                $count_sql = "SELECT COUNT(*) as count FROM search";
                $count_where_conditions = array();
                $count_params = array();

                if (!empty($search)) {
                    $count_where_conditions[] = "search_term LIKE ?";
                    $count_params[] = '%' . $search . '%';
                }

                if (!empty($count_where_conditions)) $count_sql .= " WHERE " . implode(" AND ", $count_where_conditions);

                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = $count_row['count'];
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = ceil($total_count / $page_size);

                return_json(true, '获取搜索词列表成功', array(
                    'searches' => $searches,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取搜索词列表时发生系统错误：' . $e->getMessage());
    }
}

// 处理图片上传
if (isset($_POST['action']) && $_POST['action'] === 'upload_image' && isset($_FILES['file'])) {
    ensureUploadDirectories();
    $file = $_FILES['file'];
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileError = $file['error'];
    $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

    if ($fileError !== UPLOAD_ERR_OK) {
        return_json(false, '文件上传失败');
    }

    if (!in_array($fileExt, $allowedExts)) {
        return_json(false, '不支持的文件类型');
    }

    $maxFileSize = 5 * 1024 * 1024;
    if ($fileSize > $maxFileSize) {
        return_json(false, '文件大小超过5MB限制');
    }

    $newFileName = 'article_' . uniqid('', true) . '.' . $fileExt;
    $destination = TEMP_UPLOAD_DIR . $newFileName;

    if (move_uploaded_file($fileTmpName, $destination)) {
        $imageUrl = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
        return_json(true, '图片上传成功', array('url' => $imageUrl));
    } else {
        return_json(false, '文件保存失败');
    }
}

// 处理缩略图上传
if (isset($_POST['action']) && $_POST['action'] === 'upload_thumbnail' && isset($_FILES['thumbnail'])) {
    ensureUploadDirectories();
    $file = $_FILES['thumbnail'];
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileError = $file['error'];
    $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

    if ($fileError !== UPLOAD_ERR_OK) {
        return_json(false, '文件上传失败');
    }

    if (!in_array($fileExt, $allowedExts)) {
        return_json(false, '不支持的文件类型');
    }

    $maxFileSize = 2 * 1024 * 1024;
    if ($fileSize > $maxFileSize) {
        return_json(false, '文件大小超过2MB限制');
    }

    $newFileName = 'thumbnail_' . uniqid('', true) . '.' . $fileExt;
    $destination = TEMP_UPLOAD_DIR . $newFileName;

    if (move_uploaded_file($fileTmpName, $destination)) {
        $imageUrl = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
        return_json(true, '缩略图上传成功', array('thumbnail_url' => $imageUrl, 'name' => $fileName));
    } else {
        return_json(false, '文件保存失败');
    }
}

// 获取订单列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_orders') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';
    $filter = isset($_GET['filter']) ? trim($_GET['filter']) : '';
    $time_range = isset($_GET['time_range']) ? trim($_GET['time_range']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询订单列表，支持搜索和筛选
        $sql = "SELECT o.*, u.username FROM `order` o LEFT JOIN users u ON o.user_id = u.id";
        $where_conditions = array();
        $params = array();

        if (!empty($search)) {
            $where_conditions[] = "(o.order_no LIKE ? OR u.username LIKE ?)";
            $params[] = '%' . $search . '%';
            $params[] = '%' . $search . '%';
        }

        // 时间范围筛选
        if (!empty($time_range)) {
            switch ($time_range) {
                case 'today':
                    $where_conditions[] = "DATE(o.created_at) = CURDATE()";
                    break;
                case 'yesterday':
                    $where_conditions[] = "DATE(o.created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)";
                    break;
                case 'this_month':
                    $where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE()) AND MONTH(o.created_at) = MONTH(CURDATE())";
                    break;
                case 'three_months':
                    $where_conditions[] = "o.created_at >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)";
                    break;
                case 'this_year':
                    $where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE())";
                    break;
            }
        }

        // 其他筛选条件
        if (!empty($filter)) {
            switch ($filter) {
                case 'today':
                    $where_conditions[] = "DATE(o.created_at) = CURDATE()";
                    break;
                case 'this_month':
                    $where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE()) AND MONTH(o.created_at) = MONTH(CURDATE())";
                    break;
                case 'wechat':
                    $where_conditions[] = "o.pay_type = '微信'";
                    break;
                case 'alipay':
                    $where_conditions[] = "o.pay_type = '支付宝'";
                    break;
                case 'shipped':
                    $where_conditions[] = "o.shipping_status = 1";
                    break;
                case 'unshipped':
                    $where_conditions[] = "o.shipping_status = 0";
                    break;
                case 'points':
                    $where_conditions[] = "o.type = '积分类'";
                    break;
                case 'resource':
                    $where_conditions[] = "o.type = '资源类'";
                    break;
                case 'tool':
                    $where_conditions[] = "o.type = '工具类'";
                    break;
                case 'goods':
                    $where_conditions[] = "o.type = '商品类'";
                    break;
            }
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY o.created_at DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $orders = array();
                while ($row = $result->fetch_assoc()) {
                    $orders[] = $row;
                }
                $stmt->close();

                // 计算总订单数和总页数
                $total_count = 0;
                $total_amount = 0;

                // 构建总金额查询的条件
                $count_where_conditions = array();
                $count_params = array();

                if (!empty($search)) {
                    $count_where_conditions[] = "(o.order_no LIKE ? OR u.username LIKE ?)";
                    $count_params[] = '%' . $search . '%';
                    $count_params[] = '%' . $search . '%';
                }

                // 时间范围筛选
                if (!empty($time_range)) {
                    switch ($time_range) {
                        case 'today':
                            $count_where_conditions[] = "DATE(o.created_at) = CURDATE()";
                            break;
                        case 'yesterday':
                            $count_where_conditions[] = "DATE(o.created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)";
                            break;
                        case 'this_month':
                            $count_where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE()) AND MONTH(o.created_at) = MONTH(CURDATE())";
                            break;
                        case 'three_months':
                            $count_where_conditions[] = "o.created_at >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)";
                            break;
                        case 'this_year':
                            $count_where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE())";
                            break;
                    }
                }

                // 其他筛选条件
                if (!empty($filter)) {
                    switch ($filter) {
                        case 'today':
                            $count_where_conditions[] = "DATE(o.created_at) = CURDATE()";
                            break;
                        case 'this_month':
                            $count_where_conditions[] = "YEAR(o.created_at) = YEAR(CURDATE()) AND MONTH(o.created_at) = MONTH(CURDATE())";
                            break;
                        case 'wechat':
                            $count_where_conditions[] = "o.pay_type = '微信'";
                            break;
                        case 'alipay':
                            $count_where_conditions[] = "o.pay_type = '支付宝'";
                            break;
                        case 'shipped':
                            $count_where_conditions[] = "o.shipping_status = 1";
                            break;
                        case 'unshipped':
                            $count_where_conditions[] = "o.shipping_status = 0";
                            break;
                        case 'points':
                            $count_where_conditions[] = "o.type = '积分类'";
                            break;
                        case 'resource':
                            $count_where_conditions[] = "o.type = '资源类'";
                            break;
                        case 'tool':
                            $count_where_conditions[] = "o.type = '工具类'";
                            break;
                        case 'goods':
                            $count_where_conditions[] = "o.type = '商品类'";
                            break;
                    }
                }

                // 构建总金额查询
                $count_sql = "SELECT COUNT(*) as count, SUM(amount) as total_amount FROM `order` o LEFT JOIN users u ON o.user_id = u.id";
                if (!empty($count_where_conditions)) {
                    $count_sql .= " WHERE " . implode(" AND ", $count_where_conditions);
                }

                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = $count_row['count'];
                            $total_amount = $count_row['total_amount'] ?? 0;
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = ceil($total_count / $page_size);

                return_json(true, '获取订单列表成功', array(
                    'orders' => $orders,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages,
                    'total_amount' => (float)$total_amount
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取订单列表时发生系统错误：' . $e->getMessage());
    }
}

if (isset($_GET['action']) && $_GET['action'] === 'get_publish') {
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim((string)$_GET['search']) : '';
    $status = isset($_GET['status']) ? trim((string)$_GET['status']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;
    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        $sql = "SELECT p.id, p.user_id, p.category_id, p.title, p.thumbnail, p.status, p.created_at, u.username, IFNULL(c.name,'') AS category_name
                FROM publish p
                LEFT JOIN users u ON p.user_id = u.id
                LEFT JOIN categories c ON p.category_id = c.id";
        $where_conditions = array();
        $params = array();

        if ($search !== '') {
            $where_conditions[] = "(p.title LIKE ? OR u.username LIKE ?)";
            $params[] = '%' . $search . '%';
            $params[] = '%' . $search . '%';
        }

        if ($status !== '' && $status !== 'all') {
            $st = intval($status);
            if (in_array($st, array(0, 1, 2), true)) {
                $where_conditions[] = "p.status = ?";
                $params[] = $st;
            }
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY p.id DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }
            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $rows = array();
                while ($row = $result->fetch_assoc()) {
                    $rows[] = $row;
                }
                $stmt->close();

                $count_sql = "SELECT COUNT(*) as count FROM publish p LEFT JOIN users u ON p.user_id = u.id";
                $count_where = array();
                $count_params = array();
                if ($search !== '') {
                    $count_where[] = "(p.title LIKE ? OR u.username LIKE ?)";
                    $count_params[] = '%' . $search . '%';
                    $count_params[] = '%' . $search . '%';
                }
                if ($status !== '' && $status !== 'all') {
                    $st = intval($status);
                    if (in_array($st, array(0, 1, 2), true)) {
                        $count_where[] = "p.status = ?";
                        $count_params[] = $st;
                    }
                }
                if (!empty($count_where)) $count_sql .= " WHERE " . implode(" AND ", $count_where);

                $total_count = 0;
                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = intval($count_row['count']);
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = $total_count > 0 ? ceil($total_count / $page_size) : 1;
                return_json(true, '获取投稿列表成功', array(
                    'publish' => $rows,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取投稿列表时发生系统错误：' . $e->getMessage());
    }
}

if (isset($_POST['action']) && $_POST['action'] === 'update_publish_status') {
    $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
    $status = isset($_POST['status']) ? intval($_POST['status']) : 0;
    if ($id <= 0) {
        return_json(false, '参数错误');
    }
    $status = $status === 1 ? 1 : 0;
    try {
        $current = get_single_row($conn, "SELECT id, status, post_id FROM publish WHERE id = ? LIMIT 1", array($id));
        if (!$current) {
            return_json(false, '投稿不存在或已处理');
        }
        $current_status = intval($current['status'] ?? 0);
        $current_post_id = intval($current['post_id'] ?? 0);

        if ($status === 0) {
            if ($current_status === 1 || $current_post_id > 0) {
                return_json(false, '已通过不可取消审核');
            }
            $result = execute_non_query($conn, "UPDATE publish SET status = 0 WHERE id = ?", array($id));
            if ($result !== false) {
                return_json(true, '更新成功', array('id' => $id, 'status' => 0));
            }
            return_json(false, '更新失败');
        }

        if ($current_post_id > 0 || $current_status === 1) {
            $del = execute_non_query($conn, "DELETE FROM publish WHERE id = ? LIMIT 1", array($id));
            if ($del !== false) {
                return_json(true, '已通过', array('id' => $id, 'status' => 1, 'migrated' => 0, 'deleted' => 1, 'post_id' => $current_post_id));
            }
            $result = execute_non_query($conn, "UPDATE publish SET status = 1 WHERE id = ?", array($id));
            if ($result !== false) {
                return_json(true, '已通过', array('id' => $id, 'status' => 1, 'migrated' => 0, 'deleted' => 0, 'post_id' => $current_post_id));
            }
            return_json(false, '更新失败');
        }

        $conn->begin_transaction();
        $row = get_single_row($conn, "SELECT id, category_id, user_id, title, keywords, description, content, thumbnail, created_at FROM publish WHERE id = ? LIMIT 1", array($id));
        if (!$row) {
            $conn->rollback();
            return_json(false, '投稿不存在或已处理');
        }
        $title = isset($row['title']) ? trim((string)$row['title']) : '';
        if ($title === '') {
            $conn->rollback();
            return_json(false, '标题不能为空');
        }
        $dup = get_single_row($conn, "SELECT id FROM posts WHERE title = ? LIMIT 1", array($title));
        if ($dup) {
            $conn->rollback();
            return_json(false, '标题已存在，无法通过审核');
        }

        $category_id = intval($row['category_id'] ?? 0);
        $user_id = intval($row['user_id'] ?? 0);
        $keywords = isset($row['keywords']) ? (string)$row['keywords'] : '';
        $description = isset($row['description']) ? (string)$row['description'] : '';
        $content = isset($row['content']) ? (string)$row['content'] : '';
        $thumbnail = isset($row['thumbnail']) ? (string)$row['thumbnail'] : '';
        $created_at = isset($row['created_at']) ? (string)$row['created_at'] : '';
        $content = processPublishImagesInContent($content, true);
        $thumbnail = moveImageFromPublish($thumbnail, false);

        $post_sql = "INSERT INTO posts (title, content, user_id, status, category_id, thumbnail, keywords, description, property, template, custom_url, tool_url, redirect_url, price, status_switch, function_type, views, points, mp4url, created_at, updated_at) VALUES (?, ?, ?, 1, ?, ?, ?, ?, 0, 'post.php', '', '', '', 0, 0, 'tool', 0, 0, '', ?, NOW())";
        $created_value = $created_at !== '' ? $created_at : date('Y-m-d H:i:s');
        $ins = execute_non_query($conn, $post_sql, array($title, $content, $user_id, $category_id, $thumbnail, $keywords, $description, $created_value));
        if ($ins === false || !isset($ins['insert_id']) || intval($ins['insert_id']) <= 0) {
            $conn->rollback();
            return_json(false, '写入文章失败');
        }
        $post_id = intval($ins['insert_id']);

        $del = execute_non_query($conn, "DELETE FROM publish WHERE id = ? LIMIT 1", array($id));
        if ($del === false) {
            $conn->rollback();
            return_json(false, '删除投稿失败');
        }

        $conn->commit();
        return_json(true, '已通过并发布', array('id' => $id, 'status' => 1, 'migrated' => 1, 'deleted' => 1, 'post_id' => $post_id));
    } catch (Exception $e) {
        try {
            if (isset($conn) && is_object($conn) && method_exists($conn, 'rollback')) {
                $conn->rollback();
            }
        } catch (Exception $e2) {
        }
        return_json(false, '更新失败');
    }
}

if (isset($_POST['action']) && $_POST['action'] === 'update_publish_category') {
    $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
    $category_id = isset($_POST['category_id']) ? intval($_POST['category_id']) : 0;
    if ($id <= 0 || $category_id <= 0) {
        return_json(false, '参数错误');
    }
    $cat = get_single_row($conn, "SELECT id FROM categories WHERE id = ? LIMIT 1", array($category_id));
    if (!$cat) {
        return_json(false, '分类不存在');
    }
    try {
        $result = execute_non_query($conn, "UPDATE publish SET category_id = ? WHERE id = ?", array($category_id, $id));
        if ($result !== false) {
            return_json(true, '更新成功', array('id' => $id, 'category_id' => $category_id));
        }
        return_json(false, '更新失败');
    } catch (Exception $e) {
        return_json(false, '更新失败');
    }
}

if (isset($_GET['action']) && $_GET['action'] === 'get_publish_detail') {
    $id = isset($_GET['id']) ? intval($_GET['id']) : 0;
    if ($id <= 0) {
        return_json(false, '参数错误');
    }
    $row = get_single_row($conn, "SELECT id, category_id, title, keywords, description, content, thumbnail FROM publish WHERE id = ? LIMIT 1", array($id));
    if (!$row) {
        return_json(false, '投稿不存在');
    }
    return_json(true, '获取成功', $row);
}

if (isset($_POST['action']) && $_POST['action'] === 'edit_publish') {
    $id = isset($_POST['publish_id']) ? intval($_POST['publish_id']) : 0;
    $title = isset($_POST['publish_title']) ? trim($_POST['publish_title']) : '';
    $keywords = isset($_POST['publish_keywords']) ? trim($_POST['publish_keywords']) : '';
    $description = isset($_POST['publish_description']) ? trim($_POST['publish_description']) : '';
    $content = isset($_POST['publish_content']) ? $_POST['publish_content'] : '';
    $thumbnail = isset($_POST['publish_thumbnail']) ? trim($_POST['publish_thumbnail']) : '';
    $category_id = isset($_POST['publish_category_id']) ? intval($_POST['publish_category_id']) : 0;
    if ($id <= 0 || $title === '') {
        return_json(false, '参数错误');
    }
    try {
        $publishDir = __DIR__ . '/../uploads/publish/';
        if (!is_dir($publishDir)) {
            @mkdir($publishDir, 0755, true);
        }
        $toPublishUrl = function ($fileName) {
            return qk_build_relative_upload_path($fileName, '/uploads/publish/');
        };
        $moveTempToPublish = function ($url) use ($publishDir, $toPublishUrl) {
            $url = trim((string)$url);
            if ($url === '' || strpos($url, '/uploads/Temp/') === false) return $url;
            $parsed = parse_url($url);
            $path = isset($parsed['path']) ? (string)$parsed['path'] : '';
            $fileName = basename($path);
            if ($fileName === '' || $fileName === '.' || $fileName === '..') return $url;
            $src = TEMP_UPLOAD_DIR . $fileName;
            if (!file_exists($src)) {
                return $toPublishUrl($fileName);
            }
            $destName = $fileName;
            $dest = $publishDir . $destName;
            if (file_exists($dest)) {
                $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
                $ext = $ext !== '' ? ('.' . $ext) : '';
                $destName = 'publish_' . uniqid('', true) . $ext;
                $dest = $publishDir . $destName;
            }
            if (@rename($src, $dest) || (@copy($src, $dest) && @unlink($src))) {
                return $toPublishUrl($destName);
            }
            return $url;
        };
        $content = preg_replace_callback(
            '/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i',
            function ($m) use ($moveTempToPublish) {
                $old = $m[1];
                $new = $moveTempToPublish($old);
                if ($new === $old) return $m[0];
                return str_replace($old, $new, $m[0]);
            },
            $content
        );
        $thumbnail = $moveTempToPublish($thumbnail);
        $result = execute_non_query($conn, "UPDATE publish SET title=?, keywords=?, description=?, content=?, thumbnail=?, category_id=? WHERE id=?", array($title, $keywords, $description, $content, $thumbnail, $category_id, $id));
        if ($result !== false) {
            return_json(true, '更新成功');
        }
        return_json(false, '更新失败');
    } catch (Exception $e) {
        return_json(false, '更新失败');
    }
}

if (isset($_POST['action']) && $_POST['action'] === 'update_order_shipping') {
    $orderId = isset($_POST['id']) ? intval($_POST['id']) : 0;
    $status = isset($_POST['shipping_status']) ? intval($_POST['shipping_status']) : 0;
    if ($orderId <= 0) {
        return_json(false, '参数错误');
    }
    $status = $status === 1 ? 1 : 0;

    try {
        $result = execute_non_query($conn, "UPDATE `order` SET shipping_status = ? WHERE id = ?", [$status, $orderId]);
        if ($result !== false) {
            return_json(true, '更新成功', ['id' => $orderId, 'shipping_status' => $status]);
        }
        return_json(false, '更新失败');
    } catch (Exception $e) {
        return_json(false, '更新失败');
    }
}

// 获取用户列表接口
if (isset($_GET['action']) && $_GET['action'] === 'get_users') {
    // 获取数据库连接
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';

    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;

    $offset = ($page - 1) * $page_size;

    if (!isset($conn) || !is_object($conn)) {
        return_json(false, '数据库连接未初始化');
    }
    if (isset($conn->connect_error)) {
        return_json(false, '数据库连接错误：' . $conn->connect_error);
    }

    try {
        // 查询用户列表，支持搜索
        $sql = "SELECT u.id, u.username, u.avatar, u.created_at, u.levels_id, u.status, u.points, u.email, l.name AS level_name FROM users u LEFT JOIN levels l ON u.levels_id = l.id";
        $where_conditions = array();
        $params = array();

        if (!empty($search)) {
            $where_conditions[] = "u.username LIKE ?";
            $params[] = '%' . $search . '%';
        }

        if (!empty($where_conditions)) $sql .= " WHERE " . implode(" AND ", $where_conditions);
        $sql .= " ORDER BY u.id DESC LIMIT ?, ?";
        $params[] = $offset;
        $params[] = $page_size;

        if ($stmt = $conn->prepare($sql)) {
            // 绑定参数
            $types = '';
            foreach ($params as $param) {
                $types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
            }
            if (count($params) > 0) {
                $stmt->bind_param($types, ...$params);
            }

            if ($stmt->execute()) {
                $result = $stmt->get_result();
                $users = array();
                while ($row = $result->fetch_assoc()) {
                    $users[] = $row;
                }
                $stmt->close();

                // 计算总用户数和总页数
                $total_count = 0;
                $count_sql = "SELECT COUNT(*) as count FROM users u";
                $count_where_conditions = array();
                $count_params = array();

                if (!empty($search)) {
                    $count_where_conditions[] = "u.username LIKE ?";
                    $count_params[] = '%' . $search . '%';
                }

                if (!empty($count_where_conditions)) $count_sql .= " WHERE " . implode(" AND ", $count_where_conditions);

                if ($count_stmt = $conn->prepare($count_sql)) {
                    if (!empty($count_params)) {
                        $count_types = '';
                        foreach ($count_params as $param) {
                            $count_types .= is_numeric($param) && intval($param) == $param ? 'i' : 's';
                        }
                        $count_stmt->bind_param($count_types, ...$count_params);
                    }
                    if ($count_stmt->execute()) {
                        $count_result = $count_stmt->get_result();
                        if ($count_row = $count_result->fetch_assoc()) {
                            $total_count = $count_row['count'];
                        }
                    }
                    $count_stmt->close();
                }

                $total_pages = ceil($total_count / $page_size);

                return_json(true, '获取用户列表成功', array(
                    'users' => $users,
                    'current_page' => $page,
                    'page_size' => $page_size,
                    'total_count' => $total_count,
                    'total_pages' => $total_pages
                ));
            } else {
                return_json(false, '执行查询失败：' . $conn->error);
            }
        } else {
            return_json(false, '准备查询语句失败：' . $conn->error);
        }
    } catch (Exception $e) {
        return_json(false, '获取用户列表时发生系统错误：' . $e->getMessage());
    }
}

if (isset($_GET['action']) && $_GET['action'] === 'get_counter') {
    get_db_connection();
    $conn = $GLOBALS['conn'];
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $page_size = isset($_GET['page_size']) ? intval($_GET['page_size']) : 30;
    $search = isset($_GET['search']) ? trim($_GET['search']) : '';
    $date_range = isset($_GET['date_range']) ? trim($_GET['date_range']) : '7days';
    $sort = isset($_GET['sort']) ? trim($_GET['sort']) : 'date';
    $order = isset($_GET['order']) ? strtolower(trim($_GET['order'])) : 'desc';

    if (!in_array($date_range, array('today', 'yesterday', '7days'), true)) $date_range = '7days';
    $sort_map = array(
        'date' => 'stat_date',
        'pv' => 'pv',
        'uv' => 'uv',
        'ip' => 'ip_count'
    );
    if (!isset($sort_map[$sort])) $sort = 'date';
    if (!in_array($order, array('asc', 'desc'), true)) $order = 'desc';
    $sort_field_sql = $sort_map[$sort];
    $sort_order_sql = $order === 'asc' ? 'ASC' : 'DESC';
    if ($page < 1) $page = 1;
    if ($page_size < 1) $page_size = 30;
    if ($page_size > 1000) $page_size = 1000;

    $today = date('Y-m-d');
    if ($date_range === 'today') {
        $date_start = $today;
        $date_end = $today;
    } elseif ($date_range === 'yesterday') {
        $date_start = date('Y-m-d', strtotime('-1 day'));
        $date_end = $date_start;
    } else {
        $date_start = date('Y-m-d', strtotime('-6 days'));
        $date_end = $today;
    }

    $where = " WHERE stat_date BETWEEN ? AND ? ";
    $params = array($date_start, $date_end);
    if ($search !== '') {
        $where .= " AND (page_title LIKE ? OR page_url LIKE ?) ";
        $like = '%' . $search . '%';
        $params[] = $like;
        $params[] = $like;
    }

    $count_row = get_single_row($conn, "SELECT COUNT(*) AS c FROM counter {$where}", $params);
    $total_count = isset($count_row['c']) ? (int)$count_row['c'] : 0;
    $total_pages = max(1, (int)ceil($total_count / $page_size));
    if ($page > $total_pages) $page = $total_pages;
    $offset = ($page - 1) * $page_size;

    $sql = "SELECT * FROM counter {$where} ORDER BY {$sort_field_sql} {$sort_order_sql}, stat_date DESC, pv DESC LIMIT ?, ?";
    $list_params = $params;
    $list_params[] = $offset;
    $list_params[] = $page_size;
    $rows = array();
    $result = execute_query($conn, $sql, $list_params);
    if ($result) {
        while ($row = $result->fetch_assoc()) {
            $rows[] = $row;
        }
        $result->close();
    }

    return_json(true, '获取流量统计成功', array(
        'rows' => $rows,
        'current_page' => $page,
        'page_size' => $page_size,
        'total_count' => $total_count,
        'total_pages' => $total_pages,
        'date_range' => $date_range,
        'sort' => $sort,
        'order' => $order
    ));
}

if (isset($_GET['action']) && $_GET['action'] === 'upload_temp_image') {
    if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
        return_json(false, '请选择图片文件');
    }

    $file = $_FILES['image'];
    $fileName = $file['name'];
    $fileTmpName = $file['tmp_name'];
    $fileSize = $file['size'];
    $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    $allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

    if (!in_array($fileExt, $allowedExts)) {
        return_json(false, '不支持的文件类型');
    }

    $maxFileSize = 5 * 1024 * 1024;
    if ($fileSize > $maxFileSize) {
        return_json(false, '文件大小超过5MB限制');
    }

    $type = isset($_POST['type']) ? $_POST['type'] : 'article';
    $prefix = ($type === 'thumbnail') ? 'thumbnail_' : 'article_';
    $newFileName = $prefix . uniqid('', true) . '.' . $fileExt;
    $destination = TEMP_UPLOAD_DIR . $newFileName;

    if (move_uploaded_file($fileTmpName, $destination)) {
        if ($type === 'thumbnail') {
            // 检查模板是否为post1.php，如果不是则调整缩略图尺寸
            $template = isset($_POST['template']) ? trim($_POST['template']) : (isset($_GET['template']) ? trim($_GET['template']) : 'post.php');
            // 直接使用模板路径进行判断
            if (strpos($template, 'post1.php') === false) {
                resizeThumbnail($destination);
            }
        }

        $imageUrl = qk_build_relative_upload_path($newFileName, '/uploads/Temp/');
        return_json(true, '图片上传成功', array('url' => $imageUrl));
    } else {
        return_json(false, '文件保存失败');
    }
}

// 处理删除缩略图请求
if (isset($_POST['action']) && $_POST['action'] === 'delete_thumbnail') {
    if (!isset($_POST['thumbnail_url'])) {
        return_json(false, '缺少缩略图URL参数');
    }

    $thumbnailUrl = trim((string)$_POST['thumbnail_url']);
    $thumbnailPath = qk_normalize_media_path($thumbnailUrl);
    $fullPath = realpath(__DIR__ . '/..' . $thumbnailPath);
    deleteUploadFile($thumbnailPath);
    if ($fullPath === false || !file_exists($fullPath)) {
        return_json(true, '缩略图文件删除成功');
    } else {
        return_json(false, '缩略图文件删除失败');
    }
}

// 批量更新文章分类
if (isset($_POST['action']) && $_POST['action'] === 'batch_update_category') {
    $article_ids = isset($_POST['article_ids']) ? $_POST['article_ids'] : '';
    $category_id = isset($_POST['category_id']) ? intval($_POST['category_id']) : 0;

    if (empty($article_ids) || $category_id === 0) {
        return_json(false, '参数错误');
    }

    $article_id_array = explode(',', $article_ids);
    $success_count = 0;
    $error_count = 0;

    try {
        foreach ($article_id_array as $article_id) {
            $article_id = intval($article_id);
            if ($article_id > 0) {
                if (update_article_category($conn, $article_id, $category_id)) {
                    $success_count++;
                } else {
                    $error_count++;
                }
            }
        }

        if ($success_count > 0) {
            return_json(true, "成功移动 {$success_count} 篇文章到新分类");
        } else {
            return_json(false, "移动失败");
        }
    } catch (Exception $e) {
        return_json(false, '操作失败：' . $e->getMessage());
    }
}

// 批量更新文章属性
if (isset($_POST['action']) && $_POST['action'] === 'batch_update_property') {
    $article_ids = isset($_POST['article_ids']) ? $_POST['article_ids'] : '';
    $property_id = isset($_POST['property_id']) ? intval($_POST['property_id']) : 0;

    if (empty($article_ids) || $property_id === 0) {
        return_json(false, '参数错误');
    }

    $article_id_array = explode(',', $article_ids);
    $success_count = 0;
    $error_count = 0;

    try {
        foreach ($article_id_array as $article_id) {
            $article_id = intval($article_id);
            if ($article_id > 0) {
                if (update_article_property($conn, $article_id, $property_id)) {
                    $success_count++;
                } else {
                    $error_count++;
                }
            }
        }

        if ($success_count > 0) {
            return_json(true, "成功修改 {$success_count} 篇文章属性");
        } else {
            return_json(false, "修改失败");
        }
    } catch (Exception $e) {
        return_json(false, '操作失败：' . $e->getMessage());
    }
}

// 批量更新文章模板
if (isset($_POST['action']) && $_POST['action'] === 'batch_update_template') {
    $article_ids = isset($_POST['article_ids']) ? $_POST['article_ids'] : '';
    $template = isset($_POST['template']) ? trim($_POST['template']) : '';

    if (empty($article_ids) || empty($template)) {
        return_json(false, '参数错误');
    }

    $article_id_array = explode(',', $article_ids);
    $success_count = 0;
    $error_count = 0;

    try {
        foreach ($article_id_array as $article_id) {
            $article_id = intval($article_id);
            if ($article_id > 0) {
                $sql = "UPDATE posts SET template = ? WHERE id = ?";
                if ($stmt = $conn->prepare($sql)) {
                    $stmt->bind_param("si", $template, $article_id);
                    if ($stmt->execute()) {
                        $success_count++;
                    } else {
                        $error_count++;
                    }
                    $stmt->close();
                }
            }
        }

        if ($success_count > 0) {
            return_json(true, "成功绑定 {$success_count} 篇文章模板");
        } else {
            return_json(false, "绑定失败");
        }
    } catch (Exception $e) {
        return_json(false, '操作失败：' . $e->getMessage());
    }
}

// 新增模板标签
if (isset($_POST['action']) && $_POST['action'] === 'add_tplmark') {
    if (ob_get_level() > 0) {
        ob_clean();
    }
    header('Content-Type: application/json');
    
    global $conn;
    if (!isset($conn) || !is_object($conn) || isset($conn->connect_error)) {
        $conn = get_db_connection();
    }
    
    $name_cn = isset($_POST['name_cn']) ? trim($_POST['name_cn']) : '';
    $code = isset($_POST['code']) ? trim($_POST['code']) : '';
    $category = isset($_POST['category']) ? trim($_POST['category']) : '';
    $type = isset($_POST['type']) ? trim($_POST['type']) : '';
    $example = isset($_POST['example']) ? trim($_POST['example']) : '';
    $description = isset($_POST['description']) ? trim($_POST['description']) : '';
    $description_html = isset($_POST['description_html']) ? trim($_POST['description_html']) : '';
    
    if (empty($name_cn) || empty($code) || empty($category) || empty($type)) {
        return_json(false, '请填写完整信息');
    }
    
    try {
        $max_sort = 0;
        $result = $conn->query("SELECT MAX(sort_order) as max_sort FROM tplmark WHERE category = '" . $conn->real_escape_string($category) . "'");
        if ($result) {
            $row = $result->fetch_assoc();
            if ($row && isset($row['max_sort'])) {
                $max_sort = intval($row['max_sort']);
            }
        }
        $new_sort_order = $max_sort + 1;
        
        $sql = "INSERT INTO tplmark (name_cn, code, category, type, example, description, description_html, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("sssssssi", $name_cn, $code, $category, $type, $example, $description, $description_html, $new_sort_order);
            if ($stmt->execute()) {
                $insert_id = $conn->insert_id;
                return_json(true, '新增标签成功', ['id' => $insert_id]);
            } else {
                return_json(false, '新增标签失败：' . $stmt->error);
            }
            $stmt->close();
        } else {
            return_json(false, '系统错误：准备查询语句失败');
        }
    } catch (Exception $e) {
        return_json(false, '系统错误：' . $e->getMessage());
    }
}

// 编辑模板标签
if (isset($_POST['action']) && $_POST['action'] === 'edit_tplmark') {
    if (ob_get_level() > 0) {
        ob_clean();
    }
    header('Content-Type: application/json');
    
    global $conn;
    if (!isset($conn) || !is_object($conn) || isset($conn->connect_error)) {
        $conn = get_db_connection();
    }
    
    $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
    $name_cn = isset($_POST['name_cn']) ? trim($_POST['name_cn']) : '';
    $code = isset($_POST['code']) ? trim($_POST['code']) : '';
    $category = isset($_POST['category']) ? trim($_POST['category']) : '';
    $type = isset($_POST['type']) ? trim($_POST['type']) : '';
    $example = isset($_POST['example']) ? trim($_POST['example']) : '';
    $description = isset($_POST['description']) ? trim($_POST['description']) : '';
    $description_html = isset($_POST['description_html']) ? trim($_POST['description_html']) : '';
    
    if ($id <= 0 || empty($name_cn) || empty($code) || empty($category) || empty($type)) {
        return_json(false, '请填写完整信息');
    }
    
    try {
        $sql = "UPDATE tplmark SET name_cn = ?, code = ?, category = ?, type = ?, example = ?, description = ?, description_html = ? WHERE id = ?";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("sssssssi", $name_cn, $code, $category, $type, $example, $description, $description_html, $id);
            if ($stmt->execute()) {
                // 处理description_html
                $processedDescriptionHtml = $description_html;
                if (!empty($processedDescriptionHtml) && strpos($processedDescriptionHtml, 'property=属性ID 属性筛选（') !== false) {
                    $properties = getArticleProperties();
                    $prop_list = [];
                    foreach ($properties as $prop_id => $prop) {
                        if ($prop['is_enabled'] == 1) {
                            $prop_list[] = $prop_id . '=' . $prop['name'];
                        }
                    }
                    $prop_text = implode(' &nbsp; ', $prop_list);
                    
                    $pattern = '/property=属性ID 属性筛选\（[^）]*\）/';
                    $replacement = 'property=属性ID 属性筛选（' . $prop_text . '）';
                    $processedDescriptionHtml = preg_replace($pattern, $replacement, $processedDescriptionHtml);
                }
                
                // 替换${tagNameCN}
                if (!empty($processedDescriptionHtml)) {
                    $processedDescriptionHtml = str_replace('${tagNameCN}', htmlspecialchars($name_cn, ENT_QUOTES, 'UTF-8'), $processedDescriptionHtml);
                }
                
                return_json(true, '编辑标签成功', ['processed_description_html' => $processedDescriptionHtml]);
            } else {
                return_json(false, '编辑标签失败：' . $stmt->error);
            }
            $stmt->close();
        } else {
            return_json(false, '系统错误：准备查询语句失败');
        }
    } catch (Exception $e) {
        return_json(false, '系统错误：' . $e->getMessage());
    }
}

// 删除模板标签
if (isset($_POST['action']) && $_POST['action'] === 'delete_tplmark') {
    if (ob_get_level() > 0) {
        ob_clean();
    }
    header('Content-Type: application/json');
    
    global $conn;
    if (!isset($conn) || !is_object($conn) || isset($conn->connect_error)) {
        $conn = get_db_connection();
    }
    
    $id = isset($_POST['id']) ? intval($_POST['id']) : 0;
    
    if ($id <= 0) {
        return_json(false, '无效的ID');
    }
    
    try {
        $sql = "DELETE FROM tplmark WHERE id = ?";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("i", $id);
            if ($stmt->execute()) {
                return_json(true, '删除标签成功');
            } else {
                return_json(false, '删除标签失败：' . $stmt->error);
            }
            $stmt->close();
        } else {
            return_json(false, '系统错误：准备查询语句失败');
        }
    } catch (Exception $e) {
        return_json(false, '系统错误：' . $e->getMessage());
    }
}

if (isset($_POST['action']) && $_POST['action'] === 'update_tplmark_order') {
    if (ob_get_level() > 0) {
        ob_clean();
    }
    header('Content-Type: application/json');
    
    global $conn;
    if (!isset($conn) || !is_object($conn) || isset($conn->connect_error)) {
        $conn = get_db_connection();
    }
    
    $category = isset($_POST['category']) ? trim($_POST['category']) : '';
    $ids_json = isset($_POST['ids']) ? trim($_POST['ids']) : '';
    
    if (empty($category) || empty($ids_json)) {
        return_json(false, '参数不完整');
    }
    
    try {
        $ids = json_decode($ids_json, true);
        if (!is_array($ids) || empty($ids)) {
            return_json(false, '无效的ID数组');
        }
        
        $conn->begin_transaction();
        
        foreach ($ids as $index => $id) {
            $sort_order = $index + 1;
            $sql = "UPDATE tplmark SET sort_order = ? WHERE id = ?";
            if ($stmt = $conn->prepare($sql)) {
                $stmt->bind_param("ii", $sort_order, $id);
                $stmt->execute();
                $stmt->close();
            }
        }
        
        $conn->commit();
        return_json(true, '排序保存成功');
    } catch (Exception $e) {
        if (isset($conn) && $conn->in_transaction()) {
            $conn->rollback();
        }
        return_json(false, '系统错误：' . $e->getMessage());
    }
}

return_json(false, '无效的请求操作');
if (isset($conn)) {
    $conn->close();
}
