<?php
require_once dirname(__DIR__) . '/core/lib/session.php';
cmsStartSession();

if (!cmsValidateAdminSession() || empty($_SESSION['admin_id'])) {
    header('Location: /admin/login.php');
    exit;
}

require_once dirname(__DIR__) . '/core/db/db.php';
require_once dirname(__DIR__) . '/core/lib/license.php';
require_once dirname(__DIR__) . '/core/lib/common.php';
require_once dirname(__DIR__) . '/core/lib/rbac.php';
require_once dirname(__DIR__) . '/core/lib/admin_notifications.php';

$db = \Core\Db\DB::getInstance();
$licenseObj = new \Core\Lib\License();
$adminAccess = cmsLoadCurrentAdminAccess($db);
if (empty($adminAccess['active'])) {
    session_destroy();
    header('Location: /admin/login.php');
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'mark_update_notice_seen') {
    requireAdminCsrfToken(true);
    $noticeVersion = trim((string) ($_POST['version'] ?? ''));
    if (!preg_match('/^[0-9A-Za-z._+\-]{1,40}$/', $noticeVersion)) {
        http_response_code(422);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['code' => 422]);
        exit;
    }
    $_SESSION['admin_update_notice_seen_' . md5($noticeVersion)] = time();
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['code' => 200]);
    exit;
}

$siteConfig = [];
$configs = $db->fetchAll("SELECT config_key, config_value FROM {$db->table('config')}");
foreach ($configs as $cfg) {
    $siteConfig[$cfg['config_key']] = $cfg['config_value'];
}
$updateRemind = trim((string) ($siteConfig['update_remind'] ?? 'modal'));
$updateNotice = null;
$showUpdateModal = false;
if (in_array($updateRemind, ['modal', 'backend'], true)) {
    $updateCacheKey = 'admin_update_check_cache';
    $updateCache = $_SESSION[$updateCacheKey] ?? [];
    $cachedAt = intval($updateCache['time'] ?? 0);
    $cachedUpdate = is_array($updateCache) ? ($updateCache['data'] ?? null) : null;
    $cacheLifetime = is_array($cachedUpdate) ? 600 : 30;
    $cacheIsFresh = $cachedAt > 0 && ($cachedAt + $cacheLifetime) > time();
    if ($cacheIsFresh) {
        $remoteUpdate = $cachedUpdate;
    } else {
        $remoteUpdate = cmsFetchRemoteUpdateInfo(3);
        $_SESSION[$updateCacheKey] = ['time' => time(), 'data' => $remoteUpdate];
    }
    $latestVersion = trim((string) ($remoteUpdate['latest_version'] ?? ''));
    if ($latestVersion !== '' && cmsVersionCompare($latestVersion, \Core\Lib\License::VERSION) > 0) {
        $updateNotice = [
            'latest_version' => $latestVersion,
            'current_version' => \Core\Lib\License::VERSION,
            'changelog' => trim((string) ($remoteUpdate['changelog'] ?? '')),
            'download_url' => trim((string) ($remoteUpdate['download_url'] ?? '')),
        ];
        if ($updateRemind === 'modal') {
            $seenKey = 'admin_update_notice_seen_' . md5($latestVersion);
            if (empty($_SESSION[$seenKey])) {
                $showUpdateModal = true;
            }
        }
    }
}

$licenseInfo = $licenseObj->getStatus();
$license = $licenseObj->getLocalLicense();
$currentLevel = intval($licenseInfo['level'] ?? 1);
$licenseDomain = isset($licenseInfo['domain']) ? $licenseInfo['domain'] : '';
$currentHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
$licenseDomainMismatch = false;
if ($licenseDomain !== '' && $currentHost !== '') {
    if ($currentLevel <= 1) {
        $licenseDomainMismatch = ($licenseDomain !== $currentHost);
    } else {
        $domains = array_map('trim', explode(',', $licenseDomain));
        $licenseDomainMismatch = !in_array($currentHost, $domains, true);
    }
}

$unreadMsgRow = $db->fetch("SELECT COUNT(*) AS cnt FROM {$db->table('message')} WHERE is_read = 0");
$unreadMsg = intval(isset($unreadMsgRow['cnt']) ? $unreadMsgRow['cnt'] : 0);
$adminNotifications = cmsFilterNotificationsByAccess(cmsApplyNotificationReadState($db, intval($_SESSION['admin_id']), cmsCollectAdminNotifications($db, dirname(__DIR__))), $adminAccess);
$unreadNotifications = cmsUnreadNotificationCount($adminNotifications);

$licenseCenterBase = rtrim((string) (defined('LICENSE_CENTER_URL') ? LICENSE_CENTER_URL : 'http://yutou.wtbidc.cn/license-center'), '/');
$announcementUrl = $licenseCenterBase . '/portal_updates.php';
$announcementText = '欢迎使用 芋头CMS 后台管理平台';
if (function_exists('curl_init')) {
    $announcementCh = curl_init();
    curl_setopt($announcementCh, CURLOPT_URL, $licenseCenterBase . '/api.php?action=announcement');
    curl_setopt($announcementCh, CURLOPT_TIMEOUT, 3);
    curl_setopt($announcementCh, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($announcementCh, CURLOPT_SSL_VERIFYPEER, false);
    $announcementResp = curl_exec($announcementCh);
    curl_close($announcementCh);
    if ($announcementResp) {
        $annData = json_decode($announcementResp, true);
        if (is_array($annData) && !empty($annData['content'])) {
            $announcementText = $annData['content'];
        }
    }
}

$currentModule = isset($_GET['act']) ? trim($_GET['act']) : 'dashboard';
$siteName = isset($siteConfig['site_name']) && $siteConfig['site_name'] !== '' ? $siteConfig['site_name'] : 'EnterpriseCMS';
$adminName = isset($_SESSION['admin_realname']) && $_SESSION['admin_realname'] !== ''
    ? $_SESSION['admin_realname']
    : (isset($_SESSION['admin_name']) ? $_SESSION['admin_name'] : '管理员');
$adminAvatar = function_exists('mb_substr') ? mb_substr($adminName, 0, 1, 'UTF-8') : substr($adminName, 0, 1);
$levelNames = [0 => '体验版', 1 => '免费版', 2 => '基础版', 3 => '专业版'];
$siteUrl = rtrim(isset($siteConfig['site_url']) && $siteConfig['site_url'] !== '' ? $siteConfig['site_url'] : ('http://' . $currentHost), '/');
$homeBuilderUrl = cmsAdminCan($adminAccess, 'builder') ? cmsBuildFrontendUrl('home', 0, '', [
    'builder_edit' => 1,
    'builder_window' => 1,
    'builder_type' => 'home',
    'builder_ref_id' => 0,
    'builder_token' => cmsBuildBuilderAccessToken('home', 0, time() + 7200),
]) : '';

$menus = [
    'dashboard' => [
        'name' => '概况',
        'icon' => 'fa fa-home',
        'title' => '后台概况',
        'sub' => [],
    ],
    'content' => [
        'name' => '内容',
        'icon' => 'fa fa-file-text-o',
        'title' => '内容管理',
        'sub' => [
            ['name' => '内容总览', 'url' => '/admin/main.php?act=content', 'icon' => 'fa fa-th-large'],
            ['name' => '内容质量', 'url' => '/admin/main.php?act=content_quality', 'icon' => 'fa fa-check-square-o'],
            ['name' => '数据导入', 'url' => '/admin/main.php?act=data_import', 'icon' => 'fa fa-table'],
            ['name' => '文章管理', 'url' => '/admin/main.php?act=article', 'icon' => 'fa fa-newspaper-o'],
            ['name' => '产品管理', 'url' => '/admin/main.php?act=product', 'icon' => 'fa fa-cubes'],
            ['name' => '栏目管理', 'url' => '/admin/main.php?act=channel', 'icon' => 'fa fa-sitemap'],
            ['name' => '单页管理', 'url' => '/admin/main.php?act=page', 'icon' => 'fa fa-file-o'],
            ['name' => '图册管理', 'url' => '/admin/main.php?act=image', 'icon' => 'fa fa-picture-o'],
            ['name' => '下载管理', 'url' => '/admin/main.php?act=download', 'icon' => 'fa fa-download'],
            ['name' => '视频管理', 'url' => '/admin/main.php?act=video', 'icon' => 'fa fa-play-circle-o'],
            ['name' => '招聘管理', 'url' => '/admin/main.php?act=recruit', 'icon' => 'fa fa-briefcase'],
        ],
    ],
    'user' => [
        'name' => '用户',
        'icon' => 'fa fa-users',
        'title' => '用户管理',
        'sub' => [
            ['name' => '管理员', 'url' => '/admin/main.php?act=admin_user', 'icon' => 'fa fa-user-circle'],
            ['name' => '角色权限', 'url' => '/admin/main.php?act=role', 'icon' => 'fa fa-key'],
            ['name' => '会员列表', 'url' => '/admin/main.php?act=member', 'icon' => 'fa fa-user'],
            ['name' => '会员分组', 'url' => '/admin/main.php?act=member_group', 'icon' => 'fa fa-object-group'],
            ['name' => '站内消息', 'url' => '/admin/main.php?act=message', 'icon' => 'fa fa-envelope-o'],
        ],
    ],
    'interact' => [
        'name' => '互动',
        'icon' => 'fa fa-comments-o',
        'title' => '互动营销',
        'sub' => [
            ['name' => '留言管理', 'url' => '/admin/main.php?act=guestbook', 'icon' => 'fa fa-commenting-o'],
            ['name' => '评论管理', 'url' => '/admin/main.php?act=comment', 'icon' => 'fa fa-comment-o'],
            ['name' => '在线客服', 'url' => '/admin/main.php?act=online_service', 'icon' => 'fa fa-comments-o'],
            ['name' => '投票调查', 'url' => '/admin/main.php?act=vote', 'icon' => 'fa fa-check-square-o'],
            ['name' => '投稿管理', 'url' => '/admin/main.php?act=contribute', 'icon' => 'fa fa-pencil-square'],
        ],
    ],
    'tools' => [
        'name' => '资源',
        'icon' => 'fa fa-folder-open-o',
        'title' => '展示与工具',
        'sub' => [
            ['name' => '媒体资源', 'url' => '/admin/main.php?act=media', 'icon' => 'fa fa-picture-o'],
            ['name' => '幻灯片', 'url' => '/admin/main.php?act=slide', 'icon' => 'fa fa-image'],
            ['name' => '友情链接', 'url' => '/admin/main.php?act=link', 'icon' => 'fa fa-link'],
            ['name' => '广告管理', 'url' => '/admin/main.php?act=ads', 'icon' => 'fa fa-bullhorn'],
            ['name' => '模板中心', 'url' => '/admin/main.php?act=template', 'icon' => 'fa fa-paint-brush'],
            ['name' => '页面装修', 'url' => '/admin/main.php?act=builder', 'icon' => 'fa fa-columns'],
            ['name' => '帮助中心', 'url' => '/admin/main.php?act=help_center', 'icon' => 'fa fa-life-ring'],
            ['name' => '标签帮助', 'url' => '/admin/main.php?act=tag_help', 'icon' => 'fa fa-tags'],
        ],
    ],
    'system' => [
        'name' => '系统',
        'icon' => 'fa fa-cog',
        'title' => '系统设置',
        'sub' => [
            ['name' => '通知中心', 'url' => '/admin/main.php?act=notification', 'icon' => 'fa fa-bell-o'],
            ['name' => '后台任务', 'url' => '/admin/main.php?act=task_center', 'icon' => 'fa fa-tasks'],
            ['name' => '网站设置', 'url' => '/admin/main.php?act=site', 'icon' => 'fa fa-cogs'],
            ['name' => '404 与跳转', 'url' => '/admin/main.php?act=redirect', 'icon' => 'fa fa-random'],
            ['name' => '系统状态', 'url' => '/admin/main.php?act=system_status', 'icon' => 'fa fa-heartbeat'],
            ['name' => 'SEO工具', 'url' => '/admin/main.php?act=seo_tools', 'icon' => 'fa fa-search'],
            ['name' => '授权信息', 'url' => '/admin/main.php?act=auth', 'icon' => 'fa fa-shield'],
            ['name' => '版本管理', 'url' => '/admin/main.php?act=version', 'icon' => 'fa fa-refresh'],
            ['name' => '自定义变量', 'url' => '/admin/main.php?act=custom_var', 'icon' => 'fa fa-code'],
            ['name' => '操作日志', 'url' => '/admin/main.php?act=log', 'icon' => 'fa fa-history'],
            ['name' => '数据库', 'url' => '/admin/main.php?act=database', 'icon' => 'fa fa-database'],
        ],
    ],
    'shop' => [
        'name' => '商城',
        'icon' => 'fa fa-shopping-bag',
        'title' => '商城管理',
        'sub' => [
            ['name' => '商城首页', 'url' => 'main.php?act=shop', 'icon' => 'fa fa-dashboard'],
            ['name' => '订单管理', 'url' => 'main.php?act=order', 'icon' => 'fa fa-shopping-cart'],
            ['name' => '发货管理', 'url' => 'main.php?act=shipping', 'icon' => 'fa fa-truck'],
            ['name' => '售后退款', 'url' => 'main.php?act=refund', 'icon' => 'fa fa-undo'],
            ['name' => '商品评价', 'url' => 'main.php?act=review', 'icon' => 'fa fa-star'],
            ['name' => '充值记录', 'url' => 'main.php?act=recharge', 'icon' => 'fa fa-rmb'],
            ['name' => '支付设置', 'url' => 'main.php?act=payment', 'icon' => 'fa fa-credit-card'],
            ['name' => '商城配置', 'url' => 'main.php?act=shop_config', 'icon' => 'fa fa-sliders'],
        ],
    ],
];

foreach ($menus as $groupKey => &$group) {
    if ($groupKey === 'dashboard' || empty($group['sub'])) { continue; }
    $group['sub'] = array_values(array_filter($group['sub'], function ($item) use ($adminAccess) {
        return preg_match('/act=(\w+)/', $item['url'], $matches) && cmsAdminCan($adminAccess, $matches[1]);
    }));
}
unset($group);
$menus = array_filter($menus, function ($group, $key) {
    return $key === 'dashboard' || !empty($group['sub']);
}, ARRAY_FILTER_USE_BOTH);

if ($currentLevel < 3 && isset($menus['tools']['sub']) && is_array($menus['tools']['sub'])) {
    $menus['tools']['sub'] = array_values(array_filter($menus['tools']['sub'], function ($item) {
        return !isset($item['url']) || strpos($item['url'], 'act=builder') === false;
    }));
}

$moduleMap = ['dashboard' => 'dashboard'];
$titleMap = ['dashboard' => '后台概况'];
foreach ($menus as $groupKey => $group) {
    if ($groupKey !== 'dashboard') {
        foreach ($group['sub'] as $sub) {
            if (preg_match('/act=(\w+)/', $sub['url'], $matches)) {
                $actName = $matches[1];
                $moduleMap[$actName] = $groupKey;
                $titleMap[$actName] = $sub['name'];
            }
        }
    }
}
$currentGroup = isset($moduleMap[$currentModule]) ? $moduleMap[$currentModule] : 'dashboard';
$currentTitle = isset($titleMap[$currentModule]) ? $titleMap[$currentModule] : '后台概况';
$currentGroupName = isset($menus[$currentGroup]) ? $menus[$currentGroup]['title'] : '后台概况';
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo htmlspecialchars($siteName, ENT_QUOTES, 'UTF-8'); ?> - 后台管理</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="/public/css/admin-new.css?v=<?php echo @filemtime(dirname(__DIR__) . '/public/css/admin-new.css'); ?>">
    <link rel="stylesheet" href="/public/css/admin-flat-polish.css?v=<?php echo @filemtime(dirname(__DIR__) . '/public/css/admin-flat-polish.css'); ?>">
    <link rel="stylesheet" href="/public/css/admin-enterprise-shell.css?v=<?php echo @filemtime(dirname(__DIR__) . '/public/css/admin-enterprise-shell.css'); ?>">
</head>
<body class="admin-shell">
    <button class="mobile-menu-toggle" id="mobileMenuToggle" type="button" onclick="toggleSidebar(true)" aria-label="打开后台导航" aria-controls="sidebar" aria-expanded="false">
        <i class="fa fa-bars"></i>
    </button>
    <div class="sidebar-mask" id="sidebarMask" onclick="toggleSidebar(false)"></div>

    <aside class="sidebar" id="sidebar">
        <div class="sidebar-brand">
            <div class="sidebar-brand-mark">EC</div>
            <div class="sidebar-brand-copy">
                <strong><?php echo htmlspecialchars($siteName, ENT_QUOTES, 'UTF-8'); ?></strong>
                <span>管理后台</span>
            </div>
        </div>


        <nav class="sidebar-nav" aria-label="后台主导航">
            <a
                href="/admin/main.php?act=dashboard"
                target="mainFrame"
                class="nav-link nav-link-root <?php echo $currentModule === 'dashboard' ? 'is-active' : ''; ?>"
                data-act="dashboard"
                data-title="后台概况"
                data-group="dashboard"
                data-group-title="后台概况"
            >
                <span class="nav-icon"><i class="fa fa-home"></i></span>
                <span class="nav-text">仪表盘</span>
            </a>

            <?php foreach (['content', 'shop', 'user', 'interact', 'tools', 'system'] as $groupKey): ?>
            <?php $group = $menus[$groupKey]; $isOpen = $currentGroup === $groupKey; ?>
            <div class="nav-group<?php echo $isOpen ? ' is-open' : ''; ?>" data-group="<?php echo htmlspecialchars($groupKey, ENT_QUOTES, 'UTF-8'); ?>">
                <button
                    type="button"
                    class="nav-link nav-group-toggle<?php echo $isOpen ? ' is-active' : ''; ?>"
                    onclick="toggleNavGroup(this)"
                    data-group="<?php echo htmlspecialchars($groupKey, ENT_QUOTES, 'UTF-8'); ?>"
                    data-group-title="<?php echo htmlspecialchars($group['title'], ENT_QUOTES, 'UTF-8'); ?>"
                    aria-expanded="<?php echo $isOpen ? 'true' : 'false'; ?>"
                >
                    <span class="nav-icon"><i class="<?php echo htmlspecialchars($group['icon'], ENT_QUOTES, 'UTF-8'); ?>"></i></span>
                    <span class="nav-text"><?php echo htmlspecialchars($group['name'], ENT_QUOTES, 'UTF-8'); ?></span>
                    <span class="nav-arrow"><i class="fa fa-angle-down"></i></span>
                </button>
                <div class="nav-submenu">
                    <?php foreach ($group['sub'] as $sub): ?>
                    <?php preg_match('/act=(\w+)/', $sub['url'], $matches); $actName = isset($matches[1]) ? $matches[1] : ''; ?>
                    <a
                        href="<?php echo htmlspecialchars($sub['url'], ENT_QUOTES, 'UTF-8'); ?>"
                        target="mainFrame"
                        class="nav-sublink <?php echo $actName === $currentModule ? 'is-active' : ''; ?>"
                        data-act="<?php echo htmlspecialchars($actName, ENT_QUOTES, 'UTF-8'); ?>"
                        data-title="<?php echo htmlspecialchars($sub['name'], ENT_QUOTES, 'UTF-8'); ?>"
                        data-group="<?php echo htmlspecialchars($groupKey, ENT_QUOTES, 'UTF-8'); ?>"
                        data-group-title="<?php echo htmlspecialchars($group['title'], ENT_QUOTES, 'UTF-8'); ?>"
                    >
                        <i class="<?php echo htmlspecialchars($sub['icon'], ENT_QUOTES, 'UTF-8'); ?>"></i>
                        <span><?php echo htmlspecialchars($sub['name'], ENT_QUOTES, 'UTF-8'); ?></span>
                    </a>
                    <?php endforeach; ?>
                </div>
            </div>
            <?php endforeach; ?>
        </nav>

        <div class="sidebar-footer">
            <div class="sidebar-footer-label">当前域名</div>
            <div class="sidebar-footer-value"><?php echo htmlspecialchars($currentHost !== '' ? $currentHost : '未检测到域名', ENT_QUOTES, 'UTF-8'); ?></div>
        </div>
    </aside>

    <div class="shell-main">
        <header class="topbar">
            <div class="topbar-left">
                <button type="button" class="topbar-action topbar-action-toggle" onclick="toggleSidebarCollapse()" title="收起/展开左侧栏目">
                    <span class="topbar-toggle-icon" id="sidebarCollapseIcon" aria-hidden="true"></span>
                    <span id="sidebarCollapseText">收起栏目</span>
                </button>
                <a href="<?php echo htmlspecialchars($announcementUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer" class="topbar-chip topbar-chip-brand" title="在授权平台查看官方公告">
                    <i class="fa fa-bullhorn"></i>
                    <span><?php echo htmlspecialchars($announcementText, ENT_QUOTES, 'UTF-8'); ?></span>
                </a>
            </div>

            <div class="topbar-right">
                <button type="button" class="topbar-action global-search-trigger" onclick="openGlobalSearch()" title="全局搜索 Ctrl/⌘ + K"><i class="fa fa-search"></i><span>搜索</span><kbd>Ctrl K</kbd></button>
                <?php if (cmsAdminCan($adminAccess, 'builder')): ?><a href="<?php echo htmlspecialchars($homeBuilderUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank" class="topbar-action topbar-action-primary">
                    <i class="fa fa-plus-circle"></i>
                    <span>装修网站</span>
                </a><?php endif; ?>
                <?php if (cmsAdminCan($adminAccess, 'notification')): ?><a href="/admin/main.php?act=notification" target="mainFrame" class="topbar-action" title="通知中心">
                    <i class="fa fa-bell-o"></i>
                    <span>通知</span>
                    <?php if ($unreadNotifications > 0): ?><em class="topbar-badge"><?php echo min(99,$unreadNotifications); ?></em><?php endif; ?>
                </a><?php endif; ?>
                <a href="<?php echo htmlspecialchars($siteUrl, ENT_QUOTES, 'UTF-8'); ?>" target="_blank" class="topbar-action" title="预览网站">
                    <i class="fa fa-desktop"></i>
                    <span>预览</span>
                </a>
                <?php if (cmsAdminCan($adminAccess, 'auth')): ?><a href="/admin/main.php?act=auth" target="mainFrame" class="topbar-action" title="授权信息">
                    <i class="fa fa-shield"></i>
                    <span><?php echo htmlspecialchars(isset($levelNames[$currentLevel]) ? $levelNames[$currentLevel] : '体验版', ENT_QUOTES, 'UTF-8'); ?></span>
                </a><?php endif; ?>
                <button type="button" class="topbar-user" onclick="openProfilePanel()" aria-haspopup="dialog" aria-controls="profilePanel">
                    <span class="topbar-user-avatar"><?php echo htmlspecialchars($adminAvatar, ENT_QUOTES, 'UTF-8'); ?></span>
                    <span class="topbar-user-copy">
                        <strong><?php echo htmlspecialchars($adminName, ENT_QUOTES, 'UTF-8'); ?></strong>
                        <small>账户中心</small>
                    </span>
                    <i class="fa fa-angle-down"></i>
                </button>
                <form method="post" action="/admin/login.php" style="margin:0;display:inline-flex;">
                    <input type="hidden" name="action" value="logout">
                    <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars(getAdminCsrfToken(), ENT_QUOTES, 'UTF-8'); ?>">
                    <button type="submit" class="topbar-action topbar-action-ghost" title="退出登录">
                        <i class="fa fa-sign-out"></i>
                        <span>退出</span>
                    </button>
                </form>
            </div>
        </header>

        <section class="workspace">
            <?php if ($licenseDomainMismatch): ?>
            <div class="shell-alert shell-alert-warning">
                <i class="fa fa-warning"></i>
                <span>当前访问域名为 <?php echo htmlspecialchars($currentHost, ENT_QUOTES, 'UTF-8'); ?>，授权绑定域名为 <?php echo htmlspecialchars($licenseDomain, ENT_QUOTES, 'UTF-8'); ?>，请前往“授权信息”重新激活。</span>
            </div>
            <?php endif; ?>

            <div class="workspace-frame">
                <iframe
                    id="mainFrame"
                    name="mainFrame"
                    src="/admin/main.php?act=<?php echo htmlspecialchars($currentModule, ENT_QUOTES, 'UTF-8'); ?>"
                    class="main-iframe"
                    title="<?php echo htmlspecialchars($currentTitle, ENT_QUOTES, 'UTF-8'); ?>"
                ></iframe>
            </div>
        </section>
    </div>

    <div class="profile-overlay" id="profileOverlay" onclick="closeProfilePanel()" aria-hidden="true"></div>
    <div class="profile-panel" id="profilePanel" role="dialog" aria-modal="true" aria-label="个人资料" aria-hidden="true">
        <div class="profile-panel-header">
            <div>
                <h3>个人资料</h3>
                <p>查看账号信息与登录状态</p>
            </div>
            <button class="profile-panel-close" type="button" onclick="closeProfilePanel()" aria-label="关闭个人资料">
                <i class="fa fa-times"></i>
            </button>
        </div>
        <div class="profile-panel-body" id="profilePanelBody">
            <div class="profile-panel-loading">
                <i class="fa fa-spinner fa-spin"></i>
                <span>正在加载个人资料...</span>
            </div>
        </div>
    </div>

    <div class="global-search-overlay" id="globalSearchOverlay" hidden>
        <section class="global-search-dialog" role="dialog" aria-modal="true" aria-label="后台全局搜索">
            <div class="global-search-input-wrap"><i class="fa fa-search"></i><input id="globalSearchInput" type="search" autocomplete="off" placeholder="搜索内容或输入后台功能名称"><kbd>ESC</kbd></div>
            <div class="global-search-status" id="globalSearchStatus">输入至少 2 个字符，搜索文章、产品、栏目、单页、会员和后台功能。</div>
            <div class="global-search-results" id="globalSearchResults"></div>
            <footer><span><kbd>↑</kbd><kbd>↓</kbd> 选择</span><span><kbd>Enter</kbd> 打开</span><span>结果受当前角色权限限制</span></footer>
        </section>
    </div>
    <?php if ($showUpdateModal && $updateNotice): ?>
    <div class="update-notice-overlay" id="updateNoticeOverlay">
        <section class="update-notice-card" role="dialog" aria-modal="true" aria-label="系统更新提醒">
            <div class="update-notice-head">
                <div>
                    <span>系统更新</span>
                    <h3>发现新版本 v<?php echo htmlspecialchars($updateNotice['latest_version']); ?></h3>
                </div>
                <button type="button" class="update-notice-close" onclick="closeUpdateNotice()" aria-label="关闭">×</button>
            </div>
            <div class="update-notice-body">
                <p>当前版本 v<?php echo htmlspecialchars($updateNotice['current_version']); ?>，建议尽快查看更新。</p>
                <?php if ($updateNotice['changelog'] !== ''): ?>
                <pre><?php echo htmlspecialchars($updateNotice['changelog']); ?></pre>
                <?php endif; ?>
            </div>
            <div class="update-notice-actions">
                <button type="button" class="btn btn-secondary" onclick="closeUpdateNotice()">稍后</button>
                <a class="btn btn-primary" href="/admin/main.php?act=version" target="mainFrame" onclick="closeUpdateNotice()">查看更新</a>
            </div>
        </section>
    </div>
    <?php endif; ?>

    <style>
    .global-search-trigger kbd{margin-left:4px;padding:2px 5px;border:1px solid rgba(100,116,139,.3);border-radius:5px;background:rgba(248,250,252,.8);font:600 9px/1.4 Consolas,monospace;color:#64748b}.global-search-overlay{position:fixed;inset:0;z-index:99999;background:rgba(15,23,42,.46);backdrop-filter:blur(4px)}.global-search-overlay:not([hidden]){display:flex;align-items:flex-start;justify-content:center;padding:10vh 20px 20px}.global-search-dialog{width:min(680px,100%);overflow:hidden;border:1px solid rgba(255,255,255,.72);border-radius:18px;background:#fff;box-shadow:0 35px 90px rgba(15,23,42,.28)}.global-search-input-wrap{display:grid;grid-template-columns:24px minmax(0,1fr) auto;gap:10px;align-items:center;padding:16px 18px;border-bottom:1px solid #e8edf3}.global-search-input-wrap>i{color:#64748b;font-size:17px}.global-search-input-wrap input{width:100%;border:0;outline:0;background:transparent;color:#1e293b;font:600 16px/1.5 "Microsoft YaHei",sans-serif}.global-search-input-wrap kbd,.global-search-dialog footer kbd{padding:3px 6px;border:1px solid #dbe3ee;border-radius:6px;background:#f8fafc;color:#64748b;font:600 10px Consolas,monospace}.global-search-status{padding:12px 18px;color:#94a3b8;font-size:11px}.global-search-results{max-height:min(52vh,480px);overflow:auto;padding:0 9px 9px}.global-search-result{display:grid;grid-template-columns:38px minmax(0,1fr) auto;gap:11px;align-items:center;width:100%;padding:10px;border:0;border-radius:11px;background:transparent;text-align:left;cursor:pointer}.global-search-result:hover,.global-search-result.is-active{background:#eff6ff}.global-search-icon{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;background:#f1f5f9;color:#475569}.global-search-result.is-active .global-search-icon{background:#dbeafe;color:#2563eb}.global-search-copy{min-width:0}.global-search-copy strong,.global-search-copy span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.global-search-copy strong{color:#25324a;font-size:13px}.global-search-copy span{margin-top:3px;color:#94a3b8;font-size:10px}.global-search-type{padding:4px 7px;border-radius:7px;background:#f8fafc;color:#64748b;font-size:9px;font-weight:800}.global-search-empty{padding:42px;text-align:center;color:#94a3b8;font-size:12px}.global-search-dialog footer{display:flex;gap:16px;align-items:center;padding:11px 17px;border-top:1px solid #edf2f7;background:#fbfcfe;color:#94a3b8;font-size:10px}.global-search-dialog footer span:last-child{margin-left:auto}.update-notice-overlay{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(15,23,42,.52);backdrop-filter:blur(6px)}.update-notice-overlay[hidden]{display:none}.update-notice-card{width:min(560px,100%);overflow:hidden;border:1px solid rgba(255,255,255,.75);border-radius:22px;background:#fff;box-shadow:0 32px 90px rgba(15,23,42,.34)}.update-notice-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:22px 24px 16px;border-bottom:1px solid #eef2f7}.update-notice-head span{display:block;color:#2563eb;font-size:12px;font-weight:700;letter-spacing:.06em}.update-notice-head h3{margin:8px 0 0;color:#172033;font-size:24px;line-height:1.2}.update-notice-close{width:38px;height:38px;border:0;border-radius:999px;background:#f8fafc;color:#64748b;font-size:22px;cursor:pointer}.update-notice-body{padding:18px 24px;color:#475569}.update-notice-body p{margin:0 0 14px;font-size:14px;line-height:1.8}.update-notice-body pre{max-height:240px;overflow:auto;margin:0;padding:14px 16px;border-radius:14px;background:#f8fafc;color:#334155;font:13px/1.8 Consolas,"Microsoft YaHei",monospace;white-space:pre-wrap}.update-notice-actions{display:flex;justify-content:flex-end;gap:10px;padding:0 24px 24px}@media(max-width:700px){.global-search-trigger kbd{display:none}.global-search-overlay:not([hidden]){padding:20px 12px}.global-search-dialog footer span:last-child{display:none}.update-notice-overlay{padding:16px}.update-notice-head h3{font-size:20px}.update-notice-actions{flex-direction:column}.update-notice-actions .btn{text-align:center}}
    .update-notice-actions .btn{display:inline-flex;min-width:96px;min-height:40px;align-items:center;justify-content:center;gap:7px;padding:9px 16px;border:1px solid transparent;border-radius:8px;font:600 13px/20px "Microsoft YaHei",sans-serif;text-decoration:none;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,box-shadow .16s ease}.update-notice-actions .btn-secondary{border-color:#dbe3ee;background:#fff;color:#475569}.update-notice-actions .btn-secondary:hover{border-color:#bfdbfe;background:#f8fbff;color:#1d4ed8}.update-notice-actions .btn-primary{border-color:#1d4ed8;background:#2563eb;color:#fff;box-shadow:0 3px 8px rgba(37,99,235,.2)}.update-notice-actions .btn-primary:hover{background:#1d4ed8}.update-notice-actions .cms-button-svg{display:block;width:15px;height:15px;flex:0 0 15px}.update-notice-close:hover{background:#eef2f7;color:#334155}@media(max-width:700px){.update-notice-actions .btn{width:100%}}
    </style>

    <script src="/public/js/admin-icons.js?v=<?php echo @filemtime(dirname(__DIR__) . '/public/js/admin-icons.js'); ?>"></script>
    <script>
    (function () {
        var body = document.body;
        var sidebar = document.getElementById('sidebar');
        var sidebarMask = document.getElementById('sidebarMask');
        var frame = document.getElementById('mainFrame');
        var workspaceFrame = document.querySelector('.workspace-frame');
        var titleNode = document.getElementById('workspaceTitle');
        var groupNode = document.getElementById('workspaceGroup');
        var collapseIcon = document.getElementById('sidebarCollapseIcon');
        var collapseText = document.getElementById('sidebarCollapseText');
        var mobileMenuToggle = document.getElementById('mobileMenuToggle');
        var collapseStorageKey = 'enterprisecms.sidebar.collapsed';
        var searchOverlay = document.getElementById('globalSearchOverlay');
        var searchInput = document.getElementById('globalSearchInput');
        var searchResults = document.getElementById('globalSearchResults');
        var searchStatus = document.getElementById('globalSearchStatus');
        var searchItems = [];
        var searchIndex = -1;
        var searchTimer = null;
        var searchController = null;
        var updateNoticeOverlay = document.getElementById('updateNoticeOverlay');
        var updateNoticeVersion = <?php echo json_encode($showUpdateModal && $updateNotice ? $updateNotice['latest_version'] : ''); ?>;
        var updateNoticeCsrfToken = <?php echo json_encode(getAdminCsrfToken()); ?>;
        var updateNoticeSeenSent = false;

        function markUpdateNoticeSeen() {
            if (!updateNoticeVersion || updateNoticeSeenSent) {
                return;
            }
            updateNoticeSeenSent = true;
            fetch('/admin/index.php', {
                method: 'POST',
                credentials: 'same-origin',
                headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                body: 'action=mark_update_notice_seen&version=' + encodeURIComponent(updateNoticeVersion) + '&csrf_token=' + encodeURIComponent(updateNoticeCsrfToken),
                keepalive: true
            }).catch(function () {
                updateNoticeSeenSent = false;
            });
        }

        window.closeUpdateNotice = function () {
            if (updateNoticeOverlay) {
                markUpdateNoticeSeen();
                updateNoticeOverlay.hidden = true;
            }
        };

        if (updateNoticeOverlay) {
            updateNoticeOverlay.addEventListener('click', function (event) {
                if (event.target === updateNoticeOverlay) {
                    window.closeUpdateNotice();
                }
            });
            setTimeout(function () {
                updateNoticeOverlay.hidden = false;
                if (updateNoticeOverlay.getBoundingClientRect().width > 0) {
                    markUpdateNoticeSeen();
                }
            }, 180);
        }

        function renderGlobalSearch() {
            searchResults.innerHTML = '';
            if (!searchItems.length) { searchResults.innerHTML = '<div class="global-search-empty">没有找到匹配结果</div>'; return; }
            searchItems.forEach(function (item, index) {
                var button = document.createElement('button'); button.type = 'button'; button.className = 'global-search-result' + (index === searchIndex ? ' is-active' : '');
                var icon = document.createElement('span'); icon.className = 'global-search-icon'; var iconNode = document.createElement('i'); iconNode.className = 'fa ' + (item.icon || 'fa-search'); icon.appendChild(iconNode);
                var copy = document.createElement('span'); copy.className = 'global-search-copy'; var title = document.createElement('strong'); title.textContent = item.title || ''; var description = document.createElement('span'); description.textContent = item.description || '打开管理页面'; copy.appendChild(title); copy.appendChild(description);
                var type = document.createElement('span'); type.className = 'global-search-type'; type.textContent = item.type_label || '结果'; button.appendChild(icon); button.appendChild(copy); button.appendChild(type);
                button.onclick = function () { openGlobalSearchItem(index); }; button.onmouseenter = function () { if(searchIndex!==index){searchIndex=index;renderGlobalSearch();} }; searchResults.appendChild(button);
            });
        }
        function openGlobalSearchItem(index) { var item = searchItems[index]; if (!item) return; closeGlobalSearch(); frame.src = item.url; setActiveMenu(parseAct(item.url)); if (workspaceFrame) workspaceFrame.classList.add('is-loading'); }
        function runGlobalSearch() { var query = searchInput.value.trim(); if (query.length < 2) { searchItems=[];searchIndex=-1;searchResults.innerHTML='';searchStatus.textContent='输入至少 2 个字符，搜索文章、产品、栏目、单页、会员和后台功能。';return;} if(searchController)searchController.abort();searchController=new AbortController();searchStatus.textContent='正在搜索…';fetch('/admin/main.php?act=global_search&q='+encodeURIComponent(query),{signal:searchController.signal,credentials:'same-origin'}).then(function(r){return r.json();}).then(function(data){searchItems=Array.isArray(data.results)?data.results:[];searchIndex=searchItems.length?0:-1;searchStatus.textContent='找到 '+searchItems.length+' 个结果';renderGlobalSearch();}).catch(function(error){if(error.name!=='AbortError')searchStatus.textContent='搜索暂时不可用，请稍后重试';}); }
        window.openGlobalSearch = function () { searchOverlay.hidden=false;searchInput.value='';searchItems=[];searchIndex=-1;searchResults.innerHTML='';searchStatus.textContent='输入至少 2 个字符，搜索文章、产品、栏目、单页、会员和后台功能。';setTimeout(function(){searchInput.focus();},20); };
        window.closeGlobalSearch = function () { searchOverlay.hidden=true;if(searchController)searchController.abort(); };
        searchInput.addEventListener('input',function(){clearTimeout(searchTimer);searchTimer=setTimeout(runGlobalSearch,220);});
        searchOverlay.addEventListener('click',function(event){if(event.target===searchOverlay)closeGlobalSearch();});
        searchInput.addEventListener('keydown',function(event){if(event.key==='ArrowDown'){event.preventDefault();if(searchItems.length){searchIndex=(searchIndex+1)%searchItems.length;renderGlobalSearch();}}else if(event.key==='ArrowUp'){event.preventDefault();if(searchItems.length){searchIndex=(searchIndex-1+searchItems.length)%searchItems.length;renderGlobalSearch();}}else if(event.key==='Enter'){event.preventDefault();openGlobalSearchItem(searchIndex);}});

        window.toggleSidebar = function (show) {
            var shouldShow = typeof show === 'boolean' ? show : !body.classList.contains('sidebar-open');
            body.classList.toggle('sidebar-open', shouldShow);
            sidebar.classList.toggle('is-mobile-open', shouldShow);
            sidebarMask.classList.toggle('is-visible', shouldShow);
            if(mobileMenuToggle)mobileMenuToggle.setAttribute('aria-expanded',shouldShow?'true':'false');
        };

        function syncSidebarCollapseButton() {
            var collapsed = body.classList.contains('sidebar-collapsed');
            if (collapseIcon) {
                collapseIcon.innerHTML = window.CMSAdminIcons
                    ? window.CMSAdminIcons.svg(collapsed ? 'panels' : 'menu', 'cms-shell-svg')
                    : '';
            }
            if (collapseText) {
                collapseText.textContent = collapsed ? '展开栏目' : '收起栏目';
            }
        }

        window.toggleSidebarCollapse = function () {
            if (window.innerWidth <= 1200) {
                toggleSidebar(!body.classList.contains('sidebar-open'));
                return;
            }
            body.classList.toggle('sidebar-collapsed');
            var collapsed = body.classList.contains('sidebar-collapsed');
            try {
                window.localStorage.setItem(collapseStorageKey, collapsed ? '1' : '0');
            } catch (err) {
                // Ignore storage failures.
            }
            syncSidebarCollapseButton();
        };

        window.toggleNavGroup = function (button) {
            if (body.classList.contains('sidebar-collapsed') && window.innerWidth > 1200) {
                toggleSidebarCollapse();
            }
            var group = button.closest('.nav-group');
            if (!group) {
                return;
            }
            group.classList.toggle('is-open');
            button.setAttribute('aria-expanded',group.classList.contains('is-open')?'true':'false');
        };

        function closeSidebarOnMobile() {
            if (window.innerWidth <= 1200) {
                toggleSidebar(false);
            }
        }

        function setWorkspaceTitle(title, groupTitle) {
            if (titleNode && title) {
                titleNode.textContent = title;
            }
            if (groupNode && groupTitle) {
                groupNode.textContent = groupTitle;
            }
            if(frame&&title)frame.setAttribute('title',title);
        }

        function setActiveMenu(act) {
            if (!act) {
                return;
            }

            document.querySelectorAll('.nav-link-root, .nav-sublink').forEach(function (item) {
                item.classList.toggle('is-active', item.getAttribute('data-act') === act);
            });

            document.querySelectorAll('.nav-group').forEach(function (group) {
                group.classList.remove('is-open');
                var matched = group.querySelector('.nav-sublink[data-act="' + act + '"]');
                var toggle = group.querySelector('.nav-group-toggle');
                var isActiveGroup = matched !== null;
                if (toggle) {
                    toggle.classList.toggle('is-active', isActiveGroup);
                    toggle.setAttribute('aria-expanded',isActiveGroup?'true':'false');
                }
                if (isActiveGroup) {
                    group.classList.add('is-open');
                    setWorkspaceTitle(matched.getAttribute('data-title'), matched.getAttribute('data-group-title'));
                }
            });

            var root = document.querySelector('.nav-link-root[data-act="' + act + '"]');
            if (root) {
                setWorkspaceTitle(root.getAttribute('data-title'), root.getAttribute('data-group-title'));
            }
        }

        function parseAct(url) {
            try {
                return new URL(url, window.location.origin).searchParams.get('act');
            } catch (err) {
                return null;
            }
        }

        document.querySelectorAll('.nav-link-root, .nav-sublink').forEach(function (link) {
            link.addEventListener('click', function () {
                if (workspaceFrame) {
                    workspaceFrame.classList.add('is-loading');
                }
                setActiveMenu(link.getAttribute('data-act'));
                closeSidebarOnMobile();
            });
        });

        document.querySelectorAll('a[target="mainFrame"]').forEach(function (link) {
            link.addEventListener('click', function () {
                if (workspaceFrame) {
                    workspaceFrame.classList.add('is-loading');
                }
            });
        });

        frame.addEventListener('load', function () {
            if (workspaceFrame) {
                workspaceFrame.classList.remove('is-loading');
            }
            try {
                var act = parseAct(frame.contentWindow.location.href);
                if (act) {
                    setActiveMenu(act);
                }
            } catch (err) {
                // Ignore cross-document read failures.
            }
        });

        window.openProfilePanel = function () {
            var overlay = document.getElementById('profileOverlay');
            var panel = document.getElementById('profilePanel');
            overlay.classList.add('is-active');
            panel.classList.add('is-active');
            overlay.setAttribute('aria-hidden', 'false');
            panel.setAttribute('aria-hidden', 'false');
            document.getElementById('profilePanelBody').innerHTML = '<div class="profile-panel-loading"><i class="fa fa-spinner fa-spin"></i><span>正在加载个人资料...</span></div>';
            var xhr = new XMLHttpRequest();
            xhr.open('GET', '/admin/main.php?act=profile&ajax=1', true);
            xhr.onload = function () {
                if (xhr.status === 200) {
                    document.getElementById('profilePanelBody').innerHTML = xhr.responseText;
                }
            };
            xhr.send();
        };

        window.closeProfilePanel = function () {
            var overlay = document.getElementById('profileOverlay');
            var panel = document.getElementById('profilePanel');
            overlay.classList.remove('is-active');
            panel.classList.remove('is-active');
            overlay.setAttribute('aria-hidden', 'true');
            panel.setAttribute('aria-hidden', 'true');
        };

        closeProfilePanel();

        document.addEventListener('keydown', function (event) {
            if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'k') { event.preventDefault(); if(searchOverlay.hidden)openGlobalSearch();else closeGlobalSearch(); return; }
            if (event.key === 'Escape') {
                if (updateNoticeOverlay && !updateNoticeOverlay.hidden) { window.closeUpdateNotice(); return; }
                if (!searchOverlay.hidden) { closeGlobalSearch(); return; }
                closeProfilePanel();
                if (window.innerWidth <= 1200) {
                    toggleSidebar(false);
                }
            }
        });

        try {
            if (window.innerWidth > 1200 && window.localStorage.getItem(collapseStorageKey) === '1') {
                body.classList.add('sidebar-collapsed');
            }
        } catch (err) {
            // Ignore storage failures.
        }

        syncSidebarCollapseButton();
        setActiveMenu('<?php echo htmlspecialchars($currentModule, ENT_QUOTES, 'UTF-8'); ?>');
    })();
    </script>
</body>
</html>
