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

if (!defined('ADMIN_LOADED')) {
    header('HTTP/1.1 403 Forbidden');
    exit('Access Denied');
}

if (defined('GENERATOR_LOADED')) {
    return;
}
define('GENERATOR_LOADED', true);

function process_description_html($html)
{
    if (empty($html)) {
        return $html;
    }

    if (strpos($html, '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 . '）';
        $html = preg_replace($pattern, $replacement, $html);
    }

    return $html;
}

global $conn;

$tags_by_category = [];
$categories = ['site' => '网站全局标签', 'article' => '文章页标签', 'category' => '列表页标签', 'goods' => '商品页标签', 'loop' => '常用循环标签'];
$category_counts = [];
$common_codes = ['head.html', 'posts_id', 'category_id', 'articles', 'categories', 'comments', 'members', 'tags', 'navigation', 'page', 'search', 'friendlink', 'goods_id', 'goods', 'goods_images'];
$common_codes_lookup = array_flip($common_codes);

try {
    $has_sort_order = false;
    $result = $conn->query("SHOW COLUMNS FROM tplmark LIKE 'sort_order'");
    if ($result && $result->num_rows > 0) {
        $has_sort_order = true;
    }
    
    if ($has_sort_order) {
        $sql = "SELECT * FROM tplmark ORDER BY 
            CASE category 
                WHEN 'site' THEN 1 
                WHEN 'article' THEN 2 
                WHEN 'category' THEN 3 
                WHEN 'goods' THEN 4 
                WHEN 'loop' THEN 5 
                ELSE 6 
            END, COALESCE(sort_order, id), id";
    } else {
        $sql = "SELECT * FROM tplmark ORDER BY 
            CASE category 
                WHEN 'site' THEN 1 
                WHEN 'article' THEN 2 
                WHEN 'category' THEN 3 
                WHEN 'goods' THEN 4 
                WHEN 'loop' THEN 5 
                ELSE 6 
            END, id";
    }
    $result = $conn->query($sql);

    if ($result) {
        $category_codes_map = [];
        while ($row = $result->fetch_assoc()) {
            $category = $row['category'];
            $code = $row['code'];

            if (!isset($category_codes_map[$category])) {
                $category_codes_map[$category] = [];
                $tags_by_category[$category] = [];
            }

            if (!isset($category_codes_map[$category][$code])) {
                $category_codes_map[$category][$code] = true;
                $tags_by_category[$category][] = $row;
            }
        }
    }

    foreach ($categories as $key => $name) {
        $category_counts[$key] = isset($tags_by_category[$key]) ? count($tags_by_category[$key]) : 0;
    }
} catch (Exception $e) {
    $category_counts = ['site' => 0, 'article' => 0, 'category' => 0, 'goods' => 0, 'loop' => 0];
}
?>
<link rel="stylesheet" href="/assets/css/Plugin.css">
<script type="text/javascript">
    // 立即读取本地存储，避免闪烁（参考adcategory.php）
    (function() {
        let savedTab = localStorage.getItem('generator_active_tab');
        const validTabs = ['site', 'article', 'category', 'goods', 'loop'];
        if (!validTabs.includes(savedTab)) {
            savedTab = 'site';
        }
        window.preSelectedTab = savedTab;
    })();
</script>

<style>
    .search-input {
        width: 100%;
        padding: 10px 15px;
        border: 1px solid #ddd;
        border-radius: 4px;
        font-size: 14px;
        outline: none;
        transition: border-color 0.3s;
    }

    .search-input:focus {
        border-color: var(--primary-color);
        box-shadow: 0 0 0 2px var(--primary-light);
    }

    .editable-code {
        width: 100%;
        min-height: 40px;
        resize: vertical;
        border: 1px solid #ddd;
        background: #fcfcfc;
        font-family: monospace;
        padding: 20px;
        border-radius: 5px;
        font-size: 15px;
        height: auto;
        line-height: 26px;
        outline: none;
        margin: 15px 0;
        scrollbar-width: thin;
        scrollbar-color: #c1c1c1 #f1f1f1;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    }

    .editable-code::-webkit-scrollbar {
        width: 6px;
        height: 6px;
    }

    .editable-code::-webkit-scrollbar-track {
        background: #f1f1f1;
        border-radius: 10px;
    }

    .editable-code::-webkit-scrollbar-thumb {
        background: #c1c1c1;
        border-radius: 10px;
        transition: background 0.3s;
    }

    .editable-code::-webkit-scrollbar-thumb:hover {
        background: #a8a8a8;
    }

    .tab-container {
        display: flex;
        flex-wrap: wrap;
        margin-bottom: 25px;
        border-bottom: 1px solid #eee;
        padding-bottom: 20px;
    }

    .tab-container .tab-btn {
        padding: 10px;
        background: none;
        border: none;
        border-bottom: 2px solid transparent;
        cursor: pointer;
        font-size: 15px;
        font-weight: 700;
        transition: all 0.3s;
        margin-right: 5px;
        color: #666;
        border-radius: 5px;
    }

    .tab-container .tab-btn.active {
        background: transparent;
        color: var(--primary-color);
        border-bottom-color: var(--primary-color);
        box-shadow: none !important;
    }

    .tab-container .tab-btn:not(.active):hover {
        background: transparent;
        color: var(--primary-color);
        border-bottom-color: transparent;
        box-shadow: none !important;
    }



    .modal-tab-container {
        display: none;
        gap: 6px;
        background: #f1f5f9;
        border-radius: 10px;
        margin-right: auto;
        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
        box-sizing: border-box;
        padding: 4px 6px;
    }

    .modal-tab-btn {
        padding: 0 16px;
        height: 34px;
        background: transparent;
        border: none;
        border-radius: 7px;
        cursor: pointer;
        font-size: 13px;
        font-weight: 500;
        transition: all 0.25s ease;
        color: #64748b;
        box-shadow: none;
    }

    .modal-tab-btn.active {
        background: #ffffff;
        color: var(--primary-color);
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
        font-weight: 600;
    }

    .modal-footer {
        padding: 25px 0 0 0;
        display: flex;
        gap: 10px;
        align-items: flex-end;
        flex-shrink: 0;
    }

    #tplmark-form {
        display: flex;
        flex-direction: column;
        height: 100%;
    }

    .modal-body {
        flex: 1;
        overflow-y: auto;
    }

    .modal-content {
        width: 550px;
        max-width: 550px;
        height: 600px;
        display: flex;
        flex-direction: column;
    }

    #tplmark-modal .tab-content {
        flex: 1;
        display: flex;
        flex-direction: column;
        overflow-y: auto;
    }

    #tplmark-modal .tab-content .form-group {
        margin-bottom: 18px;
    }

    #tplmark-modal .tab-content .form-group.flex-shrink {
        flex-shrink: 0;
    }

    #tplmark-tab-example .form-group,
    #tplmark-tab-description .form-group {
        height: 100%;
    }

    #tplmark-description-loop-basic,
    #tplmark-example,
    #tplmark-description-html {
        font-family: monospace;
    }

    #tplmark-description-loop-basic {
        height: calc(100% - 30px);
        min-height: 180px;
    }

    #tplmark-example,
    #tplmark-description-html {
        height: calc(100% - 30px);
        min-height: 100px;
    }

    .modal-tab-content-wrapper {
        display: flex;
        gap: 12px;
        position: relative;
    }

    .modal-tab-content-half {
        flex: 1;
        position: relative;
    }

    .modal-tab-label {
        display: block;
        margin-bottom: 6px;
        font-weight: 500;
        color: #2d3748;
        font-size: 14px;
    }

    #tplmark-cancel,
    #tplmark-delete,
    #tplmark-submit {
        width: 70px;
        height: 42px;
    }

    #tplmark-modal input,
    #tplmark-modal select,
    #tplmark-modal textarea {
        pointer-events: auto !important;
        user-select: auto !important;
    }

    #tplmark-modal .form-control {
        pointer-events: auto !important;
    }

    #tplmark-code-wrapper,
    #tplmark-type-wrapper {
        position: relative;
    }

    .tag-grid-container {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
        gap: 15px;
        margin-bottom: -20px;
    }

    .tag-card {
        border: 1px solid #e0e0e0;
        border-radius: 6px;
        padding: 15px;
        cursor: pointer;
        transition: all 0.3s;
        background-color: #fff;
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-direction: row;
        user-select: none;
    }
    .tag-card.dragging {
        opacity: 0.5;
        transform: scale(1.02);
        z-index: 100;
    }
    .tag-card.drag-over {
        border-color: var(--primary-color);
        border-style: dashed;
        background-color: var(--primary-opacity-10);
    }

    .tag-card:hover {
        border-color: var(--primary-color);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        transform: translateY(-2px);
    }

    .tag-card.active {
        border-color: var(--primary-color);
        background-color: var(--primary-opacity-10);
    }

    .tag-name {
        display: inline-block;
        font-size: 14px;
        font-weight: 500;
    }

    .tag-code {
        display: inline-block;
        font-size: 14px;
        color: #777;
        text-align: right;
        font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
        margin-left: 10px;
        white-space: nowrap;
    }

    .copy-code-btn {
        position: absolute;
        top: 25px;
        right: 20px;
        z-index: 10;
        width: 70px;
        height: 30px;
        line-height: 22px;
    }

    .copy-code-btn.copied {
        background-color: #2196F3;
    }

    #tag-description {
        font-size: 14px;
        overflow-x: auto;
        white-space: nowrap;
        word-break: break-all;
    }

    .generator-tag-container {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    }

    .generator-info-text {
        margin: 0 0 20px 0;
        font-size: 16px;
        font-weight: 500;
        color: #2c3e50;
    }

    .generator-section-title {
        margin: 0 0 12px 0;
        font-size: 15px;
        font-weight: 600;
        color: #4a5568;
        display: flex;
        align-items: center;
    }

    .generator-tags-container {
        display: flex;
        flex-wrap: wrap;
        gap: 10px;
    }

    .generator-param-tag,
    .generator-sub-tag,
    .generator-template-tag {
        position: relative;
        overflow: hidden;
        white-space: nowrap;
        padding: 6px 12px;
        border-radius: 20px;
        font-size: 13px;
        transition: all 0.2s;
    }

    .generator-param-tag {
        color: #4a5568;
        border: 1px solid #e2e8f0;
    }

    .generator-sub-tag,
    .generator-template-tag {
        color: #2b6cb0;
        font-weight: 500;
        border: 1px solid #bee3f8;
        padding: 3px 12px;
    }

    .generator-param-card,
    .generator-card {
        background: #ffffff;
        border: 1px solid #ddd;
        border-radius: 8px;
        padding: 16px;
        margin: 10px 0 20px 0;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    }

    .generator-sub-card {
        background: #ffffff;
        border: 1px solid #ddd;
        border-radius: 8px;
        padding: 16px;
        margin: 10px 0 20px 0;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    }

    @media (max-width: 768px) {
        .modal-tab-btn {
            margin-right: 0;
            width: 50%;
            box-sizing: border-box;
            text-align: center;
            font-size: 13px;
            padding: 8px;
            border: 1px solid #eee;
            margin-bottom: 5px;
        }

        .tab-container {
            border-bottom: none;
            gap: 0px;
        }
    }

    /* 标签卡片悬停显示编辑按钮 */
    .tag-card:hover .edit-tplmark-btn {
        display: flex !important;
    }

    /* 编辑按钮悬停样式 */
    .edit-tplmark-btn:hover {
        transform: scale(1.15) rotate(5deg);
        box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
        filter: brightness(0.9);
    }



    .modal-tab-btn:not(.active):hover {
        background: #e2e8f0;
        color: #334155;
    }

#add-tplmark-single-button {
    background-color: #6b7280 !important;
    border-color: #6b7280 !important;
    color: #fff !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
}

#add-tplmark-single-button:hover {
    background-color: #4b5563 !important;
    border-color: #4b5563 !important;
}

#add-tplmark-loop-button {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

    @media (max-width: 768px) {

        .section-header .btn-danger.section-header-mobile-btn,
        .section-header .btn-primary.section-header-mobile-btn {
            width: 38px !important;
            height: 38px !important;
            min-width: 38px !important;
            padding: 0 !important;
            margin-left: 6px !important;
            line-height: 38px !important;
        }

        .section-header-mobile-btn .section-header-btn-text {
            display: none !important;
        }

        .section-header-mobile-btn .section-header-btn-icon {
            margin-right: 0 !important;
        }

        .generator-tab-btns {
            display: flex !important;
            flex-wrap: wrap !important;
            justify-content: space-between !important;
        }

        .generator-tab-btns .tab-btn {
            width: 48% !important;
            flex: 0 0 48% !important;
            margin-bottom: 8px !important;
            border: 1px solid #e5e7eb !important;
        }

        .generator-tab-btns .tab-btn[data-tab="loop"] {
            width: 100% !important;
            flex: 0 0 100% !important;
        }

        .tab-count {
            display: none !important;
        }
    }
</style>
<style>
    .Template-header-nav {
        display: flex;
        align-items: center;
        align-content: center;
        flex-wrap: wrap;
        gap: 0;
        font-size: 0;
    }

    .Template-tab-link {
        text-decoration: none;
        color: inherit;
        font-size: 18px;
        transition: color .2s ease;
    }

    .Template-tab-link:hover {
        color: var(--primary-color);
    }

    .Template-tab-link-active {
        color: var(--primary-color);
    }

    .Template-tab-link-cloud {
        margin-left: 20px;
        padding-left: 15px;
    }
</style>

<div class="section-header" style="display:flex;align-items:center;justify-content:space-between;gap:12px;">
    <h2 class="Template-header-nav" style="margin:0;">
        <a href="?tab=template" class="Template-tab-link">云端模板</a>
        <a href="?tab=generator" class="Template-tab-link Template-tab-link-cloud Template-tab-link-active">模板开发</a>
    </h2>
    <div style="display: flex; align-items: center; gap: 10px;">
        <button id="add-tplmark-single-button" class="btn btn-primary action-button section-header-mobile-btn" title="新建单值标签" style="margin-right: 0; width: 150px; display: inline-flex; align-items: center; justify-content: center;">
            <svg class="section-header-btn-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" style="margin-right: 6px;">
                <circle cx="12" cy="12" r="10"></circle>
                <line x1="12" y1="8" x2="12" y2="16"></line>
                <line x1="8" y1="12" x2="16" y2="12"></line>
            </svg>
            <span class="section-header-btn-text">新建单值标签</span>
        </button>
        <button id="add-tplmark-loop-button" class="btn btn-primary action-button section-header-mobile-btn" title="新建循环标签" style="width: 150px; display: inline-flex; align-items: center; justify-content: center;">
            <svg class="section-header-btn-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" style="margin-right: 6px;">
                <circle cx="12" cy="12" r="10"></circle>
                <line x1="12" y1="8" x2="12" y2="16"></line>
                <line x1="8" y1="12" x2="16" y2="12"></line>
            </svg>
            <span class="section-header-btn-text">新建循环标签</span>
        </button>
    </div>
</div>

<div class="admin-card">
   
    <div style="font-size: 15px; line-height: 1.8;">
        <p style="margin-bottom: 10px;"><strong>存放规则：</strong>templates/ 为默认模板目录，templates/skin/ 为自定义模板目录，支持子目录分类存放</p>
        <p style="margin-bottom: 10px;"><strong>命名规则：</strong>{ID}_index.html（首页）、{ID}_catgroup.html（顶级栏目页）、{ID}_list.html（列表页）、{ID}_post.html（文章页）、{ID}_goods.html（商品页）、{ID}_template.css（样式）、{ID}_template.js（脚本）</p>
        <p><strong>引入规则：</strong>引入 {ID}_template.css 和 {ID}_template.js，资源文件与模板页面文件同目录，{ID} 为模板唯一数字ID</p>
    </div>
</div>



<div class="admin-card" style="padding-bottom:60px; visibility: hidden;" id="generator-main-card">
    <div class="tab-container" style="justify-content: space-between; align-items: center;" id="generator-tab-container">
        <div class="generator-tab-btns" style="display: flex; gap: 0; flex-wrap: wrap;" id="generator-modal-tab-btns">
            <button class="tab-btn" data-tab="site">网站全局标签<span class="tab-count">（<?php echo $category_counts['site']; ?>个）</span></button>
            <button class="tab-btn" data-tab="article">文章页标签<span class="tab-count">（<?php echo $category_counts['article']; ?>个）</span></button>
            <button class="tab-btn" data-tab="category">列表页标签<span class="tab-count">（<?php echo $category_counts['category']; ?>个）</span></button>
            <button class="tab-btn" data-tab="goods">商品页标签<span class="tab-count">（<?php echo $category_counts['goods']; ?>个）</span></button>
            <button class="tab-btn" data-tab="loop">常用循环标签<span class="tab-count">（<?php echo $category_counts['loop']; ?>个）</span></button>
        </div>
    </div>
    <script type="text/javascript">
        // 立即激活对应的tab和卡片，避免闪烁（参考adcategory.php）
        (function() {
            const activeTab = window.preSelectedTab || 'site';

            // 激活tab按钮
            const tabBtn = document.querySelector('#generator-modal-tab-btns .tab-btn[data-tab="' + activeTab + '"]');
            if (tabBtn) {
                tabBtn.classList.add('active');
            }
        })();
    </script>
    <div class="tag-grid-container">
        <?php foreach ($tags_by_category as $category => $tags): ?>
            <?php foreach ($tags as $tag): ?>
                <?php $is_common = isset($common_codes_lookup[$tag['code']]); ?>
                <div class="tag-card <?php echo $is_common ? 'common' : ''; ?>"
                    data-value="<?php echo htmlspecialchars($tag['code'], ENT_QUOTES, 'UTF-8'); ?>"
                    data-type="<?php echo htmlspecialchars($tag['type'], ENT_QUOTES, 'UTF-8'); ?>"
                    data-category="<?php echo htmlspecialchars($tag['category'], ENT_QUOTES, 'UTF-8'); ?>"
                    data-example="<?php echo htmlspecialchars($tag['example'], ENT_QUOTES, 'UTF-8'); ?>"
                    data-description="<?php echo htmlspecialchars($tag['description'], ENT_QUOTES, 'UTF-8'); ?>"
                    data-description-html="<?php echo htmlspecialchars(process_description_html($tag['description_html'] ?? ''), ENT_QUOTES, 'UTF-8'); ?>"
                    data-id="<?php echo $tag['id']; ?>"
                    data-name-cn="<?php echo htmlspecialchars($tag['name_cn'], ENT_QUOTES, 'UTF-8'); ?>"
                    draggable="true"
                    style="position: relative;">
                    <span class="tag-name"><?php echo htmlspecialchars($tag['name_cn'], ENT_QUOTES, 'UTF-8'); ?></span>
                    <span class="tag-code"><?php echo htmlspecialchars($tag['code'], ENT_QUOTES, 'UTF-8'); ?></span>
                    <button type="button" class="edit-tplmark-btn" style="position: absolute; top: -12px; right: -12px; width: 26px; height: 26px; border-radius: 50%; border: none; background: var(--primary-color); color: #fff; cursor: pointer; display: none; align-items: center; justify-content: center; transition: all 0.3s ease; z-index: 10; box-shadow: 0 4px 12px rgba(0,0,0,0.15);" title="编辑" data-id="<?php echo $tag['id']; ?>" data-name-cn="<?php echo htmlspecialchars($tag['name_cn'], ENT_QUOTES, 'UTF-8'); ?>" data-code="<?php echo htmlspecialchars($tag['code'], ENT_QUOTES, 'UTF-8'); ?>" data-category="<?php echo htmlspecialchars($tag['category'], ENT_QUOTES, 'UTF-8'); ?>" data-type="<?php echo htmlspecialchars($tag['type'], ENT_QUOTES, 'UTF-8'); ?>" data-example="<?php echo htmlspecialchars($tag['example'], ENT_QUOTES, 'UTF-8'); ?>" data-description="<?php echo htmlspecialchars($tag['description'], ENT_QUOTES, 'UTF-8'); ?>" data-description-html="<?php echo htmlspecialchars($tag['description_html'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
                        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
                            <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
                        </svg>
                    </button>
                </div>
            <?php endforeach; ?>
        <?php endforeach; ?>
    </div>
    <script type="text/javascript">
        // 立即隐藏其他分类的卡片，避免闪烁（参考adcategory.php）
        (function() {
            const activeTab = window.preSelectedTab || 'site';
            const tagCards = document.querySelectorAll('.tag-card');
            tagCards.forEach(function(card) {
                if (card.dataset.category === activeTab) {
                    card.style.display = 'flex';
                } else {
                    card.style.display = 'none';
                }
            });
        })();
    </script>
</div>

<script type="text/javascript">
    // 立即激活第一个卡片，初始化生成器，显示所有内容（参考adcategory.php）
    (function() {
        const activeTab = window.preSelectedTab || 'site';
        const firstCard = document.querySelector('.tag-card[data-category="' + activeTab + '"]');
        if (firstCard) {
            firstCard.classList.add('active');
        }

        // 显示标签列表相关内容
        const mainCard = document.getElementById('generator-main-card');
        if (mainCard) {
            mainCard.style.visibility = 'visible';
        }
        const generatorTabContainer = document.getElementById('generator-tab-container');
        if (generatorTabContainer) {
            generatorTabContainer.style.visibility = 'visible';
        }
        const tagGridContainer = document.querySelector('.tag-grid-container');
        if (tagGridContainer) {
            tagGridContainer.style.visibility = 'visible';
        }

        // 初始化生成器
        if (firstCard && firstCard.dataset.value) {
            window.generatorInitialTag = firstCard.dataset.value;
        }
    })();
</script>

<div class="admin-card">
    <h4>模板标签调用例子（前台模板调用）</h4>
    <div style="position: relative;">
        <textarea id="generated-code" class="editable-code">{qkcms:site_title}</textarea>
        <button id="copy-code-btn" class="btn btn-secondary btn-sm copy-code-btn" style="position: absolute; top: 25px; right: 20px; z-index: 10;">复制代码</button>
    </div>
    <div id="tag-description" style="font-size: 14px;">
        <p>代码说明：</p>
    </div>
</div>

<!-- 新增/编辑标签模态框 -->
<div id="tplmark-modal" class="modal">
    <div class="modal-backdrop"></div>
    <div class="modal-content">
        <div class="modal-header">
            <h3 id="tplmark-modal-title" class="modal-title">新建标签</h3>
            <button id="tplmark-modal-close" class="modal-close"></button>
        </div>
        <div class="modal-body">
            <form id="tplmark-form">
                <input type="hidden" id="tplmark-id" value="">

                <div id="tplmark-tab-basic" class="tab-content">
                    <div class="form-group flex-shrink">
                        <div class="modal-tab-content-wrapper">
                            <div class="modal-tab-content-half">
                                <label class="modal-tab-label">中文名称</label>
                                <input type="text" id="tplmark-name-cn" class="form-control" placeholder="请输入中文名称" required>
                            </div>
                            <div class="modal-tab-content-half">
                                <label class="modal-tab-label">标签代码</label>
                                <div id="tplmark-code-wrapper">
                                    <input type="text" id="tplmark-code" class="form-control" placeholder="请输入标签代码" required>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="form-group flex-shrink">
                        <div class="modal-tab-content-wrapper">
                            <div class="modal-tab-content-half">
                                <label class="modal-tab-label">分类</label>
                                <select id="tplmark-category" class="form-control">
                                    <option value="site">网站全局标签</option>
                                    <option value="article">文章页标签</option>
                                    <option value="category">列表页标签</option>
                                    <option value="goods">商品页标签</option>
                                    <option value="loop">循环标签</option>
                                </select>
                            </div>
                            <div class="modal-tab-content-half">
                                <label class="modal-tab-label">类型</label>
                                <div id="tplmark-type-wrapper">
                                    <select id="tplmark-type" class="form-control">
                                        <option value="single">单值标签</option>
                                        <option value="loop">循环标签</option>
                                    </select>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="form-group" id="tplmark-description-loop-basic-group" style="display: none;">
                        <label class="modal-tab-label">循环标签说明</label>
                        <textarea id="tplmark-description-loop-basic" class="form-control" placeholder="请输入循环标签说明"></textarea>
                    </div>
                    <div class="form-group flex-shrink" id="tplmark-description-single-basic-group">
                        <label class="modal-tab-label">标签说明</label>
                        <input type="text" id="tplmark-description-single-basic" class="form-control" placeholder="请输入标签说明">
                    </div>
                    <div class="form-group flex-shrink" id="tplmark-example-single-group">
                        <label class="modal-tab-label">调用例子</label>
                        <input type="text" id="tplmark-example-single" class="form-control" placeholder="请输入调用例子">
                    </div>
                </div>

                <div id="tplmark-tab-example" class="tab-content" style="display: none;">
                    <div class="form-group">
                        <label class="modal-tab-label">调用例子</label>
                        <textarea id="tplmark-example" class="form-control" placeholder="请输入调用例子"></textarea>
                    </div>
                </div>

                <div id="tplmark-tab-description" class="tab-content" style="display: none;">
                    <div class="form-group">
                        <label class="modal-tab-label">HTML结构标签说明</label>
                        <textarea id="tplmark-description-html" class="form-control" placeholder="请输入HTML结构标签说明"></textarea>
                    </div>
                </div>

                <div class="modal-footer">
                    <div id="tplmark-modal-tab-container" class="modal-tab-container">
                        <button type="button" class="modal-tab-btn active" data-tab="basic">基础设置</button>
                        <button type="button" class="modal-tab-btn" data-tab="example">例子</button>
                        <button type="button" class="modal-tab-btn" data-tab="description">说明文档</button>
                    </div>
                    <button type="button" id="tplmark-cancel" class="btn btn-secondary">取消</button>
                    <button type="button" id="tplmark-delete" class="btn btn-danger" style="display: none;">删除</button>
                    <button type="submit" id="tplmark-submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>

<script type="text/javascript">
    document.addEventListener('DOMContentLoaded', function() {
        let tagCards = document.querySelectorAll('.tag-card');
        const tabBtns = document.querySelectorAll('#generator-modal-tab-btns .tab-btn');
        const copyCodeBtn = document.getElementById('copy-code-btn');
        const generatedCode = document.getElementById('generated-code');
        const tagDescription = document.getElementById('tag-description');

        // 新增标签按钮
        const addTplmarkSingleBtn = document.getElementById('add-tplmark-single-button');
        const addTplmarkLoopBtn = document.getElementById('add-tplmark-loop-button');
        // 模态框元素
        const tplmarkModal = document.getElementById('tplmark-modal');
        const tplmarkModalTitle = document.getElementById('tplmark-modal-title');
        const tplmarkModalClose = document.getElementById('tplmark-modal-close');
        const tplmarkForm = document.getElementById('tplmark-form');
        const tplmarkId = document.getElementById('tplmark-id');
        const tplmarkNameCn = document.getElementById('tplmark-name-cn');
        const tplmarkCode = document.getElementById('tplmark-code');
        const tplmarkCategory = document.getElementById('tplmark-category');
        const tplmarkType = document.getElementById('tplmark-type');
        const tplmarkExample = document.getElementById('tplmark-example');
        const tplmarkExampleSingle = document.getElementById('tplmark-example-single');
        const tplmarkDescriptionSingleBasic = document.getElementById('tplmark-description-single-basic');
        const tplmarkDescriptionLoopBasic = document.getElementById('tplmark-description-loop-basic');
        const tplmarkDescriptionHtml = document.getElementById('tplmark-description-html');
        const tplmarkCancel = document.getElementById('tplmark-cancel');
        const tplmarkSubmit = document.getElementById('tplmark-submit');
        const tplmarkDelete = document.getElementById('tplmark-delete');

        // 根据标签类型更新输入框显示
        function updateInputDisplayByType(type, isEdit = false) {
            const descLoopBasicGroup = document.getElementById('tplmark-description-loop-basic-group');
            const descSingleBasicGroup = document.getElementById('tplmark-description-single-basic-group');
            const modalTabContainer = document.getElementById('tplmark-modal-tab-container');
            const exampleSingleGroup = document.getElementById('tplmark-example-single-group');

            if (type === 'single') {
                // 单值标签：隐藏调用例子和循环标签说明，禁用类型选择
                if (descLoopBasicGroup) descLoopBasicGroup.style.display = 'none';
                if (descSingleBasicGroup) descSingleBasicGroup.style.display = 'block';
                if (exampleSingleGroup) exampleSingleGroup.style.display = 'block';
                if (modalTabContainer) {
                    modalTabContainer.style.display = 'none';
                }
                const basicTab = document.getElementById('tplmark-tab-basic');
                if (basicTab) {
                    basicTab.style.display = 'flex';
                    basicTab.style.flexDirection = 'column';
                    basicTab.style.flex = '1';
                }
                document.getElementById('tplmark-tab-example').style.display = 'none';
                document.getElementById('tplmark-tab-description').style.display = 'none';
                // 只禁用类型选择，标签说明和调用例子可以编辑
                tplmarkType.disabled = true;
            } else {
                // 循环标签：显示3个选项卡，启用类型选择
                if (descLoopBasicGroup) descLoopBasicGroup.style.display = 'block';
                if (descSingleBasicGroup) descSingleBasicGroup.style.display = 'none';
                if (exampleSingleGroup) exampleSingleGroup.style.display = 'none';
                if (modalTabContainer) {
                    modalTabContainer.style.display = 'flex';
                }
                // 禁用类型选择
                tplmarkType.disabled = true;
            }
        }

        // 用pointer-events: auto的覆盖层！
        if (tplmarkCode) {
            const codeWrapper = document.getElementById('tplmark-code-wrapper');
            if (codeWrapper) {
                const overlay = document.createElement('div');
                overlay.style.cssText = 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; cursor: not-allowed; z-index: 5;';
                overlay.title = '标签代码无法修改';
                codeWrapper.appendChild(overlay);
                overlay.addEventListener('click', function() {
                    if (typeof window.showToast === 'function') {
                        window.showToast('标签代码无法修改', 'warning', 1500);
                    } else {
                        alert('标签代码无法修改');
                    }
                });
            }
        }

        if (tplmarkType) {
            const typeWrapper = document.getElementById('tplmark-type-wrapper');
            if (typeWrapper) {
                const overlay2 = document.createElement('div');
                overlay2.style.cssText = 'position: absolute; top: 0; left: 0; width: 100%; height: 100%; cursor: not-allowed; z-index: 5;';
                overlay2.title = '标签类型无法修改';
                typeWrapper.appendChild(overlay2);
                overlay2.addEventListener('click', function() {
                    if (typeof window.showToast === 'function') {
                        window.showToast('标签类型无法修改', 'warning', 1500);
                    } else {
                        alert('标签类型无法修改');
                    }
                });
            }
        }

        // 显示/隐藏覆盖层
        function updateOverlays() {
            const codeWrapper = document.getElementById('tplmark-code-wrapper');
            const typeWrapper = document.getElementById('tplmark-type-wrapper');
            if (codeWrapper && codeWrapper.querySelector('div')) {
                codeWrapper.querySelector('div').style.display = tplmarkCode.disabled ? 'block' : 'none';
            }
            if (typeWrapper && typeWrapper.querySelector('div')) {
                typeWrapper.querySelector('div').style.display = tplmarkType.disabled ? 'block' : 'none';
            }
        }

        // 重写updateInputDisplayByType，加上updateOverlays
        const originalUpdateInputDisplayByType = updateInputDisplayByType;
        updateInputDisplayByType = function(type, isEdit) {
            originalUpdateInputDisplayByType(type, isEdit);
            updateOverlays();
        }

        // 重写showAddTplmarkModal
        const originalShowAddTplmarkModal = showAddTplmarkModal;
        showAddTplmarkModal = function(type) {
            originalShowAddTplmarkModal(type);
            updateOverlays();
        }

        // 重写showEditTplmarkModal
        const originalShowEditTplmarkModal = showEditTplmarkModal;
        showEditTplmarkModal = function(id, nameCn, code, category, type, example, description, descriptionHtml) {
            originalShowEditTplmarkModal(id, nameCn, code, category, type, example, description, descriptionHtml);
            updateOverlays();
        }

        // 单值标签自动同步功能
        function initSingleTagAutoSync() {
            if (tplmarkNameCn) {
                tplmarkNameCn.addEventListener('input', function() {
                    if (tplmarkType.value === 'single' && tplmarkDescriptionSingleBasic) {
                        const name = this.value || '';
                        tplmarkDescriptionSingleBasic.value = '《' + name + '》标签说明：单值标签，用于输出' + name + '内容';
                    }
                });
            }

            if (tplmarkCode) {
                tplmarkCode.addEventListener('input', function() {
                    if (tplmarkType.value === 'single' && tplmarkExampleSingle) {
                        const code = this.value || '';
                        tplmarkExampleSingle.value = '{qkcms:' + code + '}';
                    }
                });
            }
        }
        initSingleTagAutoSync();

        // 选项卡切换
        const tabButtons = document.querySelectorAll('#tplmark-modal .modal-tab-btn');
        tabButtons.forEach(btn => {
            btn.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                const tabId = this.getAttribute('data-tab');

                // 更新按钮样式 - 添加颜色
                tabButtons.forEach(b => {
                    b.classList.remove('active');
                });
                this.classList.add('active');

                // 显示对应的内容
                document.querySelectorAll('#tplmark-modal .tab-content').forEach(content => {
                    content.style.display = 'none';
                });
                const activeTab = document.getElementById('tplmark-tab-' + tabId);
                if (activeTab) {
                    activeTab.style.display = 'flex';
                    activeTab.style.flexDirection = 'column';
                    activeTab.style.flex = '1';
                }
            });
        });

        // 标签类型改变时动态显示/隐藏选项卡
        if (tplmarkType) {
            tplmarkType.addEventListener('change', function() {
                const isEdit = tplmarkId.value !== '';
                updateInputDisplayByType(this.value, isEdit);
                // 单值标签时只显示基础设置
                if (this.value !== 'loop') {
                    tabButtons.forEach(b => {
                        b.classList.remove('active');
                    });
                    const firstTabBtn = document.querySelector('#tplmark-modal .modal-tab-btn[data-tab="basic"]');
                    if (firstTabBtn) {
                        firstTabBtn.classList.add('active');
                    }
                    const basicTab = document.getElementById('tplmark-tab-basic');
                    if (basicTab) {
                        basicTab.style.display = 'flex';
                        basicTab.style.flexDirection = 'column';
                        basicTab.style.flex = '1';
                    }
                    document.getElementById('tplmark-tab-example').style.display = 'none';
                    document.getElementById('tplmark-tab-description').style.display = 'none';
                }
            });
        }

        // 显示新增标签模态框
        function showAddTplmarkModal(type = 'single') {
            tplmarkModalTitle.textContent = type === 'single' ? '新增单值标签' : '新增循环标签';
            tplmarkId.value = '';
            tplmarkNameCn.value = '';
            tplmarkCode.value = '';
            tplmarkCategory.value = type === 'loop' ? 'loop' : 'site';
            tplmarkType.value = type;
            tplmarkExample.value = '';
            tplmarkExampleSingle.value = '';
            tplmarkDescriptionSingleBasic.value = '';
            tplmarkDescriptionLoopBasic.value = '';
            tplmarkDescriptionHtml.value = '';

            // 新增模式：启用标签代码，隐藏删除按钮
            tplmarkCode.disabled = false;
            if (tplmarkDelete) tplmarkDelete.style.display = 'none';

            // 默认显示基础设置
            const modalTabBtns = document.querySelectorAll('#tplmark-modal .modal-tab-btn');
            modalTabBtns.forEach(b => {
                b.classList.remove('active');
            });
            const firstBasicBtn = document.querySelector('#tplmark-modal .modal-tab-btn[data-tab="basic"]');
            if (firstBasicBtn) {
                firstBasicBtn.classList.add('active');
            }
            const basicTab = document.getElementById('tplmark-tab-basic');
            if (basicTab) {
                basicTab.style.display = 'flex';
                basicTab.style.flexDirection = 'column';
                basicTab.style.flex = '1';
            }
            if (type === 'loop') {
                document.getElementById('tplmark-tab-example').style.display = 'none';
                document.getElementById('tplmark-tab-description').style.display = 'none';
                tplmarkModal.querySelector('.modal-content').style.height = '600px';
            } else {
                document.getElementById('tplmark-tab-example').style.display = 'none';
                document.getElementById('tplmark-tab-description').style.display = 'none';
                tplmarkModal.querySelector('.modal-content').style.height = '540px';
            }
            updateInputDisplayByType(type, false);

            if (tplmarkModal) {
                tplmarkModal.style.display = 'flex';
                requestAnimationFrame(() => tplmarkModal.classList.add('modal-visible'));
            }
        }

        // 显示编辑标签模态框
        function showEditTplmarkModal(id, nameCn, code, category, type, example, description, descriptionHtml) {
            tplmarkModalTitle.textContent = nameCn + ' 编辑';
            tplmarkId.value = id;
            tplmarkNameCn.value = nameCn;
            tplmarkCode.value = code;
            tplmarkCategory.value = category;
            tplmarkType.value = type;
            tplmarkExample.value = example;
            tplmarkExampleSingle.value = example;
            if (type === 'single') {
                tplmarkDescriptionSingleBasic.value = '《' + nameCn + '》标签说明：单值标签，用于输出' + nameCn + '内容';
            } else {
                tplmarkDescriptionSingleBasic.value = description;
            }
            tplmarkDescriptionLoopBasic.value = description;
            tplmarkDescriptionHtml.value = descriptionHtml;

            // 编辑模式：禁用标签代码，防止误修改，显示删除按钮
            tplmarkCode.disabled = true;
            if (tplmarkDelete) tplmarkDelete.style.display = 'block';

            // 默认显示基础设置
            const modalTabBtns = document.querySelectorAll('#tplmark-modal .modal-tab-btn');
            modalTabBtns.forEach(b => {
                b.classList.remove('active');
            });
            const firstBasicBtn = document.querySelector('#tplmark-modal .modal-tab-btn[data-tab="basic"]');
            if (firstBasicBtn) {
                firstBasicBtn.classList.add('active');
            }
            const basicTab = document.getElementById('tplmark-tab-basic');
            if (basicTab) {
                basicTab.style.display = 'flex';
                basicTab.style.flexDirection = 'column';
                basicTab.style.flex = '1';
            }
            document.getElementById('tplmark-tab-example').style.display = 'none';
            document.getElementById('tplmark-tab-description').style.display = 'none';

            // 根据标签类型更新输入框显示
            updateInputDisplayByType(type, true);

            if (tplmarkModal) {
                tplmarkModal.style.display = 'flex';
                requestAnimationFrame(() => tplmarkModal.classList.add('modal-visible'));
            }
        }

        // 关闭模态框
        function closeTplmarkModal() {
            if (tplmarkModal) {
                tplmarkModal.classList.remove('modal-visible');
                setTimeout(() => {
                    tplmarkModal.style.display = 'none';
                }, 300);
            }
        }

        // 新增标签按钮点击事件
        if (addTplmarkSingleBtn) {
            addTplmarkSingleBtn.addEventListener('click', function(e) {
                e.preventDefault();
                showAddTplmarkModal('single');
            });
        }
        if (addTplmarkLoopBtn) {
            addTplmarkLoopBtn.addEventListener('click', function(e) {
                e.preventDefault();
                showAddTplmarkModal('loop');
            });
        }

        // 编辑标签按钮点击事件（事件委托）
        document.addEventListener('click', function(e) {
            const editBtn = e.target.closest('.edit-tplmark-btn');
            if (editBtn) {
                e.preventDefault();
                e.stopPropagation();
                const id = editBtn.getAttribute('data-id');
                const nameCn = editBtn.getAttribute('data-name-cn');
                const code = editBtn.getAttribute('data-code');
                const category = editBtn.getAttribute('data-category');
                const type = editBtn.getAttribute('data-type');
                const example = editBtn.getAttribute('data-example');
                const description = editBtn.getAttribute('data-description');
                const descriptionHtml = editBtn.getAttribute('data-description-html');
                showEditTplmarkModal(id, nameCn, code, category, type, example, description, descriptionHtml);
            }
        });

        // 删除按钮点击事件
        if (tplmarkDelete) {
            tplmarkDelete.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();

                if (!tplmarkId.value || isNaN(parseInt(tplmarkId.value))) {
                    return;
                }

                const tempDeleteId = tplmarkId.value;

                closeTplmarkModal();

                const formData = new FormData();
                formData.append('action', 'delete_tplmark');
                formData.append('id', tempDeleteId);

                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/admin/ajaxx.php', true);

                xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4) {
                        if (xhr.status === 200) {
                            try {
                                const data = JSON.parse(xhr.responseText);

                                if (data && data.success) {
                                    if (typeof showToast === 'function') showToast(data.message || '删除成功', 'success');
                                    else alert(data.message || '删除成功');

                                    const card = document.querySelector('.tag-card[data-id="' + tempDeleteId + '"]');
                                    if (card) {
                                        card.remove();
                                    }

                                    tagCards = document.querySelectorAll('.tag-card');
                                } else {
                                    const errorMessage = data && data.message ? data.message : '删除失败';
                                    if (typeof showToast === 'function') showToast(errorMessage, 'error');
                                    else alert(errorMessage);
                                }
                            } catch (e) {
                                console.error('删除失败:', e, xhr.responseText);
                            }
                        }
                    }
                };

                xhr.send(formData);
            });
        }

        // 关闭按钮点击事件
        if (tplmarkModalClose) {
            tplmarkModalClose.addEventListener('click', closeTplmarkModal);
        }

        // 取消按钮点击事件
        if (tplmarkCancel) {
            tplmarkCancel.addEventListener('click', closeTplmarkModal);
        }

        // 点击遮罩层关闭模态框
        if (tplmarkModal) {
            tplmarkModal.addEventListener('click', function(e) {
                if (e.target.classList.contains('modal-backdrop')) {
                    closeTplmarkModal();
                }
            });
        }

        // ESC键关闭模态框
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape' && tplmarkModal && tplmarkModal.classList.contains('modal-visible')) {
                closeTplmarkModal();
            }
        });

        // 表单提交事件
        if (tplmarkForm) {
            tplmarkForm.addEventListener('submit', function(e) {
                e.preventDefault();

                const formData = new FormData();
                if (tplmarkId.value) {
                    formData.append('action', 'edit_tplmark');
                    formData.append('id', tplmarkId.value);
                } else {
                    formData.append('action', 'add_tplmark');
                }
                formData.append('name_cn', tplmarkNameCn.value);
                formData.append('code', tplmarkCode.value);
                formData.append('category', tplmarkCategory.value);
                formData.append('type', tplmarkType.value);

                if (tplmarkType.value === 'single') {
                    formData.append('example', tplmarkExampleSingle.value);
                    formData.append('description', tplmarkDescriptionSingleBasic.value);
                } else {
                    formData.append('example', tplmarkExample.value);
                    formData.append('description', tplmarkDescriptionLoopBasic.value);
                }
                formData.append('description_html', tplmarkDescriptionHtml.value);

                tplmarkSubmit.disabled = true;
                tplmarkSubmit.textContent = '保存中...';

                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/admin/ajaxx.php', true);

                xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4) {
                        tplmarkSubmit.disabled = false;
                        tplmarkSubmit.textContent = '保存';

                        if (xhr.status === 200) {
                            try {
                                const data = JSON.parse(xhr.responseText);

                                if (data && data.success) {
                                    const formId = tplmarkId.value;
                                    const formCategory = tplmarkCategory.value;
                                    const formType = tplmarkType.value;
                                    const formCode = tplmarkCode.value;
                                    const formNameCn = tplmarkNameCn.value;
                                    let formExample = '';
                                    let formDescription = '';

                                    if (formType === 'single') {
                                        formExample = tplmarkExampleSingle.value;
                                        formDescription = tplmarkDescriptionSingleBasic.value;
                                    } else {
                                        formExample = tplmarkExample.value;
                                        formDescription = tplmarkDescriptionLoopBasic.value;
                                    }
                                    const formDescriptionHtml = tplmarkDescriptionHtml.value;
                                    const processedDescriptionHtml = (formId && data && data.processed_description_html) ? data.processed_description_html : formDescriptionHtml;

                                    closeTplmarkModal();

                                    if (typeof showToast === 'function') showToast(data.message || '保存成功', 'success');
                                    else alert(data.message || '保存成功');

                                    if (formId) {
                                        const existingCard = document.querySelector('.tag-card[data-id="' + formId + '"]');
                                        if (existingCard) {
                                            existingCard.querySelector('.tag-name').textContent = formNameCn;
                                            existingCard.querySelector('.tag-code').textContent = formCode;

                                            existingCard.dataset.value = formCode;
                                            existingCard.dataset.type = formType;
                                            existingCard.dataset.category = formCategory;
                                            existingCard.dataset.example = formExample;
                                            existingCard.dataset.description = formDescription;
                                            existingCard.dataset.descriptionHtml = processedDescriptionHtml;
                                            existingCard.dataset.nameCn = formNameCn;

                                            const editBtn = existingCard.querySelector('.edit-tplmark-btn');
                                            if (editBtn) {
                                                editBtn.setAttribute('data-name-cn', formNameCn);
                                                editBtn.setAttribute('data-code', formCode);
                                                editBtn.setAttribute('data-category', formCategory);
                                                editBtn.setAttribute('data-type', formType);
                                                editBtn.setAttribute('data-example', formExample);
                                                editBtn.setAttribute('data-description', formDescription);
                                                editBtn.setAttribute('data-description-html', formDescriptionHtml);
                                            }

                                            if (existingCard.classList.contains('active')) {
                                                updateGeneratorByTag(formCode);
                                            }
                                        }
                                    } else {
                                        const newId = data.data && data.data.id ? data.data.id : Date.now();
                                        const newCard = document.createElement('div');
                                        newCard.className = 'tag-card';
                                        newCard.dataset.value = formCode;
                                        newCard.dataset.type = formType;
                                        newCard.dataset.category = formCategory;
                                        newCard.dataset.example = formExample;
                                        newCard.dataset.description = formDescription;
                                        newCard.dataset.descriptionHtml = processedDescriptionHtml;
                                        newCard.dataset.id = newId;
                                        newCard.dataset.nameCn = formNameCn;
                                        newCard.draggable = true;
                                        newCard.style.position = 'relative';
                                        newCard.style.display = 'flex';

                                        newCard.innerHTML =
                                            '<span class="tag-name">' + escapeHtml(formNameCn) + '</span>' +
                                            '<span class="tag-code">' + escapeHtml(formCode) + '</span>' +
                                            '<button type="button" class="edit-tplmark-btn" ' +
                                            'style="position: absolute; top: -12px; right: -12px; width: 26px; height: 26px; border-radius: 50%; border: none; background: var(--primary-color); color: #fff; cursor: pointer; display: none; align-items: center; justify-content: center; transition: all 0.3s ease; z-index: 10; box-shadow: 0 4px 12px rgba(0,0,0,0.15);" ' +
                                            'title="编辑" ' +
                                            'data-id="' + newId + '" ' +
                                            'data-name-cn="' + escapeHtml(formNameCn) + '" ' +
                                            'data-code="' + escapeHtml(formCode) + '" ' +
                                            'data-category="' + escapeHtml(formCategory) + '" ' +
                                            'data-type="' + escapeHtml(formType) + '" ' +
                                            'data-example="' + escapeHtml(formExample) + '" ' +
                                            'data-description="' + escapeHtml(formDescription) + '" ' +
                                            'data-description-html="' + escapeHtml(formDescriptionHtml) + '">' +
                                            '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
                                            '<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>' +
                                            '<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>' +
                                            '</svg></button>';

                                        const gridContainer = document.querySelector('.tag-grid-container');
                                        if (gridContainer) {
                                            const firstCard = gridContainer.querySelector('.tag-card[data-category="' + formCategory + '"]');
                                            if (firstCard) {
                                                gridContainer.insertBefore(newCard, firstCard);
                                            } else {
                                                gridContainer.appendChild(newCard);
                                            }
                                        }

                                        newCard.addEventListener('click', function() {
                                            const value = this.dataset.value;
                                            if (value) {
                                                updateGeneratorByTag(value);
                                            }
                                        });

                                        const editBtn = newCard.querySelector('.edit-tplmark-btn');
                                        if (editBtn) {
                                            editBtn.addEventListener('click', function(e) {
                                                e.preventDefault();
                                                e.stopPropagation();
                                                const id = this.getAttribute('data-id');
                                                const nameCn = this.getAttribute('data-name-cn');
                                                const code = this.getAttribute('data-code');
                                                const category = this.getAttribute('data-category');
                                                const type = this.getAttribute('data-type');
                                                const example = this.getAttribute('data-example');
                                                const description = this.getAttribute('data-description');
                                                const descriptionHtml = this.getAttribute('data-description-html');
                                                showEditTplmarkModal(id, nameCn, code, category, type, example, description, descriptionHtml);
                                            });
                                        }

                                        newCard.addEventListener('mouseenter', function() {
                                            const btn = this.querySelector('.edit-tplmark-btn');
                                            if (btn) btn.style.display = 'flex';
                                        });
                                        newCard.addEventListener('mouseleave', function() {
                                            const btn = this.querySelector('.edit-tplmark-btn');
                                            if (btn) btn.style.display = 'none';
                                        });

                                        tagCards = document.querySelectorAll('.tag-card');
                                    }
                                } else {
                                    closeTplmarkModal();
                                    const errorMessage = data && data.message ? data.message : '保存失败';
                                    if (typeof showToast === 'function') showToast(errorMessage, 'error');
                                    else alert(errorMessage);
                                }
                            } catch (e) {
                                console.error('解析响应失败:', e, xhr.responseText);
                            }
                        }
                    }
                };

                xhr.send(formData);
            });
        }

        function adjustTextareaHeight(textarea) {
            const currentHeight = textarea.offsetHeight;
            textarea.style.height = 'auto';
            const minHeight = parseInt(window.getComputedStyle(textarea).lineHeight) * 3;
            const contentHeight = textarea.scrollHeight;
            const newHeight = Math.max(minHeight, contentHeight) + 'px';

            if (currentHeight !== parseInt(newHeight)) {
                textarea.style.height = newHeight;
            }
        }

        function filterTagsByTab(tab) {
            const noResults = document.querySelector('.no-search-results');
            if (noResults) {
                noResults.style.display = 'none';
            }

            tagCards.forEach(card => {
                card.style.display = card.dataset.category === tab ? 'flex' : 'none';
            });

            const visibleTags = Array.from(tagCards).filter(card => card.style.display !== 'none');
            if (visibleTags.length === 0 && noResults) {
                noResults.style.display = 'block';
            }
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        function updateGeneratorByTag(tagName) {
            const tagCard = document.querySelector(`.tag-card[data-value="${CSS.escape(tagName)}"]`);
            if (!tagCard) return;

            const tagNameCN = tagCard.querySelector('.tag-name').textContent;
            const tagType = tagCard.dataset.type;
            const example = tagCard.dataset.example;
            const descriptionHtml = tagCard.dataset.descriptionHtml;

            let code = '';
            let desc = '';

            if (descriptionHtml) {
                desc = descriptionHtml.replace(/\$\{tagNameCN\}/g, escapeHtml(tagNameCN));
            } else {
                const escapedName = escapeHtml(tagNameCN);
                if (tagType === 'loop') {
                    desc = `<p>《${escapedName}》循环标签，用于输出${escapedName}列表</p>`;
                } else {
                    desc = `<p>《${escapedName}》标签说明：单值标签，用于输出${escapedName}内容</p>`;
                }
            }

            if (tagType === 'loop') {
                code = example;
            } else {
                code = `{qkcms:${escapeHtml(tagName)}}`;
            }

            generatedCode.value = code;
            adjustTextareaHeight(generatedCode);
            tagDescription.innerHTML = desc;
        }

        function copyToClipboard(text) {
            try {
                if (navigator.clipboard && window.isSecureContext) {
                    return navigator.clipboard.writeText(text);
                } else {
                    const textArea = document.createElement('textarea');
                    textArea.value = text;
                    textArea.style.position = 'absolute';
                    textArea.style.left = '-999999px';
                    document.body.appendChild(textArea);
                    textArea.select();
                    document.execCommand('copy');
                    document.body.removeChild(textArea);
                    return Promise.resolve();
                }
            } catch (err) {
                console.error('复制失败:', err);
                return Promise.reject(err);
            }
        }

        tagCards.forEach(card => {
            card.addEventListener('click', function() {
                tagCards.forEach(c => c.classList.remove('active'));
                this.classList.add('active');
                updateGeneratorByTag(this.dataset.value);
                copyToClipboard(generatedCode.value).then(() => {
                    if (typeof showToast === 'function') showToast('复制成功', 'info');
                }).catch(err => console.error('复制失败:', err));
            });
        });

        tabBtns.forEach(btn => {
            btn.addEventListener('click', function() {
                tabBtns.forEach(b => b.classList.remove('active'));
                this.classList.add('active');

                const tab = this.dataset.tab;

                // 保存到本地存储
                localStorage.setItem('generator_active_tab', tab);

                if (window.history && window.history.replaceState) {
                    const url = new URL(window.location);
                    url.searchParams.delete('search');
                    window.history.replaceState({}, document.title, url);
                }

                filterTagsByTab(tab);

                const firstTagInTab = document.querySelector(`.tag-card[data-category="${CSS.escape(tab)}"]`);
                if (firstTagInTab) {
                    tagCards.forEach(card => card.classList.remove('active'));
                    firstTagInTab.classList.add('active');
                    updateGeneratorByTag(firstTagInTab.dataset.value);
                }
            });
        });

        copyCodeBtn.addEventListener('click', function() {
            copyToClipboard(generatedCode.value).then(() => {
                this.textContent = '已复制!';
                setTimeout(() => this.textContent = '复制代码', 2000);
                if (typeof showToast === 'function') showToast('代码复制成功', 'info');
            }).catch(() => {
                this.textContent = '已复制!';
                setTimeout(() => this.textContent = '复制代码', 2000);
                if (typeof showToast === 'function') showToast('代码复制成功', 'info');
            });
        });

        adjustTextareaHeight(generatedCode);
        generatedCode.addEventListener('input', function() {
            adjustTextareaHeight(this);
        });

        window.updateGeneratorByTag = updateGeneratorByTag;

        if (tabBtns.length > 0) {
            const urlParams = new URLSearchParams(window.location.search);
            const searchParam = urlParams.get('search') || '';

            if (searchParam) {
                filterTagsBySearch(searchParam.toLowerCase().trim());
                tabBtns.forEach(btn => btn.classList.remove('active'));
            } else {
                // 已经在HTML内联script中激活了tab和卡片，只需要初始化生成器
                if (window.generatorInitialTag) {
                    updateGeneratorByTag(window.generatorInitialTag);
                }
            }
        }

        function filterTagsBySearch(searchTerm) {
            const noResults = document.querySelector('.no-search-results');
            if (noResults) {
                noResults.style.display = 'none';
            }

            let foundCount = 0;
            tagCards.forEach(card => {
                const name = card.querySelector('.tag-name').textContent.toLowerCase();
                const code = card.querySelector('.tag-code').textContent.toLowerCase();
                const isMatch = name.includes(searchTerm) || code.includes(searchTerm);
                card.style.display = isMatch ? 'flex' : 'none';
                if (isMatch) foundCount++;
            });

            if (foundCount === 0 && noResults) {
                noResults.style.display = 'block';
            }

            if (foundCount > 0) {
                const firstMatch = Array.from(tagCards).find(card => card.style.display !== 'none');
                if (firstMatch) {
                    tagCards.forEach(card => card.classList.remove('active'));
                    firstMatch.classList.add('active');
                    updateGeneratorByTag(firstMatch.dataset.value);
                }
            }
        }
    });

    let draggedCard = null;
    const gridContainer = document.querySelector('.tag-grid-container');

    if (gridContainer) {
        gridContainer.addEventListener('dragstart', function(e) {
            const card = e.target.closest('.tag-card');
            if (card) {
                draggedCard = card;
                card.classList.add('dragging');
                e.dataTransfer.effectAllowed = 'move';
                e.dataTransfer.setData('text/plain', card.dataset.id);
            }
        });

        gridContainer.addEventListener('dragend', function(e) {
            const card = e.target.closest('.tag-card');
            if (card) {
                card.classList.remove('dragging');
                document.querySelectorAll('.tag-card').forEach(c => c.classList.remove('drag-over'));
                draggedCard = null;
            }
        });

        gridContainer.addEventListener('dragover', function(e) {
            e.preventDefault();
            e.dataTransfer.dropEffect = 'move';
        });

        gridContainer.addEventListener('dragenter', function(e) {
            const card = e.target.closest('.tag-card');
            if (card && card !== draggedCard && draggedCard) {
                const draggedCategory = draggedCard.dataset.category;
                const targetCategory = card.dataset.category;
                if (draggedCategory === targetCategory) {
                    card.classList.add('drag-over');
                }
            }
        });

        gridContainer.addEventListener('dragleave', function(e) {
            const card = e.target.closest('.tag-card');
            if (card) {
                card.classList.remove('drag-over');
            }
        });

        gridContainer.addEventListener('drop', function(e) {
            e.preventDefault();
            const targetCard = e.target.closest('.tag-card');
            if (targetCard && draggedCard && targetCard !== draggedCard) {
                const draggedCategory = draggedCard.dataset.category;
                const targetCategory = targetCard.dataset.category;
                if (draggedCategory === targetCategory) {
                    const activeTab = document.querySelector('#generator-modal-tab-btns .tab-btn.active');
                    if (activeTab && activeTab.dataset.tab === draggedCategory) {
                        const containerRect = gridContainer.getBoundingClientRect();
                        const targetRect = targetCard.getBoundingClientRect();
                        const midY = targetRect.top - containerRect.top + targetRect.height / 2;
                        const dragRect = draggedCard.getBoundingClientRect();
                        const dragY = dragRect.top - containerRect.top + dragRect.height / 2;

                        if (dragY < midY) {
                            targetCard.parentNode.insertBefore(draggedCard, targetCard);
                        } else {
                            targetCard.parentNode.insertBefore(draggedCard, targetCard.nextSibling);
                        }

                        saveTagOrder(draggedCategory);
                    }
                }
            }
            document.querySelectorAll('.tag-card').forEach(c => c.classList.remove('drag-over'));
        });
    }

    function saveTagOrder(category) {
        const cards = document.querySelectorAll('.tag-card[data-category="' + category + '"]');
        const ids = [];
        cards.forEach(card => {
            if (card.style.display !== 'none') {
                ids.push(parseInt(card.dataset.id));
            }
        });

        if (ids.length === 0) return;

        const formData = new FormData();
        formData.append('action', 'update_tplmark_order');
        formData.append('category', category);
        formData.append('ids', JSON.stringify(ids));

        const xhr = new XMLHttpRequest();
        xhr.open('POST', '/admin/ajaxx.php', true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    try {
                        const data = JSON.parse(xhr.responseText);
                        if (data && data.success) {
                            if (typeof showToast === 'function') showToast('排序保存成功', 'success');
                        } else {
                            if (typeof showToast === 'function') showToast(data.message || '排序保存失败', 'error');
                        }
                    } catch (e) {
                        console.error('排序保存失败:', e, xhr.responseText);
                    }
                }
            }
        };
        xhr.send(formData);
    }
</script>
