<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PPT编辑器 - {{ project.title }}</title>
    <link rel="icon" type="image/svg+xml" href="/static/images/favicon.svg">
    <link rel="alternate icon" href="/favicon.ico">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
    <!-- CodeMirror CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/monokai.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/material.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/dracula.min.css">
    <!-- CodeMirror Search Dialog CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/dialog/dialog.min.css">
    <style>
        :root {
            --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            --accent-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
            --success-gradient: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
            --warning-gradient: linear-gradient(135deg, #fa709a 0%, #fee140 100%);

            --glass-bg: rgba(255, 255, 255, 0.25);
            --glass-border: rgba(255, 255, 255, 0.18);
            --glass-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);

            --primary-color: #667eea;
            --secondary-color: #764ba2;

            --bg-primary: #ffffff;
            --border-color: #e2e8f0;

            --text-primary: #2d3748;
            --text-secondary: #4a5568;
            --text-muted: #718096;

            --border-radius: 8px;
            --border-radius-sm: 12px;
            --border-radius-md: 16px;
            --border-radius-lg: 24px;
            --border-radius-xl: 32px;

            --spacing-xs: 8px;
            --spacing-sm: 12px;
            --spacing-md: 16px;
            --spacing-lg: 24px;
            --spacing-xl: 32px;
            --spacing-2xl: 48px;
        }

        body {
            background: var(--primary-gradient);
            min-height: 100vh;
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            position: relative;
            overflow-x: hidden;
        }

        body::before {
            content: '';
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background:
                radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
                radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
                radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.2) 0%, transparent 50%);
            pointer-events: none;
            z-index: -1;
        }

        .editor-container {
            background: var(--glass-bg);
            backdrop-filter: blur(30px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-xl);
            box-shadow: var(--glass-shadow);
            margin: var(--spacing-lg);
            overflow: hidden;
            position: relative;
            z-index: 1;
        }

        .editor-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-md) var(--spacing-xl);
            position: relative;
            overflow: hidden;
            z-index: 10;
        }

        .editor-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
            animation: headerFloat 25s ease-in-out infinite;
        }

        @keyframes headerFloat {
            0%, 100% { transform: scale(1) rotate(0deg); }
            50% { transform: scale(1.02) rotate(1deg); }
        }

        .editor-header h1,
        .editor-header h2 {
            position: relative;
            z-index: 1;
            text-shadow: 0 2px 8px rgba(0,0,0,0.3);
            font-weight: 700;
            font-size: 1.5rem;
            letter-spacing: -0.01em;
            margin: 0;
        }

        .editor-header p {
            position: relative;
            z-index: 1;
            opacity: 0.9;
            font-size: 0.9rem;
            font-weight: 500;
            margin: var(--spacing-xs) 0 0 0;
        }
        
        .slides-sidebar {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-right: 1px solid var(--glass-border);
            height: calc(100vh - 140px);
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            min-width: 280px;
        }

        .slides-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            gap: var(--spacing-sm);
            padding: var(--spacing-md);
        }

        .slide-thumbnail {
            border: 2px solid transparent;
            border-radius: var(--border-radius-md);
            cursor: pointer;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            box-shadow: 0 4px 15px rgba(31, 38, 135, 0.2);
            position: relative;
            user-select: none;
            flex-shrink: 0;
            margin: 0;
            overflow: hidden;
        }

        .slide-thumbnail::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 2px;
            background: var(--accent-gradient);
            transform: scaleX(0);
            transition: transform 0.3s ease;
            z-index: 1;
        }

        .slide-thumbnail:hover {
            border-color: rgba(79, 172, 254, 0.5);
            transform: translateY(-4px) scale(1.02);
            box-shadow: 0 8px 25px rgba(79, 172, 254, 0.3);
        }

        .slide-thumbnail:hover::before {
            transform: scaleX(1);
        }

        .slide-thumbnail.active {
            border-color: rgba(67, 233, 123, 0.7);
            box-shadow: 0 8px 25px rgba(67, 233, 123, 0.4);
            transform: translateY(-4px) scale(1.02);
        }

        .slide-thumbnail.active::before {
            background: var(--success-gradient);
            transform: scaleX(1);
        }

        .slide-thumbnail.dragging {
            opacity: 0.5;
            transform: rotate(5deg) scale(0.95);
            z-index: 1000;
        }

        .slide-thumbnail.drag-over {
            border-color: #ffc107;
            background: rgba(255, 193, 7, 0.1);
        }

        .slide-preview {
            width: 100%;
            height: 135px; /* 调整高度以适应新的缩放比例：720*0.1875=135px */
            border: none;
            border-radius: 6px 6px 0 0;
            pointer-events: none;
            position: relative;
            overflow: hidden;
            background: #f8f9fa;
        }

        .slide-preview iframe {
            position: absolute;
            top: 0;
            left: 0;
            border: none;
            background: white;
            /* 设置iframe为1280x720，然后缩放到容器大小 */
            width: 1280px;
            height: 720px;
            transform-origin: top left;
            /* 计算缩放比例以填满容器：容器宽度约240px，240/1280=0.1875 */
            transform: scale(0.1875);
        }
        
        .slide-title {
            padding: 4px 2px;
            font-size: 10px;
            font-weight: bold;
            text-align: center;
            background: #f8f9fa;
            border-top: 1px solid #dee2e6;
            line-height: 1.1;
            height: 24px; /* 固定标题高度 */
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .main-editor {
            height: calc(100vh - 140px);
            display: flex;
            flex-direction: column;
        }
        
        .editor-toolbar {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-bottom: 1px solid var(--glass-border);
            padding: var(--spacing-sm) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 15px rgba(31, 38, 135, 0.1);
            position: relative;
        }
        
        .editor-content {
            flex: 1;
            display: flex;
        }
        
        .preview-pane {
            flex: 1;
            background: #f8f9fa;
            border-right: 1px solid #dee2e6;
            position: relative;
        }
        
        .edit-pane {
            flex: 1;
            background: white;
            height: 100%;
            overflow: hidden;
            position: relative;
        }
        
        .slide-frame {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 1280px;
            height: 720px;
            border: none;
            background: white;
            border-radius: 8px;
            transform-origin: center center;
            /* 初始变换，JavaScript会动态调整缩放比例 */
            transform: translate(-50%, -50%) scale(1);
        }

        /* 右侧iframe的响应式缩放 */
        .preview-pane {
            flex: 1;
            background: #f8f9fa;
            border-right: 1px solid #dee2e6;
            position: relative;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .slide-frame-container {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            background: #f8f9fa;
            border-radius: 8px;
            padding: 10px;
            box-sizing: border-box;
            overflow: hidden;
        }

        .slide-frame-wrapper {
            position: relative;
            display: block;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            /* 固定16:9比例，自适应缩放 */
            width: 100%;
            height: 100%;
            max-width: calc(100vh * 16/9 - 40px); /* 基于高度计算最大宽度 */
            max-height: calc(100vw * 9/16 - 40px); /* 基于宽度计算最大高度 */
        }
        
        /* Preview navigation buttons */
        .preview-nav-btn {
            position: absolute !important;
            top: 50% !important;
            transform: translateY(-50%) !important;
            width: 48px !important;
            height: 96px !important;
            display: flex !important;
            align-items: center;
            justify-content: center;
            background: rgba(0, 0, 0, 0.55);
            color: #fff;
            border: none;
            border-radius: 12px;
            box-shadow: 0 10px 24px rgba(0, 0, 0, 0.25);
            transition: opacity 0.25s ease, background-color 0.25s ease, transform 0.25s ease;
            opacity: 0;
            pointer-events: none;
            z-index: 20;
            margin: 0 !important;
            padding: 0 !important;
        }

        .slide-frame-wrapper:hover .preview-nav-btn {
            opacity: 0.2;
            pointer-events: auto;
        }

        .preview-nav-btn:hover {
            background: rgba(0, 0, 0, 0.8);
            opacity: 0.3;
            transform: translateY(-50%) scale(1.05);
        }

        .preview-nav-btn:active {
            transform: translateY(-50%) scale(0.97);
        }

        .preview-nav-btn.left {
            left: 12px !important;
            right: auto !important;
            border-radius: 12px 0 0 12px;
        }

        .preview-nav-btn.right {
            right: 12px !important;
            left: auto !important;
            border-radius: 0 12px 12px 0;
        }

        .preview-nav-btn i {
            font-size: 22px;
        }

        .code-editor {
            width: 100%;
            height: 100%;
            border: none;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            padding: 20px;
            resize: none;
            outline: none;
        }

        /* CodeMirror编辑器样式优化 */
        .CodeMirror {
            height: 100% !important;
            font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;
            font-size: 14px !important;
            line-height: 1.5 !important;
            border: none !important;
            position: absolute !important;
            top: 0 !important;
            left: 0 !important;
            right: 0 !important;
            bottom: 0 !important;
            min-height: 400px !important;
        }

        .CodeMirror-scroll {
            padding: 20px !important;
            overflow-y: auto !important;
            overflow-x: auto !important;
            max-height: none !important;
            min-height: 400px !important;
        }

        .CodeMirror-scrollbar-filler {
            background: transparent !important;
        }

        .CodeMirror-vscrollbar, .CodeMirror-hscrollbar {
            outline: none !important;
        }

        .CodeMirror-vscrollbar {
            right: 0 !important;
            top: 0 !important;
            overflow-x: hidden !important;
            overflow-y: auto !important;
        }

        .CodeMirror-hscrollbar {
            bottom: 0 !important;
            left: 0 !important;
            overflow-y: hidden !important;
            overflow-x: auto !important;
        }

        .CodeMirror-gutters {
            background: #2c3e50 !important;
            border-right: 1px solid #34495e !important;
        }

        .CodeMirror-linenumber {
            color: #7f8c8d !important;
            padding: 0 8px !important;
        }

        .CodeMirror-cursor {
            border-left: 2px solid #e74c3c !important;
        }

        .CodeMirror-selected {
            background: rgba(52, 152, 219, 0.2) !important;
        }

        .CodeMirror-focused .CodeMirror-selected {
            background: rgba(52, 152, 219, 0.3) !important;
        }

        /* 主题色彩调整 */
        .cm-s-material .CodeMirror {
            background: #263238 !important;
            color: #eeffff !important;
        }

        .cm-s-material .CodeMirror-gutters {
            background: #2c3e50 !important;
        }

        .cm-s-material .cm-tag {
            color: #f07178 !important;
        }

        .cm-s-material .cm-attribute {
            color: #c792ea !important;
        }

        .cm-s-material .cm-string {
            color: #c3e88d !important;
        }

        .cm-s-material .cm-comment {
            color: #546e7a !important;
        }

        /* CodeMirror搜索对话框样式优化 */
        .CodeMirror-dialog {
            position: absolute;
            left: 0;
            right: 0;
            background: #2c3e50 !important;
            color: white !important;
            z-index: 15;
            padding: 10px 15px !important;
            border: none !important;
            border-bottom: 2px solid #3498db !important;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3) !important;
        }

        .CodeMirror-dialog input {
            border: 1px solid #34495e !important;
            outline: none !important;
            background: #34495e !important;
            color: white !important;
            padding: 8px 12px !important;
            border-radius: 4px !important;
            font-size: 14px !important;
            margin: 0 5px !important;
            min-width: 200px !important;
        }

        .CodeMirror-dialog input:focus {
            border-color: #3498db !important;
            box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.3) !important;
        }

        .CodeMirror-dialog button {
            background: #3498db !important;
            color: white !important;
            border: none !important;
            padding: 8px 15px !important;
            border-radius: 4px !important;
            cursor: pointer !important;
            font-size: 14px !important;
            margin: 0 3px !important;
            transition: background-color 0.2s ease !important;
        }

        .CodeMirror-dialog button:hover {
            background: #2980b9 !important;
        }

        .CodeMirror-dialog span {
            color: white !important;
            font-size: 14px !important;
            margin: 0 5px !important;
        }

        /* 搜索高亮样式 */
        .CodeMirror-searching {
            background-color: rgba(255, 255, 0, 0.4) !important;
            border: 1px solid rgba(255, 193, 7, 0.8) !important;
            border-radius: 2px !important;
        }

        .cm-searching {
            background-color: rgba(255, 255, 0, 0.4) !important;
            border: 1px solid rgba(255, 193, 7, 0.8) !important;
            border-radius: 2px !important;
        }

        /* 当前搜索结果高亮 */
        .CodeMirror-search-match {
            background-color: rgba(255, 165, 0, 0.6) !important;
            border: 2px solid #ff6b35 !important;
            border-radius: 3px !important;
        }

        /* 搜索对话框关闭按钮样式 */
        .CodeMirror-dialog .CodeMirror-search-close {
            position: absolute !important;
            right: 10px !important;
            top: 50% !important;
            transform: translateY(-50%) !important;
            background: #e74c3c !important;
            color: white !important;
            border: none !important;
            border-radius: 50% !important;
            width: 24px !important;
            height: 24px !important;
            font-size: 12px !important;
            cursor: pointer !important;
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
        }

        .CodeMirror-dialog .CodeMirror-search-close:hover {
            background: #c0392b !important;
        }
        
        .btn-group-custom {
            display: flex;
            gap: var(--spacing-md);
            align-items: center;
            justify-content: center;
            flex-wrap: wrap;
        }

        .btn-group-custom .btn {
            min-width: 42px;
            width: 42px;
            height: 42px;
            white-space: nowrap;
            padding: 0;
            border-radius: var(--border-radius-sm);
            font-weight: 600;
            transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            border: 1px solid rgba(255, 255, 255, 0.2);
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
            font-size: 16px;
            backdrop-filter: blur(15px);
        }

        .btn-group-custom .btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .btn-group-custom .btn:hover::before {
            left: 100%;
        }

        .btn-primary {
            background: rgba(102, 126, 234, 0.3);
            color: white;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
            border-color: rgba(102, 126, 234, 0.4);
        }

        .btn-success {
            background: rgba(86, 171, 47, 0.3);
            color: white;
            box-shadow: 0 4px 15px rgba(86, 171, 47, 0.2);
            border-color: rgba(86, 171, 47, 0.4);
        }

        .btn-info {
            background: rgba(79, 172, 254, 0.3);
            color: white;
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.2);
            border-color: rgba(79, 172, 254, 0.4);
        }

        .btn-warning {
            background: rgba(255, 154, 158, 0.3);
            color: white;
            box-shadow: 0 4px 15px rgba(255, 154, 158, 0.2);
            border-color: rgba(255, 154, 158, 0.4);
        }

        .btn-group-custom .btn:hover {
            transform: translateY(-2px) scale(1.02);
            border-color: rgba(255, 255, 255, 0.6);
        }

        .btn-group-custom .btn:hover.btn-primary {
            background: rgba(102, 126, 234, 0.5);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
        }

        .btn-group-custom .btn:hover.btn-success {
            background: rgba(86, 171, 47, 0.5);
            box-shadow: 0 6px 20px rgba(86, 171, 47, 0.4);
        }

        .btn-group-custom .btn:hover.btn-info {
            background: rgba(79, 172, 254, 0.5);
            box-shadow: 0 6px 20px rgba(79, 172, 254, 0.4);
        }

        .btn-group-custom .btn:hover.btn-warning {
            background: rgba(255, 154, 158, 0.5);
            box-shadow: 0 6px 20px rgba(255, 154, 158, 0.4);
        }

        /* 返回按钮样式 */
        .btn-outline-light {
            background: rgba(255, 255, 255, 0.1);
            color: white;
            border: 2px solid rgba(255, 255, 255, 0.3);
            padding: var(--spacing-sm) var(--spacing-lg);
            border-radius: var(--border-radius-md);
            font-weight: 600;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            text-decoration: none;
            display: inline-flex;
            align-items: center;
            gap: var(--spacing-xs);
            position: relative;
            z-index: 20;
            cursor: pointer;
        }

        .btn-outline-light:hover {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.5);
            color: white;
            transform: translateY(-2px) scale(1.02);
            box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2);
            text-decoration: none;
        }

        .btn-outline-light:active {
            transform: translateY(0) scale(0.98);
        }

        .mode-toggle {
            background: rgba(102, 126, 234, 0.3);
            color: white;
            border: 1px solid rgba(102, 126, 234, 0.4);
            padding: 0;
            width: 42px;
            height: 42px;
            border-radius: var(--border-radius-sm);
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            font-weight: 600;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
            position: relative;
            overflow: hidden;
            backdrop-filter: blur(15px);
        }

        .mode-toggle::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
            transition: left 0.6s;
        }

        .mode-toggle:hover {
            transform: translateY(-2px) scale(1.02);
            background: rgba(102, 126, 234, 0.5);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
            border-color: rgba(255, 255, 255, 0.6);
        }

        .mode-toggle:hover::before {
            left: 100%;
        }

        .mode-toggle.active {
            background: rgba(86, 171, 47, 0.4);
            box-shadow: 0 6px 20px rgba(86, 171, 47, 0.4);
            border-color: rgba(86, 171, 47, 0.6);
        }

        /* 优化悬浮提示样式 */
        [title] {
            position: relative;
        }

        [title]:hover::after {
            content: attr(title);
            position: absolute;
            bottom: 130%;
            left: 50%;
            transform: translateX(-50%);
            background: linear-gradient(135deg, #2d3748 0%, #4a5568 100%);
            color: white;
            padding: 10px 16px;
            border-radius: 12px;
            font-size: 13px;
            font-weight: 600;
            white-space: nowrap;
            z-index: 1000;
            opacity: 0;
            animation: tooltipFadeIn 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
            pointer-events: none;
            border: 1px solid rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
        }

        [title]:hover::before {
            content: '';
            position: absolute;
            bottom: 120%;
            left: 50%;
            transform: translateX(-50%);
            border: 6px solid transparent;
            border-top-color: #2d3748;
            z-index: 1000;
            opacity: 0;
            animation: tooltipFadeIn 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
        }

        @keyframes tooltipFadeIn {
            from {
                opacity: 0;
                transform: translateX(-50%) translateY(5px);
            }
            to {
                opacity: 1;
                transform: translateX(-50%) translateY(0);
            }
        }

        /* 按钮组间距优化 */
        .editor-toolbar .btn-group-custom:first-child {
            margin-right: auto;
        }

        .editor-toolbar .btn-group-custom:last-child {
            margin-left: auto;
        }

        /* 按钮激活状态优化 */
        .btn-group-custom .btn:active {
            transform: translateY(0) scale(0.95);
        }

        .mode-toggle:active {
            transform: translateY(0) scale(0.95);
        }

        /* 按钮禁用状态 */
        .btn-group-custom .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none !important;
        }

        .btn-group-custom .btn:disabled:hover {
            transform: none !important;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1) !important;
        }

        /* 按钮脉冲动画 */
        @keyframes buttonPulse {
            0% {
                box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
            }
            50% {
                box-shadow: 0 8px 25px rgba(102, 126, 234, 0.6);
            }
            100% {
                box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
            }
        }

        /* 为活跃的模式切换按钮添加脉冲效果 */
        .mode-toggle.active {
            animation: buttonPulse 2s ease-in-out infinite;
        }

        /* 按钮组整体动画 */
        .btn-group-custom {
            animation: fadeInUp 0.6s ease-out;
        }

        @keyframes fadeInUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .export-section {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-top: 1px solid var(--glass-border);
            padding: var(--spacing-lg) var(--spacing-xl);
            text-align: center;
            position: sticky;
            bottom: 0;
            z-index: 100;
            box-shadow: 0 -4px 20px rgba(31, 38, 135, 0.2);
            min-height: 80px;
        }

        /* Slideshow styles - 优化流畅度 */
        .slideshow-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: black;
            z-index: 9999;
            display: none;
            justify-content: center;
            align-items: center;
            /* 硬件加速 */
            transform: translateZ(0);
            will-change: opacity;
        }

        .slideshow-container {
            width: 100%;
            height: 100%;
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
            /* 硬件加速 */
            transform: translateZ(0);
            padding: 20px;
            box-sizing: border-box;
        }

        .slideshow-slide {
            background: white;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(255,255,255,0.2);
            overflow: hidden;
            position: relative;
            /* 使用flex确保PPT居中且尺寸自适应 */
            width: 100%;
            height: 100%;
            max-width: calc(100vh * 16/9 - 40px); /* 基于高度计算最大宽度，保持16:9比例 */
            max-height: calc(100vw * 9/16 - 40px); /* 基于宽度计算最大高度，保持16:9比例 */
            aspect-ratio: 16/9; /* 强制保持16:9比例 */
            /* 硬件加速 */
            transform: translateZ(0);
            will-change: transform;
        }

        .slideshow-slide iframe {
            width: 100%;
            height: 100%;
            border: none;
            background: white;
            /* 移除过渡效果，避免闪烁 */
            transform-origin: center center;
            /* 硬件加速 */
            transform: translateZ(0);
            will-change: opacity;
            /* 确保iframe始终可见 */
            opacity: 1;
        }

        /* 双缓冲iframe系统 */
        .slideshow-slide .iframe-container {
            position: relative;
            width: 100%;
            height: 100%;
        }

        .slideshow-slide .iframe-container iframe {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        .slideshow-slide .iframe-container iframe.hidden {
            opacity: 0;
            pointer-events: none;
        }

        .slideshow-slide .iframe-container iframe.visible {
            opacity: 1;
            pointer-events: auto;
        }

        /* 移除加载状态覆盖层，避免闪烁 */
        .slideshow-slide::before {
            display: none;
        }

        .slideshow-controls {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 20px;
            opacity: 0;
            transition: opacity 0.4s ease;
            pointer-events: none;
        }

        .slideshow-controls.visible {
            opacity: 1;
            pointer-events: auto;
        }

        .slideshow-btn {
            background: rgba(255,255,255,0.2);
            color: white;
            border: 2px solid rgba(255,255,255,0.3);
            padding: 10px 20px;
            border-radius: 25px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 16px;
        }

        .slideshow-btn:hover {
            background: rgba(255,255,255,0.3);
            border-color: rgba(255,255,255,0.5);
        }

        .slideshow-info {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            color: white;
            font-size: 18px;
            font-weight: bold;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.4s ease;
        }

        .slideshow-info.visible {
            opacity: 1;
        }

        .slideshow-exit {
            position: absolute;
            top: 30px;
            right: 30px;
            background: rgba(255,255,255,0.2);
            color: white;
            border: 2px solid rgba(255,255,255,0.3);
            padding: 10px 15px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 20px;
            transition: all 0.4s ease;
            opacity: 0;
            pointer-events: none;
        }

        .slideshow-exit.visible {
            opacity: 1;
            pointer-events: auto;
        }

        .slideshow-exit:hover {
            background: rgba(255,255,255,0.3);
            border-color: rgba(255,255,255,0.5);
        }

        /* 响应式设计 */
        @media (max-width: 1200px) {
            .slide-preview {
                height: 115px; /* 200px容器宽度，200/1280=0.156，720*0.156=112.32px */
            }
            .slide-preview iframe {
                transform: scale(0.156);
            }

        }

        @media (max-width: 992px) {
            .slides-sidebar {
                flex: 0 0 220px !important;
            }

            .slide-preview {
                height: 115px; /* 200px容器宽度，200/1280=0.156，720*0.156=112.32px */
            }
            .slide-preview iframe {
                transform: scale(0.156);
            }

            .slide-title {
                font-size: 9px;
                padding: 3px 2px;
                height: 20px;
            }

        }

        @media (max-width: 768px) {
            .slides-sidebar {
                flex: 0 0 200px !important;
            }

            .slide-preview {
                height: 105px; /* 180px容器宽度，180/1280=0.141，720*0.141=101.52px */
            }
            .slide-preview iframe {
                transform: scale(0.141);
            }

            .slide-title {
                font-size: 8px;
                padding: 2px 1px;
                height: 18px;
            }

            .slides-container {
                gap: 3px;
                padding: 3px;
            }

        }

        @media (max-width: 576px) {
            .editor-container {
                margin: 10px;
            }

            .slides-sidebar {
                flex: 0 0 180px !important;
            }

            .slide-preview {
                height: 95px; /* 160px容器宽度，160/1280=0.125，720*0.125=90px */
            }
            .slide-preview iframe {
                transform: scale(0.125);
            }

            .slide-title {
                font-size: 7px;
                padding: 2px 1px;
                height: 16px;
            }


            /* 小屏幕上的导出按钮优化 */
            .btn-group-custom {
                gap: var(--spacing-xs);
            }

            .btn-group-custom .btn {
                width: 38px;
                height: 38px;
                font-size: 14px;
            }

            .mode-toggle {
                width: 38px;
                height: 38px;
                font-size: 14px;
            }

            .export-section {
                padding: 12px 16px;
            }

            /* 悬浮提示在小屏幕上的优化 */
            [title]:hover::after {
                font-size: 11px;
                padding: 6px 10px;
            }
        }

        /* 右键菜单样式 */
        .context-menu {
            position: fixed;
            background: white;
            border: 1px solid #ddd;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15);
            z-index: 2000;
            min-width: 180px;
            display: none;
            overflow: hidden;
        }

        .context-menu-item {
            padding: 12px 16px;
            cursor: pointer;
            border-bottom: 1px solid #f0f0f0;
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 14px;
            color: #333;
            transition: background-color 0.2s ease;
        }

        .context-menu-item:last-child {
            border-bottom: none;
        }

        .context-menu-item:hover {
            background: #f8f9fa;
        }

        .context-menu-item.disabled {
            color: #999;
            cursor: not-allowed;
        }

        .context-menu-item.disabled:hover {
            background: white;
        }

        .context-menu-item i {
            width: 16px;
            text-align: center;
        }

        /* 通知样式 */
        .notification {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 20px;
            border-radius: 8px;
            color: white;
            font-weight: bold;
            z-index: 10000;
            max-width: 300px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            animation: slideInRight 0.3s ease;
        }

        .notification-info {
            background: #17a2b8;
        }

        .notification-success {
            background: #28a745;
        }

        .notification-warning {
            background: #ffc107;
            color: #212529;
        }

        .notification-error {
            background: #dc3545;
        }

        @keyframes slideInRight {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }

        /* 拖拽指示器 */
        .drag-indicator {
            position: absolute;
            left: 5px;
            right: 5px;
            height: 3px;
            background: #ffc107;
            border-radius: 2px;
            display: none;
            z-index: 100;
        }

        .drag-indicator.top {
            top: -2px;
        }

        .drag-indicator.bottom {
            bottom: -2px;
        }

        .drag-indicator.show {
            display: block;
        }

        /* AI编辑侧栏样式 - 与页面风格统一 */
        .ai-edit-sidebar {
            position: fixed;
            top: 0;
            right: -650px; /* 增加默认宽度 */
            width: 650px; /* 增加默认宽度 */
            height: 100vh;
            background: var(--glass-bg);
            backdrop-filter: blur(30px);
            border: 1px solid var(--glass-border);
            border-right: none;
            border-radius: var(--border-radius-xl) 0 0 var(--border-radius-xl);
            box-shadow: var(--glass-shadow);
            z-index: 2000;
            transition: right 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            flex-direction: column;
            resize: horizontal; /* 允许水平调整大小 */
            min-width: 500px; /* 最小宽度 */
            max-width: 1000px; /* 最大宽度 */
            overflow: hidden;
        }

        .ai-edit-sidebar.open {
            right: 0;
        }

        .ai-edit-sidebar::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 20% 20%, rgba(79, 172, 254, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 80% 80%, rgba(67, 233, 123, 0.1) 0%, transparent 50%);
            pointer-events: none;
            z-index: -1;
        }

        .ai-edit-sidebar-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-sm) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            overflow: hidden;
            z-index: 10;
            border-radius: var(--border-radius-xl) 0 0 0;
        }

        .ai-edit-sidebar-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
            animation: headerFloat 25s ease-in-out infinite;
        }

        .ai-edit-sidebar-header h4 {
            margin: 0;
            font-size: 1.125rem;
            font-weight: 700;
            flex: 1;
            position: relative;
            z-index: 1;
            text-shadow: 0 2px 8px rgba(0,0,0,0.3);
            letter-spacing: -0.01em;
        }

        .ai-current-slide-info {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            padding: 2px var(--spacing-xs);
            border-radius: var(--border-radius-md);
            font-size: 0.75rem;
            font-weight: 600;
            margin-right: var(--spacing-sm);
            color: white;
            text-shadow: 0 1px 3px rgba(0,0,0,0.3);
            position: relative;
            z-index: 1;
        }

        .ai-header-buttons {
            display: flex;
            gap: var(--spacing-sm);
            align-items: center;
            position: relative;
            z-index: 1;
        }

        .ai-outline-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            color: white;
            padding: var(--spacing-xs) var(--spacing-sm);
            border-radius: var(--border-radius-sm);
            cursor: pointer;
            font-size: 0.875rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            overflow: hidden;
        }

        .ai-outline-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-outline-btn:hover {
            background: rgba(255,255,255,0.2);
            border-color: rgba(255,255,255,0.4);
            transform: translateY(-1px);
            box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2);
        }

        .ai-outline-btn:hover::before {
            left: 100%;
        }

        .ai-sidebar-resize-handle {
            position: absolute;
            left: 0;
            top: 0;
            width: 6px;
            height: 100%;
            background: transparent;
            cursor: ew-resize;
            z-index: 10;
            transition: background 0.3s ease;
        }

        .ai-sidebar-resize-handle:hover {
            background: var(--accent-gradient);
            opacity: 0.6;
        }

        .ai-edit-sidebar-close {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            color: white;
            font-size: 1.125rem;
            cursor: pointer;
            padding: var(--spacing-xs);
            border-radius: var(--border-radius-sm);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
        }

        .ai-edit-sidebar-close::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-edit-sidebar-close:hover {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.4);
            transform: translateY(-1px) scale(1.05);
            box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2);
        }

        .ai-edit-sidebar-close:hover::before {
            left: 100%;
        }

        .ai-edit-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: var(--spacing-xl);
            overflow: hidden;
            position: relative;
        }



        .ai-chat-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            position: relative;
        }

        .ai-chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: var(--spacing-md);
            margin-bottom: var(--spacing-md);
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            box-shadow: 0 4px 15px rgba(31, 38, 135, 0.1);
            position: relative;
        }

        .ai-chat-messages::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 10% 10%, rgba(79, 172, 254, 0.05) 0%, transparent 50%),
                radial-gradient(circle at 90% 90%, rgba(67, 233, 123, 0.05) 0%, transparent 50%);
            pointer-events: none;
            z-index: -1;
        }

        .ai-message {
            margin: var(--spacing-sm) var(--spacing-md);
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--border-radius-md);
            max-width: 85%;
            word-wrap: break-word;
            position: relative;
            backdrop-filter: blur(10px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .ai-message.user {
            background: var(--primary-gradient);
            color: white;
            margin-left: auto;
            margin-right: var(--spacing-md);
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }

        .ai-message.assistant {
            background: var(--glass-bg);
            color: var(--text-primary);
            border: 1px solid var(--glass-border);
            margin-right: auto;
            margin-left: var(--spacing-md);
            box-shadow: 0 4px 15px rgba(31, 38, 135, 0.1);
        }

        .ai-message.system {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-muted);
            font-style: italic;
            text-align: center;
            margin: var(--spacing-xs) var(--spacing-md);
            font-size: 0.75rem;
            border: 1px solid var(--glass-border);
            backdrop-filter: blur(10px);
        }

        .ai-message:hover {
            transform: translateY(-1px);
            box-shadow: 0 6px 20px rgba(31, 38, 135, 0.2);
        }

        .ai-input-container {
            display: flex;
            flex-direction: column;
            gap: var(--spacing-sm);
            position: relative;
            border: 2px solid transparent;
            border-radius: var(--border-radius-md);
            padding: var(--spacing-sm);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .ai-input-container.drag-over {
            background-color: rgba(79, 172, 254, 0.1) !important;
            border-color: rgba(79, 172, 254, 0.6) !important;
            transform: scale(1.02) !important;
            box-shadow: 0 8px 25px rgba(79, 172, 254, 0.3) !important;
        }

        .ai-input-container.drag-over::before {
            content: '📷 释放图片到此处上传';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(79, 172, 254, 0.9);
            color: white;
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--border-radius-md);
            font-size: 0.875rem;
            font-weight: 600;
            z-index: 1000;
            pointer-events: none;
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.4);
        }

        /* 选中图像信息容器样式 */
        .ai-selected-image-container {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            margin-bottom: var(--spacing-md);
            overflow: hidden;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .ai-selected-image-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-sm) var(--spacing-md);
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 0.875rem;
            font-weight: 600;
        }

        .ai-selected-image-header h6 {
            margin: 0;
            font-size: 0.875rem;
            font-weight: 600;
        }

        .ai-clear-selection-btn {
            background: rgba(255, 255, 255, 0.2);
            border: 1px solid rgba(255, 255, 255, 0.3);
            color: white;
            border-radius: var(--border-radius-sm);
            padding: 4px 8px;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 0.75rem;
        }

        .ai-clear-selection-btn:hover {
            background: rgba(255, 255, 255, 0.3);
            border-color: rgba(255, 255, 255, 0.5);
            transform: scale(1.05);
        }

        .ai-selected-image-info {
            padding: var(--spacing-md);
            display: flex;
            gap: var(--spacing-md);
            align-items: flex-start;
        }

        .ai-selected-image-preview {
            flex-shrink: 0;
            width: 60px;
            height: 60px;
            border-radius: var(--border-radius-sm);
            overflow: hidden;
            border: 2px solid var(--glass-border);
        }

        .ai-selected-image-preview img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .ai-selected-image-details {
            flex: 1;
            display: flex;
            flex-direction: column;
            gap: var(--spacing-xs);
        }

        .ai-image-detail-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 0.8125rem;
        }

        .ai-detail-label {
            color: var(--text-secondary);
            font-weight: 500;
        }

        .ai-detail-value {
            color: var(--text-primary);
            font-weight: 600;
            text-align: right;
            max-width: 120px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .ai-image-actions {
            padding: var(--spacing-sm) var(--spacing-md);
            border-top: 1px solid var(--glass-border);
            background: rgba(255, 255, 255, 0.02);
        }

        .ai-image-action-row {
            display: flex;
            gap: var(--spacing-xs);
            margin-bottom: var(--spacing-xs);
        }

        .ai-image-action-row:last-child {
            margin-bottom: 0;
        }

        .ai-regenerate-image-btn,
        .ai-replace-image-btn,
        .ai-delete-image-btn {
            flex: 1;
            border: none;
            color: white;
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--border-radius-sm);
            font-size: 0.875rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: var(--spacing-xs);
        }

        .ai-regenerate-image-btn {
            background: var(--accent-gradient);
        }

        .ai-regenerate-image-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 15px rgba(67, 233, 123, 0.3);
        }

        .ai-replace-image-btn {
            background: var(--primary-gradient);
        }

        .ai-replace-image-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.3);
        }

        .ai-delete-image-btn {
            background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
            width: 100%;
        }

        .ai-delete-image-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
        }

        .ai-regenerate-image-btn:active,
        .ai-replace-image-btn:active,
        .ai-delete-image-btn:active {
            transform: translateY(0);
        }

        .ai-input-box {
            width: 100%;
            min-height: 80px;
            max-height: 120px;
            padding: var(--spacing-sm);
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            resize: vertical;
            font-family: inherit;
            font-size: 0.875rem;
            color: var(--text-primary);
            outline: none;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-input-box:focus {
            border-color: rgba(79, 172, 254, 0.6);
            box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.2), 0 4px 15px rgba(31, 38, 135, 0.2);
            transform: translateY(-1px);
        }

        .ai-input-box::placeholder {
            color: var(--text-muted);
            opacity: 0.8;
        }

        .ai-input-buttons {
            display: flex;
            gap: var(--spacing-sm);
            align-items: center;
            justify-content: flex-end;
        }

        .ai-send-btn {
            background: var(--primary-gradient);
            color: white;
            border: none;
            padding: var(--spacing-sm) var(--spacing-lg);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            font-weight: 600;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            overflow: hidden;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
        }

        .ai-send-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-send-btn:hover {
            transform: translateY(-2px) scale(1.02);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
        }

        .ai-send-btn:hover::before {
            left: 100%;
        }

        .ai-send-btn:disabled {
            background: var(--text-muted);
            cursor: not-allowed;
            transform: none;
            box-shadow: 0 2px 8px rgba(113, 128, 150, 0.2);
        }

        .ai-send-btn:disabled::before {
            display: none;
        }

        .ai-clear-context-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-secondary);
            padding: var(--spacing-sm);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            width: 44px;
            height: 44px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-clear-context-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-clear-context-btn:hover {
            background: rgba(220, 53, 69, 0.1);
            border-color: rgba(220, 53, 69, 0.3);
            color: #dc3545;
            transform: translateY(-2px) scale(1.05);
            box-shadow: 0 4px 15px rgba(220, 53, 69, 0.2);
        }

        .ai-clear-context-btn:hover::before {
            left: 100%;
        }

        /* AI等待动画样式 - 优化设计 */
        .ai-waiting {
            display: flex;
            align-items: center;
            opacity: 0.9;
            padding: var(--spacing-sm);
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            margin: var(--spacing-sm) var(--spacing-md);
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-typing-indicator {
            display: flex;
            gap: var(--spacing-xs);
            margin-right: var(--spacing-sm);
        }

        .ai-typing-indicator span {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--accent-gradient);
            animation: typing 1.4s infinite ease-in-out;
            box-shadow: 0 2px 4px rgba(79, 172, 254, 0.3);
        }

        .ai-typing-indicator span:nth-child(1) {
            animation-delay: -0.32s;
        }

        .ai-typing-indicator span:nth-child(2) {
            animation-delay: -0.16s;
        }

        .ai-typing-indicator span:nth-child(3) {
            animation-delay: 0s;
        }

        @keyframes typing {
            0%, 80%, 100% {
                transform: scale(0.8);
                opacity: 0.5;
            }
            40% {
                transform: scale(1.2);
                opacity: 1;
            }
        }

        /* 侧栏遮罩层 - 优化设计 */
        .ai-sidebar-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.4);
            backdrop-filter: blur(8px);
            z-index: 1999;
            opacity: 0;
            visibility: hidden;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .ai-sidebar-overlay.show {
            opacity: 1;
            visibility: visible;
        }

        /* AI图片上传按钮样式 */
        .ai-image-upload-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-secondary);
            padding: var(--spacing-sm);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            width: 44px;
            height: 44px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-image-upload-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-image-upload-btn:hover {
            background: rgba(79, 172, 254, 0.1);
            border-color: rgba(79, 172, 254, 0.3);
            color: rgba(79, 172, 254, 0.8);
            transform: translateY(-2px) scale(1.05);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.2);
        }

        .ai-image-upload-btn:hover::before {
            left: 100%;
        }

        .ai-image-upload-btn.has-images {
            background: rgba(67, 233, 123, 0.1);
            border-color: rgba(67, 233, 123, 0.3);
            color: rgba(67, 233, 123, 0.8);
        }

        .ai-image-upload-btn.has-images::after {
            content: attr(data-count);
            position: absolute;
            top: -6px;
            right: -6px;
            background: #28a745;
            color: white;
            border-radius: 50%;
            width: 18px;
            height: 18px;
            font-size: 0.625rem;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            box-shadow: 0 2px 4px rgba(40, 167, 69, 0.3);
        }

        /* AI视觉模式切换按钮样式 */
        .ai-vision-toggle-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-secondary);
            padding: var(--spacing-sm);
            border-radius: var(--border-radius);
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
            min-width: 40px;
            height: 40px;
            justify-content: center;
            position: relative;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-vision-toggle-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-vision-toggle-btn:hover {
            background: rgba(240, 147, 251, 0.1);
            border-color: rgba(240, 147, 251, 0.3);
            color: rgba(240, 147, 251, 0.8);
            transform: translateY(-2px) scale(1.05);
            box-shadow: 0 4px 15px rgba(240, 147, 251, 0.2);
        }

        .ai-vision-toggle-btn:hover::before {
            left: 100%;
        }

        .ai-vision-toggle-btn.active {
            background: rgba(67, 233, 123, 0.1);
            border-color: rgba(67, 233, 123, 0.3);
            color: rgba(67, 233, 123, 0.8);
            box-shadow: 0 0 20px rgba(67, 233, 123, 0.3);
        }

        .ai-vision-toggle-btn.active::after {
            content: '';
            position: absolute;
            top: -2px;
            right: -2px;
            width: 8px;
            height: 8px;
            background: #43e97b;
            border-radius: 50%;
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% {
                transform: scale(0.95);
                box-shadow: 0 0 0 0 rgba(67, 233, 123, 0.7);
            }
            70% {
                transform: scale(1);
                box-shadow: 0 0 0 10px rgba(67, 233, 123, 0);
            }
            100% {
                transform: scale(0.95);
                box-shadow: 0 0 0 0 rgba(67, 233, 123, 0);
            }
        }

        /* AI重新生成按钮样式 */
        .ai-regenerate-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-secondary);
            padding: var(--spacing-sm);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            width: 44px;
            height: 44px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(31, 38, 135, 0.1);
        }

        .ai-regenerate-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .ai-regenerate-btn:hover {
            background: rgba(255, 193, 7, 0.1);
            border-color: rgba(255, 193, 7, 0.3);
            color: rgba(255, 193, 7, 0.8);
            transform: translateY(-2px) scale(1.05);
            box-shadow: 0 4px 15px rgba(255, 193, 7, 0.2);
        }

        .ai-regenerate-btn:hover::before {
            left: 100%;
        }

        .ai-regenerate-btn:hover i {
            animation: spin 1s linear infinite;
        }

        /* 快速编辑模式样式 */
        .quick-edit-mode .slide-frame {
            cursor: pointer;
        }

        .quick-edit-overlay {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(79, 172, 254, 0.05);
            border: 2px dashed rgba(79, 172, 254, 0.3);
            border-radius: var(--border-radius-md);
            display: none;
            z-index: 10;
            pointer-events: none;
        }

        .quick-edit-mode .quick-edit-overlay {
            display: block;
        }

        .quick-edit-overlay::before {
            content: '💡 点击文本直接编辑 | Enter保存 | ESC取消 | 再次点击修改退出';
            position: absolute;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(79, 172, 254, 0.9);
            color: white;
            padding: var(--spacing-xs) var(--spacing-sm);
            border-radius: var(--border-radius-sm);
            font-size: 0.60rem;
            font-weight: 500;
            white-space: nowrap;
            box-shadow: 0 2px 8px rgba(79, 172, 254, 0.3);
            animation: fadeInDown 0.5s ease;
        }

        @keyframes fadeInDown {
            from {
                opacity: 0;
                transform: translateX(-50%) translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateX(-50%) translateY(0);
            }
        }

        /* 可编辑元素高亮样式 */
        .quick-edit-highlight {
            outline: 2px solid rgba(67, 233, 123, 0.6) !important;
            outline-offset: 2px !important;
            background: rgba(67, 233, 123, 0.1) !important;
            cursor: text !important;
            transition: all 0.3s ease !important;
            position: relative !important;
        }

        .quick-edit-highlight:hover {
            outline-color: rgba(67, 233, 123, 0.8) !important;
            background: rgba(67, 233, 123, 0.2) !important;
            transform: scale(1.02) !important;
        }

        .quick-edit-highlight::before {
            content: '✏️';
            position: absolute !important;
            top: -8px !important;
            right: -8px !important;
            background: rgba(67, 233, 123, 0.9) !important;
            color: white !important;
            border-radius: 50% !important;
            width: 20px !important;
            height: 20px !important;
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
            font-size: 10px !important;
            z-index: 1000 !important;
            box-shadow: 0 2px 4px rgba(67, 233, 123, 0.3) !important;
        }

        /* 直接编辑状态样式 */
        .direct-editing {
            outline: 2px solid #4facfe !important;
            outline-offset: 2px !important;
            background: rgba(79, 172, 254, 0.1) !important;
            border-radius: 4px !important;
            padding: 2px 4px !important;
            transition: all 0.3s ease !important;
            position: relative !important;
        }

        /* 魔术棒按钮样式 */
        .magic-wand-btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
            color: white !important;
            border: none !important;
            border-radius: 50% !important;
            width: 28px !important;
            height: 28px !important;
            cursor: pointer !important;
            margin-left: 8px !important;
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
            font-size: 14px !important;
            transition: all 0.3s ease !important;
            opacity: 0.7 !important;
            position: relative !important;
            overflow: hidden !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3) !important;
        }

        .magic-wand-btn::before {
            content: '' !important;
            position: absolute !important;
            top: 0 !important;
            left: -100% !important;
            width: 100% !important;
            height: 100% !important;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent) !important;
            transition: left 0.6s !important;
        }

        .magic-wand-btn:hover {
            opacity: 1 !important;
            transform: translateY(-2px) scale(1.1) !important;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.5) !important;
            background: linear-gradient(135deg, #7c8cff 0%, #8a5cb8 100%) !important;
        }

        .magic-wand-btn:hover::before {
            left: 100% !important;
        }

        .magic-wand-btn:active {
            transform: translateY(0) scale(1.05) !important;
        }

        .magic-wand-btn:disabled {
            opacity: 0.5 !important;
            cursor: not-allowed !important;
            transform: none !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2) !important;
        }

        .magic-wand-btn:disabled:hover {
            transform: none !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2) !important;
        }

        /* 删除要点按钮样式 */
        .delete-bullet-btn {
            background: #dc3545 !important;
            color: white !important;
            border: none !important;
            border-radius: 50% !important;
            width: 28px !important;
            height: 28px !important;
            cursor: pointer !important;
            margin-left: 4px !important;
            display: flex !important;
            align-items: center !important;
            justify-content: center !important;
            font-size: 12px !important;
            transition: all 0.3s ease !important;
            opacity: 0.7 !important;
            box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3) !important;
        }

        .delete-bullet-btn:hover {
            opacity: 1 !important;
            transform: translateY(-2px) scale(1.1) !important;
            box-shadow: 0 4px 15px rgba(220, 53, 69, 0.5) !important;
            background: #c82333 !important;
        }

        .delete-bullet-btn:active {
            transform: translateY(0) scale(1.05) !important;
        }

        /* 要点项悬停效果 */
        .bullet-point-item:hover .delete-bullet-btn {
            opacity: 1 !important;
        }

        .bullet-point-item:hover {
            background: rgba(0, 0, 0, 0.02) !important;
            border-radius: 6px !important;
            transform: translateX(2px) !important;
        }

        /* 增强所有要点按钮样式 */
        .enhance-all-btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
            color: white !important;
            border: none !important;
            padding: 8px 16px !important;
            border-radius: 6px !important;
            cursor: pointer !important;
            font-size: 14px !important;
            transition: all 0.3s ease !important;
            display: flex !important;
            align-items: center !important;
            gap: 6px !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3) !important;
            position: relative !important;
            overflow: hidden !important;
        }

        .enhance-all-btn::before {
            content: '' !important;
            position: absolute !important;
            top: 0 !important;
            left: -100% !important;
            width: 100% !important;
            height: 100% !important;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent) !important;
            transition: left 0.6s !important;
        }

        .enhance-all-btn:hover {
            transform: translateY(-2px) scale(1.02) !important;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.5) !important;
            background: linear-gradient(135deg, #7c8cff 0%, #8a5cb8 100%) !important;
        }

        .enhance-all-btn:hover::before {
            left: 100% !important;
        }

        .enhance-all-btn:active {
            transform: translateY(0) scale(1.0) !important;
        }

        .enhance-all-btn:disabled {
            opacity: 0.6 !important;
            cursor: not-allowed !important;
            transform: none !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2) !important;
        }

        .enhance-all-btn:disabled:hover {
            transform: none !important;
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2) !important;
        }

        .direct-editing::before {
            content: '📝 正在编辑... (Enter保存 / ESC取消)';
            position: absolute !important;
            top: -30px !important;
            left: 0 !important;
            background: rgba(79, 172, 254, 0.9) !important;
            color: white !important;
            padding: 4px 8px !important;
            border-radius: 4px !important;
            font-size: 11px !important;
            font-weight: 600 !important;
            white-space: nowrap !important;
            z-index: 1001 !important;
            box-shadow: 0 2px 8px rgba(79, 172, 254, 0.3) !important;
            animation: fadeInDown 0.3s ease !important;
        }

        .direct-editing:focus {
            outline-color: #2980b9 !important;
            background: rgba(79, 172, 254, 0.15) !important;
        }

        /* 内联编辑器样式 */
        .inline-editor {
            position: absolute;
            background: white;
            border: 2px solid rgba(79, 172, 254, 0.6);
            border-radius: var(--border-radius-md);
            box-shadow: 0 8px 25px rgba(31, 38, 135, 0.3);
            z-index: 2000;
            min-width: 200px;
            max-width: 500px;
            padding: var(--spacing-sm);
            backdrop-filter: blur(15px);
        }

        .inline-editor-input {
            width: 100%;
            border: none;
            outline: none;
            font-family: inherit;
            font-size: inherit;
            color: inherit;
            background: transparent;
            resize: none;
            min-height: 30px;
            padding: var(--spacing-xs);
        }

        .inline-editor-toolbar {
            display: flex;
            gap: var(--spacing-xs);
            align-items: center;
            justify-content: flex-end;
            margin-top: var(--spacing-xs);
            padding-top: var(--spacing-xs);
            border-top: 1px solid rgba(79, 172, 254, 0.2);
        }

        .inline-editor-btn {
            background: rgba(79, 172, 254, 0.1);
            border: 1px solid rgba(79, 172, 254, 0.3);
            color: rgba(79, 172, 254, 0.8);
            padding: var(--spacing-xs) var(--spacing-sm);
            border-radius: var(--border-radius-sm);
            cursor: pointer;
            font-size: 0.75rem;
            transition: all 0.3s ease;
        }

        .inline-editor-btn:hover {
            background: rgba(79, 172, 254, 0.2);
            border-color: rgba(79, 172, 254, 0.5);
            color: rgba(79, 172, 254, 1);
        }

        .inline-editor-btn.primary {
            background: rgba(67, 233, 123, 0.1);
            border-color: rgba(67, 233, 123, 0.3);
            color: rgba(67, 233, 123, 0.8);
        }

        .inline-editor-btn.primary:hover {
            background: rgba(67, 233, 123, 0.2);
            border-color: rgba(67, 233, 123, 0.5);
            color: rgba(67, 233, 123, 1);
        }

        @keyframes spin {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
        }



        @keyframes fadeIn {
            from {
                opacity: 0;
                transform: translateY(-5px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* 图片选择菜单样式 */
        .image-select-menu {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            backdrop-filter: blur(5px);
            z-index: 9999;
            display: flex;
            align-items: center;
            justify-content: center;
            animation: fadeInOverlay 0.3s ease-out;
        }

        .image-select-content {
            background: var(--glass-bg);
            backdrop-filter: blur(20px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-xl);
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
            width: 400px;
            max-width: 90vw;
            overflow: hidden;
            animation: slideInPreview 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .image-select-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            overflow: hidden;
        }

        .image-select-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
            pointer-events: none;
        }

        .image-select-header h4 {
            margin: 0;
            font-size: 1.125rem;
            font-weight: 600;
            position: relative;
            z-index: 1;
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
        }

        .image-select-close {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            color: white;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 0.875rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            z-index: 1;
        }

        .image-select-close:hover {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.4);
            transform: scale(1.1);
        }

        .image-select-options {
            padding: var(--spacing-lg);
            display: flex;
            flex-direction: column;
            gap: var(--spacing-md);
        }

        .image-select-option {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            padding: var(--spacing-md);
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            text-align: left;
            display: flex;
            flex-direction: column;
            gap: var(--spacing-xs);
            position: relative;
            overflow: hidden;
        }

        .image-select-option::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(79, 172, 254, 0.1), transparent);
            transition: left 0.6s;
        }

        .image-select-option:hover {
            background: rgba(79, 172, 254, 0.1);
            border-color: rgba(79, 172, 254, 0.3);
            transform: translateY(-2px);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.2);
        }

        .image-select-option:hover::before {
            left: 100%;
        }

        .image-select-option i {
            font-size: 1.5rem;
            color: rgba(79, 172, 254, 0.8);
            margin-bottom: var(--spacing-xs);
        }

        .image-select-option span {
            font-size: 1rem;
            font-weight: 600;
            color: var(--text-primary);
            position: relative;
            z-index: 1;
        }

        .image-select-option small {
            font-size: 0.8125rem;
            color: var(--text-muted);
            position: relative;
            z-index: 1;
        }

        /* 图床选择器样式 */
        .image-library-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            backdrop-filter: blur(10px);
            z-index: 10001;
            display: flex;
            align-items: center;
            justify-content: center;
            animation: fadeInOverlay 0.3s ease-out;
        }

        .image-library-container {
            background: var(--glass-bg);
            backdrop-filter: blur(20px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-xl);
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
            width: 80vw;
            max-width: 1000px;
            height: 80vh;
            max-height: 800px;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            animation: slideInPreview 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .image-library-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            overflow: hidden;
        }

        .image-library-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
            pointer-events: none;
        }

        .image-library-info {
            position: relative;
            z-index: 1;
        }

        .image-library-info h4 {
            margin: 0 0 4px 0;
            font-size: 1.25rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
        }

        .image-library-info p {
            margin: 0;
            font-size: 0.875rem;
            opacity: 0.9;
        }

        .image-library-close {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            color: white;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 1.125rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            z-index: 1;
        }

        .image-library-close:hover {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.4);
            transform: scale(1.1);
        }

        .image-library-content {
            flex: 1;
            padding: var(--spacing-lg);
            overflow-y: auto;
            position: relative;
        }

        .image-library-search {
            margin-bottom: var(--spacing-md);
            position: sticky;
            top: 0;
            z-index: 10;
            background: var(--glass-bg);
            backdrop-filter: blur(20px);
            padding: var(--spacing-sm) 0;
            border-radius: var(--border-radius-lg);
        }

        .search-input-group {
            position: relative;
            display: flex;
            align-items: center;
        }

        .search-input-group i.fa-search {
            position: absolute;
            left: var(--spacing-sm);
            color: var(--text-muted);
            z-index: 1;
        }

        .search-input-group input {
            width: 100%;
            padding: var(--spacing-sm) var(--spacing-xl) var(--spacing-sm) 2.5rem;
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-lg);
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-primary);
            font-size: 0.875rem;
            transition: all 0.3s ease;
        }

        .search-input-group input:focus {
            outline: none;
            border-color: var(--primary-color);
            background: rgba(255, 255, 255, 0.15);
            box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
        }

        .search-input-group input::placeholder {
            color: var(--text-muted);
        }

        .search-clear-btn {
            position: absolute;
            right: var(--spacing-sm);
            background: none;
            border: none;
            color: var(--text-muted);
            cursor: pointer;
            padding: var(--spacing-xs);
            border-radius: 50%;
            transition: all 0.2s ease;
            z-index: 1;
        }

        .search-clear-btn:hover {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-primary);
        }

        .image-library-loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            color: var(--text-primary);
        }

        .image-library-loading i {
            font-size: 2rem;
            margin-bottom: var(--spacing-sm);
            color: rgba(79, 172, 254, 0.8);
        }

        .image-library-loading p {
            margin: 0;
            font-size: 0.875rem;
            opacity: 0.8;
        }

        .image-library-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: var(--spacing-md);
            padding: var(--spacing-sm);
        }

        .image-library-item {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 2px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            overflow: hidden;
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            aspect-ratio: 1;
        }

        .image-library-item:hover {
            transform: scale(1.05);
            border-color: rgba(79, 172, 254, 0.6);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.3);
        }

        .image-library-item.selected {
            border-color: rgba(67, 233, 123, 0.8);
            background: rgba(67, 233, 123, 0.1);
            transform: scale(1.02);
        }

        .image-library-item img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .image-library-item .image-info {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: var(--spacing-xs);
            font-size: 0.75rem;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .image-library-item:hover .image-info {
            opacity: 1;
        }

        .image-library-item .selection-indicator {
            position: absolute;
            top: 8px;
            right: 8px;
            width: 24px;
            height: 24px;
            background: rgba(67, 233, 123, 0.9);
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 0.875rem;
            opacity: 0;
            transform: scale(0.8);
            transition: all 0.3s ease;
        }

        .image-library-item.selected .selection-indicator {
            opacity: 1;
            transform: scale(1);
        }

        .image-library-empty {
            text-align: center;
            color: var(--text-muted);
            padding: var(--spacing-xl);
        }

        .image-library-empty i {
            font-size: 3rem;
            margin-bottom: var(--spacing-md);
            opacity: 0.5;
        }

        .image-library-empty p {
            margin: 0 0 var(--spacing-xs) 0;
            font-size: 1.125rem;
            font-weight: 600;
        }

        .image-library-empty small {
            font-size: 0.875rem;
            opacity: 0.8;
        }

        .image-library-pagination {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-top: 1px solid var(--glass-border);
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .pagination-info {
            color: var(--text-muted);
            font-size: 0.875rem;
        }

        .pagination-controls {
            display: flex;
            gap: var(--spacing-sm);
        }

        .pagination-btn {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-primary);
            padding: var(--spacing-xs) var(--spacing-sm);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 0.875rem;
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
        }

        .pagination-btn:hover:not(:disabled) {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.4);
            transform: translateY(-1px);
        }

        .pagination-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
        }

        .image-library-actions {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-top: 1px solid var(--glass-border);
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            gap: var(--spacing-md);
            justify-content: flex-end;
        }

        .image-library-action {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-primary);
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            font-weight: 500;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
            min-width: 120px;
            justify-content: center;
        }

        .image-library-action:hover:not(:disabled) {
            background: rgba(79, 172, 254, 0.1);
            border-color: rgba(79, 172, 254, 0.3);
            color: rgba(79, 172, 254, 0.8);
            transform: translateY(-2px);
        }

        .image-library-action:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .image-library-action.secondary {
            background: rgba(108, 117, 125, 0.1);
            border-color: rgba(108, 117, 125, 0.3);
        }

        .image-library-action.secondary:hover {
            background: rgba(108, 117, 125, 0.2);
            border-color: rgba(108, 117, 125, 0.4);
            color: rgba(108, 117, 125, 0.9);
        }

        /* 响应式设计 - 图片选择器 */
        @media (max-width: 768px) {
            .image-select-content {
                width: 95vw;
                margin: 0 10px;
            }

            .image-select-options {
                padding: var(--spacing-md);
                gap: var(--spacing-sm);
            }

            .image-select-option {
                padding: var(--spacing-sm);
            }

            .image-library-container {
                width: 95vw;
                height: 90vh;
                margin: 0 10px;
            }

            .image-library-grid {
                grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
                gap: var(--spacing-sm);
            }

            .image-library-actions {
                padding: var(--spacing-sm);
                flex-direction: column;
                gap: var(--spacing-sm);
            }

            .image-library-action {
                width: 100%;
                min-width: auto;
            }
        }

        /* 全屏图片预览样式 */
        .image-preview-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.9);
            backdrop-filter: blur(10px);
            z-index: 10000;
            display: flex;
            align-items: center;
            justify-content: center;
            animation: fadeInOverlay 0.3s ease-out;
        }

        @keyframes fadeInOverlay {
            from {
                opacity: 0;
            }
            to {
                opacity: 1;
            }
        }

        .image-preview-container {
            max-width: 90vw;
            max-height: 90vh;
            background: var(--glass-bg);
            backdrop-filter: blur(20px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-xl);
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
            display: flex;
            flex-direction: column;
            overflow: hidden;
            animation: slideInPreview 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        @keyframes slideInPreview {
            from {
                opacity: 0;
                transform: scale(0.8) translateY(20px);
            }
            to {
                opacity: 1;
                transform: scale(1) translateY(0);
            }
        }

        .image-preview-header {
            background: var(--primary-gradient);
            color: white;
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
            overflow: hidden;
        }

        .image-preview-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background:
                radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
                radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
            pointer-events: none;
        }

        .image-preview-info {
            position: relative;
            z-index: 1;
        }

        .image-preview-info h4 {
            margin: 0 0 4px 0;
            font-size: 1.125rem;
            font-weight: 600;
        }

        .image-preview-info p {
            margin: 0;
            font-size: 0.875rem;
            opacity: 0.9;
        }

        .image-preview-close {
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            color: white;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 1.125rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            z-index: 1;
            overflow: hidden;
        }

        .image-preview-close::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .image-preview-close:hover {
            background: rgba(255, 255, 255, 0.2);
            border-color: rgba(255, 255, 255, 0.4);
            transform: scale(1.1);
            box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2);
        }

        .image-preview-close:hover::before {
            left: 100%;
        }

        .image-preview-content {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            min-height: 400px;
            max-height: 70vh;
            overflow: hidden;
            background: rgba(0, 0, 0, 0.3);
        }

        .image-preview-content img {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
            border-radius: var(--border-radius-md);
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            transition: transform 0.3s ease;
        }

        .image-preview-content img:hover {
            transform: scale(1.02);
        }

        .image-preview-loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            color: white;
        }

        .image-preview-loading i {
            font-size: 2rem;
            margin-bottom: var(--spacing-sm);
            color: rgba(79, 172, 254, 0.8);
        }

        .image-preview-loading p {
            margin: 0;
            font-size: 0.875rem;
            opacity: 0.8;
        }

        .image-preview-actions {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border-top: 1px solid var(--glass-border);
            padding: var(--spacing-md) var(--spacing-lg);
            display: flex;
            gap: var(--spacing-md);
            justify-content: center;
        }

        .image-preview-action {
            background: var(--glass-bg);
            backdrop-filter: blur(15px);
            border: 1px solid var(--glass-border);
            color: var(--text-primary);
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--border-radius-md);
            cursor: pointer;
            font-size: 0.875rem;
            font-weight: 500;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: flex;
            align-items: center;
            gap: var(--spacing-xs);
            position: relative;
            overflow: hidden;
            min-width: 120px;
            justify-content: center;
        }

        .image-preview-action::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.6s;
        }

        .image-preview-action:hover {
            background: rgba(79, 172, 254, 0.1);
            border-color: rgba(79, 172, 254, 0.3);
            color: rgba(79, 172, 254, 0.8);
            transform: translateY(-2px);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.2);
        }

        .image-preview-action:hover::before {
            left: 100%;
        }

        .image-preview-action.danger:hover {
            background: rgba(220, 53, 69, 0.1);
            border-color: rgba(220, 53, 69, 0.3);
            color: #dc3545;
            box-shadow: 0 4px 15px rgba(220, 53, 69, 0.2);
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            .image-preview-container {
                max-width: 95vw;
                max-height: 95vh;
            }

            .image-preview-header {
                padding: var(--spacing-sm) var(--spacing-md);
            }

            .image-preview-info h4 {
                font-size: 1rem;
            }

            .image-preview-info p {
                font-size: 0.75rem;
            }

            .image-preview-actions {
                padding: var(--spacing-sm) var(--spacing-md);
                flex-wrap: wrap;
            }

            .image-preview-action {
                flex: 1;
                min-width: 80px;
                font-size: 0.75rem;
                padding: var(--spacing-xs) var(--spacing-sm);
            }
        }

        .ai-upload-progress {
            margin-top: var(--spacing-md);
            padding: var(--spacing-sm);
            background: rgba(79, 172, 254, 0.05);
            border-radius: var(--border-radius-sm);
            border: 1px solid var(--glass-border);
        }

        .ai-progress-bar {
            width: 100%;
            height: 8px;
            background: rgba(79, 172, 254, 0.2);
            border-radius: 4px;
            overflow: hidden;
            margin-bottom: var(--spacing-xs);
        }

        .ai-progress-fill {
            height: 100%;
            background: var(--accent-gradient);
            border-radius: 4px;
            transition: width 0.3s ease;
            width: 0%;
        }

        .ai-progress-text {
            font-size: 0.75rem;
            color: var(--text-secondary);
            text-align: center;
        }

        .ai-uploaded-images {
            margin-top: var(--spacing-sm);
            display: flex;
            flex-wrap: wrap;
            gap: var(--spacing-xs);
            max-height: 120px;
            overflow-y: auto;
            padding: var(--spacing-xs);
            background: rgba(79, 172, 254, 0.05);
            border-radius: var(--border-radius-sm);
            border: 1px solid var(--glass-border);
        }

        .ai-uploaded-images:empty {
            display: none;
        }

        .ai-uploaded-image {
            position: relative;
            width: 50px;
            height: 50px;
            border-radius: var(--border-radius-sm);
            overflow: hidden;
            border: 2px solid var(--glass-border);
            background: var(--glass-bg);
            backdrop-filter: blur(10px);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            cursor: pointer;
            flex-shrink: 0;
        }

        .ai-uploaded-image:hover {
            transform: scale(1.1);
            border-color: rgba(79, 172, 254, 0.6);
            box-shadow: 0 4px 15px rgba(79, 172, 254, 0.3);
            z-index: 10;
        }

        .ai-uploaded-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .ai-uploaded-image .ai-image-remove {
            position: absolute;
            top: -4px;
            right: -4px;
            width: 16px;
            height: 16px;
            background: #dc3545;
            color: white;
            border: none;
            border-radius: 50%;
            font-size: 0.625rem;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
            opacity: 0;
        }

        .ai-uploaded-image:hover .ai-image-remove {
            opacity: 1;
        }

        .ai-uploaded-image .ai-image-remove:hover {
            background: #c82333;
            transform: scale(1.1);
        }

        .ai-uploaded-image .ai-image-info {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            font-size: 0.5rem;
            padding: 1px 2px;
            text-align: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .ai-uploaded-image:hover .ai-image-info {
            opacity: 1;
        }



        /* 响应式设计 - AI侧栏优化 */
        @media (max-width: 1200px) {
            .ai-edit-sidebar {
                width: 550px;
                right: -550px;
                min-width: 450px;
            }
        }

        @media (max-width: 992px) {
            .ai-edit-sidebar {
                width: 500px;
                right: -500px;
                min-width: 400px;
            }

            .ai-edit-content {
                padding: var(--spacing-lg);
            }

            .ai-edit-sidebar-header {
                padding: var(--spacing-xs) var(--spacing-md);
            }

            .ai-edit-sidebar-header h4 {
                font-size: 1rem;
            }
        }

        @media (max-width: 768px) {
            .ai-edit-sidebar {
                width: 100%;
                right: -100%;
                min-width: 100%;
                border-radius: 0;
            }

            .ai-edit-sidebar-header {
                border-radius: 0;
                padding: var(--spacing-xs) var(--spacing-sm);
            }

            .ai-edit-content {
                padding: var(--spacing-md);
            }

            .ai-input-buttons {
                flex-direction: column;
                gap: var(--spacing-sm);
            }

            .ai-send-btn {
                width: 100%;
                justify-content: center;
            }

            .ai-clear-context-btn {
                align-self: center;
            }
        }

        @media (max-width: 576px) {
            .ai-edit-sidebar-header h4 {
                font-size: 0.9rem;
            }

            .ai-current-slide-info {
                font-size: 0.6875rem;
                padding: 4px 8px;
            }



            .ai-input-box {
                min-height: 60px;
                font-size: 0.8125rem;
            }

            .ai-send-btn {
                font-size: 0.8125rem;
                padding: var(--spacing-xs) var(--spacing-sm);
            }
        }

        /* Speech Script Dialog Styles */
        .speech-modal-content {
            background: linear-gradient(145deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.85) 100%);
            backdrop-filter: blur(20px);
            border: 1px solid rgba(255, 255, 255, 0.3);
            border-radius: 24px;
            box-shadow:
                0 20px 40px rgba(0, 0, 0, 0.15),
                0 8px 32px rgba(102, 126, 234, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.8);
            overflow: hidden;
            position: relative;
        }

        .speech-modal-content::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 1px;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8), transparent);
        }

        .speech-modal-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 24px 32px;
            border-bottom: none;
            position: relative;
            overflow: hidden;
        }

        .speech-modal-header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%, rgba(255, 255, 255, 0.05) 100%);
            pointer-events: none;
        }

        .speech-modal-title {
            display: flex;
            align-items: center;
            gap: 12px;
            font-weight: 600;
            font-size: 1.25rem;
            margin: 0;
            position: relative;
            z-index: 1;
        }

        .speech-modal-icon {
            width: 32px;
            height: 32px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            backdrop-filter: blur(10px);
        }

        .speech-modal-close {
            position: absolute;
            top: 24px;
            right: 32px;
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            width: 32px;
            height: 32px;
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            backdrop-filter: blur(10px);
            z-index: 2;
        }

        .speech-modal-close:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: scale(1.05);
        }

        .speech-modal-body {
            padding: 32px;
            color: var(--text-primary);
            background: transparent;
        }

        .speech-section {
            margin-bottom: 32px;
        }

        .speech-section-title {
            color: var(--text-primary);
            font-weight: 600;
            font-size: 1rem;
            margin-bottom: 16px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .speech-section-title::before {
            content: '';
            width: 4px;
            height: 16px;
            background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
            border-radius: 2px;
        }

        .speech-modal-footer {
            background: linear-gradient(145deg, rgba(248, 249, 250, 0.8) 0%, rgba(233, 236, 239, 0.6) 100%);
            border-top: 1px solid rgba(222, 226, 230, 0.5);
            padding: 24px 32px;
            display: flex;
            gap: 12px;
            justify-content: flex-end;
            backdrop-filter: blur(10px);
        }

        .speech-generation-type-group {
            display: grid;
            grid-template-columns: 1fr 1fr 1fr;
            gap: 12px;
        }

        @media (max-width: 768px) {
            .speech-generation-type-group {
                grid-template-columns: 1fr;
                gap: 8px;
            }
        }

        .speech-type-option {
            position: relative;
        }

        .speech-type-option input[type="radio"] {
            position: absolute;
            opacity: 0;
            width: 0;
            height: 0;
        }

        .speech-type-label {
            display: flex;
            flex-direction: column;
            align-items: center;
            text-align: center;
            padding: 16px 12px;
            border: 2px solid rgba(222, 226, 230, 0.6);
            border-radius: 12px;
            background: linear-gradient(145deg, rgba(255, 255, 255, 0.8) 0%, rgba(248, 249, 250, 0.6) 100%);
            cursor: pointer;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            gap: 8px;
            position: relative;
            overflow: hidden;
            backdrop-filter: blur(10px);
            height: 100%;
            min-height: 100px;
        }

        .speech-type-label::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
            opacity: 0;
            transition: opacity 0.3s ease;
            pointer-events: none;
        }

        .speech-type-label:hover {
            border-color: rgba(102, 126, 234, 0.4);
            transform: translateY(-3px);
            box-shadow:
                0 8px 25px rgba(102, 126, 234, 0.15),
                0 3px 10px rgba(0, 0, 0, 0.1);
        }

        .speech-type-label:hover::before {
            opacity: 1;
        }

        .speech-type-option input[type="radio"]:checked + .speech-type-label {
            border-color: var(--primary-color);
            background: linear-gradient(145deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.08) 100%);
            box-shadow:
                0 8px 25px rgba(102, 126, 234, 0.2),
                0 3px 10px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.8);
            transform: translateY(-2px);
        }

        .speech-type-option input[type="radio"]:checked + .speech-type-label::before {
            opacity: 1;
        }

        .speech-type-icon {
            width: 36px;
            height: 36px;
            border-radius: 8px;
            background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            flex-shrink: 0;
            position: relative;
            box-shadow:
                0 2px 6px rgba(102, 126, 234, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
            transition: all 0.3s ease;
            margin: 0 auto;
        }

        .speech-type-icon svg {
            width: 18px;
            height: 18px;
        }

        .speech-type-option input[type="radio"]:checked + .speech-type-label .speech-type-icon {
            transform: scale(1.05);
            box-shadow:
                0 6px 16px rgba(102, 126, 234, 0.4),
                inset 0 1px 0 rgba(255, 255, 255, 0.4);
        }

        .speech-type-text {
            flex: 1;
        }

        .speech-type-title {
            font-weight: 600;
            color: var(--text-primary);
            margin-bottom: 2px;
            font-size: 14px;
            line-height: 1.2;
        }

        .speech-type-desc {
            color: var(--text-secondary);
            font-size: 12px;
            line-height: 1.3;
            opacity: 0.8;
        }

        .slide-selection-grid {
            max-height: 200px;
            overflow-y: auto;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius-lg);
            padding: var(--spacing-md);
            background: var(--bg-secondary);
        }

        .slide-selection-item {
            padding: var(--spacing-sm) 0;
            border-bottom: 1px solid var(--border-color);
        }

        .slide-selection-item:last-child {
            border-bottom: none;
        }

        /* Custom Form Elements */
        .speech-form-label {
            font-weight: 600;
            color: var(--text-primary);
            margin-bottom: var(--spacing-xs);
            display: block;
            font-size: 0.875rem;
        }

        .speech-form-select,
        .speech-form-textarea {
            width: 100%;
            padding: var(--spacing-sm) var(--spacing-md);
            border: 2px solid var(--border-color);
            border-radius: var(--border-radius);
            background: var(--bg-primary);
            color: var(--text-primary);
            font-size: 0.875rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .speech-form-select:focus,
        .speech-form-textarea:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
            background: var(--bg-primary);
        }

        .speech-form-textarea {
            resize: vertical;
            min-height: 80px;
            font-family: inherit;
            line-height: 1.5;
        }

        .speech-form-input {
            width: 100%;
            padding: var(--spacing-sm) var(--spacing-md);
            border: 2px solid var(--border-color);
            border-radius: var(--border-radius);
            background: var(--bg-primary);
            color: var(--text-primary);
            font-size: 0.875rem;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .speech-form-input:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
            background: var(--bg-primary);
        }

        .speech-form-input::placeholder {
            color: var(--text-secondary);
            opacity: 0.7;
        }

        /* Speech Scripts Styles */
        .speech-script-item {
            margin-bottom: 24px;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius);
            overflow: hidden;
            background: var(--bg-primary);
        }

        .speech-script-header {
            background: linear-gradient(145deg, rgba(248, 249, 250, 0.9) 0%, rgba(233, 236, 239, 0.8) 100%);
            padding: 16px 20px;
            border-bottom: 1px solid var(--border-color);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .speech-script-header h6 {
            margin: 0;
            color: var(--text-primary);
            font-weight: 600;
        }

        .speech-script-meta {
            display: flex;
            gap: 12px;
            align-items: center;
        }

        .speech-script-date {
            color: var(--text-secondary);
            font-size: 0.875rem;
        }

        .speech-script-duration {
            background: rgba(102, 126, 234, 0.1);
            color: var(--primary-color);
            padding: 2px 8px;
            border-radius: 12px;
            font-size: 0.75rem;
            font-weight: 500;
        }

        .speech-script-content {
            padding: 20px;
            color: var(--text-primary);
            font-size: 0.9rem;
            line-height: 1.6;
            white-space: pre-wrap;
            border-left: 3px solid var(--primary-color);
            background: rgba(248, 249, 250, 0.3);
        }

        .speech-script-actions {
            padding: 16px 20px;
            background: rgba(248, 249, 250, 0.5);
            border-top: 1px solid rgba(222, 226, 230, 0.5);
            display: flex;
            gap: 8px;
            justify-content: flex-end;
        }

        .speech-script-btn {
            display: flex;
            align-items: center;
            gap: 6px;
            padding: 8px 16px;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius);
            background: var(--bg-primary);
            color: var(--text-secondary);
            font-size: 0.875rem;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .speech-script-btn:hover {
            background: var(--primary-color);
            color: white;
            border-color: var(--primary-color);
            transform: translateY(-1px);
        }

        .speech-script-btn-danger:hover {
            background: #dc3545;
            border-color: #dc3545;
        }

        /* Speech Script Edit Styles */
        .speech-script-content-wrapper {
            position: relative;
        }

        .speech-script-edit {
            width: 100%;
            padding: 16px;
            border: 2px solid var(--primary-color);
            border-radius: var(--border-radius);
            background: var(--bg-primary);
            color: var(--text-primary);
            font-size: 0.9rem;
            line-height: 1.6;
            font-family: inherit;
            resize: vertical;
            min-height: 120px;
        }

        .speech-script-edit:focus {
            outline: none;
            border-color: var(--secondary-color);
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }

        .hidden {
            display: none !important;
        }

        .save-btn {
            background: #28a745;
            border-color: #28a745;
            color: white;
        }

        .save-btn:hover {
            background: #218838;
            border-color: #1e7e34;
        }

        .edit-btn[data-editing="true"] {
            background: #6c757d;
            border-color: #6c757d;
            color: white;
        }

        .edit-btn[data-editing="true"]:hover {
            background: #5a6268;
            border-color: #545b62;
        }

        /* Speech Modal Styles - Project Consistent */
        .speech-modal-dialog {
            position: relative;
            margin: auto;
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            padding: var(--spacing-lg);
        }

        .speech-modal-content {
            background: var(--glass-bg);
            backdrop-filter: blur(20px);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-lg);
            box-shadow: var(--glass-shadow);
            width: 100%;
            max-height: 90vh;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }

        .speech-modal-header {
            padding: var(--spacing-lg) var(--spacing-xl);
            border-bottom: 1px solid var(--glass-border);
            display: flex;
            justify-content: space-between;
            align-items: center;
            background: linear-gradient(145deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
        }

        .speech-modal-title .speech-section-title {
            margin: 0;
            font-size: 1.25rem;
            font-weight: 600;
        }

        .speech-modal-close {
            background: transparent;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            padding: var(--spacing-sm);
            border-radius: var(--border-radius);
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .speech-modal-close:hover {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-primary);
            transform: scale(1.1);
        }

        .speech-modal-body {
            flex: 1;
            padding: var(--spacing-xl);
            overflow-y: auto;
            color: var(--text-primary);
        }

        .speech-modal-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: var(--spacing-lg);
            padding: var(--spacing-md) var(--spacing-lg);
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid var(--glass-border);
            border-radius: var(--border-radius-md);
            backdrop-filter: blur(10px);
        }

        .speech-duration-info {
            display: flex;
            align-items: center;
            gap: var(--spacing-sm);
            color: var(--text-primary);
            font-size: 0.9rem;
        }

        .speech-duration-info svg {
            color: var(--primary-color);
        }

        .speech-action-group {
            display: flex;
            gap: var(--spacing-sm);
        }

        .speech-scripts-container {
            max-height: 60vh;
            overflow-y: auto;
            padding-right: var(--spacing-xs);
        }

        .speech-scripts-container::-webkit-scrollbar {
            width: 6px;
        }

        .speech-scripts-container::-webkit-scrollbar-track {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 3px;
        }

        .speech-scripts-container::-webkit-scrollbar-thumb {
            background: var(--primary-color);
            border-radius: 3px;
            opacity: 0.7;
        }

        .speech-scripts-container::-webkit-scrollbar-thumb:hover {
            opacity: 1;
        }

        .speech-modal-footer {
            padding: var(--spacing-lg) var(--spacing-xl);
            border-top: 1px solid var(--glass-border);
            background: linear-gradient(145deg, rgba(248, 249, 250, 0.8) 0%, rgba(233, 236, 239, 0.6) 100%);
            display: flex;
            gap: var(--spacing-md);
            justify-content: flex-end;
        }

        /* Custom Checkbox */
        .speech-form-check {
            display: flex;
            align-items: center;
            gap: var(--spacing-sm);
        }

        .speech-form-check input[type="checkbox"] {
            position: absolute;
            opacity: 0;
            width: 0;
            height: 0;
        }

        .speech-checkbox-label {
            display: flex;
            align-items: center;
            gap: var(--spacing-sm);
            cursor: pointer;
            font-size: 0.875rem;
            color: var(--text-primary);
        }

        .speech-checkbox-custom {
            width: 20px;
            height: 20px;
            border: 2px solid var(--border-color);
            border-radius: 4px;
            background: var(--bg-primary);
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
        }

        .speech-form-check input[type="checkbox"]:checked + .speech-checkbox-label .speech-checkbox-custom {
            background: var(--primary-color);
            border-color: var(--primary-color);
        }

        .speech-form-check input[type="checkbox"]:checked + .speech-checkbox-label .speech-checkbox-custom::after {
            content: '✓';
            color: white;
            font-size: 12px;
            font-weight: bold;
        }

        /* Custom Buttons */
        .speech-btn {
            padding: 12px 24px;
            border: none;
            border-radius: 12px;
            font-weight: 600;
            font-size: 0.875rem;
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            display: inline-flex;
            align-items: center;
            gap: 8px;
            position: relative;
            overflow: hidden;
            min-width: 120px;
            justify-content: center;
        }

        .speech-btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, transparent 50%, rgba(255, 255, 255, 0.1) 100%);
            opacity: 0;
            transition: opacity 0.3s ease;
            pointer-events: none;
        }

        .speech-btn:hover::before {
            opacity: 1;
        }

        .speech-btn-secondary {
            background: linear-gradient(145deg, rgba(248, 249, 250, 0.9) 0%, rgba(233, 236, 239, 0.8) 100%);
            color: var(--text-secondary);
            border: 1px solid rgba(222, 226, 230, 0.8);
            backdrop-filter: blur(10px);
            box-shadow:
                0 2px 8px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.8);
        }

        .speech-btn-secondary:hover {
            background: linear-gradient(145deg, rgba(233, 236, 239, 0.9) 0%, rgba(222, 226, 230, 0.8) 100%);
            color: var(--text-primary);
            transform: translateY(-2px);
            box-shadow:
                0 4px 12px rgba(0, 0, 0, 0.15),
                inset 0 1px 0 rgba(255, 255, 255, 0.9);
        }

        .speech-btn-outline {
            background: transparent;
            color: var(--primary-color);
            border: 2px solid var(--primary-color);
            backdrop-filter: blur(10px);
        }

        .speech-btn-outline:hover {
            background: var(--primary-color);
            color: white;
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
        }

        .speech-btn-primary {
            background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
            color: white;
            box-shadow:
                0 4px 16px rgba(102, 126, 234, 0.3),
                0 2px 8px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.3);
            border: 1px solid rgba(255, 255, 255, 0.2);
        }

        .speech-btn-primary:hover {
            transform: translateY(-3px);
            box-shadow:
                0 6px 20px rgba(102, 126, 234, 0.4),
                0 3px 12px rgba(0, 0, 0, 0.15),
                inset 0 1px 0 rgba(255, 255, 255, 0.4);
        }

        .speech-btn-primary:active {
            transform: translateY(-1px);
            box-shadow:
                0 3px 12px rgba(102, 126, 234, 0.3),
                0 1px 6px rgba(0, 0, 0, 0.1),
                inset 0 1px 0 rgba(255, 255, 255, 0.2);
        }

        /* Speech Script Button Styles */
        #speechScriptBtn {
            background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);
            border: none;
            color: white;
            transition: all 0.3s ease;
        }

        #speechScriptBtn:hover {
            background: linear-gradient(135deg, #138496 0%, #117a8b 100%);
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(23, 162, 184, 0.3);
        }

        /* Script Preview Styles */
        .script-item {
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius-lg);
            padding: var(--spacing-lg);
            background: var(--bg-secondary);
            margin-bottom: var(--spacing-md);
        }

        .script-header {
            border-bottom: 1px solid var(--border-color);
            padding-bottom: var(--spacing-sm);
            margin-bottom: var(--spacing-md);
        }

        .script-content textarea {
            resize: vertical;
            min-height: 120px;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius);
            padding: var(--spacing-md);
            background: var(--bg-primary);
            color: var(--text-primary);
            width: 100%;
        }

        .script-content textarea:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }

        .scripts-container {
            max-height: 60vh;
            overflow-y: auto;
            padding-right: var(--spacing-xs);
        }

        .scripts-container::-webkit-scrollbar {
            width: 6px;
        }

        .scripts-container::-webkit-scrollbar-track {
            background: var(--bg-tertiary);
            border-radius: 3px;
        }

        .scripts-container::-webkit-scrollbar-thumb {
            background: var(--border-color);
            border-radius: 3px;
        }

        .scripts-container::-webkit-scrollbar-thumb:hover {
            background: var(--text-secondary);
        }
    </style>
</head>
<body>
    <div class="editor-container">
        <!-- Header -->
        <div class="editor-header">
            <div class="d-flex justify-content-between align-items-center">
                <div>
                    <h2><i class="fas fa-edit"></i> PPT编辑器</h2>
                    <p class="mb-0">{{ project.title }} - 共 {{ project.slides_data|length if project.slides_data else 0 }} 页</p>
                </div>
                <div>
                    <a href="/dashboard" class="btn btn-outline-light">
                        <i class="fas fa-tasks"></i> 返回主页
                    </a>
                </div>
            </div>
        </div>

        <div class="d-flex">
            <!-- Slides Sidebar -->
            <div class="slides-sidebar" style="flex: 0 0 260px;">
                <div class="p-3">
                    <h6><i class="fas fa-images"></i> 幻灯片</h6>
                </div>
                <div class="slides-container">
                    {% if project.slides_data and project.slides_data|length > 0 %}
                        {% for slide in project.slides_data %}
                        <div class="slide-thumbnail {% if loop.index == 1 %}active{% endif %}"
                             data-slide-index="{{ loop.index0 }}"
                             draggable="true">
                            <div class="drag-indicator top"></div>
                            <div class="slide-preview">
                                <iframe srcdoc="{{ slide.html_content | e }}"
                                        title="Slide {{ loop.index }}"></iframe>
                            </div>
                            <div class="slide-title">{{ loop.index }}. {{ slide.title }}</div>
                            <div class="drag-indicator bottom"></div>
                        </div>
                        {% endfor %}
                    {% else %}
                        <div class="text-center p-4" style="color: #7f8c8d;" id="noSlidesMessage">
                            <div style="font-size: 48px; margin-bottom: 15px;">
                                <i class="fas fa-magic"></i>
                            </div>
                            <h5 style="margin-bottom: 10px;">PPT正在生成中...</h5>
                            <p style="margin-bottom: 15px; font-size: 14px;">
                                幻灯片生成完成后，您可以在这里进行编辑和管理
                            </p>
                            <div class="spinner-border text-primary" role="status" style="margin-bottom: 15px;">
                                <span class="visually-hidden">Loading...</span>
                            </div>
                            <br>
                            <button class="btn btn-primary btn-sm" onclick="checkForUpdates()">
                                <i class="fas fa-refresh"></i> 刷新页面
                            </button>
                        </div>
                    {% endif %}
                </div>
            </div>

            <!-- Main Editor -->
            <div class="main-editor" style="flex: 1;">
                <!-- Toolbar -->
                <div class="editor-toolbar">
                    <div class="btn-group-custom">
                        <button class="mode-toggle active" id="previewMode" onclick="setMode('preview')" title="预览模式">
                            <i class="fas fa-eye"></i>
                        </button>
                        <button class="mode-toggle" id="editMode" onclick="setMode('edit')" title="编辑模式">
                            <i class="fas fa-code"></i>
                        </button>
                        <button class="mode-toggle" id="splitMode" onclick="setMode('split')" title="分屏模式">
                            <i class="fas fa-columns"></i>
                        </button>
                        <button class="mode-toggle" id="quickEditMode" onclick="toggleQuickEditMode()" title="快速修改">
                            <i class="fas fa-edit"></i>
                        </button>
                    </div>

                    <div class="btn-group-custom">
                        <button class="btn btn-warning btn-sm" id="slideshowBtn" title="开始放映">
                            <i class="fas fa-play"></i>
                        </button>
                        <button class="btn btn-success btn-sm" id="saveSlideBtn" title="保存幻灯片">
                            <i class="fas fa-save"></i>
                        </button>
                        <button class="btn btn-primary btn-sm" id="aiEditBtn" title="AI智能编辑">
                            <i class="fas fa-robot"></i>
                        </button>
                        <button class="btn btn-info btn-sm" id="speechScriptBtn" onclick="showSpeechScriptDialog()" title="生成演讲稿">
                            <i class="fas fa-comment"></i>
                        </button>
                    </div>
                </div>

                <!-- Editor Content -->
                <div class="editor-content">
                    <!-- Preview Pane -->
                    <div class="preview-pane" id="previewPane">
                        {% if project.slides_data and project.slides_data|length > 0 %}
                            <div class="slide-frame-container">
                                <div class="slide-frame-wrapper" id="slideFrameWrapper">
                                    <button class="preview-nav-btn left" id="previewPrevBtn" onclick="navigatePreviewSlide(-1)" title="&#19978;&#19968;&#39029; (&#8592;)">
                                        <i class="fas fa-chevron-left"></i>
                                    </button>

                                    <iframe class="slide-frame" id="slideFrame"
                                            srcdoc="{{ project.slides_data[0].html_content | e }}"
                                            title="Slide Preview"></iframe>
                                    <div class="quick-edit-overlay" id="quickEditOverlay"></div>

                                    <button class="preview-nav-btn right" id="previewNextBtn" onclick="navigatePreviewSlide(1)" title="&#19979;&#19968;&#39029; (&#8594;)">
                                        <i class="fas fa-chevron-right"></i>
                                    </button>
                                </div>
                            </div>
                        {% else %}
                            <div class="d-flex align-items-center justify-content-center h-100" style="background: #f8f9fa; border-radius: 8px;">
                                <div class="text-center" style="color: #6c757d;">
                                    <div style="font-size: 64px; margin-bottom: 20px;">
                                        <i class="fas fa-presentation-screen"></i>
                                    </div>
                                    <h4 style="margin-bottom: 15px;">等待PPT生成</h4>
                                    <p style="margin-bottom: 20px;">PPT生成完成后，预览将在这里显示</p>
                                    <button class="btn btn-outline-primary" onclick="window.location.reload()">
                                        <i class="fas fa-refresh"></i> 刷新查看
                                    </button>
                                </div>
                            </div>
                        {% endif %}
                    </div>

                    <!-- Edit Pane -->
                    <div class="edit-pane" id="editPane" style="display: none;">
                        <textarea class="code-editor" id="codeEditor" placeholder="HTML代码将在这里显示...">{{ project.slides_data[0].html_content if project.slides_data and project.slides_data|length > 0 else '' }}</textarea>
                    </div>
                </div>
            </div>
        </div>

        <!-- Export Section -->
        <div class="export-section">
            <div class="btn-group-custom justify-content-center">
                <button class="btn btn-primary" onclick="exportToPDF()" title="导出为PDF文件">
                    <i class="fas fa-file-pdf"></i>
                </button>
                <div class="btn-group">
                    <button class="btn btn-warning" onclick="exportToPPTX()" title="导出为PowerPoint文件">
                        <i class="fas fa-file-powerpoint"></i>
                    </button>
                    <button type="button" class="btn btn-warning dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
                        <span class="visually-hidden">Toggle Dropdown</span>
                    </button>
                    <ul class="dropdown-menu">
                        <li><a class="dropdown-item" href="#" onclick="exportToPPTX(); return false;">标准导出</a></li>
                        <li><a class="dropdown-item" href="#" onclick="exportToPPTXAsImages(); return false;">以图片形式导出</a></li>
                    </ul>
                </div>
                <button class="btn btn-success" onclick="downloadHTML()" title="下载HTML文件">
                    <i class="fas fa-download"></i>
                </button>
                <button class="btn btn-info" onclick="showShareDialog()" title="生成分享链接">
                    <i class="fas fa-share-alt"></i>
                </button>
            </div>
        </div>
    </div>

    <!-- Slideshow Overlay -->
    <div class="slideshow-overlay" id="slideshowOverlay">
        <div class="slideshow-container">
            <div class="slideshow-slide">
                <div class="iframe-container">
                    <iframe id="slideshowFrame1" class="visible" title="Slideshow Frame 1"></iframe>
                    <iframe id="slideshowFrame2" class="hidden" title="Slideshow Frame 2"></iframe>
                </div>
            </div>

            <div class="slideshow-controls">
                <button class="slideshow-btn" onclick="previousSlideshow()" title="上一页 (←)">
                    <i class="fas fa-chevron-left"></i> 上一页
                </button>
                <button class="slideshow-btn" onclick="nextSlideshow()" title="下一页 (→)">
                    下一页 <i class="fas fa-chevron-right"></i>
                </button>
            </div>

            <div class="slideshow-info" id="slideshowInfo">1 / 1</div>

            <button class="slideshow-exit" onclick="exitSlideshow()" title="退出放映">
                <i class="fas fa-times"></i>
            </button>
        </div>
    </div>

    <!-- 右键菜单 -->
    <div class="context-menu" id="contextMenu">
        <div class="context-menu-item" onclick="editSlide()">
            <i class="fas fa-edit"></i>
            <span>编辑幻灯片</span>
        </div>
        <div class="context-menu-item" onclick="copySlide()">
            <i class="fas fa-copy"></i>
            <span>复制幻灯片</span>
        </div>
        <div class="context-menu-item" onclick="pasteSlide()" id="pasteMenuItem">
            <i class="fas fa-paste"></i>
            <span>粘贴幻灯片</span>
        </div>
        <div class="context-menu-item" onclick="insertNewSlide()">
            <i class="fas fa-plus"></i>
            <span>插入新幻灯片</span>
        </div>
        <div class="context-menu-item" onclick="duplicateSlide()">
            <i class="fas fa-clone"></i>
            <span>复制当前页</span>
        </div>
        <div class="context-menu-item" onclick="regenerateContextSlide()">
            <i class="fas fa-sync"></i>
            <span>重新生成</span>
        </div>
        <div class="context-menu-item" onclick="exportSingleSlideHTML()">
            <i class="fas fa-file-code"></i>
            <span>导出为HTML</span>
        </div>
        <div class="context-menu-item" onclick="deleteSlide()">
            <i class="fas fa-trash"></i>
            <span>删除幻灯片</span>
        </div>
    </div>

    <!-- 图片选择菜单 -->
    <div class="image-select-menu" id="imageSelectMenu" style="display: none;">
        <div class="image-select-content">
            <div class="image-select-header">
                <h4><i class="fas fa-image"></i> 选择图片</h4>
                <button class="image-select-close" onclick="closeImageSelectMenu()">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <div class="image-select-options">
                <button class="image-select-option" onclick="selectFromLocal()">
                    <i class="fas fa-upload"></i>
                    <span>从本地上传</span>
                    <small>选择本地图片文件上传</small>
                </button>
                <button class="image-select-option" onclick="selectFromLibrary()">
                    <i class="fas fa-folder-open"></i>
                    <span>从图床选择</span>
                    <small>从已上传的图片中选择</small>
                </button>
            </div>
        </div>
    </div>

    <!-- 图床选择器 -->
    <div class="image-library-overlay" id="imageLibraryOverlay" style="display: none;">
        <div class="image-library-container">
            <div class="image-library-header">
                <div class="image-library-info">
                    <h4><i class="fas fa-folder-open"></i> 本地图床</h4>
                </div>
                <button class="image-library-close" onclick="closeImageLibrary()">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <div class="image-library-content">
                <div class="image-library-search">
                    <div class="search-input-group">
                        <i class="fas fa-search"></i>
                        <input type="text" id="imageLibrarySearchInput" placeholder="搜索图片..." />
                        <button class="search-clear-btn" id="imageLibrarySearchClear" style="display: none;" onclick="clearImageLibrarySearch()">
                            <i class="fas fa-times"></i>
                        </button>
                    </div>
                </div>
                <div class="image-library-loading" id="imageLibraryLoading">
                    <i class="fas fa-spinner fa-spin"></i>
                </div>
                <div class="image-library-grid" id="imageLibraryGrid"></div>
                <div class="image-library-pagination" id="imageLibraryPagination" style="display: none;">
                    <div class="pagination-info">
                        <span id="paginationInfo">第 1 页，共 1 页</span>
                    </div>
                    <div class="pagination-controls">
                        <button class="pagination-btn" id="prevPageBtn" onclick="loadPreviousPage()" disabled>
                            <i class="fas fa-chevron-left"></i> 上一页
                        </button>
                        <button class="pagination-btn" id="nextPageBtn" onclick="loadNextPage()" disabled>
                            下一页 <i class="fas fa-chevron-right"></i>
                        </button>
                    </div>
                </div>
                <div class="image-library-empty" id="imageLibraryEmpty" style="display: none;">
                    <i class="fas fa-images"></i>
                </div>
            </div>
            <div class="image-library-actions">
                <button class="image-library-action" onclick="confirmImageSelection()" id="confirmSelectionBtn" disabled>
                    <i class="fas fa-check"></i> 确认选择 (<span id="selectedCount">0</span>)
                </button>
                <button class="image-library-action secondary" onclick="closeImageLibrary()">
                    <i class="fas fa-times"></i> 取消
                </button>
            </div>
        </div>
    </div>

    <!-- 全屏图片预览 -->
    <div class="image-preview-overlay" id="imagePreviewOverlay" style="display: none;">
        <div class="image-preview-container">
            <div class="image-preview-header">
                <div class="image-preview-info">
                    <h4 id="imagePreviewTitle">图片预览</h4>
                    <p id="imagePreviewDetails">加载中...</p>
                </div>
                <button class="image-preview-close" onclick="closeImagePreview()">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <div class="image-preview-content">
                <img id="imagePreviewImg" src="" alt="图片预览">
                <div class="image-preview-loading" id="imagePreviewLoading">
                    <i class="fas fa-spinner fa-spin"></i>
                    <p>加载中...</p>
                </div>
            </div>
            <div class="image-preview-actions">
                <button class="image-preview-action" onclick="downloadCurrentImage()" title="下载图片">
                    <i class="fas fa-download"></i> 下载
                </button>
                <button class="image-preview-action danger" onclick="removeCurrentImage()" title="删除图片">
                    <i class="fas fa-trash"></i> 删除
                </button>
            </div>
        </div>
    </div>

    <!-- AI编辑侧栏遮罩层 -->
    <div class="ai-sidebar-overlay" id="aiSidebarOverlay" onclick="closeAIEditSidebar()"></div>

    <!-- AI编辑侧栏 -->
    <div class="ai-edit-sidebar" id="aiEditSidebar">
        <div class="ai-sidebar-resize-handle" id="aiSidebarResizeHandle"></div>
        <div class="ai-edit-sidebar-header">
            <h4><i class="fas fa-robot"></i> AI编辑助手</h4>
            <div class="d-flex align-items-center" style="gap: var(--spacing-sm);">
                <div class="ai-current-slide-info" id="aiCurrentSlideInfo">
                    第1页
                </div>
                <div class="ai-header-buttons">
                    <button class="ai-outline-btn" onclick="showSlideOutline()" title="查看当前页大纲">
                        <i class="fas fa-list"></i>
                    </button>
                    <button class="ai-outline-btn" onclick="autoGenerateSlideImages()" title="一键配图">
                        <i class="fas fa-magic"></i>
                    </button>
                    <button class="ai-edit-sidebar-close" onclick="closeAIEditSidebar()">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
            </div>
        </div>

        <div class="ai-edit-content">


            <!-- AI对话区域 -->
            <div class="ai-chat-container">
                <div class="ai-chat-messages" id="aiChatMessages">
                    <div class="ai-message system">
                        <div style="text-align: center; padding: var(--spacing-sm);">
                            <div style="font-size: 2rem; margin-bottom: var(--spacing-sm); color: var(--text-secondary);">
                                <i class="fas fa-magic"></i>
                            </div>
                            <div style="font-weight: 600; margin-bottom: var(--spacing-xs); color: var(--text-primary);">
                                欢迎使用AI编辑助手！
                            </div>
                            <div style="font-size: 0.8125rem; line-height: 1.5; color: var(--text-muted);">
                                您可以告诉我如何修改当前幻灯片，例如：
                                <br>• "修改标题颜色为蓝色"
                                <br>• "添加更多图表"
                                <br>• "调整布局为左右分栏"
                                <br>• "根据上传的图片设计内容"
                                <br>• "将图片居中显示"
                            </div>
                        </div>
                    </div>
                </div>

                <div class="ai-input-container">
                    <textarea
                        class="ai-input-box"
                        id="aiInputBox"
                        placeholder="请输入您的编辑指令..."
                        rows="3"></textarea>


                    <div class="ai-input-buttons">
                        <button class="ai-send-btn" id="aiSendBtn" onclick="sendAIMessage()">
                            <i class="fas fa-paper-plane"></i> 发送
                        </button>
                        <button class="ai-image-upload-btn" id="aiImageUploadBtn" onclick="triggerImageUpload()" title="上传图片">
                            <i class="fas fa-image"></i>
                        </button>
                        <button class="ai-vision-toggle-btn" id="aiVisionToggleBtn" onclick="toggleVisionMode()" title="启用视觉模式 - AI将能看到当前幻灯片">
                            <i class="fas fa-eye"></i>
                        </button>
                        <button class="ai-regenerate-btn" onclick="quickRegenerateSlide()" title="重新生成当前幻灯片">
                            <i class="fas fa-sync"></i>
                        </button>
                        <button class="ai-clear-context-btn" onclick="clearAIContext()" title="清除对话上下文">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>

                    <!-- 隐藏的文件输入 -->
                    <input type="file" id="aiImageFileInput" accept="image/*" multiple style="display: none;">

                    <!-- 上传进度 -->
                    <div class="ai-upload-progress" id="aiUploadProgress" style="display: none;">
                        <div class="ai-progress-bar">
                            <div class="ai-progress-fill" id="aiProgressFill"></div>
                        </div>
                        <div class="ai-progress-text" id="aiProgressText">上传中...</div>
                    </div>

                    <!-- 已上传图片预览 -->
                    <div class="ai-uploaded-images" id="aiUploadedImages"></div>


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

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        let currentSlideIndex = 0;
        let currentMode = 'preview';
        let slidesData = {{ project.slides_data | tojson if project.slides_data and project.slides_data|length > 0 else '[]' }};
        let slideshowIndex = 0;
        let isSlideshow = false;

        // AI编辑相关变量
        let aiChatHistory = {}; // 改为对象，按幻灯片索引存储对话历史
        let isAISending = false;
        let isResizingSidebar = false;
        let sidebarStartWidth = 500;
        let sidebarStartX = 0;

        // 图片上传相关变量
        let uploadedImages = []; // 存储已上传的图片信息
        let isImageUploadExpanded = false;
        let isUploading = false;
        let currentPreviewImage = null; // 当前预览的图片信息
        let selectedLibraryImages = []; // 从图床选择的图片
        let libraryImages = []; // 图床中的所有图片

        // 视觉模式相关变量
        let visionModeEnabled = false;
        let filteredLibraryImages = []; // 搜索过滤后的图片
        let currentSearchTerm = ''; // 当前搜索关键词
        let currentPage = 1; // 当前页码
        let totalPages = 1; // 总页数
        let totalCount = 0; // 总图片数
        let perPage = 1000; // 每页显示数量（设置为大值以获取所有图片）

        // CodeMirror编辑器相关变量
        let codeMirrorEditor = null;
        let isCodeMirrorInitialized = false;

        // 创建安全的data URL
        function createDataUrl(html) {
            try {
                const encoded = btoa(unescape(encodeURIComponent(html)));
                return `data:text/html;charset=utf-8;base64,${encoded}`;
            } catch (error) {
                throw error;
            }
        }

        // 优化的iframe内容设置函数，减少卡顿
        function setSafeIframeContent(iframe, html) {
            if (!iframe) {
                return;
            }

            if (!html) {
                return;
            }

            // 检查内容是否相同，避免不必要的更新
            if (iframe.getAttribute('data-current-content') === html) {
                return;
            }

            // 先清理现有的Chart实例，防止重复渲染
            cleanupIframeCharts(iframe);

            // 使用requestAnimationFrame优化性能
            requestAnimationFrame(() => {
                try {
                    // 直接设置srcdoc，减少延迟
                    iframe.srcdoc = html;
                    iframe.setAttribute('data-current-content', html);

                    // 简化的加载完成处理
                    iframe.onload = function() {
                        // 减少延迟，提高响应速度
                        setTimeout(() => {
                            try {
                                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                                const chartElements = iframeDoc.querySelectorAll('canvas[id*="chart"], canvas[id*="Chart"]');

                                if (chartElements.length > 0) {
                                    const iframeWindow = iframe.contentWindow;
                                    if (iframeWindow && iframeWindow.Chart) {
                                        // Chart.js库已加载，图表正常渲染
                                    }
                                }
                            } catch (e) {
                                // 静默处理错误，避免控制台噪音
                            }
                        }, 50); // 减少延迟时间
                    };
                } catch (e) {
                    // 设置iframe内容失败
                }
            });
        }

        // 清理iframe中的Chart实例，防止重复渲染
        function cleanupIframeCharts(iframe) {
            if (!iframe) return;

            try {
                const iframeWindow = iframe.contentWindow;
                const iframeDoc = iframe.contentDocument || iframeWindow.document;

                if (!iframeWindow || !iframeDoc) return;

                // 检查是否有Chart.js
                if (iframeWindow.Chart) {
                    // 清理现有Chart实例

                    // 方法1: 通过Chart.instances清理所有实例
                    if (iframeWindow.Chart.instances) {
                        Object.values(iframeWindow.Chart.instances).forEach(chart => {
                            if (chart && typeof chart.destroy === 'function') {
                                try {
                                    chart.destroy();
                                } catch (e) {
                                    // 销毁Chart实例失败
                                }
                            }
                        });
                    }

                    // 方法2: 通过canvas元素清理
                    const canvasElements = iframeDoc.querySelectorAll('canvas[id*="chart"], canvas[id*="Chart"]');
                    canvasElements.forEach((canvas, index) => {
                        if (canvas.chart) {
                            try {
                                canvas.chart.destroy();
                            } catch (e) {
                                // 销毁Chart实例失败
                            }
                        }
                        // 清理canvas的chart属性
                        delete canvas.chart;
                    });
                }
            } catch (e) {
                // 清理Chart实例时出错
            }
        }

        // 拖拽和右键菜单相关变量
        let draggedSlideIndex = -1;
        let copiedSlideData = null;
        let contextMenuSlideIndex = -1;

        // 检查是否有幻灯片数据
        let hasSlidesData = slidesData && slidesData.length > 0;

        // 项目状态和生成完成状态
        let projectStatus = '{{ project.status }}';
        let projectOutline = {{ project.outline | tojson if project.outline else 'null' }};



        // 检查PPT是否生成完成 - 简化逻辑
        function isPPTGenerationCompleted() {
            // 简单检查：有幻灯片数据就认为生成完成
            return hasSlidesData && slidesData.length > 0;
        }

        // 手动检查更新并刷新页面
        function checkForUpdates() {
            showNotification('正在检查更新...', 'info');

            // 直接刷新页面以获取最新数据
            setTimeout(() => {
                window.location.reload();
            }, 500);
        }

        // 移除自动检查功能，只保留手动刷新
        // function startAutoCheck() - 已移除定时自动检查逻辑

        // 更新功能按钮状态
        function updateFunctionButtonsState() {
            const isCompleted = isPPTGenerationCompleted();

            // 获取需要控制的按钮和菜单项
            const contextMenu = document.getElementById('contextMenu');
            if (contextMenu) {
                const copyBtn = contextMenu.querySelector('[onclick="copySlide()"]');
                const pasteBtn = contextMenu.querySelector('[onclick="pasteSlide()"]');
                const insertBtn = contextMenu.querySelector('[onclick="insertNewSlide()"]');
                const duplicateBtn = contextMenu.querySelector('[onclick="duplicateSlide()"]');
                const deleteBtn = contextMenu.querySelector('[onclick="deleteSlide()"]');

                // 禁用或启用按钮
                [copyBtn, pasteBtn, insertBtn, duplicateBtn, deleteBtn].forEach(btn => {
                    if (btn) {
                        if (isCompleted) {
                            btn.style.opacity = '1';
                            btn.style.pointerEvents = 'auto';
                            btn.style.color = '';
                        } else {
                            btn.style.opacity = '0.5';
                            btn.style.pointerEvents = 'none';
                            btn.style.color = '#999';
                        }
                    }
                });

                // 添加提示信息
                if (!isCompleted) {
                    [copyBtn, pasteBtn, insertBtn, duplicateBtn, deleteBtn].forEach(btn => {
                        if (btn) {
                            btn.title = 'PPT生成完成后才能使用此功能';
                        }
                    });
                }
            }
        }

        // 缓存缩放比例，避免重复计算
        let cachedScale = null;
        let lastContainerSize = null;

        // 计算并应用iframe缩放，确保内容完全可见
        function applyMainFrameScale() {
            const wrapper = document.getElementById('slideFrameWrapper');
            const iframe = document.getElementById('slideFrame');

            if (!wrapper || !iframe) return;

            // 获取容器的实际尺寸
            const wrapperRect = wrapper.getBoundingClientRect();
            const containerWidth = wrapperRect.width - 20; // 减去内边距
            const containerHeight = wrapperRect.height - 20; // 减去内边距

            // 检查容器尺寸是否变化，如果没有变化则使用缓存的缩放比例
            const currentSize = `${containerWidth}x${containerHeight}`;
            if (lastContainerSize === currentSize && cachedScale !== null) {
                iframe.style.transform = `translate(-50%, -50%) scale(${cachedScale})`;
                return;
            }

            // PPT标准尺寸
            const pptWidth = 1280;
            const pptHeight = 720;

            // 计算缩放比例，确保内容完全可见
            const scaleX = containerWidth / pptWidth;
            const scaleY = containerHeight / pptHeight;
            const scale = Math.min(scaleX, scaleY, 1); // 取较小值，且不超过1

            // 缓存结果
            cachedScale = scale;
            lastContainerSize = currentSize;

            // 应用缩放
            iframe.style.transform = `translate(-50%, -50%) scale(${scale})`;
        }

        // Preview navigation
        function navigatePreviewSlide(direction) {
            if (!hasSlidesData) {
                return;
            }

            const newIndex = currentSlideIndex + direction;
            if (newIndex >= 0 && newIndex < slidesData.length) {
                selectSlide(newIndex);
                updatePreviewNavButtons();
            }
        }

        function updatePreviewNavButtons() {
            const prevBtn = document.getElementById('previewPrevBtn');
            const nextBtn = document.getElementById('previewNextBtn');

            if (prevBtn && nextBtn) {
                prevBtn.disabled = currentSlideIndex <= 0;
                nextBtn.disabled = currentSlideIndex >= slidesData.length - 1;
            }
        }

        // 初始化iframe样式
        function initializeMainFrame() {
            const iframe = document.getElementById('slideFrame');
            if (!iframe) return;

            // 设置固定尺寸和居中定位
            iframe.style.position = 'absolute';
            iframe.style.top = '50%';
            iframe.style.left = '50%';
            iframe.style.width = '1280px';
            iframe.style.height = '720px';
            iframe.style.border = 'none';
            iframe.style.background = 'white';
            iframe.style.borderRadius = '8px';
            iframe.style.transformOrigin = 'center center';

            // 应用缩放
            applyMainFrameScale();
        }

        function selectSlide(index) {
            if (!hasSlidesData) {
                return;
            }

            if (index < 0 || index >= slidesData.length) {
                return;
            }

            // 如果选择的是当前幻灯片，直接返回
            if (currentSlideIndex === index) {
                return;
            }

            currentSlideIndex = index;

            updatePreviewNavButtons();

            // 更新AI编辑助手中的当前页数显示
            updateAICurrentSlideInfo();

            // 切换幻灯片时清除AI对话记录
            clearAIMessagesForSlideSwitch();

            // 切换幻灯片时清除图像选择状态
            clearImageSelection();

            // 使用requestAnimationFrame优化DOM操作
            requestAnimationFrame(() => {
                // Update active thumbnail with animation
                document.querySelectorAll('.slide-thumbnail').forEach((thumb, i) => {
                    if (i === index) {
                        thumb.classList.add('active');
                        // 使用更平滑的滚动
                        thumb.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                    } else {
                        thumb.classList.remove('active');
                    }
                });

                // Update preview and editor
                if (slidesData[index]) {
                    const slideFrame = document.getElementById('slideFrame');
                    const codeEditor = document.getElementById('codeEditor');

                    if (slideFrame) {
                        // 简化过渡效果，减少卡顿
                        slideFrame.style.opacity = '0.8';
                        slideFrame.style.transition = 'opacity 0.2s ease';

                        try {
                            setSafeIframeContent(slideFrame, slidesData[index].html_content);
                        } catch (error) {
                            // Error setting iframe content
                        }

                        // 减少延迟时间，提高响应速度
                        setTimeout(() => {
                            slideFrame.style.opacity = '1';
                            // 只在必要时重新应用缩放
                            if (cachedScale === null) {
                                applyMainFrameScale();
                            }
                            // 减少Chart.js重新初始化的频率
                            setTimeout(() => {
                                forceReinitializeIframeJS(slideFrame);

                                // 如果当前是快速编辑模式，重新初始化可编辑元素
                                if (currentMode === 'quickedit' && quickEditMode) {
                                    setTimeout(() => {
                                        initEditableElements();
                                    }, 200);
                                }
                            }, 100);
                        }, 150);
                    }

                    if (codeEditor) {
                        if (codeMirrorEditor && isCodeMirrorInitialized) {
                            codeMirrorEditor.setValue(slidesData[index].html_content);
                        } else {
                            codeEditor.value = slidesData[index].html_content;
                        }
                    }
                }
            });
        }

        // ==================== 快速编辑功能 ====================
        let quickEditMode = false;
        let currentInlineEditor = null;
        let editableElements = [];

        // 切换快速编辑模式
        function toggleQuickEditMode() {
            if (currentMode === 'quickedit') {
                // 如果当前正在编辑，先完成编辑
                if (currentInlineEditor) {
                    finishDirectEdit(true);
                }
                // 退出快速编辑模式
                setMode('preview');
            } else {
                // 进入快速编辑模式
                setMode('quickedit');
            }
        }

        // 启用快速编辑模式
        function enableQuickEdit() {
            quickEditMode = true;
            const previewPane = document.getElementById('previewPane');
            if (previewPane) {
                previewPane.classList.add('quick-edit-mode');
            }

            // 等待iframe加载完成后初始化可编辑元素
            setTimeout(() => {
                initEditableElements();

                // 重新初始化图像选择功能
                const slideFrame = document.getElementById('slideFrame');
                if (slideFrame) {
                    try {
                        const iframeWindow = slideFrame.contentWindow;
                        const iframeDoc = slideFrame.contentDocument || iframeWindow.document;
                        if (iframeWindow && iframeDoc) {
                            initializeImageSelection(slideFrame, iframeWindow, iframeDoc);
                        }
                    } catch (e) {
                        // 重新初始化图像选择功能失败
                    }
                }
            }, 500);


        }

        // 禁用快速编辑模式
        function disableQuickEdit() {
            quickEditMode = false;
            const previewPane = document.getElementById('previewPane');
            if (previewPane) {
                previewPane.classList.remove('quick-edit-mode');
            }

            // 清除所有编辑标识
            clearEditableHighlights();

            // 完成当前的直接编辑
            if (currentInlineEditor) {
                finishDirectEdit(true);
            }

            // 清除图像选择状态
            clearImageSelection();

            // 移除图像选择功能
            const slideFrame = document.getElementById('slideFrame');
            if (slideFrame) {
                try {
                    const iframeDoc = slideFrame.contentDocument || slideFrame.contentWindow.document;
                    if (iframeDoc) {
                        const selectableImages = iframeDoc.querySelectorAll('[data-image-selectable]');
                        selectableImages.forEach(element => {
                            element.removeAttribute('data-image-selectable');
                            element.style.cursor = '';
                            element.classList.remove('image-selected', 'image-selectable');
                            element.style.outline = '';
                            element.style.outlineOffset = '';
                            element.style.boxShadow = '';
                            element.style.transform = '';
                        });
                    }
                } catch (e) {
                    // 清理图像选择功能失败
                }
            }
        }

        // 初始化可编辑元素
        function initEditableElements() {
            const slideFrame = document.getElementById('slideFrame');
            if (!slideFrame || !slideFrame.contentDocument) {
                setTimeout(() => {
                    initEditableElements();
                }, 1000);
                return;
            }

            try {
                const iframeDoc = slideFrame.contentDocument;
                editableElements = [];

                // 查找可编辑的文本元素
                const textSelectors = [
                    'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
                    'p', 'span', 'div',
                    'li', 'td', 'th',
                    '.title', '.subtitle', '.content',
                    '[contenteditable]'
                ];

                textSelectors.forEach(selector => {
                    const elements = iframeDoc.querySelectorAll(selector);
                    elements.forEach(element => {
                        // 检查元素是否包含文本内容且不是容器元素
                        if (element.textContent && element.textContent.trim().length > 0) {
                            // 排除包含其他文本元素的容器
                            const hasTextChildren = Array.from(element.children).some(child =>
                                textSelectors.some(sel => child.matches(sel))
                            );

                            if (!hasTextChildren && !editableElements.includes(element)) {
                                editableElements.push(element);
                                addEditableHighlight(element);
                            }
                        }
                    });
                });


            } catch (error) {
                // 初始化可编辑元素时出错
            }
        }

        // 为元素添加编辑高亮
        function addEditableHighlight(element) {
            element.classList.add('quick-edit-highlight');
            element.style.cursor = 'text'; // 改为文本光标

            // 添加点击事件
            element.addEventListener('click', function(e) {
                if (quickEditMode) {
                    e.preventDefault();
                    e.stopPropagation();
                    makeElementDirectlyEditable(element, e);
                }
            });
        }

        // 清除所有编辑高亮
        function clearEditableHighlights() {
            const slideFrame = document.getElementById('slideFrame');
            if (!slideFrame || !slideFrame.contentDocument) return;

            try {
                const iframeDoc = slideFrame.contentDocument;
                const highlightedElements = iframeDoc.querySelectorAll('.quick-edit-highlight');
                highlightedElements.forEach(element => {
                    element.classList.remove('quick-edit-highlight');
                    element.classList.remove('direct-editing');
                    element.style.cursor = 'default';
                    element.contentEditable = false;
                });
            } catch (error) {
                // 清除编辑高亮时出错
            }
        }

        // 使元素直接可编辑
        function makeElementDirectlyEditable(element, clickEvent = null) {
            // 如果已经有元素在编辑中，先完成编辑
            if (currentInlineEditor) {
                finishDirectEdit();
            }

            // 保存原始内容
            const originalText = element.textContent;
            const originalHTML = element.innerHTML;

            // 设置当前编辑元素
            currentInlineEditor = {
                element: element,
                originalText: originalText,
                originalHTML: originalHTML
            };

            // 使元素可编辑
            element.contentEditable = true;
            element.classList.add('direct-editing');

            // 确保iframe内的样式正确应用
            const slideFrame = document.getElementById('slideFrame');
            if (slideFrame && slideFrame.contentDocument) {
                const iframeDoc = slideFrame.contentDocument;

                // 在iframe内添加直接编辑样式
                let styleElement = iframeDoc.getElementById('quick-edit-styles');
                if (!styleElement) {
                    styleElement = iframeDoc.createElement('style');
                    styleElement.id = 'quick-edit-styles';
                    styleElement.textContent = `
                        .direct-editing {
                            outline: 2px solid #4facfe !important;
                            outline-offset: 2px !important;
                            background: rgba(79, 172, 254, 0.1) !important;
                            border-radius: 4px !important;
                            padding: 2px 4px !important;
                            transition: all 0.3s ease !important;
                        }
                        .direct-editing:focus {
                            outline-color: #2980b9 !important;
                            background: rgba(79, 172, 254, 0.15) !important;
                        }
                    `;
                    iframeDoc.head.appendChild(styleElement);
                }
            }

            // 聚焦元素并设置光标位置
            element.focus();

            // 设置光标位置
            try {
                if (clickEvent) {
                    // 如果有点击事件，尝试根据点击位置设置光标
                    const range = element.ownerDocument.createRange();
                    const selection = element.ownerDocument.getSelection();

                    // 使用点击位置设置光标
                    if (element.ownerDocument.caretRangeFromPoint) {
                        const clickRange = element.ownerDocument.caretRangeFromPoint(clickEvent.clientX, clickEvent.clientY);
                        if (clickRange && element.contains(clickRange.startContainer)) {
                            selection.removeAllRanges();
                            selection.addRange(clickRange);
                        } else {
                            // 如果点击位置无效，设置到文本末尾
                            range.selectNodeContents(element);
                            range.collapse(false);
                            selection.removeAllRanges();
                            selection.addRange(range);
                        }
                    } else {
                        // 浏览器不支持caretRangeFromPoint，设置到文本末尾
                        range.selectNodeContents(element);
                        range.collapse(false);
                        selection.removeAllRanges();
                        selection.addRange(range);
                    }
                } else {
                    // 没有点击事件，设置到文本末尾
                    const range = element.ownerDocument.createRange();
                    const selection = element.ownerDocument.getSelection();
                    range.selectNodeContents(element);
                    range.collapse(false);
                    selection.removeAllRanges();
                    selection.addRange(range);
                }
            } catch (error) {
                // 光标设置失败，至少确保元素获得焦点
                element.focus();
            }

            // 添加键盘事件监听
            element.addEventListener('keydown', handleDirectEditKeydown);
            element.addEventListener('blur', handleDirectEditBlur);
            element.addEventListener('input', handleDirectEditInput);
        }

        // 处理直接编辑的键盘事件
        function handleDirectEditKeydown(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                // Enter键完成编辑
                e.preventDefault();
                finishDirectEdit(true);
            } else if (e.key === 'Escape') {
                // ESC键取消编辑
                e.preventDefault();
                finishDirectEdit(false);
            }
        }

        // 处理直接编辑失去焦点
        function handleDirectEditBlur(e) {
            // 延迟处理，避免与其他事件冲突
            setTimeout(() => {
                if (currentInlineEditor && currentInlineEditor.element === e.target) {
                    finishDirectEdit(true);
                }
            }, 100);
        }

        // 处理直接编辑输入事件
        function handleDirectEditInput(e) {
            // 可以在这里添加实时预览更新逻辑
        }

        // 完成直接编辑
        function finishDirectEdit(save = true) {
            if (!currentInlineEditor) return;

            const element = currentInlineEditor.element;
            const originalText = currentInlineEditor.originalText;
            const originalHTML = currentInlineEditor.originalHTML;
            const newText = element.textContent;

            // 移除事件监听器
            element.removeEventListener('keydown', handleDirectEditKeydown);
            element.removeEventListener('blur', handleDirectEditBlur);
            element.removeEventListener('input', handleDirectEditInput);

            // 恢复元素状态
            element.contentEditable = false;
            element.classList.remove('direct-editing');
            element.style.outline = '';
            element.style.outlineOffset = '';
            element.style.backgroundColor = '';

            if (save && newText !== originalText) {
                // 保存更改
                saveDirectEdit(element, newText);
            } else {
                // 取消更改，恢复原始内容
                element.textContent = originalText;
            }

            // 清除当前编辑状态
            currentInlineEditor = null;
        }

        // 保存直接编辑
        function saveDirectEdit(element, newText) {
            if (!element || newText === undefined) return;

            // 获取更新后的HTML内容
            const slideFrame = document.getElementById('slideFrame');
            if (slideFrame && slideFrame.contentDocument) {
                const updatedHtml = slideFrame.contentDocument.documentElement.outerHTML;

                // 更新幻灯片数据
                if (typeof slidesData !== 'undefined' && slidesData[currentSlideIndex]) {
                    slidesData[currentSlideIndex].html_content = updatedHtml;

                    // 更新代码编辑器
                    if (typeof codeMirrorEditor !== 'undefined' && codeMirrorEditor && typeof isCodeMirrorInitialized !== 'undefined' && isCodeMirrorInitialized) {
                        codeMirrorEditor.setValue(updatedHtml);
                    } else {
                        const codeEditor = document.getElementById('codeEditor');
                        if (codeEditor) {
                            codeEditor.value = updatedHtml;
                        }
                    }

                    // 更新缩略图
                    const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[currentSlideIndex];
                    if (thumbnailIframe && typeof setSafeIframeContent === 'function') {
                        setSafeIframeContent(thumbnailIframe, updatedHtml);
                    }

                    // 保存到服务器
                    if (typeof saveToServer === 'function') {
                        saveToServer();
                    }
                    if (typeof showNotification === 'function') {
                        showNotification('内容已更新并保存！', 'success');
                    }
                }
            }
        }

        function setMode(mode) {
            currentMode = mode;

            // Update button states
            document.querySelectorAll('.mode-toggle').forEach(btn => btn.classList.remove('active'));

            // 处理按钮ID映射
            let buttonId;
            switch(mode) {
                case 'quickedit':
                    buttonId = 'quickEditMode';
                    break;
                default:
                    buttonId = mode + 'Mode';
                    break;
            }

            const modeButton = document.getElementById(buttonId);
            if (modeButton) {
                modeButton.classList.add('active');
            } else {
                // Mode button not found
            }

            const previewPane = document.getElementById('previewPane');
            const editPane = document.getElementById('editPane');

            if (!previewPane || !editPane) {
                // Required panes not found
                return;
            }

            switch(mode) {
                case 'preview':
                    previewPane.style.display = 'block';
                    previewPane.style.flex = '1';
                    editPane.style.display = 'none';
                    if (typeof disableQuickEdit === 'function') {
                        disableQuickEdit();
                    }
                    break;
                case 'edit':
                    previewPane.style.display = 'none';
                    editPane.style.display = 'block';
                    editPane.style.flex = '1';
                    if (typeof disableQuickEdit === 'function') {
                        disableQuickEdit();
                    }
                    // 延迟重新计算CodeMirror尺寸，确保DOM更新完成
                    setTimeout(() => {
                        if (typeof resizeCodeMirror === 'function') {
                            resizeCodeMirror();
                        }
                    }, 100);
                    break;
                case 'split':
                    previewPane.style.display = 'block';
                    previewPane.style.flex = '1';
                    editPane.style.display = 'block';
                    editPane.style.flex = '1';
                    if (typeof disableQuickEdit === 'function') {
                        disableQuickEdit();
                    }
                    // 延迟重新计算CodeMirror尺寸，确保DOM更新完成
                    setTimeout(() => {
                        if (typeof resizeCodeMirror === 'function') {
                            resizeCodeMirror();
                        }
                    }, 100);
                    break;
                case 'quickedit':
                    previewPane.style.display = 'block';
                    previewPane.style.flex = '1';
                    editPane.style.display = 'none';
                    if (typeof enableQuickEdit === 'function') {
                        enableQuickEdit();
                    }
                    break;
                default:
                    // Unknown mode
                    break;
            }
        }

        function saveSlide() {
            const codeEditor = document.getElementById('codeEditor');
            let newContent;

            if (codeMirrorEditor && isCodeMirrorInitialized) {
                newContent = codeMirrorEditor.getValue();
            } else {
                newContent = codeEditor.value;
            }

            // Update slides data
            if (slidesData[currentSlideIndex]) {
                slidesData[currentSlideIndex].html_content = newContent;

                // Update preview
                const slideFrame = document.getElementById('slideFrame');
                setSafeIframeContent(slideFrame, newContent);

                // 延迟重新初始化JavaScript以确保内容加载完成
                setTimeout(() => {
                    forceReinitializeIframeJS(slideFrame);
                }, 300);

                // Update thumbnail
                const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[currentSlideIndex];
                if (thumbnailIframe) {
                    setSafeIframeContent(thumbnailIframe, newContent);
                    // 缩略图不需要重新初始化JavaScript，避免性能问题
                }

                // Save to server
                saveToServer();

                showNotification('幻灯片已保存！', 'success');
            }
        }

        function regenerateSlide() {
            regenerateSlideByIndex(currentSlideIndex);
        }

        // 更新AI编辑助手中的当前页数显示
        function updateAICurrentSlideInfo() {
            const slideInfo = document.getElementById('aiCurrentSlideInfo');
            if (slideInfo && slidesData && slidesData.length > 0) {
                slideInfo.textContent = `第${currentSlideIndex + 1}页 / 共${slidesData.length}页`;
            }


        }

        // 更新AI助手中选中图像的信息显示
        function updateAIAssistantSelectedImage(imageInfo) {
            // 检查是否已存在选中图像信息区域
            let selectedImageContainer = document.getElementById('aiSelectedImageContainer');

            if (!selectedImageContainer) {
                // 创建选中图像信息容器
                selectedImageContainer = document.createElement('div');
                selectedImageContainer.id = 'aiSelectedImageContainer';
                selectedImageContainer.className = 'ai-selected-image-container';

                // 插入到AI输入容器之前
                const inputContainer = document.querySelector('.ai-input-container');
                if (inputContainer) {
                    inputContainer.parentNode.insertBefore(selectedImageContainer, inputContainer);
                }
            }

            if (imageInfo) {
                // 显示选中图像信息
                selectedImageContainer.innerHTML = `
                    <div class="ai-selected-image-header">
                        <h6><i class="fas fa-image"></i> 已选择图像</h6>
                        <button class="ai-clear-selection-btn" onclick="clearImageSelection()" title="清除选择">
                            <i class="fas fa-times"></i>
                        </button>
                    </div>
                    <div class="ai-selected-image-info">
                        <div class="ai-selected-image-preview">
                            <img src="${imageInfo.src}" alt="${imageInfo.alt}" onerror="this.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSIjRjBGMEYwIi8+CjxwYXRoIGQ9Ik0yMCAyMEg0MFY0MEgyMFYyMFoiIGZpbGw9IiNDQ0NDQ0MiLz4KPC9zdmc+Cg=='">
                        </div>
                        <div class="ai-selected-image-details">
                            <div class="ai-image-detail-item">
                                <span class="ai-detail-label">类型:</span>
                                <span class="ai-detail-value">${getImageTypeDisplay(imageInfo.type)}</span>
                            </div>
                            <div class="ai-image-detail-item">
                                <span class="ai-detail-label">尺寸:</span>
                                <span class="ai-detail-value">${Math.round(imageInfo.width)} × ${Math.round(imageInfo.height)}</span>
                            </div>
                            <div class="ai-image-detail-item">
                                <span class="ai-detail-label">位置:</span>
                                <span class="ai-detail-value">第${imageInfo.slideIndex + 1}页</span>
                            </div>
                            ${imageInfo.alt ? `
                            <div class="ai-image-detail-item">
                                <span class="ai-detail-label">描述:</span>
                                <span class="ai-detail-value">${imageInfo.alt}</span>
                            </div>
                            ` : ''}
                            ${imageInfo.isBackgroundImage ? `
                            <div class="ai-image-detail-item">
                                <span class="ai-detail-label">背景:</span>
                                <span class="ai-detail-value">CSS背景图像</span>
                            </div>
                            ` : ''}
                        </div>
                    </div>
                    <div class="ai-image-actions">
                        <div class="ai-image-action-row">
                            <button class="ai-regenerate-image-btn" onclick="regenerateSelectedImage()" title="重新生成此图像">
                                <i class="fas fa-sync"></i> 重新生成
                            </button>
                            <button class="ai-replace-image-btn" onclick="replaceSelectedImageFromGallery()" title="从图床选择图片替换">
                                <i class="fas fa-images"></i> 选择替换
                            </button>
                        </div>
                        <div class="ai-image-action-row">
                            <button class="ai-delete-image-btn" onclick="deleteSelectedImage()" title="删除此图像">
                                <i class="fas fa-trash"></i> 删除图像
                            </button>
                        </div>
                    </div>
                `;
                selectedImageContainer.style.display = 'block';
            } else {
                // 隐藏选中图像信息
                selectedImageContainer.style.display = 'none';
            }
        }

        // 清除图像选择
        function clearImageSelection() {
            selectedImageInfo = null;

            // 清除幻灯片中的选择状态
            const slideFrame = document.getElementById('slideFrame');
            if (slideFrame) {
                try {
                    const iframeDoc = slideFrame.contentDocument || slideFrame.contentWindow.document;
                    const selectedImages = iframeDoc.querySelectorAll('.image-selected');
                    selectedImages.forEach(img => {
                        img.classList.remove('image-selected');
                        img.style.outline = '';
                        img.style.outlineOffset = '';
                        img.style.boxShadow = '';
                        img.style.transform = '';
                    });
                } catch (e) {
                    // 清除图像选择状态失败
                }
            }

            // 更新AI助手界面
            updateAIAssistantSelectedImage(null);
        }

        // 重新生成选中的图像
        async function regenerateSelectedImage() {
            if (!selectedImageInfo) {
                showNotification('请先选择要重新生成的图像', 'warning');
                return;
            }

            // 显示确认对话框
            const confirmed = await showImageRegenerateConfirmDialog();
            if (!confirmed) return;

            const regenerateBtn = document.querySelector('.ai-regenerate-image-btn');
            if (!regenerateBtn) return;

            // 保存原始状态用于撤销
            const originalHtmlContent = slidesData[selectedImageInfo.slideIndex].html_content;

            // 禁用按钮并显示加载状态
            const originalText = regenerateBtn.innerHTML;
            regenerateBtn.disabled = true;
            regenerateBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 生成中...';

            // 显示进度提示
            const progressToast = showProgressToast('正在分析图像上下文...');

            try {
                // 更新进度
                updateProgressToast(progressToast, '正在生成新图像...', 30);

                // 构建重新生成请求
                const requestData = {
                    slide_index: selectedImageInfo.slideIndex,
                    image_info: selectedImageInfo,
                    slide_content: {
                        title: selectedImageInfo.slideTitle,
                        html_content: slidesData[selectedImageInfo.slideIndex].html_content
                    },
                    project_topic: '{{ project.topic }}',
                    project_scenario: '{{ project.scenario }}',
                    regeneration_reason: '用户请求重新生成图像'
                };

                // 发送重新生成请求
                const response = await fetch('/api/ai/regenerate-image', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(requestData)
                });

                const result = await response.json();

                if (result.success) {
                    // 更新进度
                    updateProgressToast(progressToast, '正在更新幻灯片...', 80);

                    // 更新幻灯片内容
                    if (result.updated_html_content) {
                        slidesData[selectedImageInfo.slideIndex].html_content = result.updated_html_content;

                        // 更新预览
                        const slideFrame = document.getElementById('slideFrame');
                        if (slideFrame && selectedImageInfo.slideIndex === currentSlideIndex) {
                            setSafeIframeContent(slideFrame, result.updated_html_content);
                            setTimeout(() => {
                                forceReinitializeIframeJS(slideFrame);
                            }, 300);
                        }

                        // 更新缩略图
                        const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[selectedImageInfo.slideIndex];
                        if (thumbnailIframe) {
                            setSafeIframeContent(thumbnailIframe, result.updated_html_content);
                        }

                        // 保存到服务器
                        updateProgressToast(progressToast, '正在保存...', 90);
                        await saveToServer();

                        // 完成进度
                        updateProgressToast(progressToast, '完成！', 100);

                        // 显示撤销选项
                        showUndoOption(originalHtmlContent, selectedImageInfo.slideIndex);

                        // 清除选择状态
                        clearImageSelection();

                        // 关闭进度提示
                        setTimeout(() => closeProgressToast(progressToast), 1000);

                        showNotification('图像重新生成成功！', 'success');
                    } else {
                        closeProgressToast(progressToast);
                        showNotification('图像生成成功，但更新失败', 'warning');
                    }
                } else {
                    closeProgressToast(progressToast);
                    showNotification(result.message || '图像重新生成失败', 'error');
                }

            } catch (error) {
                closeProgressToast(progressToast);
                showNotification('网络错误，请重试', 'error');
            } finally {
                // 恢复按钮状态
                regenerateBtn.disabled = false;
                regenerateBtn.innerHTML = originalText;
            }
        }

        // 删除选中的图像
        async function deleteSelectedImage() {
            if (!selectedImageInfo) {
                showNotification('请先选择要删除的图像', 'warning');
                return;
            }

            // 显示确认对话框
            const confirmed = await showImageDeleteConfirmDialog();
            if (!confirmed) return;

            try {
                // 保存原始状态用于撤销
                const originalHtmlContent = slidesData[selectedImageInfo.slideIndex].html_content;

                // 从HTML中删除图像
                const updatedHtml = removeImageFromHtml(
                    slidesData[selectedImageInfo.slideIndex].html_content,
                    selectedImageInfo
                );

                if (updatedHtml === slidesData[selectedImageInfo.slideIndex].html_content) {
                    showNotification('未找到要删除的图像', 'warning');
                    return;
                }

                // 更新幻灯片内容
                slidesData[selectedImageInfo.slideIndex].html_content = updatedHtml;

                // 更新预览
                const slideFrame = document.getElementById('slideFrame');
                if (slideFrame && selectedImageInfo.slideIndex === currentSlideIndex) {
                    setSafeIframeContent(slideFrame, updatedHtml);
                    setTimeout(() => {
                        forceReinitializeIframeJS(slideFrame);
                    }, 300);
                }

                // 更新缩略图
                const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[selectedImageInfo.slideIndex];
                if (thumbnailIframe) {
                    setSafeIframeContent(thumbnailIframe, updatedHtml);
                }

                // 保存到服务器
                await saveToServer();

                // 显示撤销选项
                showUndoOption(originalHtmlContent, selectedImageInfo.slideIndex, '图像删除');

                // 清除选择状态
                clearImageSelection();

                showNotification('图像删除成功！', 'success');

            } catch (error) {
                showNotification('删除图像失败，请重试', 'error');
            }
        }

        // 从图床选择图片替换选中的图像
        async function replaceSelectedImageFromGallery() {
            if (!selectedImageInfo) {
                showNotification('请先选择要替换的图像', 'warning');
                return;
            }

            try {
                // 显示图片选择对话框
                const selectedImage = await showImageGalleryDialog();
                if (!selectedImage) return;

                // 保存原始状态用于撤销
                const originalHtmlContent = slidesData[selectedImageInfo.slideIndex].html_content;

                // 构建新图像URL
                const newImageUrl = selectedImage.url;

                // 替换HTML中的图像
                const updatedHtml = replaceImageInHtmlClient(
                    slidesData[selectedImageInfo.slideIndex].html_content,
                    selectedImageInfo,
                    newImageUrl
                );

                if (updatedHtml === slidesData[selectedImageInfo.slideIndex].html_content) {
                    showNotification('图像替换失败', 'warning');
                    return;
                }

                // 更新幻灯片内容
                slidesData[selectedImageInfo.slideIndex].html_content = updatedHtml;

                // 更新预览
                const slideFrame = document.getElementById('slideFrame');
                if (slideFrame && selectedImageInfo.slideIndex === currentSlideIndex) {
                    setSafeIframeContent(slideFrame, updatedHtml);
                    setTimeout(() => {
                        forceReinitializeIframeJS(slideFrame);
                    }, 300);
                }

                // 更新缩略图
                const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[selectedImageInfo.slideIndex];
                if (thumbnailIframe) {
                    setSafeIframeContent(thumbnailIframe, updatedHtml);
                }

                // 保存到服务器
                await saveToServer();

                // 显示撤销选项
                showUndoOption(originalHtmlContent, selectedImageInfo.slideIndex, '图像替换');

                // 清除选择状态
                clearImageSelection();

                showNotification('图像替换成功！', 'success');

            } catch (error) {
                showNotification('替换图像失败，请重试', 'error');
            }
        }

        // 一键配图功能
        async function autoGenerateSlideImages() {
            if (currentSlideIndex < 0 || currentSlideIndex >= slidesData.length) {
                showNotification('请先选择一个幻灯片', 'warning');
                return;
            }

            const currentSlide = slidesData[currentSlideIndex];
            if (!currentSlide) {
                showNotification('当前幻灯片数据无效', 'error');
                return;
            }

            // 显示确认对话框
            const confirmed = await showAutoImageGenerateConfirmDialog();
            if (!confirmed) return;

            // 显示进度提示
            const progressToast = showProgressToast('正在分析幻灯片内容...');

            try {
                // 更新进度
                updateProgressToast(progressToast, '正在生成配图...', 30);

                // 构建一键配图请求
                const requestData = {
                    slide_index: currentSlideIndex,
                    slide_content: {
                        title: currentSlide.title || `第${currentSlideIndex + 1}页`,
                        html_content: currentSlide.html_content
                    },
                    project_topic: '{{ project.topic }}',
                    project_scenario: '{{ project.scenario }}'
                };

                // 发送一键配图请求
                const response = await fetch('/api/ai/auto-generate-slide-images', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(requestData)
                });

                const result = await response.json();

                if (result.success) {
                    // 更新进度
                    updateProgressToast(progressToast, '正在更新幻灯片...', 80);

                    // 更新幻灯片内容
                    if (result.updated_html_content) {
                        slidesData[currentSlideIndex].html_content = result.updated_html_content;

                        // 更新预览
                        const slideFrame = document.getElementById('slideFrame');
                        if (slideFrame) {
                            setSafeIframeContent(slideFrame, result.updated_html_content);
                            setTimeout(() => {
                                forceReinitializeIframeJS(slideFrame);
                            }, 300);
                        }

                        // 更新缩略图
                        const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[currentSlideIndex];
                        if (thumbnailIframe) {
                            setSafeIframeContent(thumbnailIframe, result.updated_html_content);
                        }

                        // 更新代码编辑器
                        if (codeMirrorEditor && isCodeMirrorInitialized) {
                            codeMirrorEditor.setValue(result.updated_html_content);
                        } else {
                            const codeEditor = document.getElementById('codeEditor');
                            if (codeEditor) {
                                codeEditor.value = result.updated_html_content;
                            }
                        }

                        // 保存到服务器
                        await saveToServer();

                        // 完成进度
                        updateProgressToast(progressToast, '配图完成！', 100);
                        setTimeout(() => {
                            closeProgressToast(progressToast);
                        }, 1500);

                        // 显示成功消息
                        const imageCount = result.generated_images_count || 0;
                        showNotification(`一键配图完成！已为当前幻灯片生成${imageCount}张图片`, 'success');

                        // 显示AI分析信息
                        if (result.ai_analysis) {
                            addAIMessage('assistant', `配图分析：${result.ai_analysis.reasoning || '已完成图片生成和插入'}`);
                        }

                    } else {
                        closeProgressToast(progressToast);
                        showNotification('配图生成成功，但未能更新幻灯片内容', 'warning');
                    }

                } else {
                    closeProgressToast(progressToast);
                    showNotification(result.message || '一键配图失败，请重试', 'error');
                }

            } catch (error) {
                closeProgressToast(progressToast);
                showNotification('一键配图失败，请检查网络连接后重试', 'error');
            }
        }

        // 显示一键配图确认对话框
        async function showAutoImageGenerateConfirmDialog() {
            return new Promise((resolve) => {
                const modal = document.createElement('div');
                modal.className = 'modal fade show';
                modal.style.display = 'block';
                modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
                modal.style.zIndex = '20000';
                modal.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">
                                    <i class="fas fa-magic text-primary"></i> 一键配图
                                </h5>
                            </div>
                            <div class="modal-body">
                                <p>AI将自动分析当前幻灯片内容，为其生成合适的配图并插入到适当位置。</p>
                                <div class="alert alert-info">
                                    <i class="fas fa-info-circle"></i>
                                    <strong>功能说明：</strong>
                                    <ul class="mb-0 mt-2">
                                        <li>AI会分析幻灯片的标题和内容</li>
                                        <li>根据内容生成相关的图片描述和关键词</li>
                                        <li>自动生成配图并插入到合适位置</li>
                                        <li>保持原有的布局和样式</li>
                                    </ul>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" onclick="closeAutoImageConfirmDialog(false)">取消</button>
                                <button type="button" class="btn btn-primary" onclick="closeAutoImageConfirmDialog(true)">
                                    <i class="fas fa-magic"></i> 开始配图
                                </button>
                            </div>
                        </div>
                    </div>
                `;

                document.body.appendChild(modal);

                window.closeAutoImageConfirmDialog = (confirmed) => {
                    document.body.removeChild(modal);
                    delete window.closeAutoImageConfirmDialog;
                    resolve(confirmed);
                };
            });
        }

        // 用户体验优化功能

        // 显示图像重新生成确认对话框
        async function showImageRegenerateConfirmDialog() {
            return new Promise((resolve) => {
                const modal = document.createElement('div');
                modal.className = 'modal fade show';
                modal.style.display = 'block';
                modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
                modal.style.zIndex = '20000'; // 确保在AI助手侧边栏之上
                modal.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">
                                    <i class="fas fa-sync text-primary"></i> 重新生成图像
                                </h5>
                            </div>
                            <div class="modal-body">
                                <p>确定要重新生成选中的图像吗？</p>
                                <div class="alert alert-info">
                                    <i class="fas fa-info-circle"></i>
                                    新图像将保持原有的位置和尺寸，但内容会根据幻灯片上下文重新生成。
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" onclick="closeConfirmDialog(false)">取消</button>
                                <button type="button" class="btn btn-primary" onclick="closeConfirmDialog(true)">
                                    <i class="fas fa-sync"></i> 确定重新生成
                                </button>
                            </div>
                        </div>
                    </div>
                `;

                document.body.appendChild(modal);

                window.closeConfirmDialog = (confirmed) => {
                    document.body.removeChild(modal);
                    delete window.closeConfirmDialog;
                    resolve(confirmed);
                };
            });
        }

        // 显示图像删除确认对话框
        async function showImageDeleteConfirmDialog() {
            return new Promise((resolve) => {
                const modal = document.createElement('div');
                modal.className = 'modal fade show';
                modal.style.display = 'block';
                modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
                modal.style.zIndex = '20000';
                modal.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">
                                    <i class="fas fa-trash text-danger"></i> 删除图像
                                </h5>
                            </div>
                            <div class="modal-body">
                                <p>确定要删除选中的图像吗？</p>
                                <div class="alert alert-warning">
                                    <i class="fas fa-exclamation-triangle"></i>
                                    图像将从幻灯片中完全移除，但可以在5秒内撤销此操作。
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" onclick="closeDeleteDialog(false)">取消</button>
                                <button type="button" class="btn btn-danger" onclick="closeDeleteDialog(true)">
                                    <i class="fas fa-trash"></i> 确定删除
                                </button>
                            </div>
                        </div>
                    </div>
                `;

                document.body.appendChild(modal);

                window.closeDeleteDialog = (confirmed) => {
                    document.body.removeChild(modal);
                    delete window.closeDeleteDialog;
                    resolve(confirmed);
                };
            });
        }

        // 显示图片库选择对话框
        async function showImageGalleryDialog() {
            return new Promise((resolve) => {
                const modal = document.createElement('div');
                modal.className = 'modal fade show';
                modal.style.display = 'block';
                modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
                modal.style.zIndex = '20000';
                modal.innerHTML = `
                    <div class="modal-dialog modal-xl modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">
                                    <i class="fas fa-images text-primary"></i> 选择图片
                                </h5>
                                <button type="button" class="btn-close" onclick="closeGalleryDialog(null)"></button>
                            </div>
                            <div class="modal-body">
                                <!-- 搜索和筛选区域 -->
                                <div class="row mb-3">
                                    <div class="col-md-6">
                                        <div class="input-group">
                                            <span class="input-group-text"><i class="fas fa-search"></i></span>
                                            <input type="text" class="form-control" id="imageSearchInput"
                                                   placeholder="搜索图片标题或描述..." onkeyup="searchImages(event)">
                                        </div>
                                    </div>
                                    <div class="col-md-3">
                                        <select class="form-select" id="imageCategoryFilter" onchange="filterImages()">
                                            <option value="">所有分类</option>
                                            <option value="ai_generated">AI生成</option>
                                            <option value="network_search">网络搜索</option>
                                            <option value="local_upload">本地上传</option>
                                        </select>
                                    </div>
                                    <div class="col-md-3">
                                        <select class="form-select" id="imagePageSize" onchange="changePageSize()">
                                            <option value="12">每页12张</option>
                                            <option value="24" selected>每页24张</option>
                                            <option value="48">每页48张</option>
                                        </select>
                                    </div>
                                </div>

                                <!-- 图片展示区域 -->
                                <div id="imageGalleryContainer" style="min-height: 400px; max-height: 500px; overflow-y: auto;">
                                    <div class="text-center">
                                        <i class="fas fa-spinner fa-spin"></i> 加载图片库...
                                    </div>
                                </div>

                                <!-- 分页区域 -->
                                <div id="imagePagination" class="d-flex justify-content-between align-items-center mt-3">
                                    <div id="imageStats" class="text-muted"></div>
                                    <nav>
                                        <ul class="pagination pagination-sm mb-0" id="paginationList">
                                        </ul>
                                    </nav>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" onclick="closeGalleryDialog(null)">取消</button>
                                <button type="button" class="btn btn-primary" id="useSelectedBtn" onclick="useSelectedImage()" disabled>
                                    <i class="fas fa-check"></i> 使用选中图片
                                </button>
                            </div>
                        </div>
                    </div>
                `;

                document.body.appendChild(modal);

                // 初始化图片库
                initImageGallery();

                window.closeGalleryDialog = (selectedImage) => {
                    document.body.removeChild(modal);
                    delete window.closeGalleryDialog;
                    delete window.selectGalleryImage;
                    delete window.useSelectedImage;
                    delete window.searchImages;
                    delete window.filterImages;
                    delete window.changePageSize;
                    delete window.goToPage;
                    resolve(selectedImage);
                };

                window.selectGalleryImage = (imageData) => {
                    // 更新选中状态
                    document.querySelectorAll('.gallery-image-item').forEach(item => {
                        item.classList.remove('selected');
                    });
                    event.currentTarget.classList.add('selected');

                    // 启用使用按钮
                    document.getElementById('useSelectedBtn').disabled = false;

                    // 保存选中的图片数据
                    window.selectedImageData = imageData;
                };

                window.useSelectedImage = () => {
                    if (window.selectedImageData) {
                        window.closeGalleryDialog(window.selectedImageData);
                    }
                };
            });
        }

        // 显示进度提示
        function showProgressToast(message) {
            const toast = document.createElement('div');
            toast.className = 'progress-toast';
            toast.innerHTML = `
                <div class="progress-toast-content">
                    <div class="progress-toast-icon">
                        <i class="fas fa-spinner fa-spin"></i>
                    </div>
                    <div class="progress-toast-text">
                        <div class="progress-message">${message}</div>
                        <div class="progress-bar">
                            <div class="progress-fill" style="width: 0%"></div>
                        </div>
                    </div>
                </div>
            `;

            document.body.appendChild(toast);

            // 添加样式
            if (!document.getElementById('progress-toast-styles')) {
                const style = document.createElement('style');
                style.id = 'progress-toast-styles';
                style.textContent = `
                    .progress-toast {
                        position: fixed;
                        top: 20px;
                        right: 20px;
                        background: var(--glass-bg);
                        backdrop-filter: blur(10px);
                        border: 1px solid var(--glass-border);
                        border-radius: var(--border-radius-md);
                        padding: var(--spacing-md);
                        z-index: 25000;
                        min-width: 300px;
                        box-shadow: 0 8px 25px rgba(31, 38, 135, 0.2);
                        animation: slideInRight 0.3s ease;
                    }

                    .progress-toast-content {
                        display: flex;
                        align-items: center;
                        gap: var(--spacing-sm);
                    }

                    .progress-toast-icon {
                        color: var(--primary-color);
                        font-size: 1.2rem;
                    }

                    .progress-toast-text {
                        flex: 1;
                    }

                    .progress-message {
                        font-size: 0.875rem;
                        font-weight: 600;
                        color: var(--text-primary);
                        margin-bottom: var(--spacing-xs);
                    }

                    .progress-bar {
                        height: 4px;
                        background: rgba(0,0,0,0.1);
                        border-radius: 2px;
                        overflow: hidden;
                    }

                    .progress-fill {
                        height: 100%;
                        background: var(--primary-gradient);
                        transition: width 0.3s ease;
                    }

                    @keyframes slideInRight {
                        from { transform: translateX(100%); opacity: 0; }
                        to { transform: translateX(0); opacity: 1; }
                    }
                `;
                document.head.appendChild(style);
            }

            return toast;
        }

        // 更新进度提示
        function updateProgressToast(toast, message, progress) {
            const messageEl = toast.querySelector('.progress-message');
            const fillEl = toast.querySelector('.progress-fill');

            if (messageEl) messageEl.textContent = message;
            if (fillEl) fillEl.style.width = `${progress}%`;
        }

        // 关闭进度提示
        function closeProgressToast(toast) {
            if (toast && toast.parentNode) {
                toast.style.animation = 'slideOutRight 0.3s ease';
                setTimeout(() => {
                    if (toast.parentNode) {
                        toast.parentNode.removeChild(toast);
                    }
                }, 300);
            }
        }

        // 显示撤销选项
        function showUndoOption(originalHtmlContent, slideIndex, operationType = '图像重新生成') {
            const undoToast = document.createElement('div');
            undoToast.className = 'undo-toast';

            const operationMessages = {
                '图像重新生成': { icon: 'fa-sync', message: '图像已重新生成' },
                '图像删除': { icon: 'fa-trash', message: '图像已删除' },
                '图像替换': { icon: 'fa-images', message: '图像已替换' }
            };

            const operation = operationMessages[operationType] || operationMessages['图像重新生成'];

            undoToast.innerHTML = `
                <div class="undo-toast-content">
                    <div class="undo-message">
                        <i class="fas fa-check-circle text-success"></i>
                        ${operation.message}
                    </div>
                    <button class="undo-btn" onclick="undoImageRegeneration('${slideIndex}', this)">
                        <i class="fas fa-undo"></i> 撤销
                    </button>
                </div>
            `;

            // 保存原始内容和操作类型到按钮的数据属性中
            const undoBtn = undoToast.querySelector('.undo-btn');
            undoBtn.setAttribute('data-original-content', originalHtmlContent);
            undoBtn.setAttribute('data-operation-type', operationType);

            document.body.appendChild(undoToast);

            // 添加样式
            if (!document.getElementById('undo-toast-styles')) {
                const style = document.createElement('style');
                style.id = 'undo-toast-styles';
                style.textContent = `
                    .undo-toast {
                        position: fixed;
                        bottom: 20px;
                        right: 20px;
                        background: var(--glass-bg);
                        backdrop-filter: blur(10px);
                        border: 1px solid var(--glass-border);
                        border-radius: var(--border-radius-md);
                        padding: var(--spacing-md);
                        z-index: 25000;
                        box-shadow: 0 8px 25px rgba(31, 38, 135, 0.2);
                        animation: slideInUp 0.3s ease;
                    }

                    .undo-toast-content {
                        display: flex;
                        align-items: center;
                        gap: var(--spacing-md);
                    }

                    .undo-message {
                        font-size: 0.875rem;
                        color: var(--text-primary);
                    }

                    .undo-btn {
                        background: var(--accent-gradient);
                        border: none;
                        color: white;
                        padding: var(--spacing-xs) var(--spacing-sm);
                        border-radius: var(--border-radius-sm);
                        font-size: 0.8125rem;
                        cursor: pointer;
                        transition: all 0.2s ease;
                    }

                    .undo-btn:hover {
                        transform: translateY(-1px);
                        box-shadow: 0 4px 15px rgba(67, 233, 123, 0.3);
                    }

                    @keyframes slideInUp {
                        from { transform: translateY(100%); opacity: 0; }
                        to { transform: translateY(0); opacity: 1; }
                    }
                `;
                document.head.appendChild(style);
            }

            // 15秒后自动隐藏
            setTimeout(() => {
                if (undoToast.parentNode) {
                    undoToast.style.animation = 'slideOutDown 0.3s ease';
                    setTimeout(() => {
                        if (undoToast.parentNode) {
                            undoToast.parentNode.removeChild(undoToast);
                        }
                    }, 300);
                }
            }, 5000);
        }

        // 撤销图像操作（重新生成、删除、替换）
        async function undoImageRegeneration(slideIndex, button) {
            const originalContent = button.getAttribute('data-original-content');
            const operationType = button.getAttribute('data-operation-type') || '图像重新生成';
            if (!originalContent) return;

            try {
                // 恢复原始内容
                slidesData[slideIndex].html_content = originalContent;

                // 更新预览
                if (slideIndex == currentSlideIndex) {
                    const slideFrame = document.getElementById('slideFrame');
                    if (slideFrame) {
                        setSafeIframeContent(slideFrame, originalContent);
                        setTimeout(() => {
                            forceReinitializeIframeJS(slideFrame);
                        }, 300);
                    }
                }

                // 更新缩略图
                const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[slideIndex];
                if (thumbnailIframe) {
                    setSafeIframeContent(thumbnailIframe, originalContent);
                }

                // 保存到服务器
                await saveToServer();

                // 移除撤销提示
                const undoToast = button.closest('.undo-toast');
                if (undoToast && undoToast.parentNode) {
                    undoToast.parentNode.removeChild(undoToast);
                }

                showNotification(`已撤销${operationType}`, 'info');

            } catch (error) {
                showNotification('撤销操作失败', 'error');
            }
        }

        // 从HTML中删除图像（保持完整HTML结构）
        function removeImageFromHtml(htmlContent, imageInfo) {
            try {
                const imageType = imageInfo.type || 'img';
                const oldSrc = imageInfo.src || '';

                let updatedHtml = htmlContent;
                let removed = false;

                if (imageType === 'img') {
                    // 使用正则表达式删除整个img标签
                    const imgRegex = new RegExp(
                        `<img[^>]*src=["'][^"']*${escapeRegExp(oldSrc.split('/').pop())}[^"']*["'][^>]*>`,
                        'gi'
                    );

                    if (imgRegex.test(htmlContent)) {
                        updatedHtml = htmlContent.replace(imgRegex, '');
                        removed = true;
                    } else {
                        // 后备方案：查找包含特定src的img标签
                        const fallbackRegex = new RegExp(
                            `<img[^>]*src=["'][^"']*${escapeRegExp(oldSrc)}[^"']*["'][^>]*>`,
                            'gi'
                        );
                        if (fallbackRegex.test(htmlContent)) {
                            updatedHtml = htmlContent.replace(fallbackRegex, '');
                            removed = true;
                        }
                    }
                } else if (imageType === 'background') {
                    // 删除背景图像样式，但保留元素和其他样式
                    const bgRegex = new RegExp(
                        `(style=["'][^"']*?)background-image:\\s*url\\([^)]*${escapeRegExp(oldSrc.split('/').pop())}[^)]*\\);?([^"']*?["'])`,
                        'gi'
                    );

                    if (bgRegex.test(htmlContent)) {
                        updatedHtml = htmlContent.replace(bgRegex, (match, before, after) => {
                            // 清理可能的多余分号和空格
                            const cleanBefore = before.replace(/;\s*$/, '');
                            const cleanAfter = after.replace(/^\s*;/, '');

                            if (cleanBefore.trim() === 'style="' && cleanAfter.trim() === '"') {
                                // 如果style属性变空，则完全移除
                                return '';
                            } else {
                                return cleanBefore + (cleanBefore.endsWith(';') ? '' : ';') + cleanAfter;
                            }
                        });
                        removed = true;
                    }
                } else if (imageType === 'svg') {
                    // SVG删除相对复杂，这里提供基本支持
                    if (imageInfo.outerHTML) {
                        const svgContent = imageInfo.outerHTML.substring(0, 100); // 取前100字符作为匹配
                        if (htmlContent.includes(svgContent)) {
                            // 尝试找到完整的SVG标签
                            const svgRegex = /<svg[^>]*>[\s\S]*?<\/svg>/gi;
                            const svgMatches = htmlContent.match(svgRegex);

                            if (svgMatches) {
                                for (const svgMatch of svgMatches) {
                                    if (svgMatch.includes(svgContent)) {
                                        updatedHtml = htmlContent.replace(svgMatch, '');
                                        removed = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                // 清理可能产生的多余空白
                if (removed) {
                    updatedHtml = updatedHtml.replace(/\s{2,}/g, ' ').trim();
                }

                return removed ? updatedHtml : htmlContent;

            } catch (error) {
                return htmlContent;
            }
        }

        // 图片库状态管理
        let galleryState = {
            allImages: [],
            filteredImages: [],
            currentPage: 1,
            pageSize: 24,
            searchTerm: '',
            categoryFilter: ''
        };

        // 初始化图片库
        async function initImageGallery() {
            try {
                // 自动分页加载所有图片
                const allImages = await loadAllImages();

                if (allImages.length > 0) {
                    galleryState.allImages = allImages;
                    galleryState.filteredImages = [...allImages];
                    renderImageGallery();
                } else {
                    showEmptyGallery();
                }

            } catch (error) {
                showGalleryError(error.message);
            }
        }

        // 加载所有图片（自动分页）
        async function loadAllImages() {
            const allImages = [];
            let currentPage = 1;
            let hasMore = true;

            while (hasMore) {
                try {
                    const response = await fetch(`/api/image/gallery/list?page=${currentPage}&per_page=50`);

                    if (!response.ok) {
                        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                    }

                    const result = await response.json();

                    if (result.success && result.images && result.images.length > 0) {
                        allImages.push(...result.images);

                        // 检查是否还有更多页面
                        hasMore = result.pagination && result.pagination.has_next;
                        currentPage++;
                    } else {
                        hasMore = false;
                    }
                } catch (error) {
                    hasMore = false;
                }
            }

            return allImages;
        }

        // 渲染图片库
        function renderImageGallery() {
            const container = document.getElementById('imageGalleryContainer');
            if (!container) return;

            const { filteredImages, currentPage, pageSize } = galleryState;

            if (filteredImages.length === 0) {
                showEmptyGallery();
                return;
            }

            // 计算分页
            const totalPages = Math.ceil(filteredImages.length / pageSize);
            const startIndex = (currentPage - 1) * pageSize;
            const endIndex = Math.min(startIndex + pageSize, filteredImages.length);
            const currentImages = filteredImages.slice(startIndex, endIndex);

            // 渲染图片网格
            const imagesHtml = currentImages.map(image => `
                <div class="col-lg-2 col-md-3 col-sm-4 col-6">
                    <div class="gallery-image-item"
                         onclick="selectGalleryImage({
                             id: '${image.id}',
                             url: '${image.url}',
                             title: '${escapeHtml(image.title || '')}',
                             alt: '${escapeHtml(image.alt_text || image.title || '')}',
                             width: ${image.width || 0},
                             height: ${image.height || 0},
                             category: '${image.category || image.source || ''}',
                             description: '${escapeHtml(image.description || '')}'
                         })"
                         ondblclick="handleImageDoubleClick({
                             id: '${image.id}',
                             url: '${image.url}',
                             title: '${escapeHtml(image.title || '')}',
                             alt: '${escapeHtml(image.alt_text || image.title || '')}',
                             width: ${image.width || 0},
                             height: ${image.height || 0},
                             category: '${image.category || image.source || ''}',
                             description: '${escapeHtml(image.description || '')}'
                         })"
                         style="cursor: pointer; border: 2px solid transparent; border-radius: 8px; padding: 8px; transition: all 0.2s ease; position: relative;">
                        <div class="image-wrapper" style="position: relative; overflow: hidden; border-radius: 4px;">
                            <img src="${getImageUrl(image)}" alt="${escapeHtml(image.alt_text || image.title || '')}"
                                 style="width: 100%; height: 120px; object-fit: cover; transition: transform 0.2s ease;"
                                 onload="this.style.opacity='1'; this.parentElement.querySelector('.loading-spinner').style.display='none';"
                                 onerror="handleImageError(this, '${image.id}');">
                            <div class="loading-spinner" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ccc;">
                                <i class="fas fa-spinner fa-spin"></i>
                            </div>
                            <div class="image-overlay" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); opacity: 0; transition: opacity 0.2s ease; display: flex; align-items: center; justify-content: center;">
                                <i class="fas fa-eye text-white" style="font-size: 1.5rem;"></i>
                            </div>
                        </div>
                        <div class="text-center mt-2">
                            <small class="d-block text-truncate fw-bold">${escapeHtml(image.title || '未命名图片')}</small>
                            <small class="text-muted">${image.width || 0} × ${image.height || 0}</small>
                            ${getImageCategoryBadge(image)}
                        </div>
                    </div>
                </div>
            `).join('');

            container.innerHTML = `
                <div class="row g-3">
                    ${imagesHtml}
                </div>
                <style>
                    .gallery-image-item:hover {
                        border-color: #007bff !important;
                        background-color: rgba(0, 123, 255, 0.1);
                        transform: translateY(-2px);
                        box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2);
                    }
                    .gallery-image-item:hover .image-overlay {
                        opacity: 1;
                    }
                    .gallery-image-item:hover img {
                        transform: scale(1.05);
                    }
                    .gallery-image-item.selected {
                        border-color: #28a745 !important;
                        background-color: rgba(40, 167, 69, 0.1);
                        box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.2);
                    }
                </style>
            `;

            // 更新分页和统计信息
            updatePagination(totalPages);
            updateStats(startIndex + 1, endIndex, filteredImages.length);
        }

        // 更新分页
        function updatePagination(totalPages) {
            const paginationList = document.getElementById('paginationList');
            if (!paginationList) return;

            const { currentPage } = galleryState;
            let paginationHtml = '';

            // 上一页
            paginationHtml += `
                <li class="page-item ${currentPage === 1 ? 'disabled' : ''}">
                    <a class="page-link" href="#" onclick="goToPage(${currentPage - 1}); return false;">
                        <i class="fas fa-chevron-left"></i>
                    </a>
                </li>
            `;

            // 页码
            const maxVisiblePages = 5;
            let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
            let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);

            if (endPage - startPage < maxVisiblePages - 1) {
                startPage = Math.max(1, endPage - maxVisiblePages + 1);
            }

            for (let i = startPage; i <= endPage; i++) {
                paginationHtml += `
                    <li class="page-item ${i === currentPage ? 'active' : ''}">
                        <a class="page-link" href="#" onclick="goToPage(${i}); return false;">${i}</a>
                    </li>
                `;
            }

            // 下一页
            paginationHtml += `
                <li class="page-item ${currentPage === totalPages ? 'disabled' : ''}">
                    <a class="page-link" href="#" onclick="goToPage(${currentPage + 1}); return false;">
                        <i class="fas fa-chevron-right"></i>
                    </a>
                </li>
            `;

            paginationList.innerHTML = paginationHtml;
        }

        // 更新统计信息
        function updateStats(start, end, total) {
            const statsElement = document.getElementById('imageStats');
            if (statsElement) {
                statsElement.textContent = `显示 ${start}-${end} 项，共 ${total} 张图片`;
            }
        }

        // 初始化CodeMirror编辑器
        function initializeCodeMirror() {
            const textareaElement = document.getElementById('codeEditor');
            if (!textareaElement || isCodeMirrorInitialized) return;

            try {
                // 创建CodeMirror实例
                codeMirrorEditor = CodeMirror.fromTextArea(textareaElement, {
                    mode: 'htmlmixed',
                    theme: 'material',
                    lineNumbers: true,
                    lineWrapping: true,
                    autoCloseTags: true,
                    autoCloseBrackets: true,
                    matchTags: true,
                    foldGutter: true,
                    gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
                    indentUnit: 2,
                    tabSize: 2,
                    indentWithTabs: false,
                    extraKeys: {
                        // 保存功能
                        'Ctrl-S': function(cm) {
                            saveSlide();
                        },
                        'Cmd-S': function(cm) {
                            saveSlide();
                        },
                        // 搜索功能
                        'Ctrl-F': 'findPersistent',
                        'Cmd-F': 'findPersistent',
                        // 查找替换功能
                        'Ctrl-H': 'replace',
                        'Cmd-Alt-F': 'replace',
                        'Ctrl-Shift-H': 'replace',
                        // 查找下一个/上一个
                        'Ctrl-G': 'findNext',
                        'Cmd-G': 'findNext',
                        'Shift-Ctrl-G': 'findPrev',
                        'Shift-Cmd-G': 'findPrev',
                        'F3': 'findNext',
                        'Shift-F3': 'findPrev',
                        // ESC键关闭搜索对话框
                        'Esc': function(cm) {
                            if (cm.state.search && cm.state.search.overlay) {
                                cm.execCommand('clearSearch');
                            }
                        }
                    }
                });

                // 设置编辑器样式 - 使用具体的高度计算
                codeMirrorEditor.setSize('100%', 'auto');

                // 强制刷新编辑器以确保正确的尺寸
                setTimeout(() => {
                    codeMirrorEditor.refresh();
                    // 计算并设置正确的高度
                    const editPane = document.getElementById('editPane');
                    if (editPane) {
                        const rect = editPane.getBoundingClientRect();
                        const height = Math.max(400, rect.height - 40); // 减去padding，最小400px
                        codeMirrorEditor.setSize('100%', height + 'px');
                    }
                }, 200);

                // 绑定内容变化事件
                codeMirrorEditor.on('change', function(cm) {
                    clearTimeout(cm.saveTimeout);
                    cm.saveTimeout = setTimeout(() => {
                        if (currentMode === 'split') {
                            // Auto-update preview in split mode
                            const slideFrame = document.getElementById('slideFrame');
                            if (slideFrame && slidesData[currentSlideIndex]) {
                                const newContent = codeMirrorEditor.getValue();
                                slidesData[currentSlideIndex].html_content = newContent;
                                setSafeIframeContent(slideFrame, newContent);
                            }
                        }
                    }, 500);
                });

                isCodeMirrorInitialized = true;

                // 添加搜索功能的增强配置
                codeMirrorEditor.on('cursorActivity', function(cm) {
                    // 当光标移动时，如果有搜索状态，保持高亮
                    if (cm.state.search && cm.state.search.query) {
                        // 搜索功能已激活，保持高亮状态
                    }
                });

                // 恢复用户的主题偏好
                setTimeout(() => {
                    restoreCodeMirrorTheme();
                }, 100);
            } catch (error) {
                // 如果CodeMirror初始化失败，保持使用原始textarea
            }
        }

        // 切换CodeMirror主题
        function changeCodeMirrorTheme(themeName) {
            if (codeMirrorEditor && isCodeMirrorInitialized) {
                codeMirrorEditor.setOption('theme', themeName);

                // 保存主题偏好到localStorage
                localStorage.setItem('codeMirrorTheme', themeName);

                // 更新下拉菜单显示
                const themeDropdown = document.getElementById('themeDropdown');
                if (themeDropdown) {
                    const themeNames = {
                        'material': 'Material Dark',
                        'monokai': 'Monokai',
                        'dracula': 'Dracula',
                        'default': '默认浅色'
                    };
                    themeDropdown.innerHTML = `<i class="fas fa-palette"></i> ${themeNames[themeName] || themeName}`;
                }
            } else {
                // CodeMirror编辑器未初始化，无法切换主题
            }
        }

        // 从localStorage恢复主题偏好
        function restoreCodeMirrorTheme() {
            const savedTheme = localStorage.getItem('codeMirrorTheme');
            if (savedTheme && codeMirrorEditor && isCodeMirrorInitialized) {
                changeCodeMirrorTheme(savedTheme);
            }
        }

        // 重新计算CodeMirror编辑器的尺寸
        function resizeCodeMirror() {
            if (codeMirrorEditor && isCodeMirrorInitialized) {
                const editPane = document.getElementById('editPane');
                if (editPane && editPane.style.display !== 'none') {
                    // 刷新编辑器以重新计算尺寸
                    codeMirrorEditor.refresh();

                    // 设置正确的高度
                    const rect = editPane.getBoundingClientRect();
                    const height = Math.max(400, rect.height - 40); // 减去padding，最小400px
                    if (height > 0) {
                        codeMirrorEditor.setSize('100%', height + 'px');
                    }
                }
            }
        }



        // 初始化侧栏宽度调整功能
        function initializeSidebarResize() {
            const resizeHandle = document.getElementById('aiSidebarResizeHandle');
            const sidebar = document.getElementById('aiEditSidebar');

            if (!resizeHandle || !sidebar) return;

            resizeHandle.addEventListener('mousedown', (e) => {
                isResizingSidebar = true;
                sidebarStartWidth = sidebar.offsetWidth;
                sidebarStartX = e.clientX;

                document.addEventListener('mousemove', handleSidebarResize);
                document.addEventListener('mouseup', stopSidebarResize);

                e.preventDefault();
            });
        }

        function handleSidebarResize(e) {
            if (!isResizingSidebar) return;

            const sidebar = document.getElementById('aiEditSidebar');
            if (!sidebar) return;

            const deltaX = sidebarStartX - e.clientX; // 向左拖拽为正值
            const newWidth = Math.max(400, Math.min(800, sidebarStartWidth + deltaX));

            sidebar.style.width = newWidth + 'px';
            sidebar.style.right = sidebar.classList.contains('open') ? '0' : `-${newWidth}px`;
        }

        function stopSidebarResize() {
            isResizingSidebar = false;
            document.removeEventListener('mousemove', handleSidebarResize);
            document.removeEventListener('mouseup', stopSidebarResize);
        }

        // AI编辑侧栏控制函数
        function openAIEditSidebar() {
            const sidebar = document.getElementById('aiEditSidebar');
            const overlay = document.getElementById('aiSidebarOverlay');

            sidebar.classList.add('open');
            overlay.classList.add('show');

            // 更新当前页数显示
            updateAICurrentSlideInfo();

            // 聚焦到输入框
            setTimeout(() => {
                document.getElementById('aiInputBox').focus();
            }, 300);
        }

        function closeAIEditSidebar() {
            const sidebar = document.getElementById('aiEditSidebar');
            const overlay = document.getElementById('aiSidebarOverlay');

            sidebar.classList.remove('open');
            overlay.classList.remove('show');
        }

        // 快捷重新生成功能
        function quickRegenerateSlide() {
            if (currentSlideIndex >= 0 && currentSlideIndex < slidesData.length) {
                // 使用与enhanced_ppt_service.py相同的重新生成逻辑
                regenerateSlideByIndex(currentSlideIndex);
                closeAIEditSidebar();
            } else {
                showNotification('请先选择一个幻灯片', 'warning');
            }
        }

        // AI消息处理函数
        function addAIMessage(content, type = 'assistant', messageId = null) {
            const messagesContainer = document.getElementById('aiChatMessages');

            // 如果提供了messageId，尝试找到现有消息并更新
            if (messageId) {
                const existingMessage = document.getElementById(messageId);
                if (existingMessage) {
                    if (type === 'user') {
                        existingMessage.textContent = content;
                    } else {
                        existingMessage.innerHTML = content.replace(/\n/g, '<br>');
                    }
                    messagesContainer.scrollTop = messagesContainer.scrollHeight;
                    return existingMessage;
                }
            }

            // 创建新消息
            const messageDiv = document.createElement('div');
            messageDiv.className = `ai-message ${type}`;
            if (messageId) {
                messageDiv.id = messageId;
            }

            if (type === 'user') {
                messageDiv.textContent = content;
            } else {
                messageDiv.innerHTML = content.replace(/\n/g, '<br>');
            }

            messagesContainer.appendChild(messageDiv);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;

            // 保存到聊天历史（按幻灯片索引存储）
            if (currentSlideIndex >= 0) {
                if (!aiChatHistory[currentSlideIndex]) {
                    aiChatHistory[currentSlideIndex] = [];
                }
                // 将type转换为role格式，以便后端AI能正确理解
                const role = type === 'user' ? 'user' : 'assistant';
                aiChatHistory[currentSlideIndex].push({
                    role: role,
                    content: content,
                    timestamp: Date.now()
                });
            }

            return messageDiv;
        }

        // 添加等待响应动画
        function addWaitingAnimation() {
            const messagesContainer = document.getElementById('aiChatMessages');
            const waitingDiv = document.createElement('div');
            waitingDiv.className = 'ai-message assistant ai-waiting';
            waitingDiv.id = 'ai-waiting-animation';
            waitingDiv.innerHTML = `
                <div class="ai-typing-indicator">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
                <span style="margin-left: 10px;">AI正在思考中...</span>
            `;

            messagesContainer.appendChild(waitingDiv);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;

            return waitingDiv;
        }

        // 移除等待动画
        function removeWaitingAnimation() {
            const waitingDiv = document.getElementById('ai-waiting-animation');
            if (waitingDiv) {
                waitingDiv.remove();
            }
        }

        function clearAIMessages() {
            const messagesContainer = document.getElementById('aiChatMessages');
            // 保留系统欢迎消息
            const systemMessage = messagesContainer.querySelector('.ai-message.system');
            messagesContainer.innerHTML = '';
            if (systemMessage) {
                messagesContainer.appendChild(systemMessage);
            }
            // 清除当前幻灯片的对话历史
            if (currentSlideIndex >= 0) {
                aiChatHistory[currentSlideIndex] = [];
            }
        }

        // 切换幻灯片时清除对话记录
        function clearAIMessagesForSlideSwitch() {
            const messagesContainer = document.getElementById('aiChatMessages');
            // 保留系统欢迎消息
            const systemMessage = messagesContainer.querySelector('.ai-message.system');
            messagesContainer.innerHTML = '';
            if (systemMessage) {
                messagesContainer.appendChild(systemMessage);
            }
        }

        // 验证当前幻灯片索引的有效性
        function validateCurrentSlideIndex(functionName = 'unknown') {
            const isValid = currentSlideIndex >= 0 && currentSlideIndex < (slidesData ? slidesData.length : 0);

            if (!isValid) {
                return false;
            }

            return true;
        }

        // 清除AI对话上下文
        function clearAIContext() {
            if (confirm('确定要清除当前幻灯片的对话上下文吗？这将删除当前幻灯片的所有对话记录。')) {
                clearAIMessages();
                showNotification('对话上下文已清除', 'info');
            }
        }

        // 显示当前幻灯片大纲
        function showSlideOutline() {
            if (currentSlideIndex < 0 || currentSlideIndex >= slidesData.length) {
                showNotification('请先选择一个幻灯片', 'warning');
                return;
            }

            const currentSlide = slidesData[currentSlideIndex];
            let outlineContent = '';

            // 尝试从项目大纲中获取当前页的信息
            if (projectOutline && projectOutline.slides && projectOutline.slides[currentSlideIndex]) {
                const slideOutline = projectOutline.slides[currentSlideIndex];
                outlineContent = `
                    <h5 style="margin-bottom: 25px; color: #2c3e50; font-size: 1.3em;"><i class="fas fa-file-alt"></i> 第${currentSlideIndex + 1}页大纲编辑</h5>
                    <div style="background: #f8f9fa; padding: 25px; border-radius: 8px; margin: 15px 0;">
                        <div style="margin-bottom: 20px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">标题：</label>
                            <input type="text" id="slideTitle" value="${(slideOutline.title || currentSlide.title || '').replace(/"/g, '&quot;')}"
                                   style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box;">
                        </div>
                        <div style="margin-bottom: 20px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">类型：</label>
                            <select id="slideType" style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box;">
                                <option value="title" ${(slideOutline.slide_type || slideOutline.type) === 'title' ? 'selected' : ''}>标题页</option>
                                <option value="content" ${(slideOutline.slide_type || slideOutline.type) === 'content' ? 'selected' : ''}>内容页</option>
                                <option value="conclusion" ${(slideOutline.slide_type || slideOutline.type) === 'conclusion' ? 'selected' : ''}>结论页</option>
                            </select>
                        </div>
                        ${slideOutline.content_points ? `
                            <div style="margin-bottom: 20px;">
                                <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">要点：</label>
                                <div id="bulletPointsContainer" style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 8px; min-height: 120px;">
                                    ${slideOutline.content_points.map((point, index) => `
                                        <div class="bullet-point-item" data-index="${index}" style="display: flex; align-items: flex-start; margin-bottom: 8px; padding: 8px; border-radius: 4px; transition: all 0.2s ease; position: relative;">
                                            <span style="color: #666; margin-right: 8px; font-weight: bold; min-width: 20px;">•</span>
                                            <div style="flex: 1; position: relative;">
                                                <div class="bullet-point-text" contenteditable="true" style="outline: none; min-height: 20px; line-height: 1.4; word-wrap: break-word;">${point}</div>
                                            </div>

                                        </div>
                                    `).join('')}
                                </div>
                                <div style="margin-top: 8px; text-align: right; display: flex; gap: 8px; justify-content: flex-end;">
                                    <button class="enhance-all-btn" onclick="enhanceAllBulletPoints()" title="AI增强所有要点">
                                        🪄 <span>增强要点</span>
                                    </button>
                                    <button onclick="addNewBulletPoint()" style="background: #28a745; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; display: flex; align-items: center; gap: 6px;">
                                        <i class="fas fa-plus"></i> <span>添加要点</span>
                                    </button>
                                </div>
                            </div>
                        ` : `
                            <div style="margin-bottom: 20px;">
                                <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">要点：</label>
                                <div id="bulletPointsContainer" style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 8px; min-height: 120px;">
                                    <div class="empty-bullet-points" style="text-align: center; color: #999; padding: 40px 20px;">
                                        <i class="fas fa-list" style="font-size: 24px; margin-bottom: 10px; opacity: 0.5;"></i>
                                        <p style="margin: 0;">暂无要点，点击下方按钮添加</p>
                                    </div>
                                </div>
                                <div style="margin-top: 8px; text-align: right; display: flex; gap: 8px; justify-content: flex-end;">
                                    <button class="enhance-all-btn" onclick="enhanceAllBulletPoints()" title="AI增强所有要点">
                                        🪄 <span>增强所有要点</span>
                                    </button>
                                    <button onclick="addNewBulletPoint()" style="background: #28a745; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; display: flex; align-items: center; gap: 6px;">
                                        <i class="fas fa-plus"></i> <span>添加要点</span>
                                    </button>
                                </div>
                            </div>
                        `}
                        <div style="margin-bottom: 15px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">描述：</label>
                            <textarea id="slideDescription" rows="4" style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box; resize: vertical;">${slideOutline.description || ''}</textarea>
                        </div>
                    </div>
                `;
            } else {
                outlineContent = `
                    <h5 style="margin-bottom: 25px; color: #2c3e50; font-size: 1.3em;"><i class="fas fa-file-alt"></i> 第${currentSlideIndex + 1}页大纲编辑</h5>
                    <div style="background: #f8f9fa; padding: 25px; border-radius: 8px; margin: 15px 0;">
                        <div style="margin-bottom: 20px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">标题：</label>
                            <input type="text" id="slideTitle" value="${(currentSlide.title || '').replace(/"/g, '&quot;')}"
                                   style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box;">
                        </div>
                        <div style="margin-bottom: 20px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">类型：</label>
                            <select id="slideType" style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box;">
                                <option value="title">标题页</option>
                                <option value="content" selected>内容页</option>
                                <option value="conclusion">结论页</option>
                            </select>
                        </div>
                        <div style="margin-bottom: 20px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">要点：</label>
                            <textarea id="slidePoints" rows="6" placeholder="请输入要点，每行一个..." style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box; resize: vertical;"></textarea>
                        </div>
                        <div style="margin-bottom: 15px;">
                            <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #495057; font-size: 1.1em;">描述：</label>
                            <textarea id="slideDescription" rows="4" placeholder="请输入幻灯片描述..." style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; box-sizing: border-box; resize: vertical;"></textarea>
                        </div>
                    </div>
                `;
            }

            // 创建大纲编辑模态框
            const modal = document.createElement('div');
            modal.id = 'slideOutlineModal';
            modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.5);
                z-index: 10001;
                display: flex;
                justify-content: center;
                align-items: center;
            `;

            const outlineContainer = document.createElement('div');
            outlineContainer.style.cssText = `
                background: white;
                border-radius: 8px;
                padding: 30px;
                width: 90vw;
                max-width: 1200px;
                max-height: 85vh;
                overflow-y: auto;
                position: relative;
                box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            `;

            const closeBtn = document.createElement('button');
            closeBtn.innerHTML = '<i class="fas fa-times"></i>';
            closeBtn.style.cssText = `
                position: absolute;
                top: 15px;
                right: 15px;
                background: #dc3545;
                color: white;
                border: none;
                border-radius: 50%;
                width: 36px;
                height: 36px;
                cursor: pointer;
                font-size: 16px;
                transition: all 0.3s ease;
                z-index: 1;
            `;

            // 添加按钮区域
            const buttonArea = `
                <div style="text-align: right; margin-top: 30px; padding-top: 20px; border-top: 2px solid #e9ecef;">
                    <button onclick="saveSlideOutline()" style="background: #28a745; color: white; border: none; padding: 12px 24px; border-radius: 6px; cursor: pointer; margin-right: 15px; font-size: 16px; font-weight: 500; transition: all 0.3s ease;">
                        <i class="fas fa-save"></i> 保存大纲
                    </button>
                    <button onclick="regenerateFromOutline()" style="background: #007bff; color: white; border: none; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-size: 16px; font-weight: 500; transition: all 0.3s ease;">
                        <i class="fas fa-sync"></i> 根据大纲重新生成
                    </button>
                </div>
            `;

            closeBtn.addEventListener('click', () => {
                document.body.removeChild(modal);
            });

            modal.addEventListener('click', (e) => {
                if (e.target === modal) {
                    document.body.removeChild(modal);
                }
            });

            outlineContainer.innerHTML = outlineContent + buttonArea;
            outlineContainer.appendChild(closeBtn);
            modal.appendChild(outlineContainer);
            document.body.appendChild(modal);
        }

        // 保存幻灯片大纲
        async function saveSlideOutline() {
            const title = document.getElementById('slideTitle').value;
            const type = document.getElementById('slideType').value;
            const description = document.getElementById('slideDescription').value;

            // 从大纲编辑界面收集要点数据
            let points = [];
            const bulletPointsContainer = document.getElementById('bulletPointsContainer');
            if (bulletPointsContainer) {
                const bulletPointItems = bulletPointsContainer.querySelectorAll('.bullet-point-item');
                points = Array.from(bulletPointItems).map(item => {
                    const textElement = item.querySelector('.bullet-point-text');
                    return textElement ? textElement.textContent.trim() : '';
                }).filter(point => point); // 过滤空要点
            } else {
                // 回退到传统的textarea方式（如果没有新的要点容器）
                const pointsElement = document.getElementById('slidePoints');
                points = pointsElement ? pointsElement.value.split('\n').filter(p => p.trim()) : [];
            }

            // 更新本地数据
            if (!projectOutline) {
                projectOutline = { slides: [] };
            }
            if (!projectOutline.slides) {
                projectOutline.slides = [];
            }

            projectOutline.slides[currentSlideIndex] = {
                title: title,
                slide_type: type,
                type: type,
                description: description,
                content_points: points
            };

            // 更新幻灯片标题
            if (slidesData[currentSlideIndex]) {
                slidesData[currentSlideIndex].title = title;
            }

            try {
                // 保存大纲到数据库
                const response = await fetch(`/projects/{{ project.project_id }}/update-outline`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        outline_content: JSON.stringify(projectOutline, null, 2)
                    })
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const data = await response.json();
                if (data.status === 'success') {
                    showNotification('大纲已保存！', 'success');
                } else {
                    throw new Error(data.message || data.error || '保存失败');
                }
            } catch (error) {
                showNotification('保存大纲失败：' + error.message, 'error');
                return; // 如果保存失败，不关闭模态框
            }

            // 关闭模态框
            const modal = document.getElementById('slideOutlineModal');
            if (modal) {
                document.body.removeChild(modal);
            }

            // 更新缩略图标题
            const thumbnails = document.querySelectorAll('.slide-thumbnail .slide-title');
            if (thumbnails[currentSlideIndex]) {
                thumbnails[currentSlideIndex].textContent = `${currentSlideIndex + 1}. ${title}`;
            }

            // 更新AI编辑助手右上角的大纲显示
            updateAIOutlineDisplay();
        }

        // 更新AI编辑助手右上角的大纲显示
        function updateAIOutlineDisplay() {
            // 这里可以添加更新右上角大纲显示的逻辑
            // 目前大纲按钮点击时会显示最新的大纲信息
        }

        // 获取项目选择的全局母版模板
        async function getSelectedGlobalTemplate() {
            try {
                const response = await fetch(`/api/projects/{{ project.project_id }}/selected-global-template`);
                if (!response.ok) {
                    return null;
                }
                const data = await response.json();
                return data.template || null;
            } catch (error) {
                return null;
            }
        }

        // 使用全局母版生成幻灯片HTML内容
        async function generateSlideWithGlobalTemplate(template, title, content) {
            try {
                let htmlTemplate = template.html_template;

                // 替换模板中的占位符
                htmlTemplate = htmlTemplate.replace(/\{\{\s*page_title\s*\}\}/g, title);
                htmlTemplate = htmlTemplate.replace(/\{\{\s*main_heading\s*\}\}/g, title);
                htmlTemplate = htmlTemplate.replace(/\{\{\s*page_content\s*\}\}/g, content);
                htmlTemplate = htmlTemplate.replace(/\{\{\s*current_page_number\s*\}\}/g, '1');
                htmlTemplate = htmlTemplate.replace(/\{\{\s*total_page_count\s*\}\}/g, slidesData.length.toString());

                return htmlTemplate;
            } catch (error) {
                // 返回默认的HTML内容
                return `
                    <div style="width: 1280px; height: 720px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                                display: flex; flex-direction: column; justify-content: center; align-items: center;
                                color: white; font-family: 'Microsoft YaHei', Arial, sans-serif;">
                        <h1 style="font-size: 48px; margin-bottom: 20px; text-align: center;">${title}</h1>
                        <p style="font-size: 24px; text-align: center;">${content}</p>
                    </div>
                `;
            }
        }

        // 根据大纲重新生成幻灯片
        function regenerateFromOutline() {
            if (confirm('确定要根据当前大纲重新生成这张幻灯片吗？这将覆盖现有内容。')) {
                // 先保存大纲
                saveSlideOutline();

                // 然后重新生成
                setTimeout(() => {
                    regenerateSlideByIndex(currentSlideIndex);
                }, 500);
            }
        }

        // 同步更新大纲（插入、删除幻灯片时调用）
        async function updateOutlineForSlideOperation(operation, slideIndex, slideData = null) {
            try {
                if (!projectOutline) {
                    projectOutline = { slides: [] };
                }
                if (!projectOutline.slides) {
                    projectOutline.slides = [];
                }

                switch (operation) {
                    case 'insert':
                        // 插入新的幻灯片大纲
                        if (slideData) {
                            projectOutline.slides.splice(slideIndex, 0, slideData);
                        }
                        break;
                    case 'delete':
                        // 删除指定位置的幻灯片大纲
                        if (slideIndex >= 0 && slideIndex < projectOutline.slides.length) {
                            projectOutline.slides.splice(slideIndex, 1);
                        }
                        break;
                }

                // 保存更新后的大纲到数据库
                const response = await fetch(`/projects/{{ project.project_id }}/update-outline`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        outline_content: JSON.stringify(projectOutline, null, 2)
                    })
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const data = await response.json();
                if (data.status === 'success') {
                    // 大纲已同步更新
                } else {
                    throw new Error(data.message || data.error || '大纲更新失败');
                }
            } catch (error) {
                throw error;
            }
        }

        // 发送AI消息 - 使用流式输出
        async function sendAIMessage() {
            const inputBox = document.getElementById('aiInputBox');
            const sendBtn = document.getElementById('aiSendBtn');
            let message = inputBox.value.trim();

            if (!message || isAISending) {
                return;
            }

            // 自动将所有已上传的图片信息嵌入到消息中
            message = autoEmbedUploadedImages(message);

            if (currentSlideIndex < 0 || currentSlideIndex >= slidesData.length) {
                showNotification('请先选择一个幻灯片', 'warning');
                return;
            }

            // 禁用发送按钮和输入框
            isAISending = true;
            sendBtn.disabled = true;
            sendBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 响应中...';
            inputBox.disabled = true;

            // 添加用户消息
            addAIMessage(message, 'user');
            inputBox.value = '';

            // 添加等待动画
            const waitingDiv = addWaitingAnimation();

            try {
                // 构建AI请求上下文
                const currentSlide = slidesData[currentSlideIndex];

                // 获取当前幻灯片的大纲信息
                let slideOutline = null;
                if (projectOutline && projectOutline.slides && projectOutline.slides[currentSlideIndex]) {
                    slideOutline = projectOutline.slides[currentSlideIndex];
                }

                // 获取当前幻灯片的对话历史
                let chatHistory = [];
                if (aiChatHistory[currentSlideIndex]) {
                    chatHistory = aiChatHistory[currentSlideIndex].map(msg => ({
                        role: msg.role,
                        content: msg.content
                    }));
                }

                // 捕获幻灯片截图（如果启用了视觉模式）
                let slideScreenshot = null;
                if (visionModeEnabled) {
                    slideScreenshot = await captureSlideScreenshot();
                }

                // 获取所有已上传的图片信息
                const referencedImages = getAllUploadedImages();

                const context = {
                    slideIndex: currentSlideIndex + 1,
                    slideTitle: currentSlide.title,
                    slideContent: currentSlide.html_content,
                    userRequest: message,
                    slideOutline: slideOutline, // 添加当前幻灯片的大纲信息
                    chatHistory: chatHistory, // 添加对话历史
                    images: referencedImages, // 添加图片信息
                    visionEnabled: visionModeEnabled, // 添加视觉模式状态
                    slideScreenshot: slideScreenshot, // 添加截图数据
                    projectInfo: {
                        title: '{{ project.title }}',
                        topic: '{{ project.topic }}',
                        scenario: '{{ project.scenario }}'
                    }
                };



                // 发送流式AI编辑请求
                const response = await fetch('/api/ai/slide-edit/stream', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(context)
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                // 处理流式响应
                await handleStreamingResponse(response, waitingDiv);

            } catch (error) {
                removeWaitingAnimation();
                addAIMessage('抱歉，无法连接到AI服务。请检查网络连接后重试。', 'assistant');
            } finally {
                // 恢复发送按钮和输入框
                isAISending = false;
                sendBtn.disabled = false;
                sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i> 发送';
                inputBox.disabled = false;
                inputBox.focus();
            }
        }

        // 处理流式响应
        async function handleStreamingResponse(response, waitingDiv) {
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let buffer = '';
            let aiMessageDiv = null;
            let fullResponse = '';
            let newHtmlContent = null;

            try {
                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    buffer += decoder.decode(value, { stream: true });
                    const lines = buffer.split('\n');
                    buffer = lines.pop() || '';

                    for (const line of lines) {
                        if (line.trim().startsWith('data: ')) {
                            try {
                                const dataStr = line.slice(6).trim();
                                if (dataStr) {
                                    const data = JSON.parse(dataStr);

                                    if (data.type === 'start') {
                                        // 移除等待动画，开始显示AI回复
                                        removeWaitingAnimation();
                                        // 使用时间戳确保每次对话都有唯一的消息ID
                                        const messageId = 'ai-streaming-message-' + Date.now();
                                        aiMessageDiv = addAIMessage('', 'assistant', messageId);
                                    } else if (data.type === 'content' && data.content) {
                                        // 追加内容到AI消息
                                        fullResponse += data.content;
                                        if (aiMessageDiv) {
                                            // 转义HTML标签，防止实时渲染
                                            const escapedContent = fullResponse
                                                .replace(/&/g, '&amp;')
                                                .replace(/</g, '&lt;')
                                                .replace(/>/g, '&gt;')
                                                .replace(/\n/g, '<br>');
                                            aiMessageDiv.innerHTML = escapedContent;
                                            // 滚动到底部
                                            const messagesContainer = document.getElementById('aiChatMessages');
                                            messagesContainer.scrollTop = messagesContainer.scrollHeight;
                                        }
                                    } else if (data.type === 'complete') {
                                        // 流式输出完成
                                        newHtmlContent = data.newHtmlContent;
                                        fullResponse = data.fullResponse || fullResponse;

                                        console.log('🎯 AI流式响应完成');
                                        console.log('📝 完整响应长度:', fullResponse ? fullResponse.length : 0);
                                        console.log('🔍 提取的HTML内容:', newHtmlContent ? `长度${newHtmlContent.length}` : '无');
                                        
                                        if (newHtmlContent) {
                                            console.log('✅ 检测到HTML内容，准备添加按钮');
                                            console.log('📄 HTML内容预览:', newHtmlContent.substring(0, 200));
                                        } else {
                                            console.warn('⚠️  未检测到HTML内容');
                                            console.log('📝 完整AI响应预览:', fullResponse ? fullResponse.substring(0, 500) : '无响应内容');
                                        }

                                        // 确保最终内容正确显示，转义HTML标签
                                        if (aiMessageDiv) {
                                            const escapedContent = fullResponse
                                                .replace(/&/g, '&amp;')
                                                .replace(/</g, '&lt;')
                                                .replace(/>/g, '&gt;')
                                                .replace(/\n/g, '<br>');
                                            aiMessageDiv.innerHTML = escapedContent;
                                        }

                                        // 如果有HTML内容，添加应用按钮
                                        if (newHtmlContent) {
                                            console.log('🎯 调用addApplyChangesButton函数');
                                            addApplyChangesButton(aiMessageDiv, newHtmlContent);
                                        } else {
                                            // 即使没有HTML，也提供手动提取选项
                                            console.log('🔧 添加手动提取HTML的提示');
                                            addManualHtmlExtractPrompt(aiMessageDiv, fullResponse);
                                        }

                                        break;
                                    } else if (data.type === 'error') {
                                        removeWaitingAnimation();
                                        addAIMessage('抱歉，处理您的请求时出现了错误：' + (data.error || '未知错误'), 'assistant');
                                        break;
                                    }
                                }
                            } catch (e) {
                                // 解析流式数据失败
                            }
                        }
                    }
                }
            } catch (error) {
                removeWaitingAnimation();
                addAIMessage('抱歉，处理流式响应时出现了错误。', 'assistant');
            }
        }

        // 添加手动HTML提取提示
        function addManualHtmlExtractPrompt(messageDiv, fullResponse) {
            if (!messageDiv || !fullResponse) return;

            // 检查是否已经有提示了
            if (messageDiv.querySelector('.manual-html-extract')) return;

            const promptContainer = document.createElement('div');
            promptContainer.className = 'manual-html-extract';
            promptContainer.style.cssText = `
                margin-top: 15px;
                padding: 10px;
                background: #f8f9fa;
                border: 1px solid #dee2e6;
                border-radius: 4px;
                font-size: 14px;
                color: #6c757d;
            `;

            const promptText = document.createElement('p');
            promptText.textContent = '未能自动检测到HTML代码。如果AI的回复中包含HTML代码，您可以点击下方按钮手动提取：';
            promptText.style.margin = '0 0 10px 0';

            const extractBtn = document.createElement('button');
            extractBtn.textContent = '🔍 尝试手动提取HTML';
            extractBtn.style.cssText = `
                background: #17a2b8;
                color: white;
                border: none;
                padding: 6px 12px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 12px;
            `;

            extractBtn.addEventListener('click', () => {
                // 尝试更激进的HTML提取
                const htmlContent = extractHtmlFromResponse(fullResponse);
                if (htmlContent) {
                    console.log('🎉 手动提取HTML成功');
                    promptContainer.remove();
                    addApplyChangesButton(messageDiv, htmlContent);
                } else {
                    alert('仍然无法提取到HTML内容。请确认AI的回复中包含有效的HTML代码。');
                }
            });

            promptContainer.appendChild(promptText);
            promptContainer.appendChild(extractBtn);
            messageDiv.appendChild(promptContainer);
        }

        // 更激进的HTML提取函数
        function extractHtmlFromResponse(response) {
            if (!response) return null;

            // 尝试多种模式
            const patterns = [
                /```html\s*([\s\S]*?)\s*```/gi,
                /```HTML\s*([\s\S]*?)\s*```/gi,
                /```\s*html\s*([\s\S]*?)\s*```/gi,
                /<html[^>]*>[\s\S]*?<\/html>/gi,
                /<div[^>]*style[^>]*1280px[^>]*>[\s\S]*?<\/div>/gi,
                /<div[^>]*class[^>]*slide[^>]*>[\s\S]*?<\/div>/gi,
                /<div[^>]*>[\s\S]*?<\/div>/gi // 最宽松的匹配
            ];

            for (const pattern of patterns) {
                const matches = response.match(pattern);
                if (matches && matches.length > 0) {
                    let extracted = matches[0];
                    // 如果是代码块格式，提取内容
                    if (extracted.startsWith('```')) {
                        const lines = extracted.split('\n');
                        lines.shift(); // 移除第一行 ```html
                        lines.pop(); // 移除最后一行 ```
                        extracted = lines.join('\n').trim();
                    }
                    if (extracted.length > 50) { // 确保有实质内容
                        return extracted;
                    }
                }
            }
            return null;
        }

        // 添加应用更改按钮
        function addApplyChangesButton(messageDiv, newHtmlContent) {
            if (!messageDiv || !newHtmlContent) {
                console.error('❌ addApplyChangesButton参数无效:', {
                    messageDiv: !!messageDiv,
                    newHtmlContent: !!newHtmlContent
                });
                return;
            }

            console.log('🚀 开始添加应用更改按钮');

            // 检查是否已经有按钮了
            if (messageDiv.querySelector('.ai-apply-changes-btn')) {
                console.log('⚠️  按钮已存在，跳过添加');
                return;
            }

            console.log('✅ 开始创建按钮容器和按钮');

            const buttonContainer = document.createElement('div');
            buttonContainer.className = 'ai-apply-changes-container';
            buttonContainer.style.cssText = `
                margin-top: 15px;
                padding-top: 15px;
                border-top: 1px solid #eee;
                display: flex;
                gap: 10px;
                align-items: center;
            `;

            const applyBtn = document.createElement('button');
            applyBtn.className = 'ai-apply-changes-btn';
            applyBtn.innerHTML = '<i class="fas fa-check"></i> 应用更改';
            applyBtn.style.cssText = `
                background: #28a745;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s ease;
            `;

            const previewBtn = document.createElement('button');
            previewBtn.className = 'ai-preview-changes-btn';
            previewBtn.innerHTML = '<i class="fas fa-eye"></i> 预览';
            previewBtn.style.cssText = `
                background: #007bff;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                transition: background-color 0.2s ease;
            `;

            // 绑定事件
            applyBtn.addEventListener('click', async () => {
                applyBtn.disabled = true;
                applyBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 应用中...';
                try {
                    await applyAIChanges(newHtmlContent);
                    applyBtn.innerHTML = '<i class="fas fa-check"></i> 已保存';
                    applyBtn.style.background = '#28a745';
                    applyBtn.style.color = 'white';

                    // 3秒后变为已应用状态
                    setTimeout(() => {
                        applyBtn.innerHTML = '<i class="fas fa-check-circle"></i> 已应用';
                        applyBtn.style.background = '#6c757d';
                    }, 3000);
                } catch (error) {
                    applyBtn.innerHTML = '<i class="fas fa-exclamation-triangle"></i> 保存失败';
                    applyBtn.style.background = '#dc3545';
                    applyBtn.style.color = 'white';

                    // 显示详细错误信息
                    const errorMsg = error.message || '未知错误';
                    applyBtn.title = `保存失败: ${errorMsg}`;

                    setTimeout(() => {
                        applyBtn.innerHTML = '<i class="fas fa-check"></i> 重试应用';
                        applyBtn.style.background = '#28a745';
                        applyBtn.style.color = 'white';
                        applyBtn.title = '';
                        applyBtn.disabled = false;
                    }, 3000);
                }
            });

            previewBtn.addEventListener('click', () => {
                showHTMLPreview(newHtmlContent);
            });

            // 悬停效果
            applyBtn.addEventListener('mouseenter', () => {
                if (!applyBtn.disabled) applyBtn.style.background = '#218838';
            });
            applyBtn.addEventListener('mouseleave', () => {
                if (!applyBtn.disabled) applyBtn.style.background = '#28a745';
            });

            previewBtn.addEventListener('mouseenter', () => {
                previewBtn.style.background = '#0056b3';
            });
            previewBtn.addEventListener('mouseleave', () => {
                previewBtn.style.background = '#007bff';
            });

            buttonContainer.appendChild(applyBtn);
            buttonContainer.appendChild(previewBtn);
            messageDiv.appendChild(buttonContainer);
            
            console.log('🎉 按钮添加完成！');
            console.log('📋 按钮容器已添加到消息区域');
            
            // 验证按钮是否正确添加
            const addedButtons = messageDiv.querySelectorAll('.ai-apply-changes-btn, .ai-preview-changes-btn');
            console.log('🔍 已添加的按钮数量:', addedButtons.length);
        }

        // 显示HTML预览
        function showHTMLPreview(htmlContent) {
            // 创建全屏预览模态框
            const modal = document.createElement('div');
            modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: black;
                z-index: 10000;
                display: flex;
                justify-content: center;
                align-items: center;
                padding: 20px;
                box-sizing: border-box;
            `;

            const closeBtn = document.createElement('button');
            closeBtn.innerHTML = '<i class="fas fa-times"></i>';
            closeBtn.style.cssText = `
                position: absolute;
                top: 20px;
                right: 20px;
                background: rgba(255,255,255,0.2);
                color: white;
                border: 2px solid rgba(255,255,255,0.3);
                border-radius: 50%;
                width: 40px;
                height: 40px;
                cursor: pointer;
                font-size: 16px;
                z-index: 10001;
                transition: all 0.3s ease;
            `;

            closeBtn.addEventListener('mouseenter', () => {
                closeBtn.style.background = 'rgba(255,255,255,0.3)';
                closeBtn.style.borderColor = 'rgba(255,255,255,0.5)';
            });

            closeBtn.addEventListener('mouseleave', () => {
                closeBtn.style.background = 'rgba(255,255,255,0.2)';
                closeBtn.style.borderColor = 'rgba(255,255,255,0.3)';
            });

            // 创建PPT容器，使用与全屏放映相同的样式
            const slideContainer = document.createElement('div');
            slideContainer.style.cssText = `
                background: white;
                border-radius: 10px;
                box-shadow: 0 10px 30px rgba(255,255,255,0.2);
                overflow: hidden;
                position: relative;
                width: 100%;
                height: 100%;
                max-width: calc(100vh * 16/9 - 40px);
                max-height: calc(100vw * 9/16 - 40px);
                aspect-ratio: 16/9;
            `;

            const iframe = document.createElement('iframe');
            iframe.style.cssText = `
                width: 100%;
                height: 100%;
                border: none;
                background: white;
            `;
            iframe.srcdoc = htmlContent;

            closeBtn.addEventListener('click', () => {
                document.body.removeChild(modal);
            });

            modal.addEventListener('click', (e) => {
                if (e.target === modal) {
                    document.body.removeChild(modal);
                }
            });

            // 键盘事件支持
            const handleKeyPress = (e) => {
                if (e.key === 'Escape') {
                    document.body.removeChild(modal);
                    document.removeEventListener('keydown', handleKeyPress);
                }
            };
            document.addEventListener('keydown', handleKeyPress);

            slideContainer.appendChild(iframe);
            modal.appendChild(closeBtn);
            modal.appendChild(slideContainer);
            document.body.appendChild(modal);
        }

        // 应用AI更改
        async function applyAIChanges(newHtmlContent) {
            try {
                // 验证当前索引状态
                if (!validateCurrentSlideIndex('applyAIChanges')) {
                    throw new Error(`无效的幻灯片索引: ${currentSlideIndex}，总页数: ${slidesData ? slidesData.length : 'undefined'}`);
                }

                // 获取当前正在编辑的幻灯片索引，确保索引正确
                const targetSlideIndex = currentSlideIndex;



                // 双重验证索引有效性
                if (targetSlideIndex < 0 || targetSlideIndex >= slidesData.length) {
                    throw new Error(`无效的幻灯片索引: ${targetSlideIndex}，总页数: ${slidesData.length}`);
                }

                // 更新当前幻灯片数据
                slidesData[targetSlideIndex].html_content = newHtmlContent;

                // 标记当前幻灯片为用户编辑状态
                slidesData[targetSlideIndex].is_user_edited = true;

                // 更新预览
                const slideFrame = document.getElementById('slideFrame');
                if (slideFrame) {
                    setSafeIframeContent(slideFrame, newHtmlContent);
                    setTimeout(() => {
                        forceReinitializeIframeJS(slideFrame);
                    }, 300);
                }

                // 更新缩略图
                const thumbnailIframe = document.querySelectorAll('.slide-thumbnail .slide-preview iframe')[targetSlideIndex];
                if (thumbnailIframe) {
                    setSafeIframeContent(thumbnailIframe, newHtmlContent);
                }

                // 更新代码编辑器
                const codeEditor = document.getElementById('codeEditor');
                if (codeEditor) {
                    if (codeMirrorEditor && isCodeMirrorInitialized) {
                        codeMirrorEditor.setValue(newHtmlContent);
                    } else {
                        codeEditor.value = newHtmlContent;
                    }
                }

                // 保存到服务器 - 使用单个幻灯片保存API，确保使用正确的索引
                const saveSuccess = await saveSingleSlideToServer(targetSlideIndex, newHtmlContent);

                if (saveSuccess) {
                    showNotification(`AI更改已应用并保存！(第${targetSlideIndex + 1}页)`, 'success');
                } else {
                    showNotification(`AI更改已应用，但保存第${targetSlideIndex + 1}页时出现问题`, 'warning');
                }

            } catch (error) {
                // 尝试恢复原始内容
                try {
                    // 这里可以添加恢复逻辑，但需要保存原始内容
                } catch (restoreError) {
                    // Failed to restore original content
                }

                showNotification('应用更改失败：' + error.message, 'error');
                throw error; // 重新抛出错误以便按钮状态处理
            }
        }

        function regenerateContextSlide() {
            hideContextMenu();
            regenerateSlideByIndex(contextMenuSlideIndex);
        }

        function regenerateSlideByIndex(slideIndex) {
            if (slideIndex < 0 || slideIndex >= slidesData.length) {
                alert('无效的幻灯片索引');
                return;
            }

            const slideTitle = slidesData[slideIndex].title || `第${slideIndex + 1}页`;
            if (confirm(`确定要重新生成"${slideTitle}"吗？这将覆盖现有内容。`)) {
                // Show loading indicator
                const loadingDiv = document.createElement('div');
                loadingDiv.id = 'regenerateLoading';
                loadingDiv.style.cssText = `
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: rgba(0,0,0,0.8);
                    color: white;
                    padding: 20px;
                    border-radius: 10px;
                    z-index: 9999;
                    text-align: center;
                `;
                loadingDiv.innerHTML = `
                    <i class="fas fa-spinner fa-spin"></i>
                    <div style="margin-top: 10px;">正在重新生成幻灯片...</div>
                `;
                document.body.appendChild(loadingDiv);

                // Call API to regenerate slide
                fetch(`/api/projects/{{ project.project_id }}/slides/${slideIndex + 1}/regenerate`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        scenario: '{{ project.scenario }}',
                        topic: `{{ project.topic }}`,
                        requirements: `{{ (project.requirements or "") }}`,
                        language: 'zh'
                    })
                })
                .then(response => response.json())
                .then(data => {
                    document.body.removeChild(loadingDiv);
                    if (data.success) {
                        // 更新本地数据而不是刷新页面
                        if (data.slide_data) {
                            // 更新slidesData中的对应幻灯片
                            slidesData[slideIndex] = data.slide_data;

                            // 更新缩略图显示
                            updateThumbnailDisplay(slideIndex, data.slide_data);

                            // 如果当前正在查看这个幻灯片，更新主预览区域
                            if (currentSlideIndex === slideIndex) {
                                updateMainPreview(data.slide_data);
                                updateCodeEditor(data.slide_data);
                            }

                            showNotification('幻灯片重新生成成功！', 'success');
                        } else {
                            // 如果没有返回slide_data，则刷新页面
                            showNotification('幻灯片重新生成成功！正在刷新页面...', 'success');
                            setTimeout(() => location.reload(), 1000);
                        }
                    } else {
                        showNotification('重新生成失败：' + (data.error || '未知错误'), 'error');
                    }
                })
                .catch(error => {
                    document.body.removeChild(loadingDiv);
                    alert('重新生成失败：' + error.message);
                });
            }
        }

        // 更新缩略图显示
        function updateThumbnailDisplay(slideIndex, slideData) {
            const thumbnails = document.querySelectorAll('.slide-thumbnail');
            if (thumbnails[slideIndex]) {
                const thumbnail = thumbnails[slideIndex];

                // 更新缩略图中的iframe内容
                const iframe = thumbnail.querySelector('iframe');
                if (iframe && slideData.html_content) {
                    setSafeIframeContent(iframe, slideData.html_content);
                }

                // 更新标题
                const titleElement = thumbnail.querySelector('.slide-title');
                if (titleElement && slideData.title) {
                    titleElement.textContent = `${slideIndex + 1}. ${slideData.title}`;
                }
            }
        }

        // 更新主预览区域
        function updateMainPreview(slideData) {
            const slideFrame = document.getElementById('slideFrame');
            if (slideFrame && slideData.html_content) {
                setSafeIframeContent(slideFrame, slideData.html_content);
            }
        }

        // 更新代码编辑器
        function updateCodeEditor(slideData) {
            if (slideData.html_content) {
                if (codeMirrorEditor) {
                    // 如果使用CodeMirror
                    codeMirrorEditor.setValue(slideData.html_content);
                } else {
                    // 如果使用普通textarea
                    const codeEditor = document.getElementById('codeEditor');
                    if (codeEditor) {
                        codeEditor.value = slideData.html_content;
                    }
                }
            }
        }

        async function saveToServer() {
            try {

                // 标记所有幻灯片为用户编辑状态
                slidesData.forEach(slide => {
                    slide.is_user_edited = true;
                });

                // 使用批量保存API
                const response = await fetch(`/api/projects/{{ project.project_id }}/slides/batch-save`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        slides_data: slidesData
                    })
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const data = await response.json();

                if (data.success) {
                    return true;
                } else {
                    throw new Error(data.error || 'Unknown batch save error');
                }

            } catch (error) {
                // 如果批量保存失败，回退到逐个保存
                return await saveToServerFallback();
            }
        }

        // 回退保存方法 - 逐个保存
        async function saveToServerFallback() {
            try {

                let saveSuccessCount = 0;
                let saveFailureCount = 0;
                const saveErrors = [];

                for (let i = 0; i < slidesData.length; i++) {
                    try {
                        const slide = slidesData[i];

                        // 标记为用户编辑状态
                        slide.is_user_edited = true;

                        const success = await saveSingleSlideToServer(i, slide.html_content);
                        if (success) {
                            saveSuccessCount++;
                        } else {
                            saveFailureCount++;
                            saveErrors.push(`第${i + 1}页保存失败`);
                        }
                    } catch (error) {
                        saveFailureCount++;
                        const errorMsg = `第${i + 1}页保存异常: ${error.message}`;
                        saveErrors.push(errorMsg);
                    }
                }

                if (saveFailureCount > 0) {
                    // 即使部分失败，也不抛出错误，让用户知道部分保存成功
                    return saveSuccessCount > 0; // 只要有成功的就返回true
                } else {
                    return true;
                }

            } catch (error) {
                throw error; // 重新抛出错误以便调用者处理
            }
        }

        // 清理数据库中多余的幻灯片
        async function cleanupExcessSlides() {
            try {

                const response = await fetch(`/api/projects/{{ project.project_id }}/slides/cleanup`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        current_slide_count: slidesData.length
                    })
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const data = await response.json();

                if (data.success) {
                    return true;
                } else {
                    throw new Error(data.error || 'Unknown cleanup error');
                }

            } catch (error) {
                // 不抛出错误，因为这不应该阻止删除操作的完成
                return false;
            }
        }

        // 保存单个幻灯片到服务器
        async function saveSingleSlideToServer(slideIndex, htmlContent) {
            try {
                // 验证输入参数
                if (typeof slideIndex !== 'number' || slideIndex < 0) {
                    throw new Error(`无效的幻灯片索引: ${slideIndex}`);
                }

                if (!htmlContent || typeof htmlContent !== 'string') {
                    throw new Error('HTML内容不能为空');
                }

                // 验证索引范围
                if (slideIndex >= slidesData.length) {
                    throw new Error(`幻灯片索引超出范围: ${slideIndex}，总页数: ${slidesData.length}`);
                }



                const requestData = {
                    html_content: htmlContent
                };



                const response = await fetch(`/api/projects/{{ project.project_id }}/slides/${slideIndex}/save`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(requestData)
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const data = await response.json();

                // 验证保存是否成功
                if (data.success === true) {
                    return true;
                } else {
                    throw new Error(data.error || 'Unknown error occurred');
                }

            } catch (error) {
                throw error; // 重新抛出错误以便调用者处理
            }
        }

        let pptxExportInProgress = false;
        let pptxExportPollingTimer = null;

        async function exportToPDF() {
            const progressToast = showProgressToast('正在生成PDF文件...');
            updateProgressToast(progressToast, '正在生成PDF文件...', 20);

            try {
                triggerFileDownload(`/api/projects/{{ project.project_id }}/export/pdf`);

                updateProgressToast(progressToast, '正在准备下载...', 60);
                await new Promise(resolve => setTimeout(resolve, 1200));

                updateProgressToast(progressToast, 'PDF文件正在下载...', 100);
                setTimeout(() => closeProgressToast(progressToast), 400);
                showNotification('PDF文件生成完成，正在下载...', 'success');
            } catch (error) {
                console.error('PDF export error:', error);
                closeProgressToast(progressToast);
                showNotification(`PDF导出失败: ${error.message || error}`, 'error');
            }
        }


        function exportToPDFClientSide() {
            // 显示提示信息
            // showNotification('正在打开客户端PDF导出页面...', 'info');

            // 打开客户端PDF导出页面（原html2pdf.js方式）
           // window.open(`/api/projects/{{ project.project_id }}/export/pdf?fallback=true`, '_blank');
        }

        async function exportToPPTX() {
            if (pptxExportInProgress) {
                showNotification('PPTX导出正在进行中，请稍候...', 'warning');
                return;
            }

            pptxExportInProgress = true;
            const progressToast = showProgressToast('正在准备PPTX导出任务...');
            updateProgressToast(progressToast, '正在准备导出文件...', 10);

            try {
                const response = await fetch(`/api/projects/{{ project.project_id }}/export/pptx`);
                if (!response.ok) {
                    throw new Error(`服务返回异常(${response.status})`);
                }

                const contentType = response.headers.get('content-type') || '';
                let data = {};
                if (contentType.includes('application/json')) {
                    data = await response.json();
                } else {
                    throw new Error('服务器返回了未知的响应格式。');
                }

                if (data.status === 'processing' && data.task_id) {
                    updateProgressToast(progressToast, 'PPTX转换任务已启动，正在后台处理...', 20);
                    await trackPptxExportTask(data.task_id, progressToast);
                } else if (data.download_url) {
                    updateProgressToast(progressToast, '转换完成，正在下载...', 100);
                    triggerFileDownload(data.download_url);
                    closeProgressToast(progressToast);
                    showNotification('PPTX转换完成，正在下载...', 'success');
                } else {
                    throw new Error(data.error || data.message || 'PPTX导出请求未能启动。');
                }
            } catch (error) {
                console.error('PPTX export error:', error);
                clearPptxExportPolling();
                closeProgressToast(progressToast);
                showNotification(`PPTX导出失败: ${error.message || error}`, 'error');
            } finally {
                pptxExportInProgress = false;
                clearPptxExportPolling();
            }
        }

        function clearPptxExportPolling() {
            if (pptxExportPollingTimer) {
                clearTimeout(pptxExportPollingTimer);
                pptxExportPollingTimer = null;
            }
        }

        async function trackPptxExportTask(taskId, progressToast) {
            return new Promise((resolve, reject) => {
                const pollInterval = 2000;
                const maxAttempts = 3000;
                let attempts = 0;

                const poll = async () => {
                    attempts += 1;
                    try {
                        const response = await fetch(`/api/landppt/tasks/${taskId}`);
                        if (!response.ok) {
                            throw new Error(`任务状态查询失败(${response.status})`);
                        }

                        const data = await response.json();

                        if (data.status === 'completed' && data.result && data.result.success) {
                            updateProgressToast(progressToast, '转换完成，正在准备下载...', 100);
                            clearPptxExportPolling();
                            setTimeout(() => closeProgressToast(progressToast), 400);
                            const downloadUrl = data.download_url || `/api/landppt/tasks/${taskId}/download`;
                            triggerFileDownload(downloadUrl);
                            showNotification('PPTX转换完成，正在下载...', 'success');
                            resolve();
                            return;
                        }

                        if (data.status === 'failed') {
                            const errorMessage = data.error || (data.result && data.result.error) || 'PPTX转换失败';
                            throw new Error(errorMessage);
                        }

                        const statusTextMap = {
                            pending: '任务已排队，等待开始...',
                            running: '正在转换PPTX，请稍候...',
                        };
                        const message = statusTextMap[data.status] || '转换任务进行中，请稍候...';

                        let progressValue = 20 + Math.round((attempts / maxAttempts) * 70);
                        if (typeof data.progress === 'number') {
                            const reported = Math.round(data.progress);
                            progressValue = Math.max(progressValue, Math.min(95, reported));
                        }
                        progressValue = Math.min(progressValue, 95);

                        updateProgressToast(progressToast, message, progressValue);
                    } catch (pollError) {
                        clearPptxExportPolling();
                        reject(pollError);
                        return;
                    }

                    if (attempts >= maxAttempts) {
                        clearPptxExportPolling();
                        reject(new Error('等待PPTX转换超时，请稍后重试。'));
                        return;
                    }

                    pptxExportPollingTimer = setTimeout(poll, pollInterval);
                };

                pptxExportPollingTimer = setTimeout(poll, pollInterval);
            });
        }

        function triggerFileDownload(url) {
            const link = document.createElement('a');
            link.href = url;
            link.download = '';
            link.style.display = 'none';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }

        // 将HTML页面转换为图片并导出为PPTX（使用后端Playwright截图）
        async function exportToPPTXAsImages() {
            if (pptxExportInProgress) {
                showNotification('PPTX导出正在进行中，请稍候...', 'warning');
                return;
            }

            pptxExportInProgress = true;
            const progressToast = showProgressToast('正在准备图片导出...');

            try {
                // 使用slidesData数组
                if (!slidesData || slidesData.length === 0) {
                    throw new Error('未找到幻灯片内容');
                }

                updateProgressToast(progressToast, `正在准备 ${slidesData.length} 张幻灯片...`, 10);

                // 提取每张幻灯片的HTML内容
                const slides = slidesData.map((slide, index) => ({
                    index: index,
                    html_content: slide.html_content,
                    title: slide.title || `幻灯片 ${index + 1}`
                }));

                updateProgressToast(progressToast, '正在发送到服务器进行高质量渲染...', 20);

                // 发送HTML内容到后端，让后端使用Playwright进行截图和生成PPTX
                const response = await fetch(`/api/projects/{{ project.project_id }}/export/pptx-images`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        slides: slides
                    })
                });

                if (!response.ok) {
                    throw new Error(`服务返回异常(${response.status})`);
                }

                const contentType = response.headers.get('content-type') || '';
                let data = {};
                if (contentType.includes('application/json')) {
                    data = await response.json();
                } else {
                    throw new Error('服务器返回了未知的响应格式。');
                }

                if (data.status === 'processing' && data.task_id) {
                    updateProgressToast(progressToast, 'PPTX生成任务已启动，正在后台处理...', 80);
                    await trackPptxExportTask(data.task_id, progressToast);
                } else if (data.download_url) {
                    updateProgressToast(progressToast, '转换完成，正在下载...', 100);
                    triggerFileDownload(data.download_url);
                    closeProgressToast(progressToast);
                    showNotification('PPTX转换完成，正在下载...', 'success');
                } else {
                    throw new Error(data.error || data.message || 'PPTX导出请求未能启动。');
                }

            } catch (error) {
                console.error('PPTX image export error:', error);
                clearPptxExportPolling();
                closeProgressToast(progressToast);
                showNotification(`图片导出失败: ${error.message || error}`, 'error');
            } finally {
                pptxExportInProgress = false;
                clearPptxExportPolling();
            }
        }


        function downloadHTML() {
            // 显示提示信息
            showNotification('正在准备HTML文件包...', 'info');

            // 创建下载链接
            const downloadLink = document.createElement('a');
            downloadLink.href = `/api/projects/{{ project.project_id }}/export/html`;
            downloadLink.download = '';
            downloadLink.style.display = 'none';

            // 添加到页面并触发下载
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);

            // 延迟显示成功消息
            setTimeout(() => {
                showNotification('HTML文件包下载已开始', 'success');
            }, 1000);
        }

        function showNotification(message, type = 'info') {
            // 创建通知元素
            const notification = document.createElement('div');
            notification.className = `notification notification-${type}`;
            notification.textContent = message;

            // 添加样式
            notification.style.cssText = `
                position: fixed;
                top: 20px;
                right: 20px;
                padding: 12px 20px;
                border-radius: 6px;
                color: white;
                font-weight: 500;
                z-index: 10000;
                opacity: 0;
                transform: translateX(100%);
                transition: all 0.3s ease;
            `;

            // 根据类型设置背景色
            switch(type) {
                case 'success':
                    notification.style.backgroundColor = '#28a745';
                    break;
                case 'error':
                    notification.style.backgroundColor = '#dc3545';
                    break;
                case 'warning':
                    notification.style.backgroundColor = '#ffc107';
                    notification.style.color = '#212529';
                    break;
                default:
                    notification.style.backgroundColor = '#007bff';
            }

            // 添加到页面
            document.body.appendChild(notification);

            // 显示动画
            setTimeout(() => {
                notification.style.opacity = '1';
                notification.style.transform = 'translateX(0)';
            }, 100);

            // 自动隐藏
            setTimeout(() => {
                notification.style.opacity = '0';
                notification.style.transform = 'translateX(100%)';
                setTimeout(() => {
                    if (notification.parentNode) {
                        notification.parentNode.removeChild(notification);
                    }
                }, 300);
            }, 3000);
        }

        function exportSingleSlideHTML() {
            hideContextMenu();
            if (contextMenuSlideIndex >= 0 && contextMenuSlideIndex < slidesData.length) {
                const slide = slidesData[contextMenuSlideIndex];
                if (slide && slide.html_content) {
                    // Create a blob with the HTML content
                    const blob = new Blob([slide.html_content], { type: 'text/html' });

                    // Create download link
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `slide_${contextMenuSlideIndex + 1}_${slide.title || 'untitled'}.html`;

                    // Trigger download
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);

                    // Clean up
                    URL.revokeObjectURL(url);

                    alert(`第${contextMenuSlideIndex + 1}页已导出为HTML文件`);
                } else {
                    alert('该幻灯片没有可导出的HTML内容');
                }
            }
        }

        async function showShareDialog() {
            try {
                // 显示加载提示
                showNotification('正在生成分享链接...', 'info');

                // 调用API生成分享链接
                const response = await fetch(`/api/projects/{{ project.project_id }}/share/generate`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });

                if (!response.ok) {
                    throw new Error('生成分享链接失败');
                }

                const result = await response.json();
                const shareUrl = `${window.location.origin}${result.share_url}`;

                // 创建分享对话框
                const modal = document.createElement('div');
                modal.style.cssText = `
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0,0,0,0.5);
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    z-index: 10000;
                `;

                modal.innerHTML = `
                    <div style="
                        background: white;
                        padding: 30px;
                        border-radius: 15px;
                        max-width: 500px;
                        width: 90%;
                        text-align: center;
                        box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                    ">
                        <h4 style="margin-bottom: 20px; color: #2c3e50;">
                            <i class="fas fa-share-alt" style="color: #17a2b8;"></i> 分享链接
                        </h4>
                        
                        <div style="
                            background: #f8f9fa;
                            padding: 15px;
                            border-radius: 8px;
                            margin-bottom: 20px;
                            border: 1px solid #dee2e6;
                            word-break: break-all;
                            font-family: monospace;
                            font-size: 13px;
                            color: #495057;
                        ">${shareUrl}</div>
                        <div style="display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;">
                            <button onclick="copyShareUrl('${shareUrl}')" class="btn btn-primary">
                                <i class="fas fa-copy"></i> 复制链接
                            </button>
                            <button onclick="openShareUrl('${shareUrl}')" class="btn btn-success">
                                <i class="fas fa-external-link-alt"></i> 打开演示
                            </button>
                            <button onclick="disableSharing()" class="btn btn-warning">
                                <i class="fas fa-ban"></i> 禁用分享
                            </button>
                            <button onclick="this.closest('.share-modal').remove()" class="btn btn-secondary">
                                <i class="fas fa-times"></i> 关闭
                            </button>
                        </div>
                        <div style="margin-top: 15px; font-size: 12px; color: #6c757d;">
                            <i class="fas fa-shield-alt"></i> 分享链接已启用，可随时禁用
                        </div>
                    </div>
                `;

                modal.className = 'share-modal';
                document.body.appendChild(modal);

                // 点击背景关闭
                modal.addEventListener('click', function(e) {
                    if (e.target === modal) {
                        modal.remove();
                    }
                });

                showNotification('分享链接已生成', 'success');

            } catch (error) {
                console.error('Error generating share link:', error);
                showNotification('生成分享链接失败: ' + error.message, 'error');
            }
        }

        async function disableSharing() {
            try {
                const response = await fetch(`/api/projects/{{ project.project_id }}/share/disable`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });

                if (!response.ok) {
                    throw new Error('禁用分享失败');
                }

                // 关闭对话框
                document.querySelector('.share-modal')?.remove();
                showNotification('分享已禁用', 'success');

            } catch (error) {
                console.error('Error disabling share:', error);
                showNotification('禁用分享失败: ' + error.message, 'error');
            }
        }

        function copyShareUrl(url) {
            navigator.clipboard.writeText(url).then(() => {
                showNotification('分享链接已复制到剪贴板！', 'success');
            }).catch(() => {
                // 备用复制方法
                const textArea = document.createElement('textarea');
                textArea.value = url;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                showNotification('分享链接已复制到剪贴板！', 'success');
            });
        }

        function openShareUrl(url) {
            window.open(url, '_blank');
        }

        // Auto-save on code change (fallback for non-CodeMirror mode)
        function initializeCodeEditorAutoSave() {
            const codeEditor = document.getElementById('codeEditor');
            if (codeEditor && !isCodeMirrorInitialized) {
                codeEditor.addEventListener('input', function() {
                    clearTimeout(this.saveTimeout);
                    this.saveTimeout = setTimeout(() => {
                        if (currentMode === 'split') {
                            // Auto-update preview in split mode
                            const slideFrame = document.getElementById('slideFrame');
                            setSafeIframeContent(slideFrame, this.value);
                        }
                    }, 1000);
                });
            }
        }

        // Initialize event listeners for thumbnails using event delegation
        function initializeThumbnailEvents() {
            // Use event delegation on the slides container
            const slidesContainer = document.querySelector('.slides-container');
            if (!slidesContainer) {
                return;
            }

            // Remove existing event listeners to prevent duplicates
            slidesContainer.removeEventListener('click', slidesContainer.clickHandler);
            slidesContainer.removeEventListener('contextmenu', slidesContainer.contextHandler);
            slidesContainer.removeEventListener('dragstart', slidesContainer.dragStartHandler);
            slidesContainer.removeEventListener('dragover', slidesContainer.dragOverHandler);
            slidesContainer.removeEventListener('drop', slidesContainer.dropHandler);
            slidesContainer.removeEventListener('dragend', slidesContainer.dragEndHandler);

            // Create event handlers using event delegation
            slidesContainer.clickHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    e.preventDefault();
                    e.stopPropagation();
                    const index = parseInt(thumbnail.getAttribute('data-slide-index'));
                    if (!isNaN(index)) {
                        selectSlide(index);
                    }
                }
            };

            slidesContainer.contextHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    e.preventDefault();
                    const index = parseInt(thumbnail.getAttribute('data-slide-index'));
                    if (!isNaN(index)) {
                        showContextMenu(e, index);
                    }
                }
            };

            slidesContainer.dragStartHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    const index = parseInt(thumbnail.getAttribute('data-slide-index'));
                    if (!isNaN(index)) {
                        handleDragStart(e, index);
                    }
                }
            };

            slidesContainer.dragOverHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    handleDragOver(e);
                }
            };

            slidesContainer.dropHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    const index = parseInt(thumbnail.getAttribute('data-slide-index'));
                    if (!isNaN(index)) {
                        handleDrop(e, index);
                    }
                }
            };

            slidesContainer.dragEndHandler = (e) => {
                const thumbnail = e.target.closest('.slide-thumbnail');
                if (thumbnail) {
                    handleDragEnd(e);
                }
            };

            // Add event listeners using delegation
            slidesContainer.addEventListener('click', slidesContainer.clickHandler);
            slidesContainer.addEventListener('contextmenu', slidesContainer.contextHandler);
            slidesContainer.addEventListener('dragstart', slidesContainer.dragStartHandler);
            slidesContainer.addEventListener('dragover', slidesContainer.dragOverHandler);
            slidesContainer.addEventListener('drop', slidesContainer.dropHandler);
            slidesContainer.addEventListener('dragend', slidesContainer.dragEndHandler);
        }

        // 优化的幻灯片放映功能 - 双缓冲无闪烁系统
        let slideshowCache = new Map(); // 缓存幻灯片内容
        let isTransitioning = false; // 防止快速切换时的重复操作
        let currentFrameIndex = 1; // 当前显示的iframe索引 (1 或 2)
        let nextFrameIndex = 2; // 下一个iframe索引 (1 或 2)

        function startSlideshow() {
            if (!slidesData || slidesData.length === 0) {
                showNotification('没有可用的幻灯片！', 'warning');
                return;
            }

            isSlideshow = true;
            slideshowIndex = currentSlideIndex;

            // 重置双缓冲系统
            currentFrameIndex = 1;
            nextFrameIndex = 2;

            const overlay = document.getElementById('slideshowOverlay');
            const frame1 = document.getElementById('slideshowFrame1');
            const frame2 = document.getElementById('slideshowFrame2');

            // 初始化iframe状态
            frame1.classList.add('visible');
            frame1.classList.remove('hidden');
            frame2.classList.add('hidden');
            frame2.classList.remove('visible');

            // 使用requestAnimationFrame优化显示
            requestAnimationFrame(() => {
                overlay.style.display = 'flex';

                // 预加载当前和下一张幻灯片
                preloadSlideshowSlides();

                // 在第一个iframe中加载当前幻灯片
                const content = slideshowCache.get(slideshowIndex) || slidesData[slideshowIndex].html_content;
                setSafeIframeContentNoFlash(frame1, content, () => {
                    // 更新幻灯片信息
                    const info = document.getElementById('slideshowInfo');
                    info.textContent = `${slideshowIndex + 1} / ${slidesData.length}`;
                });
            });

            // Add keyboard event listeners
            document.addEventListener('keydown', handleSlideshowKeyboard);

            // Add touch gesture support
            initializeSlideshowTouchGestures();

            // Add mouse movement detection for controls visibility
            initializeSlideshowMouseControls();
        }

        // 预加载幻灯片内容，提升切换流畅度
        function preloadSlideshowSlides() {
            // 预加载当前、前一张和后一张幻灯片
            const indicesToPreload = [
                slideshowIndex - 1,
                slideshowIndex,
                slideshowIndex + 1
            ].filter(index => index >= 0 && index < slidesData.length);

            indicesToPreload.forEach(index => {
                if (!slideshowCache.has(index)) {
                    const content = slidesData[index].html_content;
                    slideshowCache.set(index, content);
                }
            });
        }

        function exitSlideshow() {
            isSlideshow = false;
            isTransitioning = false;

            const overlay = document.getElementById('slideshowOverlay');
            const frame1 = document.getElementById('slideshowFrame1');
            const frame2 = document.getElementById('slideshowFrame2');

            // 使用fade out效果
            overlay.style.opacity = '0';
            setTimeout(() => {
                overlay.style.display = 'none';
                overlay.style.opacity = '1';

                // 清理iframe内容，避免内存泄漏
                frame1.srcdoc = '';
                frame2.srcdoc = '';
                frame1.removeAttribute('data-current-content');
                frame2.removeAttribute('data-current-content');
            }, 200);

            // Remove keyboard event listeners
            document.removeEventListener('keydown', handleSlideshowKeyboard);

            // Remove touch gesture listeners
            removeSlideshowTouchGestures();

            // Remove mouse movement listeners
            removeSlideshowMouseControls();

            // 清理缓存（可选，节省内存）
            slideshowCache.clear();
        }

        // 无闪烁幻灯片更新函数 - 双缓冲系统
        function updateSlideshowSlide() {
            if (!slidesData || slidesData.length === 0 || isTransitioning) return;

            isTransitioning = true;

            const info = document.getElementById('slideshowInfo');

            // 立即更新幻灯片信息
            info.textContent = `${slideshowIndex + 1} / ${slidesData.length}`;

            // 获取当前显示的iframe和下一个iframe
            const currentFrame = document.getElementById(`slideshowFrame${currentFrameIndex}`);
            const nextFrame = document.getElementById(`slideshowFrame${nextFrameIndex}`);

            // 在后台iframe中预加载新内容
            const content = slideshowCache.get(slideshowIndex) || slidesData[slideshowIndex].html_content;

            // 使用优化的内容设置方法
            setSafeIframeContentNoFlash(nextFrame, content, () => {
                // 内容加载完成后，瞬间切换显示
                requestAnimationFrame(() => {
                    // 隐藏当前iframe，显示新iframe
                    currentFrame.classList.remove('visible');
                    currentFrame.classList.add('hidden');
                    nextFrame.classList.remove('hidden');
                    nextFrame.classList.add('visible');

                    // 交换iframe索引
                    [currentFrameIndex, nextFrameIndex] = [nextFrameIndex, currentFrameIndex];

                    isTransitioning = false;

                    // 预加载相邻幻灯片
                    preloadSlideshowSlides();

                    // 异步初始化JavaScript，不阻塞UI
                    setTimeout(() => {
                        forceReinitializeIframeJS(nextFrame);
                    }, 100);
                });
            });
        }

        // 优化的iframe内容设置，避免闪烁
        function setSafeIframeContentNoFlash(iframe, html, callback) {
            if (!iframe || !html) {
                if (callback) callback();
                return;
            }

            // 检查内容是否相同，避免不必要的更新
            if (iframe.getAttribute('data-current-content') === html) {
                if (callback) callback();
                return;
            }

            // 直接设置内容，不使用过渡效果
            try {
                iframe.srcdoc = html;
                iframe.setAttribute('data-current-content', html);

                // 监听加载完成
                const handleLoad = () => {
                    iframe.removeEventListener('load', handleLoad);
                    if (callback) {
                        // 短暂延迟确保内容完全渲染
                        setTimeout(callback, 50);
                    }
                };

                iframe.addEventListener('load', handleLoad);

                // 备用超时机制
                setTimeout(() => {
                    iframe.removeEventListener('load', handleLoad);
                    if (callback) callback();
                }, 500);

            } catch (e) {
                if (callback) callback();
            }
        }

        // 优化的切换函数，支持快速响应和防抖
        function previousSlideshow() {
            if (isTransitioning) return; // 防止快速切换时的重复操作

            if (slideshowIndex > 0) {
                slideshowIndex--;
                updateSlideshowSlide();
            } else {
                // 到达第一张时的视觉反馈
                const slideContainer = document.querySelector('.slideshow-slide');
                slideContainer.style.transform = 'translateX(-10px)';
                setTimeout(() => {
                    slideContainer.style.transform = 'translateX(0)';
                }, 150);
            }
        }

        function nextSlideshow() {
            if (isTransitioning) return; // 防止快速切换时的重复操作

            if (slideshowIndex < slidesData.length - 1) {
                slideshowIndex++;
                updateSlideshowSlide();
            } else {
                // 到达最后一张时的视觉反馈
                const slideContainer = document.querySelector('.slideshow-slide');
                slideContainer.style.transform = 'translateX(10px)';
                setTimeout(() => {
                    slideContainer.style.transform = 'translateX(0)';
                }, 150);
            }
        }

        // 快速跳转到指定幻灯片
        function jumpToSlide(index) {
            if (isTransitioning || index < 0 || index >= slidesData.length) return;

            slideshowIndex = index;
            updateSlideshowSlide();
        }

        // 优化的键盘事件处理，支持更多快捷键和防抖
        let keyboardTimeout;

        function handleSlideshowKeyboard(e) {
            if (!isSlideshow) return;

            // 防抖处理，避免按键过快
            clearTimeout(keyboardTimeout);
            keyboardTimeout = setTimeout(() => {
                switch(e.key) {
                    case 'ArrowLeft':
                    case 'ArrowUp':
                    case 'PageUp':
                    case 'Backspace':
                        e.preventDefault();
                        previousSlideshow();
                        break;
                    case 'ArrowRight':
                    case 'ArrowDown':
                    case 'PageDown':
                    case ' ':
                    case 'Enter':
                        e.preventDefault();
                        nextSlideshow();
                        break;
                    case 'Escape':
                    case 'q':
                    case 'Q':
                        e.preventDefault();
                        exitSlideshow();
                        break;
                    case 'Home':
                        e.preventDefault();
                        jumpToSlide(0);
                        break;
                    case 'End':
                        e.preventDefault();
                        jumpToSlide(slidesData.length - 1);
                        break;
                    case 'f':
                    case 'F':
                    case 'F11':
                        e.preventDefault();
                        toggleSlideshowFullscreen();
                        break;
                    default:
                        // 数字键快速跳转
                        if (e.key >= '1' && e.key <= '9') {
                            e.preventDefault();
                            const slideNum = parseInt(e.key) - 1;
                            if (slideNum < slidesData.length) {
                                jumpToSlide(slideNum);
                            }
                        }
                        break;
                }
            }, 50); // 50ms防抖
        }

        // 全屏切换功能
        function toggleSlideshowFullscreen() {
            const overlay = document.getElementById('slideshowOverlay');

            if (!document.fullscreenElement) {
                overlay.requestFullscreen().catch(err => {
                    // 无法进入全屏
                });
            } else {
                document.exitFullscreen().catch(err => {
                    // 无法退出全屏
                });
            }
        }

        // 拖拽功能
        function handleDragStart(event, slideIndex) {
            draggedSlideIndex = slideIndex;
            event.target.classList.add('dragging');
            event.dataTransfer.effectAllowed = 'move';
            event.dataTransfer.setData('text/html', event.target.outerHTML);
        }

        function handleDragOver(event) {
            event.preventDefault();
            event.dataTransfer.dropEffect = 'move';

            const thumbnail = event.currentTarget;
            const rect = thumbnail.getBoundingClientRect();
            const midY = rect.top + rect.height / 2;

            // 清除所有指示器
            document.querySelectorAll('.drag-indicator').forEach(indicator => {
                indicator.classList.remove('show');
            });

            // 显示适当的指示器
            if (event.clientY < midY) {
                thumbnail.querySelector('.drag-indicator.top').classList.add('show');
            } else {
                thumbnail.querySelector('.drag-indicator.bottom').classList.add('show');
            }

            thumbnail.classList.add('drag-over');
        }

        function handleDrop(event, targetIndex) {
            event.preventDefault();

            if (draggedSlideIndex === -1 || draggedSlideIndex === targetIndex) {
                return;
            }

            const rect = event.currentTarget.getBoundingClientRect();
            const midY = rect.top + rect.height / 2;
            const insertBefore = event.clientY < midY;

            // 计算新的插入位置
            let newIndex = targetIndex;
            if (!insertBefore) {
                newIndex = targetIndex + 1;
            }

            // 如果拖拽的元素在目标位置之前，需要调整索引
            if (draggedSlideIndex < newIndex) {
                newIndex--;
            }

            // 移动幻灯片
            moveSlide(draggedSlideIndex, newIndex);
        }

        function handleDragEnd(event) {
            event.target.classList.remove('dragging');
            document.querySelectorAll('.slide-thumbnail').forEach(thumb => {
                thumb.classList.remove('drag-over');
            });
            document.querySelectorAll('.drag-indicator').forEach(indicator => {
                indicator.classList.remove('show');
            });
            draggedSlideIndex = -1;
        }

        function moveSlide(fromIndex, toIndex) {
            if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 ||
                fromIndex >= slidesData.length || toIndex > slidesData.length) {
                return;
            }

            // 移动数据
            const movedSlide = slidesData.splice(fromIndex, 1)[0];
            slidesData.splice(toIndex, 0, movedSlide);

            // 更新页码
            slidesData.forEach((slide, index) => {
                slide.page_number = index + 1;
            });

            // 更新当前选中的索引
            if (currentSlideIndex === fromIndex) {
                currentSlideIndex = toIndex;
            } else if (currentSlideIndex > fromIndex && currentSlideIndex <= toIndex) {
                currentSlideIndex--;
            } else if (currentSlideIndex < fromIndex && currentSlideIndex >= toIndex) {
                currentSlideIndex++;
            }

            // 重新渲染侧边栏
            refreshSidebar();

            // 保存到服务器
            saveToServer();
        }

        // 右键菜单功能
        function showContextMenu(event, slideIndex) {
            event.preventDefault();
            contextMenuSlideIndex = slideIndex;

            const contextMenu = document.getElementById('contextMenu');
            const pasteMenuItem = document.getElementById('pasteMenuItem');

            // 更新粘贴菜单项状态
            if (copiedSlideData) {
                pasteMenuItem.classList.remove('disabled');
            } else {
                pasteMenuItem.classList.add('disabled');
            }

            // 显示菜单
            contextMenu.style.display = 'block';
            contextMenu.style.left = event.pageX + 'px';
            contextMenu.style.top = event.pageY + 'px';

            // 确保菜单不超出屏幕
            const rect = contextMenu.getBoundingClientRect();
            if (rect.right > window.innerWidth) {
                contextMenu.style.left = (event.pageX - rect.width) + 'px';
            }
            if (rect.bottom > window.innerHeight) {
                contextMenu.style.top = (event.pageY - rect.height) + 'px';
            }
        }

        function hideContextMenu() {
            document.getElementById('contextMenu').style.display = 'none';
        }

        function editSlide() {
            hideContextMenu();
            selectSlide(contextMenuSlideIndex);
            setMode('edit');
        }

        function copySlide() {
            hideContextMenu();
            if (!isPPTGenerationCompleted()) {
                showNotification('PPT生成完成后才能使用复制功能', 'warning');
                return;
            }
            if (contextMenuSlideIndex >= 0 && contextMenuSlideIndex < slidesData.length) {
                copiedSlideData = JSON.parse(JSON.stringify(slidesData[contextMenuSlideIndex]));
                showNotification('幻灯片已复制到剪贴板', 'success');
            }
        }

        async function pasteSlide() {
            hideContextMenu();
            if (!isPPTGenerationCompleted()) {
                showNotification('PPT生成完成后才能使用粘贴功能', 'warning');
                return;
            }
            if (!copiedSlideData) {
                showNotification('剪贴板中没有幻灯片数据', 'warning');
                return;
            }

            try {
                // 获取全局母版模板
                const globalTemplate = await getSelectedGlobalTemplate();

                // 创建新的幻灯片数据
                const newSlide = JSON.parse(JSON.stringify(copiedSlideData));
                newSlide.page_number = contextMenuSlideIndex + 2;
                newSlide.title = newSlide.title + ' (副本)';

                // 如果有全局母版，使用模板生成新的HTML内容
                if (globalTemplate) {
                    newSlide.html_content = await generateSlideWithGlobalTemplate(
                        globalTemplate,
                        newSlide.title,
                        '复制的幻灯片内容'
                    );
                }

                // 插入到指定位置
                slidesData.splice(contextMenuSlideIndex + 1, 0, newSlide);

                // 更新后续幻灯片的页码
                for (let i = contextMenuSlideIndex + 2; i < slidesData.length; i++) {
                    slidesData[i].page_number = i + 1;
                }

                // 同步更新大纲
                await updateOutlineForSlideOperation('insert', contextMenuSlideIndex + 1, {
                    title: newSlide.title,
                    slide_type: 'content',
                    type: 'content',
                    description: '复制的幻灯片内容',
                    content_points: []
                });

                // 刷新界面
                refreshSidebar();
                saveToServer();
                showNotification('幻灯片已粘贴', 'success');
            } catch (error) {
                showNotification('粘贴幻灯片失败：' + error.message, 'error');
            }
        }

        async function insertNewSlide() {
            hideContextMenu();
            if (!isPPTGenerationCompleted()) {
                showNotification('PPT生成完成后才能添加新幻灯片', 'warning');
                return;
            }

            try {
                // 获取全局母版模板
                const globalTemplate = await getSelectedGlobalTemplate();

                const slideTitle = `第${contextMenuSlideIndex + 2}页`;
                let htmlContent = `
                    <div style="width: 1280px; height: 720px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                                display: flex; flex-direction: column; justify-content: center; align-items: center;
                                color: white; font-family: 'Microsoft YaHei', Arial, sans-serif;">
                        <h1 style="font-size: 48px; margin-bottom: 20px; text-align: center;">新建幻灯片</h1>
                        <p style="font-size: 24px; text-align: center;">请编辑此幻灯片内容</p>
                    </div>
                `;

                // 如果有全局母版，使用模板生成HTML内容
                if (globalTemplate) {
                    htmlContent = await generateSlideWithGlobalTemplate(
                        globalTemplate,
                        slideTitle,
                        '新建幻灯片，请编辑内容'
                    );
                }

                // 创建新的空白幻灯片
                const newSlide = {
                    page_number: contextMenuSlideIndex + 2,
                    title: slideTitle,
                    html_content: htmlContent
                };

                // 插入到指定位置
                slidesData.splice(contextMenuSlideIndex + 1, 0, newSlide);

                // 更新后续幻灯片的页码
                for (let i = contextMenuSlideIndex + 2; i < slidesData.length; i++) {
                    slidesData[i].page_number = i + 1;
                }

                // 同步更新大纲
                await updateOutlineForSlideOperation('insert', contextMenuSlideIndex + 1, {
                    title: slideTitle,
                    slide_type: 'content',
                    type: 'content',
                    description: '新建幻灯片，请编辑内容',
                    content_points: []
                });

                // 刷新界面
                refreshSidebar();
                saveToServer();
                showNotification('新幻灯片已插入', 'success');
            } catch (error) {
                showNotification('插入新幻灯片失败：' + error.message, 'error');
            }
        }

        async function duplicateSlide() {
            hideContextMenu();
            if (!isPPTGenerationCompleted()) {
                showNotification('PPT生成完成后才能复制幻灯片', 'warning');
                return;
            }
            if (contextMenuSlideIndex >= 0 && contextMenuSlideIndex < slidesData.length) {
                try {
                    // 获取全局母版模板
                    const globalTemplate = await getSelectedGlobalTemplate();

                    const originalSlide = slidesData[contextMenuSlideIndex];
                    const duplicatedSlide = JSON.parse(JSON.stringify(originalSlide));
                    duplicatedSlide.page_number = contextMenuSlideIndex + 2;
                    duplicatedSlide.title = duplicatedSlide.title + ' (副本)';

                    // 如果有全局母版，使用模板重新生成HTML内容
                    if (globalTemplate) {
                        duplicatedSlide.html_content = await generateSlideWithGlobalTemplate(
                            globalTemplate,
                            duplicatedSlide.title,
                            '复制的幻灯片内容'
                        );
                    }

                    // 插入到原幻灯片后面
                    slidesData.splice(contextMenuSlideIndex + 1, 0, duplicatedSlide);

                    // 更新后续幻灯片的页码
                    for (let i = contextMenuSlideIndex + 2; i < slidesData.length; i++) {
                        slidesData[i].page_number = i + 1;
                    }

                    // 同步更新大纲
                    await updateOutlineForSlideOperation('insert', contextMenuSlideIndex + 1, {
                        title: duplicatedSlide.title,
                        slide_type: 'content',
                        type: 'content',
                        description: '复制的幻灯片内容',
                        content_points: []
                    });

                    // 刷新界面
                    refreshSidebar();
                    saveToServer();
                    showNotification('幻灯片已复制', 'success');
                } catch (error) {
                    showNotification('复制幻灯片失败：' + error.message, 'error');
                }
            }
        }

        async function deleteSlide() {
            hideContextMenu();
            if (!isPPTGenerationCompleted()) {
                showNotification('PPT生成完成后才能删除幻灯片', 'warning');
                return;
            }
            if (slidesData.length <= 1) {
                showNotification('至少需要保留一张幻灯片', 'warning');
                return;
            }

            if (confirm('确定要删除这张幻灯片吗？')) {
                try {
                    // 删除幻灯片
                    slidesData.splice(contextMenuSlideIndex, 1);

                    // 更新后续幻灯片的页码
                    for (let i = contextMenuSlideIndex; i < slidesData.length; i++) {
                        slidesData[i].page_number = i + 1;
                    }

                    // 调整当前选中的索引
                    if (currentSlideIndex >= contextMenuSlideIndex) {
                        currentSlideIndex = Math.max(0, currentSlideIndex - 1);
                    }

                    // 同步更新大纲
                    await updateOutlineForSlideOperation('delete', contextMenuSlideIndex);

                    // 刷新界面
                    refreshSidebar();
                    selectSlide(currentSlideIndex);

                    // 保存当前幻灯片数据
                    await saveToServer();

                    // 清理数据库中多余的幻灯片
                    await cleanupExcessSlides();

                    showNotification('幻灯片已删除', 'success');
                } catch (error) {
                    showNotification('删除幻灯片失败：' + error.message, 'error');
                }
            }
        }

        function refreshSidebar() {
            const slidesContainer = document.querySelector('.slides-container');
            if (!slidesContainer) return;

            // 如果没有slides数据，显示提示信息
            if (!slidesData || slidesData.length === 0) {
                slidesContainer.innerHTML = `
                    <div class="text-center p-4" style="color: #7f8c8d;" id="noSlidesMessage">
                        <div style="font-size: 48px; margin-bottom: 15px;">
                            <i class="fas fa-magic"></i>
                        </div>
                        <h5 style="margin-bottom: 10px;">PPT正在生成中...</h5>
                        <p style="margin-bottom: 15px; font-size: 14px;">
                            幻灯片生成完成后，您可以在这里进行编辑和管理
                        </p>
                        <div class="spinner-border text-primary" role="status" style="margin-bottom: 15px;">
                            <span class="visually-hidden">Loading...</span>
                        </div>
                        <br>
                        <button class="btn btn-primary btn-sm" onclick="checkForUpdates()">
                            <i class="fas fa-refresh"></i> 刷新页面
                        </button>
                    </div>
                `;
                return;
            }

            // 清除现有的幻灯片缩略图和提示信息
            const existingThumbnails = slidesContainer.querySelectorAll('.slide-thumbnail');
            const noSlidesMessage = slidesContainer.querySelector('#noSlidesMessage');
            existingThumbnails.forEach(thumb => thumb.remove());
            if (noSlidesMessage) noSlidesMessage.remove();

            // 重新生成幻灯片缩略图
            slidesData.forEach((slide, index) => {
                const thumbnailDiv = document.createElement('div');
                thumbnailDiv.className = `slide-thumbnail ${index === currentSlideIndex ? 'active' : ''}`;
                thumbnailDiv.setAttribute('data-slide-index', index);
                thumbnailDiv.setAttribute('draggable', 'true');
                // 不再使用内联事件处理器，依赖事件委托

                thumbnailDiv.innerHTML = `
                    <div class="drag-indicator top"></div>
                    <div class="slide-preview">
                        <iframe title="Slide ${index + 1}"
                                loading="lazy"></iframe>
                    </div>
                    <div class="slide-title">${index + 1}. ${slide.title}</div>
                    <div class="drag-indicator bottom"></div>
                `;

                // 设置iframe内容并应用缩放
                const iframe = thumbnailDiv.querySelector('iframe');
                if (iframe) {
                    // 安全设置iframe内容
                    setSafeIframeContent(iframe, slide.html_content);

                    iframe.onload = function() {
                        // 应用响应式缩放
                        this.style.transform = getResponsiveScale();
                        this.style.width = getResponsiveWidth();
                        this.style.height = getResponsiveHeight();
                    };
                }

                slidesContainer.appendChild(thumbnailDiv);
            });

            // 重新初始化事件监听器
            initializeThumbnailEvents();
        }

        // 优化的iframe JavaScript重新初始化函数
        let isReinitializing = false; // 防止重复初始化

        function forceReinitializeIframeJS(iframe) {
            if (!iframe || isReinitializing) return;

            isReinitializing = true;

            // 使用requestAnimationFrame优化性能
            requestAnimationFrame(() => {
                try {
                    const iframeWindow = iframe.contentWindow;
                    const iframeDoc = iframe.contentDocument || iframeWindow.document;

                    if (!iframeWindow || !iframeDoc) {
                        isReinitializing = false;
                        return;
                    }

                    // 只检查Chart.js，减少不必要的操作
                    if (iframeWindow.Chart) {
                        const canvasElements = iframeDoc.querySelectorAll('canvas[id*="chart"], canvas[id*="Chart"]');

                        if (canvasElements.length > 0) {
                            // 简化检查逻辑
                            let needsReinitialization = false;
                            canvasElements.forEach(canvas => {
                                if (!canvas.chart) {
                                    needsReinitialization = true;
                                }
                            });

                            // 只在真正需要时才重新初始化
                            if (needsReinitialization) {
                                const scripts = iframeDoc.querySelectorAll('script');
                                scripts.forEach(script => {
                                    if (script.textContent && script.textContent.includes('Chart')) {
                                        try {
                                            iframeWindow.eval(script.textContent);
                                        } catch (e) {
                                            // 静默处理错误
                                        }
                                    }
                                });
                            }
                        }
                    }

                    // 初始化图像选择功能
                    initializeImageSelection(iframe, iframeWindow, iframeDoc);

                } catch (e) {
                    // 静默处理错误，避免控制台噪音
                } finally {
                    // 延迟重置标志，避免过于频繁的调用
                    setTimeout(() => {
                        isReinitializing = false;
                    }, 500);
                }
            });
        }

        // 图像选择功能相关变量
        let selectedImageInfo = null;
        let imageSelectionEnabled = false;

        // 初始化图像选择功能（仅在快速编辑模式下启用）
        function initializeImageSelection(iframe, iframeWindow, iframeDoc) {
            try {
                // 移除之前的事件监听器
                const existingSelectables = iframeDoc.querySelectorAll('[data-image-selectable]');
                existingSelectables.forEach(element => {
                    element.removeAttribute('data-image-selectable');
                    element.style.cursor = '';
                    element.classList.remove('image-selected', 'image-selectable');
                    // 移除之前添加的事件监听器
                    if (element._imageClickHandler) {
                        element.removeEventListener('click', element._imageClickHandler);
                        element.removeEventListener('mouseenter', element._imageMouseEnterHandler);
                        element.removeEventListener('mouseleave', element._imageMouseLeaveHandler);
                        delete element._imageClickHandler;
                        delete element._imageMouseEnterHandler;
                        delete element._imageMouseLeaveHandler;
                    }
                });

                // 只在快速编辑模式下启用图像选择功能
                if (!quickEditMode || currentMode !== 'quickedit') {
                    return;
                }

                let imageIndex = 0;

                // 1. 处理 <img> 标签
                const images = iframeDoc.querySelectorAll('img');
                images.forEach((img) => {
                    // 跳过装饰性图像或很小的图像
                    if (img.width < 30 || img.height < 30) return;

                    setupImageSelection(img, imageIndex++, iframe, 'img');
                });

                // 2. 处理具有背景图像的元素
                const allElements = iframeDoc.querySelectorAll('*');
                allElements.forEach((element) => {
                    const computedStyle = iframeWindow.getComputedStyle(element);
                    const backgroundImage = computedStyle.backgroundImage;

                    // 检查是否有背景图像（排除 none 和渐变）
                    if (backgroundImage &&
                        backgroundImage !== 'none' &&
                        backgroundImage.includes('url(')) {

                        // 获取元素尺寸
                        const rect = element.getBoundingClientRect();

                        // 跳过太小的元素
                        if (rect.width < 50 || rect.height < 50) return;

                        // 跳过已经处理过的img元素
                        if (element.tagName.toLowerCase() === 'img') return;

                        setupImageSelection(element, imageIndex++, iframe, 'background');
                    }
                });

                // 3. 处理SVG图像
                const svgElements = iframeDoc.querySelectorAll('svg');
                svgElements.forEach((svg) => {
                    const rect = svg.getBoundingClientRect();
                    if (rect.width < 30 || rect.height < 30) return;

                    setupImageSelection(svg, imageIndex++, iframe, 'svg');
                });

                // 添加样式到iframe文档
                addImageSelectionStyles(iframeDoc);



            } catch (e) {
                // 初始化图像选择功能失败
            }
        }

        // 设置单个元素的图像选择功能
        function setupImageSelection(element, index, iframe, type) {
            element.setAttribute('data-image-selectable', 'true');
            element.setAttribute('data-image-index', index);
            element.setAttribute('data-image-type', type);
            element.style.cursor = 'pointer';
            element.classList.add('image-selectable');

            // 创建事件处理器并保存引用以便后续移除
            element._imageClickHandler = function(e) {
                // 只在快速编辑模式下响应点击
                if (!quickEditMode || currentMode !== 'quickedit') {
                    return;
                }
                e.preventDefault();
                e.stopPropagation();
                selectImage(element, iframe);
            };

            element._imageMouseEnterHandler = function() {
                // 只在快速编辑模式下显示悬停效果
                if (!quickEditMode || currentMode !== 'quickedit') {
                    return;
                }
                if (!element.classList.contains('image-selected')) {
                    element.style.outline = '2px dashed #007bff';
                    element.style.outlineOffset = '2px';
                }
            };

            element._imageMouseLeaveHandler = function() {
                // 只在快速编辑模式下处理悬停离开
                if (!quickEditMode || currentMode !== 'quickedit') {
                    return;
                }
                if (!element.classList.contains('image-selected')) {
                    element.style.outline = '';
                    element.style.outlineOffset = '';
                }
            };

            // 添加事件监听器
            element.addEventListener('click', element._imageClickHandler);
            element.addEventListener('mouseenter', element._imageMouseEnterHandler);
            element.addEventListener('mouseleave', element._imageMouseLeaveHandler);
        }

        // 添加图像选择相关样式
        function addImageSelectionStyles(iframeDoc) {
            let styleElement = iframeDoc.getElementById('image-selection-styles');
            if (!styleElement) {
                styleElement = iframeDoc.createElement('style');
                styleElement.id = 'image-selection-styles';
                styleElement.textContent = `
                    .image-selectable {
                        transition: all 0.2s ease;
                    }
                    .image-selectable:hover {
                        transform: scale(1.02);
                    }
                    .image-selected {
                        outline: 3px solid #007bff !important;
                        outline-offset: 3px !important;
                        box-shadow: 0 0 10px rgba(0, 123, 255, 0.3) !important;
                        transform: scale(1.02) !important;
                    }
                `;
                iframeDoc.head.appendChild(styleElement);
            }
        }

        // 选择图像
        function selectImage(imgElement, iframe) {
            try {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

                // 清除之前的选择
                const previousSelected = iframeDoc.querySelectorAll('.image-selected');
                previousSelected.forEach(img => {
                    img.classList.remove('image-selected');
                    img.style.outline = '';
                    img.style.outlineOffset = '';
                    img.style.boxShadow = '';
                    img.style.transform = '';
                });

                // 选择当前图像
                imgElement.classList.add('image-selected');

                // 提取图像信息
                const imageInfo = extractImageInfo(imgElement, iframe);
                selectedImageInfo = imageInfo;

                // 通知AI助手
                notifyAIAssistantImageSelected(imageInfo);

            } catch (e) {
                // 选择图像失败
            }
        }

        // 提取图像信息
        function extractImageInfo(imageElement, iframe) {
            const rect = imageElement.getBoundingClientRect();
            const computedStyle = iframe.contentWindow.getComputedStyle(imageElement);
            const imageType = imageElement.getAttribute('data-image-type') || 'img';

            let imageInfo = {
                index: imageElement.getAttribute('data-image-index'),
                type: imageType,
                className: imageElement.className,
                id: imageElement.id || '',
                style: imageElement.getAttribute('style') || '',
                width: rect.width,
                height: rect.height,
                position: {
                    top: rect.top,
                    left: rect.left,
                    right: rect.right,
                    bottom: rect.bottom
                },
                computedStyle: {
                    position: computedStyle.position,
                    display: computedStyle.display,
                    float: computedStyle.float,
                    margin: computedStyle.margin,
                    padding: computedStyle.padding,
                    border: computedStyle.border,
                    borderRadius: computedStyle.borderRadius,
                    transform: computedStyle.transform,
                    zIndex: computedStyle.zIndex,
                    opacity: computedStyle.opacity,
                    backgroundImage: computedStyle.backgroundImage,
                    backgroundSize: computedStyle.backgroundSize,
                    backgroundPosition: computedStyle.backgroundPosition,
                    backgroundRepeat: computedStyle.backgroundRepeat
                },
                slideIndex: currentSlideIndex,
                slideTitle: slidesData[currentSlideIndex]?.title || '',
                outerHTML: imageElement.outerHTML,
                parentInfo: extractParentInfo(imageElement)
            };

            // 根据图像类型提取特定信息
            if (imageType === 'img') {
                // <img> 标签的特定属性
                imageInfo.src = imageElement.src;
                imageInfo.alt = imageElement.alt || '';
                imageInfo.title = imageElement.title || '';
                imageInfo.naturalWidth = imageElement.naturalWidth;
                imageInfo.naturalHeight = imageElement.naturalHeight;
                imageInfo.computedStyle.objectFit = computedStyle.objectFit;
                imageInfo.computedStyle.objectPosition = computedStyle.objectPosition;
            } else if (imageType === 'background') {
                // 背景图像的特定属性
                const backgroundImage = computedStyle.backgroundImage;
                const urlMatch = backgroundImage.match(/url\(['"]?([^'"]+)['"]?\)/);
                imageInfo.src = urlMatch ? urlMatch[1] : '';
                imageInfo.alt = imageElement.getAttribute('alt') || imageElement.getAttribute('title') || '背景图像';
                imageInfo.title = imageElement.getAttribute('title') || '背景图像';
                imageInfo.isBackgroundImage = true;
            } else if (imageType === 'svg') {
                // SVG 的特定属性
                imageInfo.src = imageElement.getAttribute('src') || 'data:image/svg+xml;base64,' + btoa(imageElement.outerHTML);
                imageInfo.alt = imageElement.getAttribute('alt') || imageElement.getAttribute('title') || 'SVG图像';
                imageInfo.title = imageElement.getAttribute('title') || 'SVG图像';
                imageInfo.isSVG = true;
            }

            return imageInfo;
        }

        // 提取父容器信息
        function extractParentInfo(imgElement) {
            const parent = imgElement.parentElement;
            if (!parent) return null;

            return {
                tagName: parent.tagName,
                className: parent.className,
                style: parent.getAttribute('style') || '',
                id: parent.id || ''
            };
        }

        // 获取图像类型的显示名称
        function getImageTypeDisplay(type) {
            const typeMap = {
                'img': '图片标签',
                'background': '背景图像',
                'svg': 'SVG图像'
            };
            return typeMap[type] || '未知类型';
        }

        // 客户端图像替换函数（保持完整HTML结构）
        function replaceImageInHtmlClient(htmlContent, imageInfo, newImageUrl) {
            try {
                // 使用字符串替换而不是DOM解析，避免样式丢失
                const imageType = imageInfo.type || 'img';
                const oldSrc = imageInfo.src || '';

                let updatedHtml = htmlContent;
                let replaced = false;

                if (imageType === 'img') {
                    // 使用正则表达式替换img标签的src属性
                    const imgRegex = new RegExp(
                        `(<img[^>]*src=["'])[^"']*${escapeRegExp(oldSrc.split('/').pop())}[^"']*(['"][^>]*>)`,
                        'gi'
                    );

                    if (imgRegex.test(htmlContent)) {
                        updatedHtml = htmlContent.replace(imgRegex, `$1${newImageUrl}$2`);
                        replaced = true;
                    } else {
                        // 后备方案：直接字符串替换
                        if (htmlContent.includes(oldSrc)) {
                            updatedHtml = htmlContent.replace(new RegExp(escapeRegExp(oldSrc), 'g'), newImageUrl);
                            replaced = true;
                        }
                    }
                } else if (imageType === 'background') {
                    // 替换CSS背景图像
                    const bgRegex = new RegExp(
                        `(background-image:\\s*url\\(['"]?)[^'"\\)]*${escapeRegExp(oldSrc.split('/').pop())}[^'"\\)]*(['"]?\\))`,
                        'gi'
                    );

                    if (bgRegex.test(htmlContent)) {
                        updatedHtml = htmlContent.replace(bgRegex, `$1${newImageUrl}$2`);
                        replaced = true;
                    } else {
                        // 后备方案
                        if (htmlContent.includes(oldSrc)) {
                            updatedHtml = htmlContent.replace(new RegExp(escapeRegExp(oldSrc), 'g'), newImageUrl);
                            replaced = true;
                        }
                    }
                }

                return replaced ? updatedHtml : htmlContent;

            } catch (error) {
                return htmlContent;
            }
        }

        // 搜索图片
        function searchImages(event) {
            if (event.key === 'Enter' || event.type === 'input') {
                galleryState.searchTerm = event.target.value.toLowerCase();
                galleryState.currentPage = 1;
                applyFilters();
            }
        }



        // 筛选图片分类
        function filterImages() {
            const categoryFilter = document.getElementById('imageCategoryFilter');
            galleryState.categoryFilter = categoryFilter.value;
            galleryState.currentPage = 1;
            applyFilters();
        }

        // 改变每页显示数量
        function changePageSize() {
            const pageSizeSelect = document.getElementById('imagePageSize');
            galleryState.pageSize = parseInt(pageSizeSelect.value);
            galleryState.currentPage = 1;
            renderImageGallery();
        }

        // 跳转到指定页面
        function goToPage(page) {
            const totalPages = Math.ceil(galleryState.filteredImages.length / galleryState.pageSize);
            if (page >= 1 && page <= totalPages) {
                galleryState.currentPage = page;
                renderImageGallery();
            }
        }

        // 应用筛选条件
        function applyFilters() {
            const { allImages, searchTerm, categoryFilter } = galleryState;

            galleryState.filteredImages = allImages.filter(image => {
                // 搜索筛选
                const matchesSearch = !searchTerm ||
                    (image.title && image.title.toLowerCase().includes(searchTerm)) ||
                    (image.description && image.description.toLowerCase().includes(searchTerm)) ||
                    (image.alt_text && image.alt_text.toLowerCase().includes(searchTerm));

                // 分类筛选 - 兼容多种可能的字段名
                let matchesCategory = true;
                if (categoryFilter) {
                    matchesCategory =
                        image.category === categoryFilter ||
                        image.source === categoryFilter ||
                        image.source_type === categoryFilter ||
                        image.type === categoryFilter ||
                        // 根据图片来源推断分类 - 修复字段映射
                        (categoryFilter === 'ai_generated' && (image.source === 'ai_generated' || image.source_type === 'ai_generated' || image.generation_prompt)) ||
                        (categoryFilter === 'network_search' && (image.source === 'web_search' || image.source_type === 'web_search')) ||
                        (categoryFilter === 'local_upload' && (image.source === 'local_storage' || image.source_type === 'local_storage'));
                }

                return matchesSearch && matchesCategory;
            });

            renderImageGallery();
        }

        // 双击图片直接选择
        function handleImageDoubleClick(imageData) {
            // 双击图片直接选择并关闭对话框
            window.closeGalleryDialog(imageData);
        }

        // 获取正确的图片URL
        function getImageUrl(image) {
            if (!image) return '';

            // 如果已经是完整URL，直接返回
            if (image.url && (image.url.startsWith('http') || image.url.startsWith('/api/'))) {
                return image.url;
            }

            // 如果有image.id，构建API URL
            if (image.id) {
                return `/api/image/view/${image.id}`;
            }

            // 如果有相对路径，转换为API URL
            if (image.url) {
                return image.url.startsWith('/') ? image.url : `/api/image/view/${image.url}`;
            }

            // 默认占位图
            return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwIiBoZWlnaHQ9IjEyMCIgdmlld0JveD0iMCAwIDEyMCAxMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiBmaWxsPSIjRjVGNUY1Ii8+CjxwYXRoIGQ9Ik02MCA0NUw3NSA2NUg0NUw2MCA0NVoiIGZpbGw9IiNEREREREQiLz4KPGNpcmNsZSBjeD0iNTAiIGN5PSI0MCIgcj0iNSIgZmlsbD0iI0RERERERCIvPgo8L3N2Zz4K';
        }

        // 处理图片加载错误
        function handleImageError(imgElement, imageId) {
            // 隐藏加载动画
            const spinner = imgElement.parentElement.querySelector('.loading-spinner');
            if (spinner) spinner.style.display = 'none';

            // 尝试备用URL
            const originalSrc = imgElement.src;

            // 如果不是API URL，尝试API URL
            if (!originalSrc.includes('/api/image/view/')) {
                const apiUrl = `/api/image/view/${imageId}`;
                if (originalSrc !== apiUrl) {
                    imgElement.src = apiUrl;
                    return;
                }
            }

            // 如果API URL也失败，尝试添加时间戳避免缓存
            if (!originalSrc.includes('?t=')) {
                const timestampUrl = `${originalSrc}?t=${Date.now()}`;
                imgElement.src = timestampUrl;
                return;
            }

            // 最终使用占位图
            imgElement.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwIiBoZWlnaHQ9IjEyMCIgdmlld0JveD0iMCAwIDEyMCAxMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiBmaWxsPSIjRjVGNUY1Ii8+CjxwYXRoIGQ9Ik02MCA0NUw3NSA2NUg0NUw2MCA0NVoiIGZpbGw9IiNEREREREQiLz4KPGNpcmNsZSBjeD0iNTAiIGN5PSI0MCIgcj0iNSIgZmlsbD0iI0RERERERCIvPjx0ZXh0IHg9IjYwIiB5PSI4MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSI4IiBmaWxsPSIjOTk5Ij7liqDovb3lpLHotKU8L3RleHQ+PC9zdmc+';
            imgElement.style.opacity = '0.5';
            imgElement.title = '图片加载失败';
        }

        // 显示空图片库
        function showEmptyGallery() {
            const container = document.getElementById('imageGalleryContainer');
            if (container) {
                container.innerHTML = `
                    <div class="text-center text-muted py-5">
                        <i class="fas fa-images fa-4x mb-3" style="opacity: 0.3;"></i>
                        <h5>图片库中暂无图片</h5>
                        <p>您可以先上传一些图片到图片库</p>
                        <a href="/image-gallery" class="btn btn-outline-primary" target="_blank">
                            <i class="fas fa-upload"></i> 前往图片库上传
                        </a>
                    </div>
                `;
            }

            // 清空分页
            const paginationList = document.getElementById('paginationList');
            if (paginationList) paginationList.innerHTML = '';

            const statsElement = document.getElementById('imageStats');
            if (statsElement) statsElement.textContent = '共 0 张图片';
        }

        // 显示图片库错误
        function showGalleryError(errorMessage) {
            const container = document.getElementById('imageGalleryContainer');
            if (container) {
                container.innerHTML = `
                    <div class="text-center text-danger py-5">
                        <i class="fas fa-exclamation-triangle fa-3x mb-3"></i>
                        <h5>加载图片库失败</h5>
                        <p>${escapeHtml(errorMessage)}</p>
                        <button class="btn btn-outline-danger" onclick="initImageGallery()">
                            <i class="fas fa-redo"></i> 重新加载
                        </button>
                    </div>
                `;
            }
        }

        // 获取分类名称
        function getCategoryName(category) {
            const categoryNames = {
                'ai_generated': 'AI生成',
                'web_search': '网络搜索',
                'network_search': '网络搜索',
                'network': '网络搜索',
                'local_storage': '本地上传',
                'local_upload': '本地上传',
                'local': '本地上传'
            };
            return categoryNames[category] || category;
        }

        // 获取图片分类标签
        function getImageCategoryBadge(image) {
            let category = '';
            let badgeClass = 'bg-secondary';

            // 尝试从多个字段确定分类
            if (image.category) {
                category = image.category;
            } else if (image.source) {
                category = image.source;
            } else if (image.source_type) {
                category = image.source_type;
            } else if (image.generation_prompt) {
                category = 'ai_generated';
            } else if (image.url && image.url.includes('/network/')) {
                category = 'web_search';
            } else if (image.url && image.url.includes('/local/')) {
                category = 'local_storage';
            }

            // 设置对应的样式 - 修复分类映射
            switch (category) {
                case 'ai_generated':
                    badgeClass = 'bg-success';
                    break;
                case 'web_search':
                case 'network_search':
                case 'network':
                    badgeClass = 'bg-info';
                    break;
                case 'local_storage':
                case 'local_upload':
                case 'local':
                    badgeClass = 'bg-primary';
                    break;
            }

            if (category) {
                return `<small class="d-block"><span class="badge ${badgeClass}">${getCategoryName(category)}</span></small>`;
            }

            return '';
        }

        // HTML转义函数
        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        // 辅助函数：转义正则表达式特殊字符
        function escapeRegExp(string) {
            return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        }

        // 通知AI助手图像已选择
        function notifyAIAssistantImageSelected(imageInfo) {
            // 更新AI助手界面显示选中的图像信息
            updateAIAssistantSelectedImage(imageInfo);

            // 如果AI助手侧栏未打开，则打开它
            const sidebar = document.getElementById('aiEditSidebar');
            if (!sidebar.classList.contains('open')) {
                openAIEditSidebar();
            }
        }

        // 响应式缩放辅助函数
        function getResponsiveScale() {
            const width = window.innerWidth;
            if (width <= 576) return 'scale(0.06)';
            if (width <= 768) return 'scale(0.08)';
            if (width <= 992) return 'scale(0.1)';
            if (width <= 1200) return 'scale(0.12)';
            return 'scale(0.15)';
        }

        function getResponsiveWidth() {
            const width = window.innerWidth;
            if (width <= 576) return '1667%';
            if (width <= 768) return '1250%';
            if (width <= 992) return '1000%';
            if (width <= 1200) return '833%';
            return '667%';
        }

        function getResponsiveHeight() {
            const width = window.innerWidth;
            if (width <= 576) return '1667%';
            if (width <= 768) return '1250%';
            if (width <= 992) return '1000%';
            if (width <= 1200) return '833%';
            return '667%';
        }

        // 窗口大小改变时重新应用缩放
        window.addEventListener('resize', function() {
            const iframes = document.querySelectorAll('.slide-preview iframe');
            iframes.forEach(iframe => {
                iframe.style.transform = getResponsiveScale();
                iframe.style.width = getResponsiveWidth();
                iframe.style.height = getResponsiveHeight();
            });
        });

        // 点击其他地方隐藏右键菜单
        document.addEventListener('click', function(event) {
            if (!event.target.closest('.context-menu')) {
                hideContextMenu();
            }
        });

        // 阻止页面默认右键菜单
        document.addEventListener('contextmenu', function(event) {
            if (!event.target.closest('.slide-thumbnail')) {
                // 只在非幻灯片区域阻止默认右键菜单
                // event.preventDefault();
            }
        });



        // 移除重复的checkForUpdates函数定义 - 已在上面定义

        // 更新主预览区域
        function updateMainPreviewArea() {
            const previewPane = document.getElementById('previewPane');
            if (!previewPane) return;

            if (hasSlidesData && slidesData.length > 0) {
                // 如果有幻灯片数据，更新预览区域
                previewPane.innerHTML = `
                    <div class="slide-frame-container">
                        <div class="slide-frame-wrapper" id="slideFrameWrapper">
                            <button class="preview-nav-btn left" id="previewPrevBtn" onclick="navigatePreviewSlide(-1)" title="&#19978;&#19968;&#39029; (&#8592;)">
                                <i class="fas fa-chevron-left"></i>
                            </button>

                            <iframe class="slide-frame" id="slideFrame"
                                    title="Slide Preview"></iframe>
                            <div class="quick-edit-overlay" id="quickEditOverlay"></div>

                            <button class="preview-nav-btn right" id="previewNextBtn" onclick="navigatePreviewSlide(1)" title="&#19979;&#19968;&#39029; (&#8594;)">
                                <i class="fas fa-chevron-right"></i>
                            </button>
                        </div>
                    </div>
                `;

                updatePreviewNavButtons();

                // 设置第一张幻灯片的内容
                const slideFrame = document.getElementById('slideFrame');
                if (slideFrame && slidesData[0]) {
                    setSafeIframeContent(slideFrame, slidesData[0].html_content);

                    // 初始化iframe和重新初始化JavaScript
                    setTimeout(() => {
                        initializeMainFrame();
                        applyMainFrameScale();
                        forceReinitializeIframeJS(slideFrame);
                        updatePreviewNavButtons();
                    }, 100);
                }
            } else {
                // 如果没有幻灯片数据，显示等待界面
                previewPane.innerHTML = `
                    <div class="d-flex align-items-center justify-content-center h-100" style="background: #f8f9fa; border-radius: 8px;">
                        <div class="text-center" style="color: #6c757d;">
                            <div style="font-size: 64px; margin-bottom: 20px;">
                                <i class="fas fa-presentation-screen"></i>
                            </div>
                            <h4 style="margin-bottom: 15px;">等待PPT生成</h4>
                            <p style="margin-bottom: 20px;">PPT生成完成后，预览将在这里显示</p>
                            <button class="btn btn-outline-primary" onclick="checkForUpdates()">
                                <i class="fas fa-refresh"></i> 刷新页面
                            </button>
                        </div>
                    </div>
                `;
            }
        }

        // 页面加载完成后应用响应式缩放和绑定事件
        document.addEventListener('DOMContentLoaded', function() {
            // 为所有现有的iframe应用响应式缩放
            const iframes = document.querySelectorAll('.slide-preview iframe');
            iframes.forEach(iframe => {
                iframe.style.transform = getResponsiveScale();
                iframe.style.width = getResponsiveWidth();
                iframe.style.height = getResponsiveHeight();
            });

            // 初始化右侧主iframe
            setTimeout(() => {
                initializeMainFrame();
                applyMainFrameScale();
            }, 100);

            // 初始化缩略图事件监听器
            initializeThumbnailEvents();

            // 初始化AI侧栏宽度调整功能
            initializeSidebarResize();

            // 初始化CodeMirror编辑器
            initializeCodeMirror();

            // 初始化代码编辑器自动保存（fallback）
            initializeCodeEditorAutoSave();

            // 绑定按钮事件监听器
            const slideshowBtn = document.getElementById('slideshowBtn');
            const saveSlideBtn = document.getElementById('saveSlideBtn');
            const aiEditBtn = document.getElementById('aiEditBtn');

            if (slideshowBtn) {
                slideshowBtn.addEventListener('click', startSlideshow);
            }
            if (saveSlideBtn) {
                saveSlideBtn.addEventListener('click', saveSlide);
            }
            if (aiEditBtn) {
                aiEditBtn.addEventListener('click', openAIEditSidebar);
            }

            // 绑定AI输入框回车键事件
            const aiInputBox = document.getElementById('aiInputBox');
            if (aiInputBox) {
                aiInputBox.addEventListener('keydown', function(event) {
                    if (event.key === 'Enter' && !event.shiftKey) {
                        event.preventDefault();
                        sendAIMessage();
                    }
                });
            }

            // 确保第一张幻灯片被选中
            if (hasSlidesData && slidesData.length > 0) {
                selectSlide(0);
            }

            // 更新功能按钮状态
            updateFunctionButtonsState();

            // 移除自动检查逻辑，只在页面加载时检查一次
            // setTimeout(checkForUpdates, 1000); - 已移除
            // setTimeout(startAutoCheck, 2000); - 已移除
        });

        // 防抖函数，优化窗口大小变化时的性能
        let resizeTimeout;
        function debounceResize() {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(() => {
                // 重新计算左侧缩略图缩放
                const iframes = document.querySelectorAll('.slide-preview iframe');
                iframes.forEach(iframe => {
                    iframe.style.transform = getResponsiveScale();
                    iframe.style.width = getResponsiveWidth();
                    iframe.style.height = getResponsiveHeight();
                });

                // 清除缓存的缩放比例，强制重新计算
                cachedScale = null;
                lastContainerSize = null;

                // 重新计算主iframe缩放
                applyMainFrameScale();

                // 重新计算CodeMirror编辑器尺寸
                resizeCodeMirror();
            }, 150); // 防抖延迟150ms
        }

        // 窗口大小改变时使用防抖处理
        window.addEventListener('resize', debounceResize);

        // 触摸手势支持，提升移动设备体验
        let touchStartX = 0;
        let touchStartY = 0;
        let touchEndX = 0;
        let touchEndY = 0;
        let touchStartTime = 0;

        function initializeSlideshowTouchGestures() {
            const overlay = document.getElementById('slideshowOverlay');

            overlay.addEventListener('touchstart', handleTouchStart, { passive: true });
            overlay.addEventListener('touchend', handleTouchEnd, { passive: true });
            overlay.addEventListener('touchmove', handleTouchMove, { passive: false });
        }

        function removeSlideshowTouchGestures() {
            const overlay = document.getElementById('slideshowOverlay');

            overlay.removeEventListener('touchstart', handleTouchStart);
            overlay.removeEventListener('touchend', handleTouchEnd);
            overlay.removeEventListener('touchmove', handleTouchMove);
        }

        function handleTouchStart(e) {
            if (!isSlideshow || e.touches.length !== 1) return;

            const touch = e.touches[0];
            touchStartX = touch.clientX;
            touchStartY = touch.clientY;
            touchStartTime = Date.now();
        }

        function handleTouchMove(e) {
            if (!isSlideshow || e.touches.length !== 1) return;

            // 防止页面滚动
            e.preventDefault();
        }

        function handleTouchEnd(e) {
            if (!isSlideshow || e.changedTouches.length !== 1) return;

            const touch = e.changedTouches[0];
            touchEndX = touch.clientX;
            touchEndY = touch.clientY;

            const deltaX = touchEndX - touchStartX;
            const deltaY = touchEndY - touchStartY;
            const deltaTime = Date.now() - touchStartTime;

            // 检查是否为有效的滑动手势
            const minSwipeDistance = 50;
            const maxSwipeTime = 500;
            const maxVerticalDistance = 100;

            if (deltaTime > maxSwipeTime) return;
            if (Math.abs(deltaY) > maxVerticalDistance) return;

            if (Math.abs(deltaX) > minSwipeDistance) {
                if (deltaX > 0) {
                    // 向右滑动 - 上一张
                    previousSlideshow();
                } else {
                    // 向左滑动 - 下一张
                    nextSlideshow();
                }
            } else if (Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
                // 点击手势 - 下一张
                nextSlideshow();
            }
        }
    </script>

    <!-- CodeMirror JavaScript -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/xml/xml.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/css/css.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/htmlmixed/htmlmixed.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/edit/closetag.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/edit/closebrackets.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/edit/matchtags.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/foldcode.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/foldgutter.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/xml-fold.min.js"></script>
    <!-- CodeMirror Search功能 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/dialog/dialog.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/search/searchcursor.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/search/search.min.js"></script>

    <script>
        // 图片上传相关函数
        function triggerImageUpload() {
            if (isUploading) {
                showNotification('正在上传中，请稍候...', 'warning');
                return;
            }
            showImageSelectMenu();
        }

        // 初始化图片上传功能
        function initImageUpload() {
            const fileInput = document.getElementById('aiImageFileInput');
            const uploadBtn = document.getElementById('aiImageUploadBtn');
            const inputContainer = document.querySelector('.ai-input-container');



            if (!fileInput || !uploadBtn || !inputContainer) {
                return;
            }

            // 文件选择处理
            fileInput.addEventListener('change', handleFileSelect);

            // 拖拽事件处理 - 使用重命名的函数避免冲突
            inputContainer.addEventListener('dragenter', handleImageDragEnter);
            inputContainer.addEventListener('dragover', handleImageDragOver);
            inputContainer.addEventListener('dragleave', handleImageDragLeave);
            inputContainer.addEventListener('drop', handleImageFileDrop);

            // 阻止默认拖拽行为
            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                inputContainer.addEventListener(eventName, preventImageDefaults, false);
            });


        }

        // 检查是否为文件拖拽
        function isFileDrag(e) {
            return e.dataTransfer &&
                   e.dataTransfer.types &&
                   (e.dataTransfer.types.includes('Files') ||
                    e.dataTransfer.types.includes('application/x-moz-file'));
        }

        function preventImageDefaults(e) {
            // 只处理文件拖拽，不影响其他拖拽操作
            if (isFileDrag(e)) {
                e.preventDefault();
                e.stopPropagation();
            }
        }

        function handleImageDragEnter(e) {
            if (isFileDrag(e)) {
                e.preventDefault();
                const inputContainer = document.querySelector('.ai-input-container');
                inputContainer.classList.add('drag-over');
            }
        }

        function handleImageDragOver(e) {
            if (isFileDrag(e)) {
                e.preventDefault();
                e.dataTransfer.dropEffect = 'copy';
            }
        }

        function handleImageDragLeave(e) {
            if (isFileDrag(e)) {
                // 检查是否真的离开了容器区域
                const inputContainer = document.querySelector('.ai-input-container');
                const rect = inputContainer.getBoundingClientRect();
                const x = e.clientX;
                const y = e.clientY;

                if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
                    inputContainer.classList.remove('drag-over');
                }
            }
        }

        function handleImageFileDrop(e) {
            // 总是阻止默认行为
            e.preventDefault();
            e.stopPropagation();

            const inputContainer = document.querySelector('.ai-input-container');
            inputContainer.classList.remove('drag-over');

            if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
                const files = e.dataTransfer.files;

                // 过滤出图片文件
                const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'));

                if (imageFiles.length > 0) {
                    handleFiles(imageFiles);
                    showNotification(`检测到 ${imageFiles.length} 张图片，正在上传...`, 'info');
                } else {
                    showNotification('请拖拽图片文件到此区域', 'warning');
                }
            } else {
                showNotification('拖拽失败，请重试', 'error');
            }
        }

        function handleFileSelect(e) {
            const files = e.target.files;
            handleFiles(files);
        }

        function handleFiles(files) {
            if (isUploading) {
                showNotification('正在上传中，请稍候...', 'warning');
                return;
            }

            // 支持的图片格式
            const supportedTypes = [
                'image/jpeg', 'image/jpg', 'image/png', 'image/gif',
                'image/webp', 'image/bmp', 'image/svg+xml'
            ];

            const validFiles = [];
            const errors = [];

            Array.from(files).forEach(file => {
                // 验证文件类型
                if (!supportedTypes.includes(file.type.toLowerCase())) {
                    errors.push(`${file.name}: 不支持的图片格式 (${file.type})`);
                    return;
                }

                // 验证文件大小 (10MB)
                if (file.size > 10 * 1024 * 1024) {
                    errors.push(`${file.name}: 文件大小超过10MB限制 (${formatFileSize(file.size)})`);
                    return;
                }

                // 验证文件名
                if (file.name.length > 100) {
                    errors.push(`${file.name}: 文件名过长，请使用较短的文件名`);
                    return;
                }

                validFiles.push(file);
            });

            // 显示错误信息
            if (errors.length > 0) {
                const errorMessage = '以下文件无法上传：\n' + errors.join('\n');
                showNotification(errorMessage, 'error');
            }

            if (validFiles.length === 0) {
                if (errors.length === 0) {
                    showNotification('没有选择有效的图片文件', 'warning');
                }
                return;
            }

            // 检查是否超过最大上传数量
            const maxImages = 10;
            if (uploadedImages.length + validFiles.length > maxImages) {
                showNotification(`最多只能上传${maxImages}张图片，当前已有${uploadedImages.length}张`, 'warning');
                return;
            }

            // 上传文件
            uploadFiles(validFiles);
        }

        async function uploadFiles(files) {
            if (files.length === 0) return;

            isUploading = true;
            showUploadProgress(true);

            try {
                for (let i = 0; i < files.length; i++) {
                    const file = files[i];
                    updateUploadProgress((i / files.length) * 100, `上传中 ${i + 1}/${files.length}: ${file.name}`);

                    const result = await uploadSingleFile(file);
                    if (result.success) {
                        addUploadedImage(result.data);
                    } else {
                        showNotification(`上传失败: ${file.name} - ${result.message}`, 'error');
                    }
                }

                updateUploadProgress(100, '上传完成');
                setTimeout(() => showUploadProgress(false), 1000);

                showNotification(`成功上传 ${files.length} 张图片`, 'success');

            } catch (error) {
                showNotification('上传失败，请重试', 'error');
            } finally {
                isUploading = false;
                setTimeout(() => showUploadProgress(false), 1000);
            }
        }

        async function uploadSingleFile(file) {
            const formData = new FormData();
            formData.append('file', file);
            formData.append('title', file.name.split('.')[0]);
            formData.append('description', `AI编辑助手上传的图片: ${file.name}`);
            formData.append('category', 'ai_assistant');
            formData.append('tags', 'ai_assistant,ppt_edit');

            try {
                const response = await fetch('/api/image/upload', {
                    method: 'POST',
                    body: formData
                });

                const result = await response.json();

                if (result.success) {
                    // 获取图片的绝对URL
                    const imageUrl = await getImageAbsoluteUrl(result.image_id);
                    return {
                        success: true,
                        data: {
                            id: result.image_id,
                            name: file.name,
                            size: file.size,
                            url: imageUrl,
                            file: file
                        }
                    };
                } else {
                    return {
                        success: false,
                        message: result.message || '上传失败'
                    };
                }
            } catch (error) {
                return {
                    success: false,
                    message: '网络错误'
                };
            }
        }

        async function getImageAbsoluteUrl(imageId) {
            try {
                const response = await fetch(`/api/image/${imageId}/info`);
                const result = await response.json();

                if (result.success && result.image_info) {
                    return result.image_info.absolute_url;
                } else {
                    // 如果获取失败，使用默认的URL格式
                    return `${window.location.origin}/api/image/${imageId}`;
                }
            } catch (error) {
                return `${window.location.origin}/api/image/${imageId}`;
            }
        }

        function showUploadProgress(show) {
            const progressDiv = document.getElementById('aiUploadProgress');
            progressDiv.style.display = show ? 'block' : 'none';

            if (!show) {
                updateUploadProgress(0, '');
            }
        }

        function updateUploadProgress(percent, text) {
            const progressFill = document.getElementById('aiProgressFill');
            const progressText = document.getElementById('aiProgressText');

            progressFill.style.width = `${percent}%`;
            progressText.textContent = text;
        }

        function addUploadedImage(imageData) {
            uploadedImages.push(imageData);
            renderUploadedImages();
        }

        function renderUploadedImages() {
            const container = document.getElementById('aiUploadedImages');
            const uploadBtn = document.getElementById('aiImageUploadBtn');

            container.innerHTML = '';

            // 更新上传按钮状态
            if (uploadedImages.length === 0) {
                uploadBtn.classList.remove('has-images');
                uploadBtn.removeAttribute('data-count');
                return;
            } else {
                uploadBtn.classList.add('has-images');
                uploadBtn.setAttribute('data-count', uploadedImages.length);
            }

            uploadedImages.forEach((image, index) => {
                const imageDiv = document.createElement('div');
                imageDiv.className = 'ai-uploaded-image';
                imageDiv.title = `${image.name} (${formatFileSize(image.size)}) - 点击查看大图`;

                // 创建图片预览
                const img = document.createElement('img');
                if (image.file) {
                    // 本地上传的图片
                    img.src = URL.createObjectURL(image.file);
                } else {
                    // 从图床选择的图片
                    img.src = image.url;
                }
                img.alt = image.name;

                // 创建删除按钮
                const removeBtn = document.createElement('button');
                removeBtn.className = 'ai-image-remove';
                removeBtn.innerHTML = '<i class="fas fa-times"></i>';
                removeBtn.onclick = (e) => {
                    e.stopPropagation();
                    removeUploadedImage(index);
                };

                // 创建信息显示
                const infoDiv = document.createElement('div');
                infoDiv.className = 'ai-image-info';
                infoDiv.textContent = formatFileSize(image.size);

                imageDiv.appendChild(img);
                imageDiv.appendChild(removeBtn);
                imageDiv.appendChild(infoDiv);

                // 点击图片显示全屏预览
                imageDiv.addEventListener('click', () => {
                    showImagePreview(image);
                });

                container.appendChild(imageDiv);
            });
        }

        function removeUploadedImage(index) {
            if (index >= 0 && index < uploadedImages.length) {
                const image = uploadedImages[index];
                // 释放blob URL（仅对本地上传的图片）
                if (image.file) {
                    URL.revokeObjectURL(URL.createObjectURL(image.file));
                }
                uploadedImages.splice(index, 1);
                renderUploadedImages();
                showNotification('图片已移除', 'info');
            }
        }



        function formatFileSize(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
        }

        function clearUploadedImages() {
            // 释放所有blob URLs（仅对本地上传的图片）
            uploadedImages.forEach(image => {
                if (image.file) {
                    URL.revokeObjectURL(URL.createObjectURL(image.file));
                }
            });
            uploadedImages = [];
            renderUploadedImages();
        }



        // 自动将所有已上传的图片信息嵌入到消息中
        function autoEmbedUploadedImages(message) {
            if (uploadedImages.length === 0) {
                return message;
            }

            // 构建图片信息文本
            let imageInfoText = '\n\n📷 图片信息：\n';
            uploadedImages.forEach((image, index) => {
                imageInfoText += `${index + 1}. 图片名称：${image.name}\n`;
                imageInfoText += `   图片地址：${image.url}\n`;
                imageInfoText += `   文件大小：${formatFileSize(image.size)}\n`;
                if (index < uploadedImages.length - 1) {
                    imageInfoText += '\n';
                }
            });

            // imageInfoText += '\n请分析这些图片的内容，并根据我的要求进行处理。';

            return message + imageInfoText;
        }

        // 获取所有已上传的图片信息
        function getAllUploadedImages() {
            return uploadedImages.map(image => ({
                name: image.name,
                url: image.url,
                size: image.size > 0 ? formatFileSize(image.size) : '未知大小',
                id: image.id
            }));
        }

        // 视觉模式切换功能
        function toggleVisionMode() {
            visionModeEnabled = !visionModeEnabled;
            const visionBtn = document.getElementById('aiVisionToggleBtn');

            if (visionModeEnabled) {
                visionBtn.classList.add('active');
                visionBtn.title = '关闭视觉模式 - AI将不再看到当前幻灯片';
                showNotification('视觉模式已启用 - AI现在可以看到当前幻灯片', 'success');
            } else {
                visionBtn.classList.remove('active');
                visionBtn.title = '启用视觉模式 - AI将能看到当前幻灯片';
                showNotification('视觉模式已关闭', 'info');
            }
        }

        // 捕获当前幻灯片截图
        async function captureSlideScreenshot() {
            if (!visionModeEnabled) {
                return null;
            }

            try {
                const slideFrame = document.getElementById('slideFrame');
                if (!slideFrame) {
                    return null;
                }

                // 等待iframe内容加载完成
                await new Promise(resolve => {
                    if (slideFrame.contentDocument && slideFrame.contentDocument.readyState === 'complete') {
                        resolve();
                    } else {
                        slideFrame.onload = resolve;
                        setTimeout(resolve, 1000); // 超时保护
                    }
                });

                // 获取iframe内容
                const iframeDoc = slideFrame.contentDocument || slideFrame.contentWindow.document;
                if (!iframeDoc) {
                    return null;
                }

                // 使用html2canvas捕获iframe内容
                if (typeof html2canvas === 'undefined') {
                    await loadHtml2Canvas();
                }

                const canvas = await html2canvas(iframeDoc.body, {
                    width: 1280,
                    height: 720,
                    scale: 1,
                    useCORS: true,
                    allowTaint: true,
                    backgroundColor: '#ffffff'
                });

                // 转换为base64
                const dataURL = canvas.toDataURL('image/jpeg', 0.8);
                return dataURL;

            } catch (error) {
                return null;
            }
        }

        // 动态加载html2canvas库
        async function loadHtml2Canvas() {
            return new Promise((resolve, reject) => {
                if (typeof html2canvas !== 'undefined') {
                    resolve();
                    return;
                }

                const script = document.createElement('script');
                script.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
                script.onload = resolve;
                script.onerror = reject;
                document.head.appendChild(script);
            });
        }



        // 全屏图片预览相关函数
        function showImagePreview(image) {
            currentPreviewImage = image;

            const overlay = document.getElementById('imagePreviewOverlay');
            const title = document.getElementById('imagePreviewTitle');
            const details = document.getElementById('imagePreviewDetails');
            const img = document.getElementById('imagePreviewImg');
            const loading = document.getElementById('imagePreviewLoading');

            // 显示遮罩层
            overlay.style.display = 'flex';

            // 设置图片信息
            title.textContent = image.name;
            details.textContent = `大小: ${formatFileSize(image.size)} | 发送消息时自动包含此图片`;

            // 显示加载状态
            loading.style.display = 'block';
            img.style.display = 'none';

            // 加载图片
            img.onload = function() {
                loading.style.display = 'none';
                img.style.display = 'block';
            };

            img.onerror = function() {
                loading.style.display = 'none';
                img.style.display = 'block';
                img.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZGRkIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuWbvueJh+WKoOi9veWksei0pTwvdGV4dD48L3N2Zz4=';
            };

            // 设置图片源
            img.src = image.url;

            // 阻止页面滚动
            document.body.style.overflow = 'hidden';
        }

        function closeImagePreview() {
            const overlay = document.getElementById('imagePreviewOverlay');
            overlay.style.display = 'none';
            currentPreviewImage = null;

            // 恢复页面滚动
            document.body.style.overflow = '';
        }

        function downloadCurrentImage() {
            if (!currentPreviewImage) return;

            const link = document.createElement('a');
            link.href = currentPreviewImage.url;
            link.download = currentPreviewImage.name;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);

            showNotification(`开始下载: ${currentPreviewImage.name}`, 'success');
        }



        function removeCurrentImage() {
            if (!currentPreviewImage) return;

            const index = uploadedImages.findIndex(img => img.id === currentPreviewImage.id);
            if (index !== -1) {
                if (confirm(`确定要删除图片 "${currentPreviewImage.name}" 吗？`)) {
                    removeUploadedImage(index);
                    closeImagePreview();
                }
            }
        }

        // 键盘事件处理
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape' && currentPreviewImage) {
                closeImagePreview();
            }
        });

        // 点击遮罩层关闭预览
        document.addEventListener('click', function(e) {
            if (e.target.id === 'imagePreviewOverlay') {
                closeImagePreview();
            }
        });

        // 图片选择菜单相关函数
        function showImageSelectMenu() {
            const menu = document.getElementById('imageSelectMenu');
            menu.style.display = 'flex';
            document.body.style.overflow = 'hidden';
        }

        function closeImageSelectMenu() {
            const menu = document.getElementById('imageSelectMenu');
            menu.style.display = 'none';
            document.body.style.overflow = '';
        }

        function selectFromLocal() {
            closeImageSelectMenu();
            const fileInput = document.getElementById('aiImageFileInput');
            fileInput.click();
        }

        function selectFromLibrary() {
            closeImageSelectMenu();
            showImageLibrary();
        }

        // 图床选择器相关函数
        function showImageLibrary() {
            const overlay = document.getElementById('imageLibraryOverlay');
            const loading = document.getElementById('imageLibraryLoading');
            const grid = document.getElementById('imageLibraryGrid');
            const empty = document.getElementById('imageLibraryEmpty');

            overlay.style.display = 'flex';
            loading.style.display = 'block';
            grid.style.display = 'none';
            empty.style.display = 'none';

            selectedLibraryImages = [];
            updateSelectionCount();

            document.body.style.overflow = 'hidden';

            // 初始化搜索功能
            initImageLibrarySearch();

            // 加载图床图片
            loadLibraryImages();
        }

        function closeImageLibrary() {
            const overlay = document.getElementById('imageLibraryOverlay');
            overlay.style.display = 'none';
            selectedLibraryImages = [];
            document.body.style.overflow = '';

            // 重置搜索状态
            const searchInput = document.getElementById('imageLibrarySearchInput');
            const clearBtn = document.getElementById('imageLibrarySearchClear');
            if (searchInput) {
                searchInput.value = '';
            }
            if (clearBtn) {
                clearBtn.style.display = 'none';
            }
            currentSearchTerm = '';
            filteredLibraryImages = [];

            // 重置分页状态
            currentPage = 1;
            totalPages = 1;
            totalCount = 0;
            hidePaginationUI();
        }

        async function loadLibraryImages(searchTerm = '', page = 1) {
            try {
                // 使用与image_gallery.html相同的API端点
                const params = new URLSearchParams({
                    page: page,
                    per_page: perPage,
                    category: '', // 不限制分类
                    search: searchTerm,
                    sort: 'created_desc'
                });

                const response = await fetch(`/api/image/gallery/list?${params}`);
                const result = await response.json();

                const loading = document.getElementById('imageLibraryLoading');
                const grid = document.getElementById('imageLibraryGrid');
                const empty = document.getElementById('imageLibraryEmpty');

                loading.style.display = 'none';

                if (result.success && result.images && result.images.length > 0) {
                    libraryImages = result.images;
                    filteredLibraryImages = libraryImages;

                    // 更新分页信息
                    if (result.pagination) {
                        currentPage = result.pagination.current_page;
                        totalPages = result.pagination.total_pages;
                        totalCount = result.pagination.total_count;
                        updatePaginationUI();
                    }

                    renderLibraryImages();
                    grid.style.display = 'grid';
                } else {
                    empty.style.display = 'block';
                    hidePaginationUI();
                }
            } catch (error) {
                const loading = document.getElementById('imageLibraryLoading');
                const empty = document.getElementById('imageLibraryEmpty');

                loading.style.display = 'none';
                empty.style.display = 'block';
                empty.innerHTML = `
                    <i class="fas fa-exclamation-triangle"></i>
                `;
                showNotification('加载图床图片失败', 'error');
            }
        }

        function renderLibraryImages() {
            const grid = document.getElementById('imageLibraryGrid');
            grid.innerHTML = '';

            filteredLibraryImages.forEach(image => {
                const item = document.createElement('div');
                item.className = 'image-library-item';
                item.dataset.imageId = image.image_id;

                // 构建图片URL
                const imageUrl = `/api/image/view/${image.image_id}`;

                // 格式化文件大小 - 检查多个可能的位置
                let fileSize = '未知大小';
                if (image.file_size && image.file_size > 0) {
                    // 直接从根级别获取file_size
                    fileSize = formatFileSize(image.file_size);
                } else if (image.metadata) {
                    // 从metadata中获取
                    if (image.metadata.file_size && image.metadata.file_size > 0) {
                        fileSize = formatFileSize(image.metadata.file_size);
                    } else if (image.metadata.size && image.metadata.size > 0) {
                        fileSize = formatFileSize(image.metadata.size);
                    }
                }

                item.innerHTML = `
                    <img src="${imageUrl}" alt="${image.title || '未命名图片'}" loading="lazy" onerror="this.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjBmMGYwIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPuWbvueJh+WKoOi9veWksei0pTwvdGV4dD48L3N2Zz4='">
                    <div class="image-info">
                        <div>${image.title || '未命名图片'}</div>
                        <div>${fileSize}</div>
                    </div>
                    <div class="selection-indicator">
                        <i class="fas fa-check"></i>
                    </div>
                `;

                item.addEventListener('click', () => toggleImageSelection(image, item));
                grid.appendChild(item);
            });
        }

        function toggleImageSelection(image, element) {
            const imageId = image.image_id;
            const index = selectedLibraryImages.findIndex(img => img.image_id === imageId);

            if (index === -1) {
                // 添加到选择列表
                selectedLibraryImages.push(image);
                element.classList.add('selected');
            } else {
                // 从选择列表移除
                selectedLibraryImages.splice(index, 1);
                element.classList.remove('selected');
            }

            updateSelectionCount();
        }

        function updateSelectionCount() {
            const countSpan = document.getElementById('selectedCount');
            const confirmBtn = document.getElementById('confirmSelectionBtn');

            countSpan.textContent = selectedLibraryImages.length;
            confirmBtn.disabled = selectedLibraryImages.length === 0;
        }

        async function confirmImageSelection() {
            if (selectedLibraryImages.length === 0) return;

            let addedCount = 0;

            // 显示处理进度
            showNotification('正在处理选择的图片...', 'info');

            // 逐个处理选择的图片，获取完整信息
            for (const image of selectedLibraryImages) {
                try {
                    // 获取图片的完整信息和绝对URL
                    const imageInfo = await getImageCompleteInfo(image.image_id);

                    const imageData = {
                        id: image.image_id,
                        name: imageInfo.name || image.title || '未命名图片',
                        size: imageInfo.size || 0,
                        url: imageInfo.absoluteUrl,
                        file: null // 从图床选择的图片没有file对象
                    };

                    // 检查是否已经存在
                    const exists = uploadedImages.find(img => img.id === imageData.id);
                    if (!exists) {
                        uploadedImages.push(imageData);
                        addedCount++;
                    }
                } catch (error) {
                    // 如果获取详细信息失败，使用基本信息
                    const imageData = {
                        id: image.image_id,
                        name: image.title || '未命名图片',
                        size: image.file_size || (image.metadata && image.metadata.file_size) || 0,
                        url: `${window.location.origin}/api/image/view/${image.image_id}`,
                        file: null
                    };

                    const exists = uploadedImages.find(img => img.id === imageData.id);
                    if (!exists) {
                        uploadedImages.push(imageData);
                        addedCount++;
                    }
                }
            }

            renderUploadedImages();
            closeImageLibrary();

            if (addedCount > 0) {
                showNotification(`已添加 ${addedCount} 张图片`, 'success');
            } else {
                showNotification('所选图片已存在，未添加新图片', 'info');
            }
        }

        // 获取图片的完整信息，包括绝对URL
        async function getImageCompleteInfo(imageId) {
            try {
                const response = await fetch(`/api/image/${imageId}/info`);
                const result = await response.json();

                if (result.success && result.image_info) {
                    return {
                        name: result.image_info.title || result.image_info.filename,
                        size: result.image_info.file_size || 0,
                        absoluteUrl: result.image_info.absolute_url
                    };
                } else {
                    throw new Error('获取图片信息失败');
                }
            } catch (error) {
                // 如果专用接口失败，尝试使用详情接口
                try {
                    const detailResponse = await fetch(`/api/image/detail/${imageId}`);
                    const detailResult = await detailResponse.json();

                    if (detailResult.success && detailResult.image) {
                        const image = detailResult.image;
                        return {
                            name: image.title || image.filename,
                            size: (image.metadata && image.metadata.file_size) ? image.metadata.file_size : 0,
                            absoluteUrl: `${window.location.origin}/api/image/view/${imageId}`
                        };
                    }
                } catch (detailError) {
                    // 获取图片详情也失败
                }

                throw error;
            }
        }

        // 分页相关函数
        function updatePaginationUI() {
            const pagination = document.getElementById('imageLibraryPagination');
            const paginationInfo = document.getElementById('paginationInfo');
            const prevBtn = document.getElementById('prevPageBtn');
            const nextBtn = document.getElementById('nextPageBtn');

            if (!pagination) return;

            // 显示分页控件
            pagination.style.display = 'flex';

            // 更新分页信息
            paginationInfo.textContent = `第 ${currentPage} 页，共 ${totalPages} 页 (总计 ${totalCount} 张图片)`;

            // 更新按钮状态
            prevBtn.disabled = currentPage <= 1;
            nextBtn.disabled = currentPage >= totalPages;
        }

        function hidePaginationUI() {
            const pagination = document.getElementById('imageLibraryPagination');
            if (pagination) {
                pagination.style.display = 'none';
            }
        }

        function loadPreviousPage() {
            if (currentPage > 1) {
                loadLibraryImages(currentSearchTerm, currentPage - 1);
            }
        }

        function loadNextPage() {
            if (currentPage < totalPages) {
                loadLibraryImages(currentSearchTerm, currentPage + 1);
            }
        }

        // 图片库搜索相关函数
        function initImageLibrarySearch() {
            const searchInput = document.getElementById('imageLibrarySearchInput');
            const clearBtn = document.getElementById('imageLibrarySearchClear');

            if (!searchInput) return;

            // 搜索输入事件
            searchInput.addEventListener('input', function(e) {
                const searchTerm = e.target.value.trim();
                currentSearchTerm = searchTerm;

                if (searchTerm) {
                    clearBtn.style.display = 'block';
                    // 搜索时重置到第一页
                    loadLibraryImages(searchTerm, 1);
                } else {
                    clearBtn.style.display = 'none';
                    // 清空搜索时重置到第一页
                    loadLibraryImages('', 1);
                }
            });

            // 回车键搜索
            searchInput.addEventListener('keydown', function(e) {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    const searchTerm = e.target.value.trim();
                    currentSearchTerm = searchTerm;
                    loadLibraryImages(searchTerm, 1);
                }
            });
        }



        function clearImageLibrarySearch() {
            const searchInput = document.getElementById('imageLibrarySearchInput');
            const clearBtn = document.getElementById('imageLibrarySearchClear');

            searchInput.value = '';
            clearBtn.style.display = 'none';
            currentSearchTerm = '';

            // 重新加载第一页数据
            loadLibraryImages('', 1);
        }

        // AI增强所有要点功能
        async function enhanceAllBulletPoints() {
            const bulletPointsContainer = document.getElementById('bulletPointsContainer');
            if (!bulletPointsContainer) {
                showNotification('找不到要点容器', 'error');
                return;
            }

            const bulletPointItems = bulletPointsContainer.querySelectorAll('.bullet-point-item');
            if (bulletPointItems.length === 0) {
                showNotification('没有要点可以增强', 'warning');
                return;
            }

            // 收集所有要点的原始内容
            const originalPoints = [];
            bulletPointItems.forEach((item, index) => {
                const textElement = item.querySelector('.bullet-point-text');
                const text = textElement ? textElement.textContent.trim() : '';
                if (text) {
                    originalPoints.push({
                        index: index,
                        text: text,
                        element: textElement
                    });
                }
            });

            if (originalPoints.length === 0) {
                showNotification('没有有效的要点内容可以增强', 'warning');
                return;
            }

            // 显示加载状态
            const enhanceAllBtn = event.target;
            const originalBtnContent = enhanceAllBtn.innerHTML;
            enhanceAllBtn.disabled = true;
            enhanceAllBtn.style.opacity = '0.6';
            enhanceAllBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <span>正在增强...</span>';

            try {
                // 获取当前幻灯片和项目信息
                const currentSlide = slidesData[currentSlideIndex];
                let slideOutline = null;
                if (projectOutline && projectOutline.slides && projectOutline.slides[currentSlideIndex]) {
                    slideOutline = projectOutline.slides[currentSlideIndex];
                }

                // 构建AI增强请求
                const enhanceRequest = {
                    slideIndex: currentSlideIndex + 1,
                    slideTitle: currentSlide.title || `第${currentSlideIndex + 1}页`,
                    slideContent: currentSlide.html_content,
                    userRequest: `请增强和优化以下所有要点，使它们更加详细、准确和有吸引力。保持每个要点的核心意思不变，但可以添加更多细节、使用更好的表达方式或提供更具体的描述。要点之间应该保持逻辑连贯性和风格一致性。`,
                    slideOutline: slideOutline,
                    projectInfo: {
                        title: '{{ project.title }}',
                        topic: '{{ project.topic }}',
                        scenario: '{{ project.scenario }}'
                    },
                    contextInfo: {
                        allBulletPoints: originalPoints.map(p => p.text),
                        totalPoints: originalPoints.length
                    }
                };

                // 发送AI增强请求
                const response = await fetch('/api/ai/enhance-all-bullet-points', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(enhanceRequest)
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                }

                const result = await response.json();

                if (result.success && result.enhancedPoints && Array.isArray(result.enhancedPoints)) {
                    // 显示增强结果的确认对话框
                    showAllBulletPointsEnhancementDialog(originalPoints, result.enhancedPoints);
                } else {
                    throw new Error(result.error || result.message || '增强失败');
                }

            } catch (error) {
                showNotification('AI增强失败：' + error.message, 'error');
            } finally {
                // 恢复按钮状态
                enhanceAllBtn.disabled = false;
                enhanceAllBtn.style.opacity = '1';
                enhanceAllBtn.innerHTML = originalBtnContent;
            }
        }

        // 键盘事件处理
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape') {
                if (document.getElementById('bulletPointEnhancementDialog')) {
                    closeBulletPointEnhancementDialog();
                } else if (document.getElementById('imageSelectMenu').style.display === 'flex') {
                    closeImageSelectMenu();
                } else if (document.getElementById('imageLibraryOverlay').style.display === 'flex') {
                    closeImageLibrary();
                } else if (currentPreviewImage) {
                    closeImagePreview();
                }
            }
        });

        // 显示所有要点增强结果对话框
        function showAllBulletPointsEnhancementDialog(originalPoints, enhancedPoints) {
            // 创建对话框
            const dialog = document.createElement('div');
            dialog.id = 'bulletPointEnhancementDialog';
            dialog.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.6);
                z-index: 10002;
                display: flex;
                justify-content: center;
                align-items: center;
                backdrop-filter: blur(5px);
            `;

            const dialogContent = document.createElement('div');
            dialogContent.style.cssText = `
                background: white;
                border-radius: 12px;
                padding: 30px;
                width: 95vw;
                max-width: 1000px;
                max-height: 85vh;
                overflow-y: auto;
                position: relative;
                box-shadow: 0 20px 40px rgba(0,0,0,0.3);
                animation: slideInUp 0.3s ease;
            `;

            // 构建对比内容
            let comparisonContent = '';
            const maxLength = Math.max(originalPoints.length, enhancedPoints.length);

            for (let i = 0; i < maxLength; i++) {
                const original = originalPoints[i] ? originalPoints[i].text : '';
                const enhanced = enhancedPoints[i] ? cleanAIContent(enhancedPoints[i]) : '';

                if (original || enhanced) {
                    comparisonContent += `
                        <div style="margin-bottom: 25px; border: 1px solid #e9ecef; border-radius: 8px; overflow: hidden;">
                            <div style="background: #f8f9fa; padding: 10px 15px; border-bottom: 1px solid #e9ecef; font-weight: bold; color: #495057;">
                                要点 ${i + 1}
                            </div>
                            <div style="padding: 15px;">
                                <div style="margin-bottom: 15px;">
                                    <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #dc3545; font-size: 13px;">原始内容：</label>
                                    <div style="background: #fff5f5; padding: 12px; border-radius: 6px; border-left: 3px solid #dc3545; font-size: 14px; line-height: 1.4; min-height: 20px;">
                                        ${original || '<em style="color: #999;">无内容</em>'}
                                    </div>
                                </div>
                                <div>
                                    <label style="font-weight: bold; display: block; margin-bottom: 8px; color: #28a745; font-size: 13px;">AI增强后：</label>
                                    <div style="background: #f0fff4; padding: 12px; border-radius: 6px; border-left: 3px solid #28a745; font-size: 14px; line-height: 1.4; min-height: 20px;">
                                        ${enhanced || '<em style="color: #999;">无增强内容</em>'}
                                    </div>
                                </div>
                            </div>
                        </div>
                    `;
                }
            }

            dialogContent.innerHTML = `
                <style>
                    @keyframes slideInUp {
                        from {
                            opacity: 0;
                            transform: translateY(30px);
                        }
                        to {
                            opacity: 1;
                            transform: translateY(0);
                        }
                    }
                </style>
                <h4 style="margin: 0 0 25px 0; color: #2c3e50; display: flex; align-items: center; gap: 10px;">
                    <span style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 50%; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; font-size: 16px;">🪄</span>
                    AI要点增强结果 (共 ${maxLength} 个要点)
                </h4>

                <div style="margin-bottom: 30px;">
                    ${comparisonContent}
                </div>

                <div style="text-align: right; display: flex; gap: 15px; justify-content: flex-end; border-top: 1px solid #e9ecef; padding-top: 20px;">
                    <button onclick="closeBulletPointEnhancementDialog()"
                            style="background: #6c757d; color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.3s ease;">
                        <i class="fas fa-times"></i> 取消
                    </button>
                    <button onclick="applyAllBulletPointsEnhancement()"
                            style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);">
                        <i class="fas fa-check"></i> 应用所有增强
                    </button>
                </div>
            `;

            dialog.appendChild(dialogContent);
            document.body.appendChild(dialog);

            // 存储增强结果供后续使用
            dialog._enhancedPoints = enhancedPoints;
            dialog._originalPoints = originalPoints;

            // 点击遮罩关闭
            dialog.addEventListener('click', (e) => {
                if (e.target === dialog) {
                    closeBulletPointEnhancementDialog();
                }
            });
        }

        // 关闭要点增强对话框
        function closeBulletPointEnhancementDialog() {
            const dialog = document.getElementById('bulletPointEnhancementDialog');
            if (dialog) {
                document.body.removeChild(dialog);
            }
        }

        // 清理AI返回的内容，移除无关的开场白和格式标记
        function cleanAIContent(content) {
            if (!content) return '';

            // 移除常见的开场白模式
            const unwantedPatterns = [
                /^好的[，,。.]*.*?[。.]/,
                /^作为.*?专家[，,。.]*.*?[。.]/,
                /^我将.*?[。.]/,
                /^我会.*?[。.]/,
                /^以下是.*?[：:]/,
                /^根据.*?[：:]/,
                /^请注意.*?[：:]/,
                /^需要说明.*?[：:]/,
                /^增强后的要点.*?[：:]/,
                /^优化后的.*?[：:]/,
                /^改进后的.*?[：:]/
            ];

            let cleaned = content.trim();

            // 应用清理模式
            unwantedPatterns.forEach(pattern => {
                cleaned = cleaned.replace(pattern, '');
            });

            // 移除开头的编号和符号
            cleaned = cleaned.replace(/^[\d\s\.\-\*\•\·\→\▪\▫]+/, '').trim();

            return cleaned;
        }

        // 应用所有要点增强
        function applyAllBulletPointsEnhancement() {
            const dialog = document.getElementById('bulletPointEnhancementDialog');
            if (!dialog || !dialog._enhancedPoints || !dialog._originalPoints) {
                showNotification('无法获取增强结果', 'error');
                return;
            }

            const enhancedPoints = dialog._enhancedPoints;
            const originalPoints = dialog._originalPoints;
            const bulletPointsContainer = document.getElementById('bulletPointsContainer');

            if (!bulletPointsContainer) {
                showNotification('找不到要点容器', 'error');
                return;
            }

            let appliedCount = 0;

            // 更新现有要点，并清理内容
            originalPoints.forEach((originalPoint, index) => {
                if (enhancedPoints[index] && originalPoint.element) {
                    const cleanedContent = cleanAIContent(enhancedPoints[index]);
                    if (cleanedContent && cleanedContent.length >= 5) {
                        originalPoint.element.textContent = cleanedContent;
                        appliedCount++;
                    }
                }
            });

            // 如果增强后的要点比原始要点多，添加新要点
            if (enhancedPoints.length > originalPoints.length) {
                for (let i = originalPoints.length; i < enhancedPoints.length; i++) {
                    if (enhancedPoints[i]) {
                        const cleanedContent = cleanAIContent(enhancedPoints[i]);
                        if (cleanedContent && cleanedContent.length >= 5) {
                            addNewBulletPointWithContent(cleanedContent);
                            appliedCount++;
                        }
                    }
                }
            }

            closeBulletPointEnhancementDialog();

            if (appliedCount > 0) {
                showNotification(`已成功增强 ${appliedCount} 个要点！`, 'success');
            } else {
                showNotification('没有要点被增强', 'warning');
            }
        }

        // 添加带内容的新要点（用于增强功能）
        function addNewBulletPointWithContent(content) {
            const container = document.getElementById('bulletPointsContainer');
            if (!container) return;

            // 移除空状态提示
            const emptyState = container.querySelector('.empty-bullet-points');
            if (emptyState) {
                emptyState.remove();
            }

            // 获取当前要点数量
            const existingPoints = container.querySelectorAll('.bullet-point-item');
            const newIndex = existingPoints.length;

            // 创建新要点元素
            const newBulletPoint = document.createElement('div');
            newBulletPoint.className = 'bullet-point-item';
            newBulletPoint.setAttribute('data-index', newIndex);
            newBulletPoint.style.cssText = `
                display: flex;
                align-items: flex-start;
                margin-bottom: 8px;
                padding: 8px;
                border-radius: 4px;
                transition: all 0.2s ease;
                position: relative;
            `;

            newBulletPoint.innerHTML = `
                <span style="color: #666; margin-right: 8px; font-weight: bold; min-width: 20px;">•</span>
                <div style="flex: 1; position: relative;">
                    <div class="bullet-point-text" contenteditable="true"
                         style="outline: none; min-height: 20px; line-height: 1.4; word-wrap: break-word;">${content}</div>
                </div>
                <button class="delete-bullet-btn" onclick="deleteBulletPoint(${newIndex})"
                        style="background: #dc3545; color: white; border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer; margin-left: 4px; display: flex; align-items: center; justify-content: center; font-size: 12px; transition: all 0.3s ease; opacity: 0.7;"
                        title="删除此要点">
                    <i class="fas fa-trash"></i>
                </button>
            `;

            container.appendChild(newBulletPoint);
        }

        // 点击遮罩层关闭
        document.addEventListener('click', function(e) {
            if (e.target.id === 'imageSelectMenu') {
                closeImageSelectMenu();
            } else if (e.target.id === 'imageLibraryOverlay') {
                closeImageLibrary();
            } else if (e.target.id === 'imagePreviewOverlay') {
                closeImagePreview();
            }
        });

        // 添加新要点功能
        function addNewBulletPoint() {
            const container = document.getElementById('bulletPointsContainer');
            if (!container) return;

            // 移除空状态提示
            const emptyState = container.querySelector('.empty-bullet-points');
            if (emptyState) {
                emptyState.remove();
            }

            // 获取当前要点数量
            const existingPoints = container.querySelectorAll('.bullet-point-item');
            const newIndex = existingPoints.length;

            // 创建新要点元素
            const newBulletPoint = document.createElement('div');
            newBulletPoint.className = 'bullet-point-item';
            newBulletPoint.setAttribute('data-index', newIndex);
            newBulletPoint.style.cssText = `
                display: flex;
                align-items: flex-start;
                margin-bottom: 8px;
                padding: 8px;
                border-radius: 4px;
                transition: all 0.2s ease;
                position: relative;
                background: rgba(40, 167, 69, 0.1);
                border: 2px dashed #28a745;
            `;

            newBulletPoint.innerHTML = `
                <span style="color: #666; margin-right: 8px; font-weight: bold; min-width: 20px;">•</span>
                <div style="flex: 1; position: relative;">
                    <div class="bullet-point-text" contenteditable="true"
                         style="outline: none; min-height: 20px; line-height: 1.4; word-wrap: break-word; background: white; padding: 8px; border-radius: 4px; border: 1px solid #28a745;"
                         placeholder="请输入新要点内容...">
                    </div>
                </div>

                <button class="delete-bullet-btn" onclick="deleteBulletPoint(${newIndex})"
                        style="background: #dc3545; color: white; border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer; margin-left: 4px; display: flex; align-items: center; justify-content: center; font-size: 12px; transition: all 0.3s ease; opacity: 0.7;"
                        title="删除此要点">
                    <i class="fas fa-trash"></i>
                </button>
            `;

            container.appendChild(newBulletPoint);

            // 聚焦到新要点的文本区域
            const textArea = newBulletPoint.querySelector('.bullet-point-text');
            textArea.focus();

            // 添加事件监听器
            textArea.addEventListener('blur', function() {
                // 移除新建状态样式
                newBulletPoint.style.background = '';
                newBulletPoint.style.border = '';
                textArea.style.background = '';
                textArea.style.border = '';
                textArea.style.padding = '';
            });

            textArea.addEventListener('input', function() {
                if (this.textContent.trim()) {
                    // 有内容时移除新建状态样式
                    newBulletPoint.style.background = '';
                    newBulletPoint.style.border = '';
                    textArea.style.background = '';
                    textArea.style.border = '';
                    textArea.style.padding = '';
                }
            });

            showNotification('已添加新要点，请输入内容', 'info');
        }

        // 删除要点功能
        function deleteBulletPoint(pointIndex) {
            const bulletPointItem = document.querySelector(`.bullet-point-item[data-index="${pointIndex}"]`);
            if (!bulletPointItem) return;

            const pointText = bulletPointItem.querySelector('.bullet-point-text')?.textContent.trim();
            const confirmMessage = pointText ?
                `确定要删除要点"${pointText.substring(0, 30)}${pointText.length > 30 ? '...' : ''}"吗？` :
                '确定要删除这个要点吗？';

            if (confirm(confirmMessage)) {
                bulletPointItem.remove();

                // 重新编号剩余要点
                const container = document.getElementById('bulletPointsContainer');
                const remainingPoints = container.querySelectorAll('.bullet-point-item');

                remainingPoints.forEach((item, index) => {
                    item.setAttribute('data-index', index);
                    // 更新删除按钮的onclick事件
                    const deleteBtn = item.querySelector('.delete-bullet-btn');
                    if (deleteBtn) deleteBtn.setAttribute('onclick', `deleteBulletPoint(${index})`);
                });

                // 如果没有要点了，显示空状态
                if (remainingPoints.length === 0) {
                    container.innerHTML = `
                        <div class="empty-bullet-points" style="text-align: center; color: #999; padding: 40px 20px;">
                            <i class="fas fa-list" style="font-size: 24px; margin-bottom: 10px; opacity: 0.5;"></i>
                            <p style="margin: 0;">暂无要点，点击下方按钮添加</p>
                        </div>
                    `;
                }

                showNotification('要点已删除', 'info');
            }
        }

        // 验证和修复图片URL
        function validateAndFixImageUrls() {
            uploadedImages.forEach(image => {
                // 确保URL是绝对路径
                if (image.url && !image.url.startsWith('http') && !image.url.startsWith(window.location.origin)) {
                    if (image.url.startsWith('/')) {
                        image.url = window.location.origin + image.url;
                    } else {
                        image.url = window.location.origin + '/' + image.url;
                    }
                }

                // 确保文件大小是数字
                if (typeof image.size === 'string') {
                    image.size = parseInt(image.size) || 0;
                }
            });
        }

        // 添加键盘快捷键支持
        document.addEventListener('keydown', function(e) {
            // Ctrl/Cmd + E 切换快速编辑模式
            if ((e.ctrlKey || e.metaKey) && e.key === 'e' && !e.shiftKey && !e.altKey) {
                e.preventDefault();
                toggleQuickEditMode();
            }

            // ESC 键退出快速编辑模式
            if (e.key === 'Escape' && currentMode === 'quickedit') {
                if (currentInlineEditor) {
                    finishDirectEdit(false); // 取消编辑
                } else {
                    setMode('preview');
                }
            }
        });

        // 在页面加载完成后初始化图片上传功能
        document.addEventListener('DOMContentLoaded', function() {
            // 延迟初始化，确保所有元素都已加载
            setTimeout(() => {
                const imageUploadBtn = document.getElementById('aiImageUploadBtn');
                const inputContainer = document.querySelector('.ai-input-container');

                if (imageUploadBtn && inputContainer) {
                    if (typeof initImageUpload === 'function') {
                        initImageUpload();
                    }

                    // 验证和修复现有图片数据
                    if (typeof validateAndFixImageUrls === 'function') {
                        validateAndFixImageUrls();
                    }
                } else {
                    console.log('图片上传元素未找到:', {
                        uploadBtn: !!imageUploadBtn,
                        inputContainer: !!inputContainer
                    });
                }
            }, 100);
        });

        // Speech Script Generation Functions
        let speechScriptData = null;
        let speechScriptModal = null;

        function showSpeechScriptDialog() {
            if (speechScriptModal) {
                document.body.removeChild(speechScriptModal);
            }

            speechScriptModal = document.createElement('div');
            speechScriptModal.className = 'modal fade show';
            speechScriptModal.style.display = 'flex';
            speechScriptModal.style.alignItems = 'center';
            speechScriptModal.style.justifyContent = 'center';
            speechScriptModal.style.position = 'fixed';
            speechScriptModal.style.top = '0';
            speechScriptModal.style.left = '0';
            speechScriptModal.style.width = '100%';
            speechScriptModal.style.height = '100%';
            speechScriptModal.style.backgroundColor = 'rgba(0,0,0,0.5)';
            speechScriptModal.style.zIndex = '20000';
            speechScriptModal.innerHTML = `
                <div class="speech-modal-content" style="max-width: 1000px; width: 90vw; margin: auto;">
                        <div class="speech-modal-header">
                            <div class="speech-modal-title">
                                <div class="speech-modal-icon">
                                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <path d="M12 2C13.1 2 14 2.9 14 4V12C14 13.1 13.1 14 12 14C10.9 14 10 13.1 10 12V4C10 2.9 10.9 2 12 2Z" fill="currentColor"/>
                                        <path d="M19 10V12C19 15.87 15.87 19 12 19C8.13 19 5 15.87 5 12V10H7V12C7 14.76 9.24 17 12 17C14.76 17 17 14.76 17 12V10H19Z" fill="currentColor"/>
                                        <path d="M10 21H14V23H10V21Z" fill="currentColor"/>
                                    </svg>
                                </div>
                                <span>生成演讲稿</span>
                            </div>
                            <button type="button" class="speech-modal-close" onclick="closeSpeechScriptDialog()">
                                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </button>
                        </div>
                        <div class="speech-modal-body">
                            <!-- Generation Type Selection -->
                            <div class="speech-section">
                                <h6 class="speech-section-title">生成范围</h6>
                                <div class="speech-generation-type-group">
                                    <div class="speech-type-option">
                                        <input type="radio" name="generationType" id="singleSlide" value="single" checked>
                                        <label for="singleSlide" class="speech-type-label">
                                            <div class="speech-type-icon">
                                                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.89 22 5.99 22H18C19.1 22 20 21.1 20 20V8L14 2Z" stroke="currentColor" stroke-width="2" fill="none"/>
                                                    <path d="M14 2V8H20" stroke="currentColor" stroke-width="2" fill="none"/>
                                                </svg>
                                            </div>
                                            <div class="speech-type-text">
                                                <div class="speech-type-title">当前页</div>
                                                <div class="speech-type-desc">为当前选中的幻灯片生成演讲稿</div>
                                            </div>
                                        </label>
                                    </div>

                                    <div class="speech-type-option">
                                        <input type="radio" name="generationType" id="multiSlide" value="multi">
                                        <label for="multiSlide" class="speech-type-label">
                                            <div class="speech-type-icon">
                                                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M15 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.89 22 5.99 22H18C19.1 22 20 21.1 20 20V9L15 2Z" stroke="currentColor" stroke-width="2" fill="none"/>
                                                    <path d="M15 2V9H20" stroke="currentColor" stroke-width="2" fill="none"/>
                                                    <path d="M9 2H8C6.9 2 6 2.9 6 4V18C6 19.1 6.89 20 7.99 20H11" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.6"/>
                                                </svg>
                                            </div>
                                            <div class="speech-type-text">
                                                <div class="speech-type-title">多页选择</div>
                                                <div class="speech-type-desc">选择多个幻灯片生成演讲稿</div>
                                            </div>
                                        </label>
                                    </div>

                                    <div class="speech-type-option">
                                        <input type="radio" name="generationType" id="fullPresentation" value="full">
                                        <label for="fullPresentation" class="speech-type-label">
                                            <div class="speech-type-icon">
                                                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M3 3V21H21V3H3Z" stroke="currentColor" stroke-width="2" fill="none"/>
                                                    <path d="M9 9L15 15M15 9L9 15" stroke="currentColor" stroke-width="1.5" opacity="0.4"/>
                                                    <path d="M7 1V5M17 1V5M1 7H23" stroke="currentColor" stroke-width="2"/>
                                                </svg>
                                            </div>
                                            <div class="speech-type-text">
                                                <div class="speech-type-title">全部幻灯片</div>
                                                <div class="speech-type-desc">为整个演示生成完整演讲稿</div>
                                            </div>
                                        </label>
                                    </div>
                                </div>
                            </div>

                            <!-- Multi-slide Selection (hidden by default) -->
                            <div id="multiSlideSelection" class="mb-4" style="display: none;">
                                <h6 class="mb-3" style="color: var(--text-primary); font-weight: 600;">选择幻灯片</h6>
                                <div class="slide-selection-grid" id="slideSelectionGrid">
                                    <!-- Will be populated by JavaScript -->
                                </div>
                            </div>

                            <!-- Customization Options -->
                            <div class="speech-section">
                                <h6 class="speech-section-title">自定义选项</h6>

                                <div class="row">
                                    <div class="col-md-6 mb-3">
                                        <label class="speech-form-label">语调风格</label>
                                        <select class="speech-form-select" id="speechTone" onchange="toggleCustomToneInput()">
                                            <option value="conversational">对话式</option>
                                            <option value="formal">正式</option>
                                            <option value="casual">轻松</option>
                                            <option value="persuasive">说服性</option>
                                            <option value="educational">教学式</option>
                                            <option value="authoritative">权威式</option>
                                            <option value="storytelling">叙事性</option>
                                            <option value="custom">自定义</option>
                                        </select>
                                        <div id="customToneContainer" style="display: none; margin-top: 8px;">
                                            <input type="text" class="speech-form-input" id="customTone"
                                                   placeholder="请描述您希望的语调风格，例如：幽默风趣、严肃专业、温和亲切等...">
                                        </div>
                                    </div>

                                    <div class="col-md-6 mb-3">
                                        <label class="speech-form-label">目标受众</label>
                                        <select class="speech-form-select" id="targetAudience" onchange="toggleCustomAudienceInput()">
                                            <option value="general_public">普通大众</option>
                                            <option value="executives">企业高管</option>
                                            <option value="students">学生</option>
                                            <option value="technical_experts">技术专家</option>
                                            <option value="colleagues">同事</option>
                                            <option value="clients">客户</option>
                                            <option value="investors">投资者</option>
                                            <option value="custom">自定义</option>
                                        </select>
                                        <div id="customAudienceContainer" style="display: none; margin-top: 8px;">
                                            <input type="text" class="speech-form-input" id="customAudience"
                                                   placeholder="请描述您的目标受众，例如：中小企业主、医疗从业者、教育工作者等...">
                                        </div>
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="col-md-6 mb-3">
                                        <label class="speech-form-label">语言复杂度</label>
                                        <select class="speech-form-select" id="languageComplexity">
                                            <option value="moderate">适中</option>
                                            <option value="simple">简单</option>
                                            <option value="advanced">高级</option>
                                        </select>
                                    </div>

                                    <div class="col-md-6 mb-3">
                                        <label class="speech-form-label">演讲节奏</label>
                                        <select class="speech-form-select" id="speakingPace">
                                            <option value="normal">正常</option>
                                            <option value="slow">缓慢</option>
                                            <option value="fast">快速</option>
                                        </select>
                                    </div>
                                </div>

                                <div class="mb-3">
                                    <div class="speech-form-check">
                                        <input type="checkbox" id="includeTransitions" checked>
                                        <label for="includeTransitions" class="speech-checkbox-label">
                                            <span class="speech-checkbox-custom"></span>
                                            包含过渡语句
                                        </label>
                                    </div>
                                </div>

                                <div class="mb-3">
                                    <label class="speech-form-label">自定义风格要求（可选）</label>
                                    <textarea class="speech-form-textarea" id="customStylePrompt" rows="3"
                                              placeholder="例如：使用更多的数据支撑，增加互动问题，保持幽默感等..."></textarea>
                                </div>
                            </div>
                        </div>
                        <div class="speech-modal-footer">
                            <button type="button" class="speech-btn speech-btn-outline" onclick="showCurrentSpeechScripts()">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M1 12S5 4 12 4s11 8 11 8-4 8-11 8S1 12 1 12z" stroke="currentColor" stroke-width="2"/>
                                    <circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="2"/>
                                </svg>
                                查看演讲稿
                            </button>
                            <button type="button" class="speech-btn speech-btn-secondary" onclick="closeSpeechScriptDialog()">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                取消
                            </button>
                            <button type="button" class="speech-btn speech-btn-primary" onclick="generateSpeechScript()">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                    <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                    <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                </svg>
                                生成演讲稿
                            </button>
                        </div>
                </div>
            `;

            document.body.appendChild(speechScriptModal);

            // Close modal when clicking on the backdrop only
            speechScriptModal.addEventListener('click', function(e) {
                // Only close if clicking directly on the modal backdrop, not on child elements
                if (e.target === speechScriptModal) {
                    closeSpeechScriptDialog();
                }
            });

            // Prevent modal content from closing the modal
            const modalContent = speechScriptModal.querySelector('.speech-modal-content');
            if (modalContent) {
                modalContent.addEventListener('click', function(e) {
                    e.stopPropagation();
                });
            }

            // Initialize the dialog
            initializeSpeechScriptDialog();
        }

        function initializeSpeechScriptDialog() {
            // Handle generation type changes
            const typeRadios = document.querySelectorAll('input[name="generationType"]');
            typeRadios.forEach(radio => {
                radio.addEventListener('change', function() {
                    const multiSlideSelection = document.getElementById('multiSlideSelection');
                    if (this.value === 'multi') {
                        multiSlideSelection.style.display = 'block';
                        populateSlideSelection();
                    } else {
                        multiSlideSelection.style.display = 'none';
                    }
                });
            });
        }

        function populateSlideSelection() {
            const grid = document.getElementById('slideSelectionGrid');
            if (!grid || !slidesData) return;

            grid.innerHTML = '';

            slidesData.forEach((slide, index) => {
                const slideItem = document.createElement('div');
                slideItem.className = 'slide-selection-item';
                slideItem.innerHTML = `
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" id="slide_${index}" value="${index}">
                        <label class="form-check-label" for="slide_${index}">
                            第${index + 1}页: ${slide.title || '无标题'}
                        </label>
                    </div>
                `;
                grid.appendChild(slideItem);
            });
        }

        function closeSpeechScriptDialog() {
            if (speechScriptModal) {
                document.body.removeChild(speechScriptModal);
                speechScriptModal = null;
            }
        }

        function startProgressTracking(taskId, progressToast, totalSlides) {
            let lastProgress = 0;
            let checkCount = 0;
            const maxChecks = 300; // Maximum 5 minutes of tracking

            const interval = setInterval(async () => {
                checkCount++;

                try {
                    const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts/progress/${taskId}`);
                    const result = await response.json();

                    console.log(`Progress check ${checkCount}:`, result);

                    if (result.success && result.progress) {
                        const progress = result.progress;
                        const percentage = progress.progress_percentage;

                        // Update progress toast
                        updateProgressToast(progressToast, progress.message, percentage);

                        // Check if completed or failed
                        if (progress.status === 'completed') {
                            clearInterval(interval);
                            updateProgressToast(progressToast, progress.message, 100);

                            // Close progress toast and start polling for data
                            setTimeout(() => {
                                closeProgressToast(progressToast);
                                showNotification('演讲稿生成完成！', 'success');

                                // 使用轮询机制等待数据库数据可用
                                console.log('Starting to poll for speech scripts...');
                                pollForSpeechScripts();
                            }, 500);

                        } else if (progress.status === 'failed') {
                            clearInterval(interval);
                            closeProgressToast(progressToast);
                            showNotification(`生成失败: ${progress.message}`, 'error');
                        }

                        lastProgress = percentage;
                    } else {
                        // Task not found or error, stop tracking
                        clearInterval(interval);
                        console.warn('Progress tracking failed, task not found');
                        closeProgressToast(progressToast);
                        showNotification('进度跟踪失败，请刷新页面查看结果', 'warning');
                    }
                } catch (error) {
                    console.error('Progress tracking error:', error);

                    // If too many errors or max checks reached, stop tracking
                    if (checkCount >= maxChecks) {
                        clearInterval(interval);
                        closeProgressToast(progressToast);
                        showNotification('进度跟踪超时，请刷新页面查看结果', 'warning');
                    }
                }
            }, 1000); // Check every second

            return interval;
        }

        function startSingleScriptProgressTracking(taskId, progressToast, slideIndex) {
            let checkCount = 0;
            const maxChecks = 60; // Maximum 1 minute of tracking

            const interval = setInterval(async () => {
                checkCount++;

                try {
                    const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts/progress/${taskId}`);
                    const result = await response.json();

                    console.log(`Single script progress check ${checkCount}:`, result);

                    if (result.success && result.progress) {
                        const progress = result.progress;
                        const percentage = progress.progress_percentage;

                        // Update progress toast
                        updateProgressToast(progressToast, progress.message, percentage);

                        // Check if completed or failed
                        if (progress.status === 'completed') {
                            clearInterval(interval);
                            updateProgressToast(progressToast, `第${slideIndex + 1}页演讲稿重新生成完成！`, 100);

                            // Close progress toast and refresh display
                            setTimeout(() => {
                                closeProgressToast(progressToast);
                                showNotification(`第${slideIndex + 1}页演讲稿已更新`, 'success');

                                // 刷新当前弹窗显示
                                setTimeout(() => {
                                    showCurrentSpeechScripts();
                                }, 1000);
                            }, 1500);

                        } else if (progress.status === 'failed') {
                            clearInterval(interval);
                            closeProgressToast(progressToast);
                            showNotification(`第${slideIndex + 1}页重新生成失败: ${progress.message}`, 'error');
                        }

                    } else {
                        // Task not found or error, stop tracking
                        clearInterval(interval);
                        console.warn('Single script progress tracking failed, task not found');
                        closeProgressToast(progressToast);
                        showNotification('进度跟踪失败，请刷新页面查看结果', 'warning');
                    }
                } catch (error) {
                    console.error('Single script progress tracking error:', error);

                    // If too many errors or max checks reached, stop tracking
                    if (checkCount >= maxChecks) {
                        clearInterval(interval);
                        closeProgressToast(progressToast);
                        showNotification('进度跟踪超时，请刷新页面查看结果', 'warning');
                    }
                }
            }, 1000); // Check every second

            return interval;
        }

        async function generateSpeechScript() {
            try {
                // Get generation type
                const generationType = document.querySelector('input[name="generationType"]:checked').value;

                // Get slide indices based on type
                let slideIndices = [];
                if (generationType === 'single') {
                    slideIndices = [currentSlideIndex];
                } else if (generationType === 'multi') {
                    const checkedBoxes = document.querySelectorAll('#slideSelectionGrid input[type="checkbox"]:checked');
                    slideIndices = Array.from(checkedBoxes).map(cb => parseInt(cb.value));

                    if (slideIndices.length === 0) {
                        showNotification('请至少选择一页幻灯片', 'warning');
                        return;
                    }
                } else if (generationType === 'full') {
                    slideIndices = Array.from({length: slidesData.length}, (_, i) => i);
                }

                // Show progress toast
                const progressToast = showProgressToast('正在生成演讲稿...', 0);
                let progressInterval = null;

                // Get customization options
                const toneValue = document.getElementById('speechTone').value;
                const audienceValue = document.getElementById('targetAudience').value;

                const customization = {
                    tone: toneValue === 'custom' ? 'conversational' : toneValue,
                    target_audience: audienceValue === 'custom' ? 'general_public' : audienceValue,
                    language_complexity: document.getElementById('languageComplexity').value,
                    speaking_pace: document.getElementById('speakingPace').value,
                    include_transitions: document.getElementById('includeTransitions').checked,
                    custom_style_prompt: document.getElementById('customStylePrompt').value.trim() || null
                };

                // Add custom tone if specified
                if (toneValue === 'custom') {
                    const customTone = document.getElementById('customTone').value.trim();
                    if (customTone) {
                        customization.custom_tone = customTone;
                        // Append to custom style prompt
                        const existingPrompt = customization.custom_style_prompt || '';
                        customization.custom_style_prompt = existingPrompt ?
                            `${existingPrompt}。语调风格：${customTone}` :
                            `语调风格：${customTone}`;
                    } else {
                        showNotification('请输入自定义语调风格描述', 'warning');
                        return;
                    }
                }

                // Add custom audience if specified
                if (audienceValue === 'custom') {
                    const customAudience = document.getElementById('customAudience').value.trim();
                    if (customAudience) {
                        customization.custom_audience = customAudience;
                        // Append to custom style prompt
                        const existingPrompt = customization.custom_style_prompt || '';
                        customization.custom_style_prompt = existingPrompt ?
                            `${existingPrompt}。目标受众：${customAudience}` :
                            `目标受众：${customAudience}`;
                    } else {
                        showNotification('请输入自定义目标受众描述', 'warning');
                        return;
                    }
                }

                // Close the dialog
                closeSpeechScriptDialog();

                // Show progress with detailed info for full generation
                let progressMessage = '正在生成演讲稿...';
                if (generationType === 'full') {
                    progressMessage = `正在生成全部演讲稿 (共${slideIndices.length}页)...`;
                } else if (generationType === 'multi') {
                    progressMessage = `正在生成演讲稿 (共${slideIndices.length}页)...`;
                }

                // Update progress toast message
                updateProgressToast(progressToast, progressMessage, 0);

                // Make API request
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-script/generate`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        generation_type: generationType,
                        slide_indices: slideIndices,
                        customization: customization
                    })
                });

                const result = await response.json();

                if (result.success && result.task_id) {
                    console.log('Starting progress tracking for task:', result.task_id);
                    // Start progress tracking immediately
                    progressInterval = startProgressTracking(result.task_id, progressToast, slideIndices.length);
                } else {
                    closeProgressToast(progressToast);
                    showNotification(`演讲稿生成失败: ${result.error || '未知错误'}`, 'error');
                }

            } catch (error) {
                console.error('Speech script generation error:', error);

                // Clear progress tracking
                if (progressInterval) {
                    clearInterval(progressInterval);
                }
                closeProgressToast(progressToast);

                showNotification('演讲稿生成失败，请稍后重试', 'error');
            } finally {
                // Close speech script dialog
                closeSpeechScriptDialog();
            }
        }

        function showSpeechScriptPreview(result, editMode = false) {
            if (speechScriptModal) {
                document.body.removeChild(speechScriptModal);
            }

            speechScriptModal = document.createElement('div');
            speechScriptModal.className = 'modal fade show';
            speechScriptModal.style.display = 'flex';
            speechScriptModal.style.alignItems = 'center';
            speechScriptModal.style.justifyContent = 'center';
            speechScriptModal.style.position = 'fixed';
            speechScriptModal.style.top = '0';
            speechScriptModal.style.left = '0';
            speechScriptModal.style.width = '100%';
            speechScriptModal.style.height = '100%';
            speechScriptModal.style.backgroundColor = 'rgba(0,0,0,0.5)';
            speechScriptModal.style.zIndex = '20000';

            let scriptsHtml = '';
            result.scripts.forEach((script, index) => {
                const slideTitle = script.slide_index === -1 ? '开场白' :
                                 script.slide_index >= result.scripts.length - 1 && script.slide_title === '结束语' ? '结束语' :
                                 script.slide_title;

                const scriptId = `script-${script.slide_index}-${index}`;
                const contentId = `content-${script.slide_index}-${index}`;
                const editId = `edit-${script.slide_index}-${index}`;

                scriptsHtml += `
                    <div class="speech-script-item" data-slide-index="${script.slide_index}" data-script-index="${index}">
                        <div class="speech-script-header">
                            <h6>${slideTitle}</h6>
                            <div class="speech-script-meta">
                                <span class="speech-script-duration">${script.estimated_duration || '未知时长'}</span>
                            </div>
                        </div>
                        <div class="speech-script-content-wrapper">
                            <div id="${contentId}" class="speech-script-content ${editMode ? 'hidden' : ''}">${script.script_content}</div>
                            <textarea id="${editId}" class="speech-script-edit ${editMode ? '' : 'hidden'}" rows="8">${script.script_content}</textarea>
                        </div>
                        <div class="speech-script-actions">
                            <button class="speech-script-btn save-btn ${editMode ? '' : 'hidden'}" onclick="saveSpeechScript(${script.slide_index}, ${index})">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M19 21H5C4.44772 21 4 20.5523 4 20V4C4 3.44772 4.44772 3 5 3H16L20 7V20C20 20.5523 19.5523 21 19 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <polyline points="9,9 9,15 15,15 15,9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                保存
                            </button>
                            <button class="speech-script-btn edit-btn ${editMode ? 'hidden' : ''}" onclick="toggleEditMode(${script.slide_index}, ${index})">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M11 4H4C3.44772 4 3 4.44772 3 5V20C3 20.5523 3.44772 21 4 21H19C19.5523 21 20 20.5523 20 20V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M18.5 2.5C18.8978 2.10217 19.4374 1.87868 20 1.87868C20.5626 1.87868 21.1022 2.10217 21.5 2.5C21.8978 2.89783 22.1213 3.43739 22.1213 4C22.1213 4.56261 21.8978 5.10217 21.5 5.5L12 15L8 16L9 12L18.5 2.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                编辑
                            </button>
                            <button class="speech-script-btn" onclick="regenerateSingleScript(${script.slide_index})">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M23 20V14H17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M20.49 9C19.9828 7.56678 19.1209 6.28392 17.9845 5.27304C16.8482 4.26216 15.4745 3.55682 13.9917 3.21834C12.5089 2.87986 10.9652 2.91902 9.50481 3.33329C8.04437 3.74757 6.70779 4.52433 5.64 5.59L1 10M23 14L18.36 18.41C17.2922 19.4757 15.9556 20.2524 14.4952 20.6667C13.0348 21.081 11.4911 21.1201 10.0083 20.7817C8.52547 20.4432 7.1518 19.7378 6.01547 18.727C4.87913 17.7161 4.01717 16.4332 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                重新生成
                            </button>
                            <button class="speech-script-btn speech-script-btn-danger" onclick="deleteSpeechScriptBySlide(${script.slide_index})">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M3 6H5H21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M8 6V4C8 3.44772 8.44772 3 9 3H15C15.5523 3 16 3.44772 16 4V6M19 6V20C19 20.5523 18.4477 21 18 21H6C5.44772 21 5 20.5523 5 20V6H19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                删除
                            </button>
                        </div>
                    </div>`;
            });

            speechScriptModal.innerHTML = `
                <div class="speech-modal-dialog" style="max-width: 90vw; width: 1200px;">
                    <div class="speech-modal-content">
                        <div class="speech-modal-header">
                            <div class="speech-modal-title">
                                <div class="speech-section-title">
                                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                        <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                        <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                                    </svg>
                                    演讲稿${editMode ? '编辑' : '预览'}
                                </div>
                            </div>
                            <button type="button" class="speech-modal-close" onclick="closeSpeechScriptDialog()">
                                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </button>
                        </div>
                        <div class="speech-modal-body">
                            <div class="speech-modal-controls">
                                <div class="speech-duration-info">
                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
                                        <polyline points="12,6 12,12 16,14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    </svg>
                                    <span>总预计时长: <strong>${result.total_estimated_duration || '未知'}</strong></span>
                                </div>
                                <div class="speech-action-group">
                                    <button class="speech-btn speech-btn-outline" onclick="exportSpeechScript('docx')">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <path d="M14 2H6C5.44772 2 5 2.44772 5 3V21C5 21.5523 5.44772 22 6 22H18C18.5523 22 19 21.5523 19 21V7L14 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                            <polyline points="14,2 14,8 20,8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                        导出DOCX
                                    </button>
                                    <button class="speech-btn speech-btn-outline" onclick="exportSpeechScript('markdown')">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <path d="M14 2H6C5.44772 2 5 2.44772 5 3V21C5 21.5523 5.44772 22 6 22H18C18.5523 22 19 21.5523 19 21V7L14 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                            <polyline points="14,2 14,8 20,8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                        导出Markdown
                                    </button>
                                    <button class="speech-btn ${editMode ? 'speech-btn-secondary' : 'speech-btn-primary'}" onclick="toggleAllEditMode()">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            ${editMode ?
                                                '<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>' :
                                                '<path d="M11 4H4C3.44772 4 3 4.44772 3 5V20C3 20.5523 3.44772 21 4 21H19C19.5523 21 20 20.5523 20 20V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18.5 2.5C18.8978 2.10217 19.4374 1.87868 20 1.87868C20.5626 1.87868 21.1022 2.10217 21.5 2.5C21.8978 2.89783 22.1213 3.43739 22.1213 4C22.1213 4.56261 21.8978 5.10217 21.5 5.5L12 15L8 16L9 12L18.5 2.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>'
                                            }
                                        </svg>
                                        ${editMode ? '退出编辑' : '编辑模式'}
                                    </button>
                                </div>
                            </div>
                            <div class="speech-scripts-container">
                                ${scriptsHtml}
                            </div>
                        </div>
                        <div class="speech-modal-footer">
                            <button type="button" class="speech-btn speech-btn-secondary" onclick="closeSpeechScriptDialog()">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                关闭
                            </button>
                            <button type="button" class="speech-btn speech-btn-primary" onclick="regenerateSpeechScript()">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M23 20V14H17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M20.49 9C19.9828 7.56678 19.1209 6.28392 17.9845 5.27304C16.8482 4.26216 15.4745 3.55682 13.9917 3.21834C12.5089 2.87986 10.9652 2.91902 9.50481 3.33329C8.04437 3.74757 6.70779 4.52433 5.64 5.59L1 10M23 14L18.36 18.41C17.2922 19.4757 15.9556 20.2524 14.4952 20.6667C13.0348 21.081 11.4911 21.1201 10.0083 20.7817C8.52547 20.4432 7.1518 19.7378 6.01547 18.727C4.87913 17.7161 4.01717 16.4332 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                重新生成全部
                            </button>
                        </div>
                    </div>
                </div>
            `;

            document.body.appendChild(speechScriptModal);

            // Close modal when clicking on the backdrop
            speechScriptModal.addEventListener('click', function(e) {
                if (e.target === speechScriptModal) {
                    closeSpeechScriptDialog();
                }
            });
        }

        async function exportSpeechScript(format) {
            if (!speechScriptData) {
                showNotification('没有可导出的演讲稿数据', 'warning');
                return;
            }

            try {
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-script/export`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        export_format: format,
                        scripts_data: speechScriptData.scripts,
                        include_metadata: true
                    })
                });

                if (response.ok) {
                    // Trigger file download
                    const blob = await response.blob();
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;

                    const contentDisposition = response.headers.get('Content-Disposition');
                    let filename = `{{ project.topic }}_演讲稿.${format === 'docx' ? 'docx' : 'md'}`;
                    if (contentDisposition) {
                        const filenameMatch = contentDisposition.match(/filename\*=UTF-8''(.+)/);
                        if (filenameMatch) {
                            filename = decodeURIComponent(filenameMatch[1]);
                        }
                    }

                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    window.URL.revokeObjectURL(url);

                    showNotification(`演讲稿已导出为 ${format.toUpperCase()} 格式`, 'success');
                } else {
                    const result = await response.json();
                    showNotification(`导出失败: ${result.error}`, 'error');
                }
            } catch (error) {
                console.error('Export error:', error);
                showNotification('导出失败，请稍后重试', 'error');
            }
        }

        function regenerateSpeechScript() {
            closeSpeechScriptDialog();
            showSpeechScriptDialog();
        }

        function toggleEditMode(slideIndex, scriptIndex, forceMode = null) {
            const contentDiv = document.getElementById(`content-${slideIndex}-${scriptIndex}`);
            const editTextarea = document.getElementById(`edit-${slideIndex}-${scriptIndex}`);
            const saveBtn = document.querySelector(`[data-slide-index="${slideIndex}"] .save-btn`);
            const editBtn = document.querySelector(`[data-slide-index="${slideIndex}"] .edit-btn`);

            // 确定当前状态
            const isCurrentlyEditing = editTextarea && !editTextarea.classList.contains('hidden');

            // 确定目标状态
            let shouldEdit;
            if (forceMode !== null) {
                shouldEdit = forceMode;
            } else {
                shouldEdit = !isCurrentlyEditing;
            }

            if (shouldEdit) {
                // 进入编辑模式
                if (contentDiv) contentDiv.classList.add('hidden');
                if (editTextarea) {
                    editTextarea.classList.remove('hidden');
                    editTextarea.focus();
                }
                if (saveBtn) saveBtn.classList.remove('hidden');
                if (editBtn) editBtn.classList.add('hidden');
            } else {
                // 退出编辑模式
                if (contentDiv) contentDiv.classList.remove('hidden');
                if (editTextarea) editTextarea.classList.add('hidden');
                if (saveBtn) saveBtn.classList.add('hidden');
                if (editBtn) editBtn.classList.remove('hidden');
            }
        }

        async function saveSpeechScript(slideIndex, scriptIndex) {
            try {
                const editTextarea = document.getElementById(`edit-${slideIndex}-${scriptIndex}`);
                const contentDiv = document.getElementById(`content-${slideIndex}-${scriptIndex}`);
                const newContent = editTextarea.value.trim();

                if (!newContent) {
                    showNotification('演讲稿内容不能为空', 'warning');
                    return;
                }

                // 显示保存中状态
                const saveBtn = document.querySelector(`[data-slide-index="${slideIndex}"] .save-btn`);
                const originalText = saveBtn.innerHTML;
                saveBtn.innerHTML = '保存中...';
                saveBtn.disabled = true;

                // 调用API保存
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts/slide/${slideIndex}`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        script_content: newContent,
                        slide_title: document.querySelector(`[data-slide-index="${slideIndex}"] h6`).textContent
                    })
                });

                const result = await response.json();

                if (result.success) {
                    // 更新显示内容
                    contentDiv.textContent = newContent;

                    // 退出编辑模式
                    toggleEditMode(slideIndex, scriptIndex, false);

                    showNotification('演讲稿已保存', 'success');
                } else {
                    showNotification(`保存失败: ${result.error}`, 'error');
                }

            } catch (error) {
                console.error('Save speech script error:', error);
                showNotification('保存演讲稿失败', 'error');
            } finally {
                // 恢复按钮状态
                const saveBtn = document.querySelector(`[data-slide-index="${slideIndex}"] .save-btn`);
                saveBtn.innerHTML = originalText;
                saveBtn.disabled = false;
            }
        }

        async function regenerateSingleScript(slideIndex) {
            if (!confirm(`确定要重新生成第${slideIndex + 1}页的演讲稿吗？当前内容将被覆盖。`)) {
                return;
            }

            try {
                // 显示进度提示
                const progressToast = showProgressToast(`正在重新生成第${slideIndex + 1}页演讲稿...`, 0);

                // 使用默认参数直接生成（使用正确的API结构）
                const defaultCustomization = {
                    tone: 'conversational',
                    target_audience: 'general_public',
                    language_complexity: 'moderate',
                    speaking_pace: 'normal',
                    include_transitions: true,
                    include_timing_notes: false,
                    custom_style_prompt: null,
                    custom_audience: null
                };

                // 调用生成API
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-script/generate`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        generation_type: 'single',
                        slide_indices: [slideIndex],
                        customization: defaultCustomization
                    })
                });

                const result = await response.json();

                console.log('Single script regeneration API response:', result);

                if (result.success && result.task_id) {
                    console.log('Starting progress tracking for single script regeneration:', result.task_id);

                    // 开始进度跟踪
                    startSingleScriptProgressTracking(result.task_id, progressToast, slideIndex);
                } else {
                    console.error('Single script regeneration failed:', result);
                    closeProgressToast(progressToast);
                    showNotification(`重新生成失败: ${result.error || result.message || '未知错误'}`, 'error');
                }

            } catch (error) {
                console.error('Regenerate single script error:', error);
                showNotification('重新生成失败', 'error');
            }
        }

        function toggleAllEditMode() {
            // 获取当前是否处于编辑模式（检查第一个textarea是否可见）
            const firstTextarea = document.querySelector('.speech-script-edit');
            const isCurrentlyEditing = firstTextarea && !firstTextarea.classList.contains('hidden');

            // 切换所有项目的编辑模式
            document.querySelectorAll('.speech-script-item').forEach(item => {
                const slideIndex = parseInt(item.dataset.slideIndex);
                const scriptIndex = parseInt(item.dataset.scriptIndex);

                // 强制设置为相反的模式
                toggleEditMode(slideIndex, scriptIndex, !isCurrentlyEditing);
            });

            const newEditMode = !isCurrentlyEditing;

            // 同时更新所有单独的编辑按钮状态
            document.querySelectorAll('.edit-btn').forEach(btn => {
                if (newEditMode) {
                    btn.classList.add('hidden');
                } else {
                    btn.classList.remove('hidden');
                }
            });

            // 更新标题
            const titleElement = document.querySelector('.speech-section-title');
            if (titleElement) {
                titleElement.innerHTML = `
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 2L2 7L12 12L22 7L12 2Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                        <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                        <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                    </svg>
                    演讲稿${newEditMode ? '编辑' : '预览'}
                `;
            }

            // 更新按钮文本和样式 - 查找正确的编辑模式按钮
            const toggleBtn = document.querySelector('.speech-action-group .speech-btn:last-child');
            if (toggleBtn) {
                // 更新按钮样式
                if (newEditMode) {
                    toggleBtn.className = 'speech-btn speech-btn-secondary';
                } else {
                    toggleBtn.className = 'speech-btn speech-btn-primary';
                }

                // 更新按钮内容
                toggleBtn.innerHTML = `
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        ${newEditMode ?
                            '<path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>' :
                            '<path d="M11 4H4C3.44772 4 3 4.44772 3 5V20C3 20.5523 3.44772 21 4 21H19C19.5523 21 20 20.5523 20 20V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18.5 2.5C18.8978 2.10217 19.4374 1.87868 20 1.87868C20.5626 1.87868 21.1022 2.10217 21.5 2.5C21.8978 2.89783 22.1213 3.43739 22.1213 4C22.1213 4.56261 21.8978 5.10217 21.5 5.5L12 15L8 16L9 12L18.5 2.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>'
                        }
                    </svg>
                    ${newEditMode ? '退出编辑' : '编辑模式'}
                `;
            }
        }

        function toggleCustomToneInput() {
            const toneSelect = document.getElementById('speechTone');
            const customContainer = document.getElementById('customToneContainer');

            if (toneSelect.value === 'custom') {
                customContainer.style.display = 'block';
                document.getElementById('customTone').focus();
            } else {
                customContainer.style.display = 'none';
                document.getElementById('customTone').value = '';
            }
        }

        function toggleCustomAudienceInput() {
            const audienceSelect = document.getElementById('targetAudience');
            const customContainer = document.getElementById('customAudienceContainer');

            if (audienceSelect.value === 'custom') {
                customContainer.style.display = 'block';
                document.getElementById('customAudience').focus();
            } else {
                customContainer.style.display = 'none';
                document.getElementById('customAudience').value = '';
            }
        }

        async function pollForSpeechScripts() {
            const maxAttempts = 30; // 最多尝试30次
            const pollInterval = 1000; // 每1000ms查询一次
            let attempts = 0;

            const poll = async () => {
                attempts++;
                console.log(`Polling attempt ${attempts}/${maxAttempts}...`);

                try {
                    const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts`);
                    const result = await response.json();

                    if (result.success && result.scripts && result.scripts.length > 0) {
                        console.log(`Found ${result.scripts.length} scripts, displaying...`);
                        // 找到数据，显示演讲稿
                        showCurrentSpeechScripts();
                        return;
                    }

                    // 如果还没到最大尝试次数，继续轮询
                    if (attempts < maxAttempts) {
                        setTimeout(poll, pollInterval);
                    } else {
                        console.warn('Polling timeout: No scripts found after max attempts');
                        showNotification('获取演讲稿超时，请手动刷新页面后查看', 'warning');
                    }
                } catch (error) {
                    console.error('Polling error:', error);
                    // 出错继续尝试
                    if (attempts < maxAttempts) {
                        setTimeout(poll, pollInterval);
                    } else {
                        showNotification('获取演讲稿失败，请刷新页面重试', 'error');
                    }
                }
            };

            // 开始轮询
            poll();
        }

        async function showCurrentSpeechScripts() {
            try {
                // Close current dialog
                closeSpeechScriptDialog();

                console.log('Fetching speech scripts from API...');
                // Fetch current speech scripts
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts`);
                const result = await response.json();

                console.log('API response:', result);

                if (!result.success) {
                    console.error('API returned error:', result.error);
                    showNotification(`获取演讲稿失败: ${result.error}`, 'error');
                    return;
                }

                const scripts = result.scripts;
                console.log(`Found ${scripts.length} scripts`);

                if (scripts.length === 0) {
                    console.warn('No scripts found in database');
                    showNotification('暂无演讲稿，请先生成演讲稿', 'info');
                    return;
                }

                // Sort by slide index
                scripts.sort((a, b) => a.slide_index - b.slide_index);

                // 转换为预览格式
                const totalMinutes = scripts.reduce((total, script) => {
                    if (script.estimated_duration && script.estimated_duration.includes('分钟')) {
                        const minutes = parseFloat(script.estimated_duration.replace('分钟', ''));
                        return total + (isNaN(minutes) ? 0 : minutes);
                    }
                    return total;
                }, 0);

                const previewData = {
                    success: true,
                    scripts: scripts,
                    total_estimated_duration: totalMinutes > 0 ? totalMinutes.toFixed(1) + '分钟' : '未知',
                    generation_metadata: {}
                };

                // 设置全局演讲稿数据，以便导出功能可以使用
                speechScriptData = previewData;

                // 直接使用预览弹窗显示，默认为非编辑模式
                showSpeechScriptPreview(previewData, false);

            } catch (error) {
                console.error('Show current speech scripts error:', error);
                showNotification('获取演讲稿失败，请稍后重试', 'error');
            }
        }

        function closeSpeechScriptsDialog() {
            const scriptsModal = document.getElementById('speechScriptsModal');
            if (scriptsModal) {
                document.body.removeChild(scriptsModal);
            }
        }

        function getGenerationTypeText(type) {
            const types = {
                'single': '单页',
                'multi': '多页',
                'full': '全部'
            };
            return types[type] || type;
        }

        function getToneText(tone) {
            const tones = {
                'conversational': '对话式',
                'formal': '正式',
                'casual': '轻松',
                'persuasive': '说服性',
                'educational': '教学式',
                'authoritative': '权威式',
                'storytelling': '叙事性'
            };
            return tones[tone] || tone;
        }

        function getAudienceText(audience) {
            const audiences = {
                'general_public': '普通大众',
                'executives': '企业高管',
                'students': '学生',
                'technical_experts': '技术专家',
                'colleagues': '同事',
                'clients': '客户',
                'investors': '投资者'
            };
            return audiences[audience] || audience;
        }

        // 这个函数已经被regenerateSingleScript替代，保留为兼容性
        async function reuseSpeechScriptParams(slideIndex) {
            regenerateSingleScript(slideIndex);
        }

        async function deleteSpeechScriptBySlide(slideIndex) {
            if (!confirm(`确定要删除第${slideIndex + 1}页的演讲稿吗？此操作不可撤销。`)) {
                return;
            }

            try {
                const response = await fetch(`/api/projects/{{ project.project_id }}/speech-scripts/slide/${slideIndex}`, {
                    method: 'DELETE'
                });

                const result = await response.json();

                if (result.success) {
                    showNotification(result.message, 'success');
                    // Refresh scripts dialog
                    showCurrentSpeechScripts();
                } else {
                    showNotification(`删除失败: ${result.error}`, 'error');
                }

            } catch (error) {
                console.error('Delete speech script error:', error);
                showNotification('删除演讲稿失败', 'error');
            }
        }

        // 放映模式鼠标控制功能
        let mouseMoveTimeout;
        let isMouseIdle = false;
        let slideshowControls, slideshowExitBtn, slideshowOverlay;

        function handleSlideshowMouseMove() {
            // 显示控制按钮
            showSlideshowControls();

            // 清除之前的定时器
            clearTimeout(mouseMoveTimeout);

            // 设置新的定时器，3秒后隐藏控制按钮
            mouseMoveTimeout = setTimeout(() => {
                hideSlideshowControls();
            }, 3000);
        }

        function showSlideshowControls() {
            if (slideshowControls) slideshowControls.classList.add('visible');
            if (slideshowExitBtn) slideshowExitBtn.classList.add('visible');
            const slideshowInfo = document.getElementById('slideshowInfo');
            if (slideshowInfo) slideshowInfo.classList.add('visible');
            isMouseIdle = false;
            // 显示鼠标光标
            if (slideshowOverlay) slideshowOverlay.style.cursor = 'default';
        }

        function hideSlideshowControls() {
            if (slideshowControls) slideshowControls.classList.remove('visible');
            if (slideshowExitBtn) slideshowExitBtn.classList.remove('visible');
            const slideshowInfo = document.getElementById('slideshowInfo');
            if (slideshowInfo) slideshowInfo.classList.remove('visible');
            isMouseIdle = true;
            // 隐藏鼠标光标
            if (slideshowOverlay) slideshowOverlay.style.cursor = 'none';
        }

        function initializeSlideshowMouseControls() {
            slideshowOverlay = document.getElementById('slideshowOverlay');
            slideshowControls = document.querySelector('.slideshow-controls');
            slideshowExitBtn = document.querySelector('.slideshow-exit');

            // 初始状态：隐藏控制按钮
            hideSlideshowControls();

            // 鼠标移动事件
            slideshowOverlay.addEventListener('mousemove', handleSlideshowMouseMove);

            // 鼠标离开事件
            slideshowOverlay.addEventListener('mouseleave', hideSlideshowControls);
        }

        function removeSlideshowMouseControls() {
            // 清除定时器
            clearTimeout(mouseMoveTimeout);

            // 移除事件监听器
            if (slideshowOverlay) {
                slideshowOverlay.removeEventListener('mousemove', handleSlideshowMouseMove);
                slideshowOverlay.removeEventListener('mouseleave', hideSlideshowControls);

                // 恢复鼠标光标
                slideshowOverlay.style.cursor = 'default';
            }

            // 清理引用
            slideshowControls = null;
            slideshowExitBtn = null;
            slideshowOverlay = null;
        }
    </script>
</body>
</html>
