{% extends "base.html" %}

{% block title %}TODO 看板 - {{ todo_board.title }} - LandPPT{% endblock %}

{% block extra_css %}
<style>
/* Outline view specific styles */
.outline-card {
    transition: all 0.3s ease;
}

.outline-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}

.slide-number {
    background: #3498db;
    color: white;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8em;
    font-weight: bold;
}

.slide-number.large {
    width: 32px;
    height: 32px;
    font-size: 1em;
}

.slide-type-tag {
    background: #e8f4fd;
    color: #3498db;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.8em;
}

.content-points {
    margin: 0;
    padding-left: 20px;
    color: #555;
    line-height: 1.6;
}

.content-points li {
    margin-bottom: 5px;
}

/* Modal styles */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.5);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

/* Button hover effects */
.btn:hover {
    opacity: 0.9;
    transform: translateY(-1px);
}

/* Animation for loading states */
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* 脉冲动画 */
@keyframes pulse {
    0% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.1); opacity: 0.7; }
    100% { transform: scale(1); opacity: 1; }
}

/* 波浪动画 */
@keyframes wave {
    0%, 60%, 100% { transform: initial; }
    30% { transform: translateY(-15px); }
}

/* 渐变背景动画 */
@keyframes gradientShift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

/* 打字机效果 */
@keyframes typing {
    from { width: 0; }
    to { width: 100%; }
}

/* 闪烁光标 */
@keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}

/* 进度条动画 */
@keyframes progressBar {
    0% { width: 0%; }
    25% { width: 30%; }
    50% { width: 60%; }
    75% { width: 85%; }
    100% { width: 100%; }
}

/* 浮动动画 */
@keyframes float {
    0%, 100% { transform: translateY(0px); }
    50% { transform: translateY(-10px); }
}

/* 等待动画容器样式 */
.loading-container {
    text-align: center;
    padding: 30px 20px;
    background: linear-gradient(-45deg, #f8f9fa, #e9ecef, #f8f9fa, #e9ecef);
    background-size: 400% 400%;
    animation: gradientShift 4s ease infinite;
    border-radius: 15px;
    margin: 15px 0;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    max-height: 500px;
    overflow: hidden;
}

.loading-icon {
    font-size: 2.5em;
    color: #3498db;
    margin-bottom: 15px;
    animation: pulse 2s ease-in-out infinite;
}

.loading-title {
    font-size: 1.2em;
    font-weight: 600;
    color: #2c3e50;
    margin-bottom: 10px;
}

/* 创意AI大脑思考动画 */
.brain-container {
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 20px 0;
    height: 180px;
    perspective: 1000px;
    position: relative;
}

.ai-brain {
    position: relative;
    width: 120px;
    height: 120px;
    animation: brainFloat 4s ease-in-out infinite;
}

@keyframes brainFloat {
    0%, 100% {
        transform: translateY(0px) scale(1);
    }
    50% {
        transform: translateY(-10px) scale(1.05);
    }
}

.brain-core {
    position: absolute;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
    border-radius: 50%;
    box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
    overflow: hidden;
}

.brain-core::before {
    content: '';
    position: absolute;
    top: 20%;
    left: 20%;
    width: 60%;
    height: 60%;
    background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 70%);
    border-radius: 50%;
    animation: brainPulse 2s ease-in-out infinite;
}

@keyframes brainPulse {
    0%, 100% {
        opacity: 0.3;
        transform: scale(1);
    }
    50% {
        opacity: 0.7;
        transform: scale(1.1);
    }
}

.brain-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 48px;
    color: white;
    text-shadow: 0 2px 10px rgba(0,0,0,0.3);
    animation: iconGlow 3s ease-in-out infinite;
}

@keyframes iconGlow {
    0%, 100% {
        text-shadow: 0 2px 10px rgba(0,0,0,0.3);
    }
    50% {
        text-shadow: 0 2px 20px rgba(255,255,255,0.5), 0 0 30px rgba(102, 126, 234, 0.8);
    }
}

/* 思维连接线动画 */
.neural-network {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.neural-line {
    position: absolute;
    background: linear-gradient(90deg, transparent 0%, rgba(102, 126, 234, 0.6) 50%, transparent 100%);
    border-radius: 2px;
    opacity: 0;
    animation: neuralPulse 3s ease-in-out infinite;
}

.neural-line:nth-child(1) {
    top: 30%;
    left: -20%;
    width: 60px;
    height: 2px;
    transform: rotate(45deg);
    animation-delay: 0s;
}

.neural-line:nth-child(2) {
    top: 60%;
    right: -20%;
    width: 50px;
    height: 2px;
    transform: rotate(-30deg);
    animation-delay: 0.5s;
}

.neural-line:nth-child(3) {
    bottom: 20%;
    left: -15%;
    width: 45px;
    height: 2px;
    transform: rotate(-45deg);
    animation-delay: 1s;
}

.neural-line:nth-child(4) {
    top: 20%;
    right: -15%;
    width: 55px;
    height: 2px;
    transform: rotate(60deg);
    animation-delay: 1.5s;
}

@keyframes neuralPulse {
    0%, 70% {
        opacity: 0;
        transform: scale(0.5) rotate(var(--rotation, 0deg));
    }
    10%, 60% {
        opacity: 1;
        transform: scale(1) rotate(var(--rotation, 0deg));
    }
    100% {
        opacity: 0;
        transform: scale(0.5) rotate(var(--rotation, 0deg));
    }
}

/* 思考气泡动画 */
.thought-bubbles {
    position: absolute;
    top: -20px;
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    height: 60px;
}

.thought-bubble {
    position: absolute;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 50%;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    opacity: 0;
    animation: bubbleFloat 4s ease-in-out infinite;
}

.thought-bubble:nth-child(1) {
    width: 12px;
    height: 12px;
    bottom: 0;
    left: 45%;
    animation-delay: 0s;
}

.thought-bubble:nth-child(2) {
    width: 18px;
    height: 18px;
    bottom: 15px;
    left: 35%;
    animation-delay: 0.3s;
}

.thought-bubble:nth-child(3) {
    width: 24px;
    height: 24px;
    bottom: 35px;
    left: 25%;
    animation-delay: 0.6s;
}

@keyframes bubbleFloat {
    0%, 80% {
        opacity: 0;
        transform: translateY(20px) scale(0.5);
    }
    10%, 70% {
        opacity: 1;
        transform: translateY(0px) scale(1);
    }
    100% {
        opacity: 0;
        transform: translateY(-10px) scale(0.8);
    }
}

/* 进度环动画 */
.progress-ring {
    position: absolute;
    top: -10px;
    left: -10px;
    width: 140px;
    height: 140px;
}

.progress-ring-circle {
    fill: none;
    stroke: rgba(102, 126, 234, 0.3);
    stroke-width: 3;
    stroke-linecap: round;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
    animation: progressRotate 8s linear infinite;
}

.progress-ring-progress {
    fill: none;
    stroke: #667eea;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-dasharray: 440;
    stroke-dashoffset: 440;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
    animation: progressFill 8s ease-in-out infinite;
}

@keyframes progressRotate {
    0% {
        transform: rotate(-90deg);
    }
    100% {
        transform: rotate(270deg);
    }
}

@keyframes progressFill {
    0%, 20% {
        stroke-dashoffset: 440;
    }
    80%, 100% {
        stroke-dashoffset: 0;
    }
}

/* 文字生成效果 */
.text-generation {
    position: absolute;
    bottom: -40px;
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    text-align: center;
}

.generating-text {
    color: #667eea;
    font-size: 14px;
    font-weight: 600;
    margin-bottom: 8px;
    opacity: 0;
    animation: textFade 4s ease-in-out infinite;
}

.generating-dots {
    color: #667eea;
    font-size: 16px;
    letter-spacing: 2px;
    animation: dotsAnimation 2s ease-in-out infinite;
}

@keyframes textFade {
    0%, 20% {
        opacity: 0;
        transform: translateY(10px);
    }
    30%, 70% {
        opacity: 1;
        transform: translateY(0px);
    }
    80%, 100% {
        opacity: 0;
        transform: translateY(-10px);
    }
}

@keyframes dotsAnimation {
    0%, 20% {
        opacity: 0.3;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0.3;
    }
}

/* 完成状态动画 */
.ai-brain.completed {
    animation: brainComplete 2s ease-out forwards;
}

.ai-brain.completed .brain-core {
    background: linear-gradient(135deg, #27ae60 0%, #2ecc71 50%, #58d68d 100%);
    animation: completionGlow 1.5s ease-out;
}

.ai-brain.completed .brain-icon::before {
    content: '✓';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 32px;
    color: white;
    animation: checkmarkAppear 1s ease-out;
}

@keyframes brainComplete {
    0% {
        transform: translateY(0px) scale(1);
    }
    50% {
        transform: translateY(-20px) scale(1.2);
    }
    100% {
        transform: translateY(-5px) scale(1.1);
    }
}

@keyframes completionGlow {
    0% {
        box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
    }
    50% {
        box-shadow: 0 12px 48px rgba(39, 174, 96, 0.6);
    }
    100% {
        box-shadow: 0 10px 40px rgba(39, 174, 96, 0.4);
    }
}

@keyframes checkmarkAppear {
    0% {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.3);
    }
    50% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1.3);
    }
    100% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }
}

.progress-container {
    width: 100%;
    height: 6px;
    background: #e9ecef;
    border-radius: 3px;
    margin: 20px 0;
    overflow: hidden;
}

.progress-bar {
    height: 100%;
    background: linear-gradient(90deg, #3498db, #2ecc71);
    border-radius: 3px;
    animation: progressBar 15s ease-in-out infinite;
}

.loading-tips {
    margin-top: 20px;
    padding: 12px;
    background: rgba(52, 152, 219, 0.1);
    border-radius: 8px;
    border-left: 4px solid #3498db;
}

.loading-tips h5 {
    color: #2c3e50;
    margin-bottom: 8px;
    font-size: 1em;
}

.loading-tips p {
    color: #666;
    margin: 0;
    font-size: 0.9em;
    line-height: 1.4;
}

@keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}

/* 表单美化 */
.form-group {
    margin-bottom: 25px;
}

.form-group label {
    display: block;
    margin-bottom: 8px;
    color: #2c3e50;
    font-weight: 600;
    font-size: 14px;
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 12px 16px;
    border: 2px solid #e9ecef;
    border-radius: 10px;
    font-size: 14px;
    transition: all 0.3s ease;
    background: white;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: #667eea;
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
    transform: translateY(-1px);
}

/* 按钮美化 */
.btn {
    padding: 12px 24px;
    border-radius: 10px;
    font-weight: 600;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}

.btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0,0,0,0.15);
}

.btn-primary {
    background: linear-gradient(135deg, #667eea, #764ba2);
    color: white;
}

.btn-success {
    background: linear-gradient(135deg, #27ae60, #229954);
    color: white;
}

.btn-outline-primary {
    background: transparent;
    color: #667eea;
    border: 2px solid #667eea;
}

.btn-outline-primary:hover {
    background: #667eea;
    color: white;
}

.btn-secondary {
    background: linear-gradient(135deg, #95a5a6, #7f8c8d);
    color: white;
}

/* 小尺寸按钮 */
.btn-sm {
    padding: 8px 16px;
    font-size: 13px;
    gap: 6px;
}

.btn-xs {
    padding: 6px 12px;
    font-size: 12px;
    gap: 4px;
}

/* 大纲相关按钮样式 */
.btn-outline-warning {
    background: transparent;
    color: #f39c12;
    border: 2px solid #f39c12;
}

.btn-outline-warning:hover {
    background: #f39c12;
    color: white;
}

.btn-info {
    background: linear-gradient(135deg, #3498db, #2980b9);
    color: white;
}

/* 响应式设计 */
@media (max-width: 768px) {
    .scenarios-hero {
        padding: 30px 15px;
        margin: -20px -15px 30px -15px;
    }

    .scenarios-hero h2 {
        font-size: 1.8em;
    }

    #requirements-section {
        margin: 15px;
        padding: 25px 20px;
    }

    .btn-group-custom {
        flex-direction: column;
        gap: 10px;
    }

    .btn-group-custom a {
        width: 100%;
        justify-content: center;
    }
}
</style>
{% endblock %}

{% block content %}
<!-- 页面头部美化 -->
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 0; margin: -20px -20px 30px -20px; text-align: center; position: relative; overflow: hidden;">
    <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><defs><pattern id=\"dots\" width=\"20\" height=\"20\" patternUnits=\"userSpaceOnUse\"><circle cx=\"10\" cy=\"10\" r=\"1\" fill=\"white\" opacity=\"0.1\"/></pattern></defs><rect width=\"100\" height=\"100\" fill=\"url(%23dots)\"/></svg></div>
    <div style="position: relative; z-index: 1;">
        <h2 style="font-size: 2em; font-weight: 700; margin-bottom: 12px; text-shadow: 0 2px 10px rgba(0,0,0,0.3);">📋 {{ todo_board.title }}</h2>
        <p style="opacity: 0.9; font-size: 1em;">项目ID: <code style="background: rgba(255,255,255,0.2); padding: 4px 10px; border-radius: 6px; font-family: 'Consolas', monospace; font-size: 0.9em;">{{ todo_board.task_id }}</code></p>
    </div>
</div>

    <!-- Requirements Confirmation Section -->
    {% set requirements_stage = todo_board.stages | selectattr('id', 'equalto', 'requirements_confirmation') | first %}
    {% if requirements_stage and requirements_stage.status == 'pending' %}
    <div id="requirements-section" style="max-width: 900px; margin: 15px auto; background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); border-radius: 16px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.08); border: 1px solid rgba(102, 126, 234, 0.15);">
        <div style="text-align: center; margin-bottom: 25px;">
            <div style="display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 12px 20px; border-radius: 40px; margin-bottom: 15px; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.25);">
                <h3 style="margin: 0; font-weight: 600; font-size: 1.1em;">📝 需求确认</h3>
            </div>
            <p style="color: #7f8c8d; margin-bottom: 0; font-size: 1em; line-height: 1.5;">请确认以下信息，AI将根据您的确认生成定制化的PPT内容</p>
        </div>

        <!-- Loading indicator for requirements form -->
        <div id="ai-loading" class="loading-container" style="display: block;">
            <div class="loading-icon">
                <i class="fas fa-cog"></i>
            </div>
            <div class="loading-title">正在准备需求表单</div>
            <div class="progress-container">
                <div class="progress-bar" style="animation-duration: 2s;"></div>
            </div>
            <div class="loading-tips">
                <h5><i class="fas fa-info-circle"></i> 提示</h5>
                <p>请稍候，系统正在为您准备项目需求确认表单...</p>
            </div>
        </div>

        <form id="requirements-form" style="text-align: left; display: none;" enctype="multipart/form-data">

            <!-- Content Source Selection -->
            <div style="margin-bottom: 20px;">
                <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">内容来源选择</label>
                <div style="display: flex; gap: 15px; margin-bottom: 15px;">
                    <label style="display: flex; align-items: center; cursor: pointer;">
                        <input type="radio" name="content_source" value="manual" checked onchange="toggleContentSourceTodo()" style="margin-right: 8px;">
                        <span>手动输入主题</span>
                    </label>
                    <label style="display: flex; align-items: center; cursor: pointer;">
                        <input type="radio" name="content_source" value="file" onchange="toggleContentSourceTodo()" style="margin-right: 8px;">
                        <span>从文件生成</span>
                    </label>
                </div>
            </div>

            <!-- File Upload Section (hidden by default) -->
            <div id="file-upload-section-todo" style="display: none; margin-bottom: 20px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef;">
                <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">📁 上传文件 (支持多文件)</label>
                <input type="file" id="file_upload_todo" name="file_upload" accept=".pdf,.docx,.txt,.md,.jpg,.jpeg,.png,.xlsx,.csv"
                       multiple
                       style="width: 100%; padding: 8px; border: 2px dashed #3498db; background: #f8f9fa; border-radius: 6px;">
                <small style="color: #7f8c8d; display: block; margin-top: 5px;">
                    📌 支持同时选择多个文件 | 支持 PDF、DOCX、TXT、MD 等格式 | 单个文件最大 100MB
                </small>

                <!-- Multiple Files List Display -->
                <div id="selected-files-list-todo" style="margin-top: 10px; display: none;">
                    <div style="background: white; padding: 10px; border-radius: 6px; border: 1px solid #e0e0e0;">
                        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
                            <strong style="color: #2c3e50;">已选择的文件：</strong>
                            <button type="button" onclick="clearAllFiles()"
                                    style="padding: 4px 12px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;">
                                清除所有
                            </button>
                        </div>
                        <div id="files-list-container-todo" style="max-height: 200px; overflow-y: auto;">
                            <!-- Files will be listed here -->
                        </div>
                    </div>
                </div>

                <!-- File Processing Options -->
                <div id="file-processing-options-todo" style="margin-top: 15px; padding: 15px; background: white; border-radius: 8px; border: 1px solid #e9ecef; display: none;">
                    <h6 style="margin-bottom: 10px; color: #2c3e50;">文件处理选项</h6>

                    <div style="display: flex; flex-wrap: wrap; gap: 15px;">
                        <!-- PDF专用处理方式选项 -->
                        <div id="pdf-processing-mode-todo" style="display: none; flex: 1; min-width: 200px;">
                            <label style="display: block; margin-bottom: 5px; color: #2c3e50; font-weight: normal;">处理方式：</label>
                            <select name="file_processing_mode" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
                                <option value="markitdown">标准处理 (MarkItDown)</option>
                                <option value="magic_pdf">高质量处理 (Mineru)</option>
                            </select>
                        </div>

                        <!-- 通用解析深度选项 -->
                        <div style="flex: 1; min-width: 200px;">
                            <label style="display: block; margin-bottom: 5px; color: #2c3e50; font-weight: normal;">解析深度：</label>
                            <select name="content_analysis_depth" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
                                <option value="fast" selected>快速解析</option>
                                <option value="standard">标准解析</option>
                                <option value="deep">深度解析</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>

            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
                <div>
                    <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">主题 (Topic)</label>
                    <input type="text" id="topic" name="topic" value="{{ todo_board.title.split(' - ')[0] if ' - ' in todo_board.title else todo_board.title }}"
                           style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px;" required>
                    <small style="color: #7f8c8d; font-size: 12px; margin-top: 5px; display: block;">文件上传时可留空，将自动从文件提取标题</small>
                </div>
                <div>
                    <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">目标受众 (Target Audience)</label>
                    <div style="margin-bottom: 10px;">
                        <select id="audience_type" name="audience_type" style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px;" onchange="toggleCustomAudience()" required>
                            <option value="">请选择目标受众</option>
                            <option value="企业管理层">企业管理层</option>
                            <option value="技术团队">技术团队</option>
                            <option value="销售团队">销售团队</option>
                            <option value="学生群体">学生群体</option>
                            <option value="学术研究者">学术研究者</option>
                            <option value="投资人">投资人</option>
                            <option value="客户群体">客户群体</option>
                            <option value="培训学员">培训学员</option>
                            <option value="项目团队">项目团队</option>
                            <option value="行业专家">行业专家</option>
                            <option value="普通大众">普通大众</option>
                            <option value="自定义">自定义受众</option>
                        </select>
                    </div>
                    <!-- 自定义受众输入框 -->
                    <div id="custom-audience-section" style="display: none;">
                        <input type="text" id="custom_audience" name="custom_audience"
                               placeholder="请描述您的目标受众，例如：初级程序员、产品经理、高中生等..."
                               style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px;">
                        <small style="color: #7f8c8d; font-size: 12px; margin-top: 5px; display: block;">详细描述您的目标受众特征，AI将据此调整内容深度和表达方式</small>
                    </div>
                </div>
            </div>





            <div style="margin-bottom: 25px;">
                <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">PPT页数设置 (Page Count)</label>
                <p style="font-size: 12px; color: #7f8c8d; margin-bottom: 15px;">选择PPT的页数生成方式：</p>
                <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;">
                    <div class="page-count-option active" data-mode="ai_decide" style="border: 2px solid #3498db; border-radius: 10px; padding: 15px; cursor: pointer; text-align: center; transition: all 0.3s ease;">
                        <div style="font-size: 24px; margin-bottom: 8px;">🤖</div>
                        <h5 style="color: #2c3e50; margin-bottom: 5px;">AI智能决定</h5>
                        <p style="font-size: 12px; color: #7f8c8d;">AI根据内容深度和逻辑结构自主决定最合适的页数</p>
                    </div>
                    <div class="page-count-option" data-mode="custom_range" style="border: 2px solid #ddd; border-radius: 10px; padding: 15px; cursor: pointer; text-align: center; transition: all 0.3s ease;">
                        <div style="font-size: 24px; margin-bottom: 8px;">📊</div>
                        <h5 style="color: #2c3e50; margin-bottom: 5px;">自定义范围</h5>
                        <p style="font-size: 12px; color: #7f8c8d;">在指定范围内生成PPT页数</p>
                    </div>
                </div>
                <input type="hidden" id="page_count_mode" name="page_count_mode" value="ai_decide">

                <!-- Custom range section (hidden by default) -->
                <div id="custom-range-section" style="display: none; margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef;">
                    <div style="display: flex; gap: 15px; align-items: center;">
                        <div style="flex: 1;">
                            <label style="display: block; margin-bottom: 5px; color: #2c3e50; font-weight: bold;">最少页数</label>
                            <input type="number" id="min_pages" name="min_pages" value="8" min="5" max="50"
                                   style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px;">
                        </div>
                        <div style="flex: 1;">
                            <label style="display: block; margin-bottom: 5px; color: #2c3e50; font-weight: bold;">最多页数</label>
                            <input type="number" id="max_pages" name="max_pages" value="15" min="5" max="50"
                                   style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px;">
                        </div>
                    </div>
                    <p style="font-size: 12px; color: #7f8c8d; margin-top: 10px; margin-bottom: 0;">
                        建议范围：5-50页，AI会在此范围内生成最合适的页数
                    </p>
                </div>
            </div>

            <div style="margin-bottom: 25px;">
                <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">PPT风格 (Style)</label>
                <p style="font-size: 12px; color: #7f8c8d; margin-bottom: 15px;">选择适合您内容的PPT风格：</p>
                <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 15px;">
                    <div class="style-option" data-style="general" style="border: 2px solid #ddd; border-radius: 10px; padding: 15px; cursor: pointer; text-align: center; transition: all 0.3s ease;">
                        <div style="font-size: 24px; margin-bottom: 8px;">📋</div>
                        <h5 style="color: #2c3e50; margin-bottom: 5px;">通用场景</h5>
                        <p style="font-size: 12px; color: #7f8c8d;">适用于商务汇报、学术演讲等通用场景</p>
                    </div>
                    <div class="style-option" data-style="keynote" style="border: 2px solid #ddd; border-radius: 10px; padding: 15px; cursor: pointer; text-align: center; transition: all 0.3s ease;">
                        <div style="font-size: 24px; margin-bottom: 8px;">🎯</div>
                        <h5 style="color: #2c3e50; margin-bottom: 5px;">发布会</h5>
                        <p style="font-size: 12px; color: #7f8c8d;">Apple风格发布会，卡片式布局，科技感强</p>
                    </div>
                    <div class="style-option" data-style="custom" style="border: 2px solid #ddd; border-radius: 10px; padding: 15px; cursor: pointer; text-align: center; transition: all 0.3s ease;">
                        <div style="font-size: 24px; margin-bottom: 8px;">🎨</div>
                        <h5 style="color: #2c3e50; margin-bottom: 5px;">自定义风格</h5>
                        <p style="font-size: 12px; color: #7f8c8d;">使用自定义提示词定制独特风格</p>
                    </div>
                </div>
                <input type="hidden" id="ppt_style" name="ppt_style" value="general" required>

                <!-- Custom style prompt input (hidden by default) -->
                <div id="custom-style-section" style="display: none; margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef;">
                    <label style="display: block; margin-bottom: 8px; color: #2c3e50; font-weight: bold;">自定义风格提示词</label>
                    <textarea id="custom_style_prompt" name="custom_style_prompt"
                              style="width: 100%; height: 120px; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; resize: vertical;"
                              placeholder="请输入您希望的PPT风格描述，例如：简约现代风格，使用蓝色主题，卡片式布局..."></textarea>
                    <p style="font-size: 12px; color: #7f8c8d; margin-top: 5px;">详细描述您期望的PPT风格，AI将根据您的描述生成相应的设计</p>
                </div>
            </div>

            <div style="text-align: center;">
                <button type="submit" id="confirm-requirements-btn"
                        style="background: #27ae60; color: white; border: none; padding: 15px 30px; border-radius: 8px; font-size: 16px; cursor: pointer; font-weight: bold;">
                    🚀 确认需求并跳转到大纲生成
                </button>
            </div>
        </form>
    </div>
    {% endif %}

<!-- Project Actions -->
<div style="text-align: center; margin-bottom: 40px;">
    <div style="display: inline-flex; gap: 12px; flex-wrap: wrap; justify-content: center; background: white; padding: 20px; border-radius: 16px; box-shadow: 0 8px 25px rgba(0,0,0,0.08);">
        <a href="/projects/{{ todo_board.task_id }}" style="background: linear-gradient(135deg, #3498db, #2980b9); color: white; text-decoration: none; padding: 10px 20px; border-radius: 10px; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 3px 12px rgba(52, 152, 219, 0.25); display: flex; align-items: center; gap: 6px; font-size: 0.9em;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 16px rgba(52, 152, 219, 0.35)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 3px 12px rgba(52, 152, 219, 0.25)'">
            📊 项目详情
        </a>

        {% if todo_board.overall_progress >= 100 %}
        <a href="/projects/{{ todo_board.task_id }}/preview" target="_blank" style="background: linear-gradient(135deg, #27ae60, #229954); color: white; text-decoration: none; padding: 10px 20px; border-radius: 10px; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 3px 12px rgba(39, 174, 96, 0.25); display: flex; align-items: center; gap: 6px; font-size: 0.9em;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 16px rgba(39, 174, 96, 0.35)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 3px 12px rgba(39, 174, 96, 0.25)'">
            🔍 预览 PPT
        </a>
        <a href="/projects/{{ todo_board.task_id }}/edit" target="_blank" style="background: linear-gradient(135deg, #e74c3c, #c0392b); color: white; text-decoration: none; padding: 10px 20px; border-radius: 10px; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 3px 12px rgba(231, 76, 60, 0.25); display: flex; align-items: center; gap: 6px; font-size: 0.9em;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 16px rgba(231, 76, 60, 0.35)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 3px 12px rgba(231, 76, 60, 0.25)'">
            ✏️ 编辑 PPT
        </a>
        {% endif %}

        <a href="/projects" style="background: linear-gradient(135deg, #95a5a6, #7f8c8d); color: white; text-decoration: none; padding: 10px 20px; border-radius: 10px; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 3px 12px rgba(149, 165, 166, 0.25); display: flex; align-items: center; gap: 6px; font-size: 0.9em;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 5px 16px rgba(149, 165, 166, 0.35)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 3px 12px rgba(149, 165, 166, 0.25)'">
            📋 返回项目列表
        </a>
    </div>
</div>

<!-- Task execution is now handled directly in the stage cards -->

<style>
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

@keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0; }
}

.todo-stage {
    transition: all 0.3s ease;
}

.todo-stage:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px rgba(0,0,0,0.15);
}

.btn {
    transition: all 0.3s ease;
}

.btn:hover {
    transform: translateY(-1px);
}

.btn-stream:hover {
    background: #2980b9 !important;
    transform: scale(1.05);
}

.task-item {
    transition: all 0.3s ease;
}

.task-item.active {
    background: #e8f4fd !important;
    border-left: 4px solid #3498db;
}

.output-cursor {
    display: inline-block;
}

.output-cursor.hidden {
    display: none;
}

.style-option {
    transition: all 0.3s ease;
}

.style-option:hover {
    border-color: #3498db !important;
    transform: translateY(-2px);
    box-shadow: 0 4px 15px rgba(52, 152, 219, 0.2);
}

.style-option.selected {
    border-color: #3498db !important;
    background: #e8f4fd !important;
    transform: translateY(-1px);
    box-shadow: 0 2px 10px rgba(52, 152, 219, 0.3);
}

.page-count-option {
    transition: all 0.3s ease;
}

.page-count-option:hover {
    border-color: #3498db !important;
    transform: translateY(-2px);
    box-shadow: 0 4px 15px rgba(52, 152, 219, 0.2);
}

.page-count-option.active {
    border-color: #3498db !important;
    background: #e8f4fd !important;
    transform: translateY(-1px);
    box-shadow: 0 2px 10px rgba(52, 152, 219, 0.3);
}
</style>
{% endblock %}

{% block extra_js %}
<script>
let currentProjectId = '{{ todo_board.task_id }}';
let outlineGenerationStarted = false; // 防止重复调用大纲生成

// Page count selection functionality
function initializePageCountSelection() {
    const pageCountOptions = document.querySelectorAll('.page-count-option');
    const pageCountModeInput = document.getElementById('page_count_mode');
    const customRangeSection = document.getElementById('custom-range-section');

    pageCountOptions.forEach(option => {
        option.addEventListener('click', function() {
            // Remove active class from all options
            pageCountOptions.forEach(opt => opt.classList.remove('active'));

            // Add active class to clicked option
            this.classList.add('active');

            // Update hidden input value
            const selectedMode = this.getAttribute('data-mode');
            pageCountModeInput.value = selectedMode;

            // Show/hide custom range section
            if (selectedMode === 'custom_range') {
                customRangeSection.style.display = 'block';
            } else {
                customRangeSection.style.display = 'none';
            }

            // Update visual styles
            updatePageCountStyles();
        });
    });

    // Set default selection
    const defaultOption = document.querySelector('.page-count-option[data-mode="ai_decide"]');
    if (defaultOption) {
        defaultOption.classList.add('active');
    }

    // Initialize visual styles
    updatePageCountStyles();
}

// Update page count option visual styles
function updatePageCountStyles() {
    const pageCountOptions = document.querySelectorAll('.page-count-option');
    pageCountOptions.forEach(option => {
        if (option.classList.contains('active')) {
            option.style.borderColor = '#3498db';
            option.style.background = '#e8f4fd';
        } else {
            option.style.borderColor = '#ddd';
            option.style.background = 'white';
        }
    });
}

// Style selection functionality
function initializeStyleSelection() {
    const styleOptions = document.querySelectorAll('.style-option');
    const pptStyleInput = document.getElementById('ppt_style');
    const customStyleSection = document.getElementById('custom-style-section');

    styleOptions.forEach(option => {
        option.addEventListener('click', function() {
            // Remove selected class from all options
            styleOptions.forEach(opt => opt.classList.remove('selected'));

            // Add selected class to clicked option
            this.classList.add('selected');

            // Update hidden input value
            const selectedStyle = this.getAttribute('data-style');
            pptStyleInput.value = selectedStyle;

            // Show/hide custom style section
            if (selectedStyle === 'custom') {
                customStyleSection.style.display = 'block';
            } else {
                customStyleSection.style.display = 'none';
            }
        });
    });

    // Set default selection
    const defaultOption = document.querySelector('.style-option[data-style="general"]');
    if (defaultOption) {
        defaultOption.classList.add('selected');
    }
}

// Initialize outline display for completed stages
function initializeOutlineDisplay() {
    // Check if outline generation stage is completed and has content
    const outlineStage = document.querySelector('[data-stage-id="outline_generation"]');
    if (outlineStage) {
        const statusIcon = outlineStage.querySelector('.stage-status-icon');
        if (statusIcon && statusIcon.textContent === '✓') {
            // Stage is completed, ensure output area is visible
            const outputDiv = document.getElementById('outline-output-outline_generation');
            if (outputDiv) {
                outputDiv.style.display = 'block';

                // Hide cursor for completed stage
                const cursorDiv = document.getElementById('outline-cursor-outline_generation');
                if (cursorDiv) {
                    cursorDiv.style.display = 'none';
                }
            }
        }
    }
}

// AI大脑思考动画控制函数
let brainAnimationInterval = null;
let activeBrains = new Set();

function startBrainAnimation(prefix = '') {
    const brainId = prefix ? `loading-brain-${prefix}` : 'loading-brain';
    const brain = document.getElementById(brainId);

    if (!brain) return;

    // 添加到活动大脑集合
    activeBrains.add(prefix);

    // 启动大脑思考状态
    brain.classList.remove('completed');

    // 创建动态文字效果
    function updateThinkingText() {
        if (!activeBrains.has(prefix)) return;

        const textElement = brain.querySelector('.generating-text');
        if (textElement) {
            const texts = [
                '正在分析内容结构',
                '正在构建逻辑框架',
                '正在优化大纲层次',
                '正在完善内容要点',
                '正在生成PPT大纲'
            ];

            const randomText = texts[Math.floor(Math.random() * texts.length)];
            textElement.textContent = randomText;
        }
    }

    // 每3秒更新思考文字
    updateThinkingText();
    const textInterval = setInterval(updateThinkingText, 3000);

    // 存储定时器引用
    if (!brainAnimationInterval) {
        brainAnimationInterval = {};
    }
    brainAnimationInterval[prefix] = textInterval;
}

function stopBrainAnimation(prefix = '') {
    const brainId = prefix ? `loading-brain-${prefix}` : 'loading-brain';
    const brain = document.getElementById(brainId);

    // 从活动大脑集合中移除
    activeBrains.delete(prefix);

    if (brain) {
        brain.classList.add('completed');

        // 更新完成文字
        const textElement = brain.querySelector('.generating-text');
        if (textElement) {
            textElement.textContent = '大纲生成完成';
        }

        const dotsElement = brain.querySelector('.generating-dots');
        if (dotsElement) {
            dotsElement.textContent = '✓';
        }
    }

    // 清除文字更新定时器
    if (brainAnimationInterval && brainAnimationInterval[prefix]) {
        clearInterval(brainAnimationInterval[prefix]);
        delete brainAnimationInterval[prefix];
    }
}

// 兼容旧的函数名
function startLoadingAnimation(prefix = '') {
    startBrainAnimation(prefix);
}

function stopLoadingAnimation(prefix = '') {
    stopBrainAnimation(prefix);
}

// 兼容漏斗动画函数名
function startFunnelAnimation(prefix = '') {
    startBrainAnimation(prefix);
}

function stopFunnelAnimation(prefix = '') {
    stopBrainAnimation(prefix);
}

// 兼容书本动画函数名
function startBookAnimation(prefix = '') {
    startBrainAnimation(prefix);
}

function stopBookAnimation(prefix = '') {
    stopBrainAnimation(prefix);
}



// 显示成功完成动画
function showBrainCompletion(prefix = '') {
    const brainId = prefix ? `loading-brain-${prefix}` : 'loading-brain';
    const brain = document.getElementById(brainId);

    if (brain) {
        // 停止思考动画并显示完成状态
        stopBrainAnimation(prefix);
        brain.classList.add('completed');

        // 2秒后隐藏整个动画容器
        setTimeout(() => {
            if (brain.parentNode && brain.parentNode.parentNode) {
                brain.parentNode.parentNode.style.display = 'none';
            }
        }, 2000);
    }
}

// 兼容旧的函数名
function showBookCompletion(prefix = '') {
    showBrainCompletion(prefix);
}

function showFunnelCompletion(prefix = '') {
    showBrainCompletion(prefix);
}

// Handle requirements form submission and AI suggestions loading
document.addEventListener('DOMContentLoaded', function() {
    // Initialize outline display if already completed
    initializeOutlineDisplay();

    // Initialize page count selection
    initializePageCountSelection();

    // Initialize style selection
    initializeStyleSelection();

    // Check if we should auto-start outline generation
    checkAutoStartOutline();

    // 直接显示需求表单，不再加载AI建议
    showRequirementsForm();

    const requirementsForm = document.getElementById('requirements-form');
    if (requirementsForm) {
        requirementsForm.addEventListener('submit', async function(e) {
            e.preventDefault();

            const formData = new FormData(requirementsForm);
            const confirmBtn = document.getElementById('confirm-requirements-btn');

            const requirementsSection = document.getElementById('requirements-section');
            if (requirementsSection) {
                requirementsSection.style.display = 'none';
            }

            
            showOutlineSection();

            
            try {
                const response = await fetch(`/projects/${currentProjectId}/confirm-requirements`, {
                    method: 'POST',
                    body: formData
                });

                const result = await response.json();

                if (response.ok && result.status === 'success') {
                    
                    setTimeout(() => {
                        const contentSource = document.querySelector('input[name="content_source"]:checked');
                        if (contentSource && contentSource.value === 'file') {
                            
                            startFileOutlineGeneration();
                        } else {
                            
                            startOutlineGenerationNew();
                        }
                    }, 1000); 
                } else {
                    console.error('Requirements confirmation failed:', result.message);
                    
                    alert('需求确认失败: ' + (result.message || '未知错误'));
                    
                    const requirementsSection = document.getElementById('requirements-section');
                    const outlineSection = document.getElementById('outline-section');
                    if (requirementsSection) requirementsSection.style.display = 'block';
                    if (outlineSection) outlineSection.style.display = 'none';
                }
            } catch (error) {
                console.error('Error confirming requirements:', error);
                alert('需求确认失败: ' + error.message);
                
                const requirementsSection = document.getElementById('requirements-section');
                const outlineSection = document.getElementById('outline-section');
                if (requirementsSection) requirementsSection.style.display = 'block';
                if (outlineSection) outlineSection.style.display = 'none';
            }
        });
    }
});

// Check if we should auto-start outline generation
function checkAutoStartOutline() {
    // 防止重复调用
    if (outlineGenerationStarted) {
        console.log('Outline generation already started, skipping auto-start check...');
        return;
    }

    // Check if outline section is visible and outline generation should start
    const outlineSection = document.getElementById('outline-section');
    if (outlineSection && outlineSection.style.display !== 'none') {
        // Check if outline generation is in running state
        const outlineCursor = document.getElementById('outline-cursor');
        if (outlineCursor && outlineCursor.style.display !== 'none') {
            // Auto-start outline generation
            setTimeout(() => {
                startOutlineGenerationNew();
            }, 500);
        }
    }
}

// Show outline section
function showOutlineSection() {
    // Create and show outline section if it doesn't exist
    let outlineSection = document.getElementById('outline-section');
    if (!outlineSection) {
        outlineSection = document.createElement('div');
        outlineSection.id = 'outline-section';
        outlineSection.style.cssText = 'max-width: 1200px; margin: 20px auto; background: white; border-radius: 15px; padding: 30px; box-shadow: 0 4px 20px rgba(0,0,0,0.1);';

        outlineSection.innerHTML = `
            <div style="text-align: center; margin-bottom: 30px;">
                <h3 style="color: #2c3e50; margin-bottom: 10px;">
                    <i class="fas fa-brain"></i> PPT 大纲生成
                </h3>
                <p style="color: #7f8c8d;">AI正在为您生成专业的PPT大纲，您可以实时查看并编辑</p>
            </div>

            <div style="background: #f8f9fa; border-radius: 10px; padding: 20px; border: 2px solid #e9ecef;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                    <h5 style="color: #2c3e50; margin: 0;">
                        <i class="fas fa-list-alt"></i> 大纲内容
                        <span id="outline-status" style="color: #f39c12; font-size: 0.8em; margin-left: 10px; display: none;">
                        </span>
                    </h5>

                    <div style="display: flex; align-items: center; gap: 10px;">
                        <!-- View Toggle Buttons - Always show -->
                        <div style="display: flex; background: #e9ecef; border-radius: 5px; padding: 2px;">
                            <button id="json-view-btn-new" onclick="switchOutlineViewNew('json')"
                                    style="background: #3498db; color: white; border: none; padding: 5px 10px; border-radius: 3px; font-size: 11px; cursor: pointer; transition: all 0.3s ease;">
                                <i class="fas fa-code"></i> JSON
                            </button>
                            <button id="outline-view-btn-new" onclick="switchOutlineViewNew('outline')"
                                    style="background: transparent; color: #6c757d; border: none; padding: 5px 10px; border-radius: 3px; font-size: 11px; cursor: pointer; transition: all 0.3s ease;">
                                <i class="fas fa-list-ul"></i> 大纲视图
                            </button>
                        </div>

                        <!-- Action Buttons -->
                        <div id="outline-actions" style="display: none;">
                            <button onclick="regenerateOutlineNew()" class="btn btn-sm btn-outline-warning" style="margin-right: 8px;">
                                <i class="fas fa-sync"></i> 重新生成大纲
                            </button>
                            <button onclick="editOutlineNew()" class="btn btn-sm btn-outline-primary" style="margin-right: 8px;">
                                <i class="fas fa-edit"></i> 编辑大纲
                            </button>
                        </div>
                    </div>
                </div>

                <!-- JSON View (default) -->
                <div id="outline-content-display" style="background: white; border: 1px solid #dee2e6; border-radius: 8px; padding: 25px; min-height: 400px; max-height: 600px; overflow-y: auto; font-family: 'Microsoft YaHei', Arial, sans-serif; line-height: 1.8; font-size: 14px; display: block; position: relative;">
                    <div id="outline-placeholder" class="loading-container">
                        <div class="loading-icon">
                            <i class="fas fa-brain"></i>
                        </div>
                        <div class="loading-title">AI正在生成PPT大纲</div>

                        <div class="brain-container">
                            <div class="ai-brain" id="loading-brain-dynamic">
                                <div class="brain-core">
                                    <div class="brain-icon">🧠</div>
                                </div>
                                <svg class="progress-ring" width="140" height="140">
                                    <circle class="progress-ring-circle" cx="70" cy="70" r="70"></circle>
                                    <circle class="progress-ring-progress" cx="70" cy="70" r="70"></circle>
                                </svg>
                                <div class="neural-network">
                                    <div class="neural-line" style="--rotation: 45deg;"></div>
                                    <div class="neural-line" style="--rotation: -30deg;"></div>
                                    <div class="neural-line" style="--rotation: -45deg;"></div>
                                    <div class="neural-line" style="--rotation: 60deg;"></div>
                                </div>
                                <div class="thought-bubbles">
                                    <div class="thought-bubble"></div>
                                    <div class="thought-bubble"></div>
                                    <div class="thought-bubble"></div>
                                </div>
                                <div class="text-generation">
                                    <div class="generating-text">正在分析内容结构</div>
                                    <div class="generating-dots">• • •</div>
                                </div>
                            </div>
                        </div>

                        <div class="loading-tips">
                            <h5><i class="fas fa-lightbulb"></i> 小贴士</h5>
                            <p>AI正在根据您的需求智能生成PPT大纲，包括标题、内容要点和逻辑结构。生成完成后您可以实时编辑和调整。</p>
                        </div>
                    </div>

                    <!-- 光标元素移到内容容器内部，使用绝对定位，默认隐藏 -->
                    <div id="outline-cursor" style="position: absolute; bottom: 20px; right: 20px; display: none; width: 2px; height: 16px; background: #3498db; animation: blink 1s infinite; pointer-events: none;"></div>
                </div>

                <!-- Outline View -->
                <div id="outline-view-new" style="display: none;">
                    <!-- Outline Toolbar -->
                    <div id="outline-toolbar-new" style="background: #f8f9fa; border: 1px solid #dee2e6; border-bottom: none; border-radius: 8px 8px 0 0; padding: 10px; display: flex; align-items: center; justify-content: space-between;">
                        <div style="display: flex; align-items: center; gap: 10px;">
                            <span style="color: #2c3e50; font-weight: 500;">
                                <i class="fas fa-list-ul"></i> PPT大纲预览
                            </span>
                            <span style="color: #7f8c8d; font-size: 12px;">支持简洁视图和详细视图切换</span>
                        </div>
                        <div style="display: flex; gap: 8px;">
                            <button onclick="toggleOutlineViewModeNew()" class="btn btn-xs btn-info" title="切换视图模式">
                                <i class="fas fa-eye"></i> <span id="viewToggleTextNew">详细视图</span>
                            </button>
                            <button onclick="editOutlineNew()" class="btn btn-xs btn-primary" title="修改大纲">
                                <i class="fas fa-edit"></i> 修改大纲
                            </button>
                            <button onclick="exportOutlineJSONNew()" class="btn btn-xs btn-success" title="导出JSON">
                                <i class="fas fa-download"></i> 导出JSON
                            </button>
                        </div>
                    </div>

                    <div id="outline-container-new" style="background: white; border: 1px solid #dee2e6; border-radius: 0 0 8px 8px; height: 500px; overflow-y: auto; position: relative;">
                        <div id="outline-content-new" style="width: 100%; height: 100%; padding: 20px;">
                            <!-- 大纲内容将在这里显示 -->
                        </div>
                        <div id="outline-loading-new" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #7f8c8d; display: none;">
                            <i class="fas fa-spinner fa-spin fa-2x" style="margin-bottom: 15px;"></i>
                            <p>正在加载大纲...</p>
                        </div>
                        <div id="outline-error-new" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #e74c3c; display: none;">
                            <i class="fas fa-exclamation-triangle fa-2x" style="margin-bottom: 15px;"></i>
                            <p>大纲加载失败，请检查数据格式</p>
                        </div>
                        <div id="outline-empty-new" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #7f8c8d; display: block;">
                            <i class="fas fa-list-ul fa-3x" style="margin-bottom: 20px; opacity: 0.3;"></i>
                            <h4 style="color: #95a5a6; margin-bottom: 15px;">大纲视图</h4>
                            <p style="margin-bottom: 20px;">大纲生成完成后，结构化内容将在这里显示</p>
                            <p style="font-size: 14px; color: #bdc3c7;">支持简洁视图和详细视图切换，可编辑大纲内容</p>
                        </div>
                    </div>
                </div>



                <div id="outline-edit-area" style="display: none; margin-top: 20px;">
                    <h6 style="color: #2c3e50; margin-bottom: 15px;">
                        <i class="fas fa-code"></i> 编辑大纲JSON
                    </h6>
                    <div style="background: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 10px; font-size: 12px; color: #6c757d;">
                        <i class="fas fa-info-circle"></i>
                        请编辑JSON格式的大纲。确保JSON格式正确，包含title和slides数组。
                    </div>
                    <textarea id="outline-editor"
                              style="width: 100%; height: 400px; padding: 15px; border: 1px solid #ddd; border-radius: 8px;
                                     font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 13px; line-height: 1.4;
                                     resize: vertical; background: #f8f9fa;"
                              placeholder='请输入JSON格式的大纲，例如：
{
  "title": "PPT标题",
  "slides": [
    {
      "page_number": 1,
      "title": "页面标题",
      "content_points": ["要点1", "要点2"],
      "slide_type": "title"
    }
  ]
}'></textarea>
                    <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px;">
                        <div style="font-size: 12px; color: #6c757d;">
                            <i class="fas fa-lightbulb"></i>
                            提示：slide_type可选值：title, content, agenda, thankyou
                        </div>
                        <div>
                            <button onclick="validateJSON()" class="btn btn-sm btn-info" style="margin-right: 8px;">
                                <i class="fas fa-check-circle"></i> 验证JSON
                            </button>
                            <button onclick="cancelEditOutlineNew()" class="btn btn-sm btn-secondary" style="margin-right: 8px;">
                                <i class="fas fa-times"></i> 取消
                            </button>
                            <button onclick="saveOutlineEditNew()" class="btn btn-sm btn-primary">
                                <i class="fas fa-save"></i> 保存修改
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        `;

        // Insert after requirements section or at the beginning
        const requirementsSection = document.getElementById('requirements-section');
        if (requirementsSection) {
            requirementsSection.parentNode.insertBefore(outlineSection, requirementsSection.nextSibling);
        } else {
            const container = document.querySelector('div[style*="text-align: center"]');
            if (container) {
                container.appendChild(outlineSection);
            }
        }
    }

    outlineSection.style.display = 'block';

    // 启动等待动画
    setTimeout(() => {
        startFunnelAnimation('dynamic');
    }, 100);
}


function showRequirementsForm() {
    try {
        // Hide loading indicator
        const loadingElement = document.getElementById('ai-loading');
        if (loadingElement) {
            loadingElement.style.display = 'none';
        }

        // Show form
        const formElement = document.getElementById('requirements-form');
        if (formElement) {
            formElement.style.display = 'block';
        }


    } catch (error) {
        console.error('Error showing requirements form:', error);

        // Hide loading and show form with default options
        const loadingElement = document.getElementById('ai-loading');
        if (loadingElement) {
            loadingElement.style.display = 'none';
        }

        const formElement = document.getElementById('requirements-form');
        if (formElement) {
            formElement.style.display = 'block';
        }
    }
}

// Populate checkbox options
function populateCheckboxOptions(containerId, options, name) {
    const container = document.getElementById(containerId);
    container.innerHTML = '';

    options.forEach(option => {
        const div = document.createElement('div');
        div.style.cssText = 'padding: 10px; border: 1px solid #ddd; border-radius: 6px; background: white; cursor: pointer; transition: all 0.3s ease;';

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.name = name;
        checkbox.value = option;
        checkbox.id = `${name}_${options.indexOf(option)}`;
        checkbox.style.marginRight = '8px';

        const label = document.createElement('label');
        label.htmlFor = checkbox.id;
        label.textContent = option;
        label.style.cursor = 'pointer';

        div.appendChild(checkbox);
        div.appendChild(label);

        // Add click handler for the entire div
        div.addEventListener('click', function(e) {
            if (e.target !== checkbox) {
                checkbox.checked = !checkbox.checked;
            }
            updateCheckboxStyle(div, checkbox.checked);
        });

        // Add change handler for checkbox
        checkbox.addEventListener('change', function() {
            updateCheckboxStyle(div, this.checked);
        });

        container.appendChild(div);
    });
}

// Populate radio options
function populateRadioOptions(containerId, options, name) {
    const container = document.getElementById(containerId);
    container.innerHTML = '';

    options.forEach(option => {
        const div = document.createElement('div');
        div.style.cssText = 'padding: 10px 15px; border: 1px solid #ddd; border-radius: 6px; background: white; cursor: pointer; transition: all 0.3s ease;';

        const radio = document.createElement('input');
        radio.type = 'radio';
        radio.name = name;
        radio.value = option;
        radio.id = `${name}_${options.indexOf(option)}`;
        radio.style.marginRight = '8px';

        const label = document.createElement('label');
        label.htmlFor = radio.id;
        label.textContent = option;
        label.style.cursor = 'pointer';

        div.appendChild(radio);
        div.appendChild(label);

        // Add click handler for the entire div
        div.addEventListener('click', function(e) {
            if (e.target !== radio) {
                radio.checked = true;
            }
            updateRadioStyles(name);
        });

        // Add change handler for radio
        radio.addEventListener('change', function() {
            updateRadioStyles(name);
        });

        container.appendChild(div);
    });
}

// Update checkbox visual style
function updateCheckboxStyle(div, checked) {
    if (checked) {
        div.style.background = '#e8f4fd';
        div.style.borderColor = '#3498db';
        div.style.transform = 'scale(1.02)';
    } else {
        div.style.background = 'white';
        div.style.borderColor = '#ddd';
        div.style.transform = 'scale(1)';
    }
}

// Update radio button visual styles
function updateRadioStyles(name) {
    const radios = document.querySelectorAll(`input[name="${name}"]`);
    radios.forEach(radio => {
        const div = radio.parentElement;
        if (radio.checked) {
            div.style.background = '#e8f4fd';
            div.style.borderColor = '#3498db';
            div.style.transform = 'scale(1.02)';
        } else {
            div.style.background = 'white';
            div.style.borderColor = '#ddd';
            div.style.transform = 'scale(1)';
        }
    });
}


// Outline editing functions
function editOutline(stageId) {
    const outlineContent = document.getElementById(`outline-content-${stageId}`);
    const outlineEdit = document.getElementById(`outline-edit-${stageId}`);
    const outlineEditor = document.getElementById(`outline-editor-${stageId}`);

    if (outlineContent && outlineEdit && outlineEditor) {
        // Copy current content to editor
        outlineEditor.value = outlineContent.textContent;

        // Hide content, show editor
        outlineContent.parentElement.style.display = 'none';
        outlineEdit.style.display = 'block';
    }
}

function cancelEditOutline(stageId) {
    const outlineContent = document.getElementById(`outline-content-${stageId}`);
    const outlineEdit = document.getElementById(`outline-edit-${stageId}`);

    if (outlineContent && outlineEdit) {
        // Show content, hide editor
        outlineContent.parentElement.style.display = 'block';
        outlineEdit.style.display = 'none';
    }
}



// 重试文件大纲生成函数
function retryFileOutlineGeneration() {
    console.log('Retrying file outline generation');

    // 重置状态
    outlineGenerationStarted = false;

    // 清除错误内容，但保留placeholder div
    const contentDiv = document.getElementById('outline-content-display');
    if (contentDiv) {
        // 只清除非placeholder的子元素
        const children = Array.from(contentDiv.children);
        children.forEach(child => {
            if (child.id !== 'outline-placeholder') {
                child.remove();
            }
        });
    }

    // 重置placeholder div状态
    const placeholderDiv = document.getElementById('outline-placeholder');
    if (placeholderDiv) {
        console.log('Resetting placeholder div for file retry');
        placeholderDiv.style.display = 'none';
        placeholderDiv.className = '';
        placeholderDiv.innerHTML = '';
    } else {
        console.log('Placeholder div not found, creating new one for file retry');
        // 如果找不到，创建一个新的
        const newPlaceholderDiv = document.createElement('div');
        newPlaceholderDiv.id = 'outline-placeholder';
        newPlaceholderDiv.className = 'loading-container';
        contentDiv.appendChild(newPlaceholderDiv);
    }

    // 隐藏操作按钮
    const actionsDiv = document.getElementById('outline-actions');
    if (actionsDiv) {
        actionsDiv.style.display = 'none';
    }

    // 调用生成函数
    startFileOutlineGeneration();
}

// File outline generation function for file uploads (non-streaming)
async function startFileOutlineGeneration() {
    console.log('Starting file outline generation (non-streaming)');

    // 防止重复调用
    if (outlineGenerationStarted) {
        console.log('Outline generation already started, skipping...');
        return;
    }

    const contentDiv = document.getElementById('outline-content-display');
    const cursorDiv = document.getElementById('outline-cursor');
    const statusDiv = document.getElementById('outline-status');
    const placeholderDiv = document.getElementById('outline-placeholder');

    if (!contentDiv) {
        console.error('Outline content div not found');
        return;
    }

    // 标记为已开始
    outlineGenerationStarted = true;

    // 显示增强的加载状态
    if (placeholderDiv) {
        placeholderDiv.innerHTML = `
            <div class="loading-icon">
                <i class="fas fa-file-alt"></i>
            </div>
            <div class="loading-title">正在从文件生成PPT大纲</div>

            <div class="brain-container">
                <div class="ai-brain" id="loading-brain-file">
                    <div class="brain-core">
                        <div class="brain-icon">📄</div>
                    </div>
                    <svg class="progress-ring" width="140" height="140">
                        <circle class="progress-ring-circle" cx="70" cy="70" r="70"></circle>
                        <circle class="progress-ring-progress" cx="70" cy="70" r="70"></circle>
                    </svg>
                    <div class="neural-network">
                        <div class="neural-line" style="--rotation: 45deg;"></div>
                        <div class="neural-line" style="--rotation: -30deg;"></div>
                        <div class="neural-line" style="--rotation: -45deg;"></div>
                        <div class="neural-line" style="--rotation: 60deg;"></div>
                    </div>
                    <div class="thought-bubbles">
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                    </div>
                    <div class="text-generation">
                        <div class="generating-text">正在解析文件内容</div>
                        <div class="generating-dots">• • •</div>
                    </div>
                </div>
            </div>

            <div class="loading-tips">
                <h5><i class="fas fa-lightbulb"></i> 小贴士</h5>
                <p>AI正在智能分析您上传的文件内容，提取关键信息并生成结构化的PPT大纲。</p>
            </div>
        `;
        placeholderDiv.className = 'loading-container';
        placeholderDiv.style.display = 'block';

        // 启动文件处理动画
        startBrainAnimation('file');
    }

    // 隐藏光标（文件生成不需要流式效果）
    if (cursorDiv) {
        cursorDiv.style.display = 'none';
    }

    try {
        // 调用文件大纲生成接口（非流式）
        const response = await fetch(`/projects/${currentProjectId}/generate-file-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            }
        });

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

        const result = await response.json();

        if (result.error || result.status === "error") {
            // 停止加载动画
            stopBookAnimation('file');

            // 显示错误信息和重新生成按钮，但保留placeholder div
            // 先确保placeholder div存在
            let placeholderDiv = document.getElementById('outline-placeholder');
            if (!placeholderDiv) {
                placeholderDiv = document.createElement('div');
                placeholderDiv.id = 'outline-placeholder';
                placeholderDiv.className = 'loading-container';
                contentDiv.appendChild(placeholderDiv);
            }

            // 清除其他内容，只保留placeholder
            const children = Array.from(contentDiv.children);
            children.forEach(child => {
                if (child.id !== 'outline-placeholder') {
                    child.remove();
                }
            });

            // 在placeholder前添加错误信息
            const errorDiv = document.createElement('div');
            errorDiv.innerHTML = `
                <div style="color: #e74c3c; text-align: center; padding: 20px;">
                    <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                    <div style="margin-bottom: 15px;">文件大纲生成失败</div>
                    <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">${result.error || result.message || '未知错误'}</div>
                    <button onclick="retryFileOutlineGeneration()" class="btn btn-warning btn-sm">
                        <i class="fas fa-sync"></i> 重新生成大纲
                    </button>
                </div>
            `;
            contentDiv.insertBefore(errorDiv, placeholderDiv);
            if (placeholderDiv) placeholderDiv.style.display = 'none';

            // 重置标志，允许重试
            outlineGenerationStarted = false;
            return;
        }

        // 停止加载动画
        stopBookAnimation('file');

        // 隐藏加载状态
        if (placeholderDiv) {
            placeholderDiv.style.display = 'none';
        }

        // 一次性显示完整的大纲内容
        if (result.outline_content) {
            // 格式化JSON内容
            let formattedContent;
            try {
                const parsed = JSON.parse(result.outline_content);
                formattedContent = JSON.stringify(parsed, null, 2);
            } catch (e) {
                formattedContent = result.outline_content;
            }

            // 显示格式化的内容 - 使用textContent而不是innerHTML来避免HTML转义问题
            const preElement = document.createElement('pre');
            preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
            preElement.textContent = formattedContent;
            contentDiv.innerHTML = '';
            contentDiv.appendChild(preElement);
        }

        // 重置标志，允许下次生成
        outlineGenerationStarted = false;

        // Show action buttons
        const actionsDiv = document.getElementById('outline-actions');
        if (actionsDiv) {
            actionsDiv.style.display = 'block';
        }

        // 尝试解析并渲染大纲预览
        try {
            const parsedOutline = JSON.parse(result.outline_content);
            if (parsedOutline && parsedOutline.slides) {
                renderOutlinePreview(parsedOutline);
            }
        } catch (e) {
            console.log('大纲内容正在生成中，暂时无法解析为JSON');
        }

        // Show start PPT generation button
        showStartPPTButton();

    } catch (error) {
        console.error('Error generating file outline:', error);

        // 停止加载动画
        stopFunnelAnimation('file');

        // 显示连接错误和重新生成按钮，但保留placeholder div
        // 先确保placeholder div存在
        let placeholderDiv = document.getElementById('outline-placeholder');
        if (!placeholderDiv) {
            placeholderDiv = document.createElement('div');
            placeholderDiv.id = 'outline-placeholder';
            placeholderDiv.className = 'loading-container';
            contentDiv.appendChild(placeholderDiv);
        }

        // 清除其他内容，只保留placeholder
        const children = Array.from(contentDiv.children);
        children.forEach(child => {
            if (child.id !== 'outline-placeholder') {
                child.remove();
            }
        });

        // 在placeholder前添加错误信息
        const errorDiv = document.createElement('div');
        errorDiv.innerHTML = `
            <div style="color: #e74c3c; text-align: center; padding: 20px;">
                <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                <div style="margin-bottom: 15px;">连接失败</div>
                <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">连接错误: ${error.message}</div>
                <button onclick="retryFileOutlineGeneration()" class="btn btn-warning btn-sm">
                    <i class="fas fa-sync"></i> 重新生成大纲
                </button>
            </div>
        `;
        contentDiv.insertBefore(errorDiv, placeholderDiv);
        if (placeholderDiv) placeholderDiv.style.display = 'none';

        // 重置标志，允许重试
        outlineGenerationStarted = false;
    }
}

// 重试大纲生成函数
function retryOutlineGeneration() {
    console.log('Retrying outline generation');

    // 重置状态
    outlineGenerationStarted = false;

    // 清除错误内容，但保留placeholder div
    const contentDiv = document.getElementById('outline-content-display');
    if (contentDiv) {
        // 只清除非placeholder的子元素
        const children = Array.from(contentDiv.children);
        children.forEach(child => {
            if (child.id !== 'outline-placeholder') {
                child.remove();
            }
        });
    }

    // 重置placeholder div状态
    const placeholderDiv = document.getElementById('outline-placeholder');
    if (placeholderDiv) {
        console.log('Resetting placeholder div for retry');
        placeholderDiv.style.display = 'none';
        placeholderDiv.className = '';
        placeholderDiv.innerHTML = '';
    } else {
        console.log('Placeholder div not found, creating new one');
        // 如果找不到，创建一个新的
        const newPlaceholderDiv = document.createElement('div');
        newPlaceholderDiv.id = 'outline-placeholder';
        newPlaceholderDiv.className = 'loading-container';
        contentDiv.appendChild(newPlaceholderDiv);
    }

    // 隐藏操作按钮
    const actionsDiv = document.getElementById('outline-actions');
    if (actionsDiv) {
        actionsDiv.style.display = 'none';
    }

    // 调用生成函数
    startOutlineGenerationNew();
}

// New outline generation function for the new UI (non-streaming)
async function startOutlineGenerationNew() {
    console.log('Starting new outline generation (non-streaming)');

    // 防止重复调用
    if (outlineGenerationStarted) {
        console.log('Outline generation already started, skipping...');
        return;
    }

    const contentDiv = document.getElementById('outline-content-display');
    const cursorDiv = document.getElementById('outline-cursor');
    const statusDiv = document.getElementById('outline-status');
    const placeholderDiv = document.getElementById('outline-placeholder');

    if (!contentDiv) {
        console.error('Outline content div not found');
        return;
    }

    // 标记为已开始
    outlineGenerationStarted = true;

    // 显示增强的加载状态
    if (placeholderDiv) {
        console.log('Setting up placeholder div for outline generation');
        placeholderDiv.innerHTML = `
            <div class="loading-icon">
                <i class="fas fa-brain"></i>
            </div>
            <div class="loading-title">AI正在生成PPT大纲</div>

            <div class="brain-container">
                <div class="ai-brain" id="loading-brain-stream">
                    <div class="brain-core">
                        <div class="brain-icon">🧠</div>
                    </div>
                    <svg class="progress-ring" width="140" height="140">
                        <circle class="progress-ring-circle" cx="70" cy="70" r="70"></circle>
                        <circle class="progress-ring-progress" cx="70" cy="70" r="70"></circle>
                    </svg>
                    <div class="neural-network">
                        <div class="neural-line" style="--rotation: 45deg;"></div>
                        <div class="neural-line" style="--rotation: -30deg;"></div>
                        <div class="neural-line" style="--rotation: -45deg;"></div>
                        <div class="neural-line" style="--rotation: 60deg;"></div>
                    </div>
                    <div class="thought-bubbles">
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                    </div>
                    <div class="text-generation">
                        <div class="generating-text">正在生成PPT大纲</div>
                        <div class="generating-dots">• • •</div>
                    </div>
                </div>
            </div>

            <div class="loading-tips">
                <h5><i class="fas fa-lightbulb"></i> 小贴士</h5>
                <p>AI正在根据您的需求智能生成PPT大纲，包括标题、内容要点和逻辑结构。生成完成后将一次性显示完整大纲，您可以编辑和调整。</p>
            </div>
        `;
        placeholderDiv.className = 'loading-container';
        placeholderDiv.style.display = 'block';
        console.log('Placeholder div set up, starting brain animation');

        // 启动动画
        startBrainAnimation('stream');
        console.log('Brain animation started');
    } else {
        console.error('Placeholder div not found!');
    }

    // 隐藏光标元素（非流式生成不需要）
    if (cursorDiv) {
        cursorDiv.style.display = 'none';
    }

    // Hide status div during generation
    if (statusDiv) {
        statusDiv.style.display = 'none';
    }

    try {
        // 调用非流式大纲生成接口
        const response = await fetch(`/projects/${currentProjectId}/generate-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            }
        });

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

        const result = await response.json();

        if (result.error || result.status === "error") {
            // 停止加载动画
            stopBookAnimation('stream');

            // 显示错误信息和重新生成按钮，但保留placeholder div
            // 先确保placeholder div存在
            let errorPlaceholderDiv = document.getElementById('outline-placeholder');
            if (!errorPlaceholderDiv) {
                errorPlaceholderDiv = document.createElement('div');
                errorPlaceholderDiv.id = 'outline-placeholder';
                errorPlaceholderDiv.className = 'loading-container';
                contentDiv.appendChild(errorPlaceholderDiv);
            }

            // 隐藏加载状态
            errorPlaceholderDiv.style.display = 'none';

            // 清除其他内容，只保留placeholder
            const children = Array.from(contentDiv.children);
            children.forEach(child => {
                if (child.id !== 'outline-placeholder') {
                    child.remove();
                }
            });

            // 在placeholder前添加错误信息
            const errorDiv = document.createElement('div');
            errorDiv.innerHTML = `
                <div style="color: #e74c3c; text-align: center; padding: 20px;">
                    <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                    <div style="margin-bottom: 15px;">大纲生成失败</div>
                    <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">${result.error || result.message || '未知错误'}</div>
                    <button onclick="retryOutlineGeneration()" class="btn btn-warning btn-sm">
                        <i class="fas fa-sync"></i> 重新生成大纲
                    </button>
                </div>
            `;
            contentDiv.insertBefore(errorDiv, errorPlaceholderDiv);
            if (cursorDiv) cursorDiv.style.display = 'none';

            // 重置标志，允许重试
            outlineGenerationStarted = false;
            return;
        }

        // 停止加载动画
        stopBookAnimation('stream');

        // 隐藏加载状态
        if (placeholderDiv) {
            placeholderDiv.style.display = 'none';
        }

        // 一次性显示完整的大纲内容
        if (result.outline_content) {
            // 格式化JSON内容
            let formattedContent;
            try {
                const parsed = JSON.parse(result.outline_content);
                formattedContent = JSON.stringify(parsed, null, 2);
            } catch (e) {
                formattedContent = result.outline_content;
            }

            // 显示格式化的内容
            const preElement = document.createElement('pre');
            preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
            preElement.textContent = formattedContent;
            contentDiv.innerHTML = '';
            contentDiv.appendChild(preElement);
        }

        // 重置标志，允许下次生成
        outlineGenerationStarted = false;

        // Show action buttons
        const actionsDiv = document.getElementById('outline-actions');
        if (actionsDiv) {
            actionsDiv.style.display = 'block';
        }

        // Generate outline view if currently in outline view
        if (currentViewNew === 'outline') {
            setTimeout(() => {
                renderOutlineViewNew();
            }, 500);
        }

        // Show start PPT generation button
        showStartPPTButton();
    } catch (error) {
        console.error('Error streaming outline generation:', error);

        // 停止加载动画
        stopFunnelAnimation('stream');

        // 隐藏加载状态
        if (placeholderDiv) {
            placeholderDiv.style.display = 'none';
        }

        // 显示连接错误和重新生成按钮，但保留placeholder div
        // 先确保placeholder div存在
        let placeholderDiv = document.getElementById('outline-placeholder');
        if (!placeholderDiv) {
            placeholderDiv = document.createElement('div');
            placeholderDiv.id = 'outline-placeholder';
            placeholderDiv.className = 'loading-container';
            contentDiv.appendChild(placeholderDiv);
        }

        // 清除其他内容，只保留placeholder
        const children = Array.from(contentDiv.children);
        children.forEach(child => {
            if (child.id !== 'outline-placeholder') {
                child.remove();
            }
        });

        // 在placeholder前添加错误信息
        const errorDiv = document.createElement('div');
        errorDiv.innerHTML = `
            <div style="color: #e74c3c; text-align: center; padding: 20px;">
                <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                <div style="margin-bottom: 15px;">连接失败</div>
                <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">连接错误: ${error.message}</div>
                <button onclick="retryOutlineGeneration()" class="btn btn-warning btn-sm">
                    <i class="fas fa-sync"></i> 重新生成大纲
                </button>
            </div>
        `;
        contentDiv.insertBefore(errorDiv, placeholderDiv);
        if (cursorDiv) cursorDiv.style.display = 'none';
        // Keep status div hidden

        // 重置标志，允许重试
        outlineGenerationStarted = false;
    }
}

// 显示自定义需求输入弹窗
function showCustomRequirementsModal() {
    return new Promise((resolve) => {
        // 创建遮罩层
        const overlay = document.createElement('div');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 10000;
        `;
        
        // 创建弹窗
        const modal = document.createElement('div');
        modal.style.cssText = `
            background: white;
            border-radius: 8px;
            padding: 24px;
            max-width: 500px;
            width: 90%;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        `;
        
        modal.innerHTML = `
            <h4 style="margin-top: 0; margin-bottom: 16px; color: #333;">
                <i class="fas fa-magic" style="color: #3498db; margin-right: 8px;"></i>
                重新生成大纲
            </h4>
            <p style="margin-bottom: 16px; color: #666; font-size: 14px;">
                您可以输入额外的自定义需求，或者直接点击“生成”使用原有设置。
            </p>
            <textarea 
                id="custom-requirements-input" 
                placeholder="例如：\n- 需要更多图表和数据展示\n- 增加案例分析部分\n- 突出创新点和亮点"
                style="
                    width: 100%;
                    height: 120px;
                    padding: 12px;
                    border: 1px solid #ddd;
                    border-radius: 4px;
                    font-size: 14px;
                    resize: vertical;
                    font-family: inherit;
                    box-sizing: border-box;
                "
            ></textarea>
            <div style="margin-top: 20px; display: flex; gap: 12px; justify-content: flex-end;">
                <button 
                    id="modal-cancel-btn"
                    style="
                        padding: 10px 20px;
                        border: 1px solid #ddd;
                        border-radius: 4px;
                        background: white;
                        color: #666;
                        cursor: pointer;
                        font-size: 14px;
                    "
                >
                    取消
                </button>
                <button 
                    id="modal-confirm-btn"
                    style="
                        padding: 10px 20px;
                        border: none;
                        border-radius: 4px;
                        background: #3498db;
                        color: white;
                        cursor: pointer;
                        font-size: 14px;
                    "
                >
                    <i class="fas fa-sync" style="margin-right: 6px;"></i>
                    生成
                </button>
            </div>
        `;
        
        overlay.appendChild(modal);
        document.body.appendChild(overlay);
        
        // 获取元素
        const textarea = modal.querySelector('#custom-requirements-input');
        const cancelBtn = modal.querySelector('#modal-cancel-btn');
        const confirmBtn = modal.querySelector('#modal-confirm-btn');
        
        // 自动聚焦到输入框
        setTimeout(() => textarea.focus(), 100);
        
        // 取消按钮
        cancelBtn.onclick = () => {
            document.body.removeChild(overlay);
            resolve(null);
        };
        
        // 确认按钮
        confirmBtn.onclick = () => {
            const value = textarea.value.trim();
            document.body.removeChild(overlay);
            resolve(value);
        };
        
        // 点击遮罩层关闭
        overlay.onclick = (e) => {
            if (e.target === overlay) {
                document.body.removeChild(overlay);
                resolve(null);
            }
        };
        
        // 键盘事件
        textarea.onkeydown = (e) => {
            // Ctrl/Cmd + Enter 提交
            if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                e.preventDefault();
                confirmBtn.click();
            }
            // Escape 取消
            if (e.key === 'Escape') {
                e.preventDefault();
                cancelBtn.click();
            }
        };
    });
}

// 重新生成大纲函数
async function regenerateOutlineNew() {
    console.log('Starting outline regeneration');

    // 使用自定义弹窗让用户输入额外需求
    const customRequirements = await showCustomRequirementsModal();
    
    // 如果用户点击取消，返回 null
    if (customRequirements === null) {
        return;
    }

    // 隐藏操作按钮
    const actionsDiv = document.getElementById('outline-actions');
    if (actionsDiv) {
        actionsDiv.style.display = 'none';
    }

    // 隐藏开始PPT生成按钮
    hideStartPPTButton();

    // 确保切换到JSON视图以显示生成过程
    switchOutlineViewNew('json');

    // 清空当前内容并显示加载状态
    const contentDiv = document.getElementById('outline-content-display');

    // 先获取placeholder div引用，然后清空其他内容
    let placeholderDiv = document.getElementById('outline-placeholder');

    if (contentDiv) {
        // 只清除非placeholder的子元素
        const children = Array.from(contentDiv.children);
        children.forEach(child => {
            if (child.id !== 'outline-placeholder') {
                child.remove();
            }
        });

        // 如果placeholder div不存在，创建一个新的
        if (!placeholderDiv) {
            placeholderDiv = document.createElement('div');
            placeholderDiv.id = 'outline-placeholder';
            placeholderDiv.className = 'loading-container';
            contentDiv.appendChild(placeholderDiv);
        }
    }

    if (placeholderDiv) {
        placeholderDiv.style.display = 'block';
        placeholderDiv.innerHTML = `
            <div class="loading-icon">
                <i class="fas fa-brain"></i>
            </div>
            <div class="loading-title">正在重新生成大纲</div>

            <div class="brain-container">
                <div class="ai-brain" id="loading-brain-regenerate">
                    <div class="brain-core">
                        <div class="brain-icon">🧠</div>
                    </div>
                    <svg class="progress-ring" width="140" height="140">
                        <circle class="progress-ring-circle" cx="70" cy="70" r="70"></circle>
                        <circle class="progress-ring-progress" cx="70" cy="70" r="70"></circle>
                    </svg>
                    <div class="neural-network">
                        <div class="neural-line" style="--rotation: 45deg;"></div>
                        <div class="neural-line" style="--rotation: -30deg;"></div>
                        <div class="neural-line" style="--rotation: -45deg;"></div>
                        <div class="neural-line" style="--rotation: 60deg;"></div>
                    </div>
                    <div class="thought-bubbles">
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                        <div class="thought-bubble"></div>
                    </div>
                    <div class="text-generation">
                        <div class="generating-text">正在重新分析内容</div>
                        <div class="generating-dots">• • •</div>
                    </div>
                </div>
            </div>

            <div class="loading-tips">
                <h5><i class="fas fa-lightbulb"></i> 小贴士</h5>
                <p>AI正在重新分析您的需求并生成全新的PPT大纲，请稍候...</p>
            </div>
        `;

        // 启动重新生成动画
        setTimeout(() => {
            startBrainAnimation('regenerate');
        }, 100);
    }

    // 重置生成标志
    outlineGenerationStarted = false;

    // 重置大纲生成阶段状态（不触发页面重新加载）
    try {
        await updateStageStatusSilent('outline_generation', 'running', 0);
    } catch (error) {
        console.warn('Failed to update stage status:', error);
    }

    // 调用专门的重新生成大纲接口，带上自定义需求
    try {
        console.log('Calling regenerate outline API with custom requirements:', customRequirements);
        const response = await fetch(`/projects/${currentProjectId}/regenerate-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                custom_requirements: customRequirements || ''
            })
        });

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

        const result = await response.json();

        if (result.error || result.status === "error") {
            // 显示错误信息
            if (contentDiv) {
                contentDiv.innerHTML = `<div style="color: #e74c3c; text-align: center; padding: 20px;">
                    <i class="fas fa-exclamation-triangle"></i> 错误: ${result.error || result.message || '未知错误'}
                </div>`;
            }
            stopBrainAnimation('regenerate');
            if (placeholderDiv) placeholderDiv.style.display = 'none';

            // 重新显示操作按钮
            if (actionsDiv) {
                actionsDiv.style.display = 'block';
            }

            // 重置标志，允许重试
            outlineGenerationStarted = false;
            return;
        }

        // 停止重新生成动画并隐藏加载状态
        stopBrainAnimation('regenerate');
        if (placeholderDiv) {
            placeholderDiv.style.display = 'none';
        }

        // 显示生成的大纲内容
        if (contentDiv && result.outline_content) {
            const preElement = document.createElement('pre');
            preElement.style.cssText = 'white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New", monospace; font-size: 12px; line-height: 1.4; margin: 0; padding: 0; background: transparent; border: none;';
            preElement.textContent = result.outline_content;
            contentDiv.appendChild(preElement);
        }

        // 重置标志，允许下次生成
        outlineGenerationStarted = false;

        // Show action buttons
        if (actionsDiv) {
            actionsDiv.style.display = 'block';
        }

        // Generate outline view if currently in outline view
        if (currentViewNew === 'outline') {
            setTimeout(() => {
                renderOutlineViewNew();
            }, 500);
        }

        // Show start PPT generation button
        showStartPPTButton();
    } catch (error) {
        console.error('Error during outline regeneration:', error);

        // 显示错误信息
        if (contentDiv) {
            contentDiv.innerHTML = `<div style="color: #e74c3c; text-align: center; padding: 20px;">
                <i class="fas fa-exclamation-triangle"></i> 重新生成失败: ${error.message}
            </div>`;
        }

        stopBrainAnimation('regenerate');
        if (placeholderDiv) {
            placeholderDiv.style.display = 'none';
        }

        // 重新显示操作按钮
        if (actionsDiv) {
            actionsDiv.style.display = 'block';
        }

        // 重置标志，允许重试
        outlineGenerationStarted = false;
    }
}

// New outline editing functions for JSON
function editOutlineNew() {
    const contentDiv = document.getElementById('outline-content-display');
    const editArea = document.getElementById('outline-edit-area');
    const editor = document.getElementById('outline-editor');

    if (contentDiv && editArea && editor) {
        // Get current JSON content - 优先从pre元素获取
        let jsonContent = '';
        const preElement = contentDiv.querySelector('pre');
        if (preElement) {
            jsonContent = preElement.textContent || preElement.innerText || '';
        } else {
            // 如果没有pre元素，从整个div获取内容
            jsonContent = contentDiv.textContent || contentDiv.innerText || '';
        }

        // Try to parse and reformat the JSON for better editing
        try {
            const parsed = JSON.parse(jsonContent);
            jsonContent = JSON.stringify(parsed, null, 2);
        } catch (e) {
            console.warn('Content is not valid JSON, using as-is:', e);
        }

        editor.value = jsonContent;

        // Hide content, show editor
        contentDiv.style.display = 'none';
        editArea.style.display = 'block';
    }
}

function cancelEditOutlineNew() {
    const contentDiv = document.getElementById('outline-content-display');
    const editArea = document.getElementById('outline-edit-area');

    if (contentDiv && editArea) {
        // Show content, hide editor
        contentDiv.style.display = 'block';
        editArea.style.display = 'none';
    }
}

// JSON validation function
function validateJSON() {
    const editor = document.getElementById('outline-editor');
    if (!editor) return;

    try {
        const jsonData = JSON.parse(editor.value);

        // Validate required structure
        if (!jsonData.title) {
            throw new Error('缺少必需字段: title');
        }
        if (!jsonData.slides || !Array.isArray(jsonData.slides)) {
            throw new Error('缺少必需字段: slides (必须是数组)');
        }

        // Validate each slide
        for (let i = 0; i < jsonData.slides.length; i++) {
            const slide = jsonData.slides[i];
            if (!slide.title) {
                throw new Error(`第${i+1}个幻灯片缺少title字段`);
            }
            if (!slide.content_points || !Array.isArray(slide.content_points)) {
                throw new Error(`第${i+1}个幻灯片缺少content_points字段 (必须是数组)`);
            }
            if (!slide.slide_type) {
                throw new Error(`第${i+1}个幻灯片缺少slide_type字段`);
            }
        }

        // Format and update editor content
        editor.value = JSON.stringify(jsonData, null, 2);

        alert('✅ JSON格式验证通过！');
        return true;

    } catch (error) {
        alert('❌ JSON格式错误: ' + error.message);
        return false;
    }
}

async function saveOutlineEditNew() {
    const editor = document.getElementById('outline-editor');
    const contentDiv = document.getElementById('outline-content-display');

    if (!editor || !contentDiv) return;

    // Validate JSON before saving
    if (!validateJSON()) {
        return;
    }

    try {
        const response = await fetch(`/projects/${currentProjectId}/update-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                outline_content: editor.value
            })
        });

        if (response.ok) {
            // Update display content with formatted JSON - 使用textContent避免HTML转义问题
            const preElement = document.createElement('pre');
            preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
            preElement.textContent = editor.value;
            contentDiv.innerHTML = '';
            contentDiv.appendChild(preElement);

            // Hide editor, show content
            cancelEditOutlineNew();

            // Show success message
            alert('✅ 大纲已更新');

            // 立即更新大纲视图，确保使用最新的数据
            setTimeout(() => {
                // 强制刷新大纲视图，使用编辑器中的最新内容
                try {
                    const parsedOutline = JSON.parse(editor.value);

                    // 如果当前是大纲视图，重新渲染
                    if (currentView === 'outline') {
                        renderOutlineView();
                    }

                    // 如果当前是新的大纲视图，强制使用最新数据重新渲染
                    if (currentViewNew === 'outline') {
                        // 直接传递解析后的大纲数据，避免从DOM重新读取
                        renderOutlineViewNewWithData(parsedOutline);
                    }
                } catch (parseError) {
                    console.error('Failed to parse updated outline:', parseError);
                    // 如果解析失败，仍然尝试常规渲染
                    if (currentView === 'outline') {
                        renderOutlineView();
                    }
                    if (currentViewNew === 'outline') {
                        renderOutlineViewNew();
                    }
                }
            }, 100); // 减少延迟，立即更新
        } else {
            alert('❌ 保存失败，请重试');
        }
    } catch (error) {
        console.error('Error saving outline:', error);
        alert('❌ 保存失败: ' + error.message);
    }
}

function confirmOutlineNew() {
    if (confirm('确认大纲内容？')) {
        // Mark outline as confirmed
        fetch(`/projects/${currentProjectId}/confirm-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            }
        }).then(response => {
            if (response.ok) {
                // Hide edit/confirm buttons and show start PPT button
                const actionsDiv = document.getElementById('outline-actions');
                if (actionsDiv) {
                    actionsDiv.style.display = 'none';
                }

                // Show start PPT generation button
                showStartPPTButton();
            } else {
                alert('确认失败，请重试');
            }
        }).catch(error => {
            console.error('Error confirming outline:', error);
            alert('确认失败: ' + error.message);
        });
    }
}



// Show start PPT generation button
function showStartPPTButton() {
    // Check if button already exists
    let startPPTButton = document.getElementById('start-ppt-button');

    if (!startPPTButton) {
        // Create start PPT button only if it doesn't exist
        const outlineSection = document.getElementById('outline-section');
        if (outlineSection) {
            startPPTButton = document.createElement('div');
            startPPTButton.id = 'start-ppt-button';
            startPPTButton.style.cssText = 'text-align: center; margin-top: 30px; padding: 20px; background: #e8f5e8; border-radius: 10px; border: 2px solid #27ae60;';

            startPPTButton.innerHTML = `
                <button onclick="startPPTGenerationFromOutline()" class="btn btn-success btn-lg" style="padding: 15px 30px; font-size: 18px;">
                    <i class="fas fa-rocket"></i> 开始生成PPT
                </button>
            `;

            // Insert after outline section
            outlineSection.parentNode.insertBefore(startPPTButton, outlineSection.nextSibling);
        }
    }

    if (startPPTButton) {
        startPPTButton.style.display = 'block';
    }
}

// Hide start PPT generation button
function hideStartPPTButton() {
    const startPPTButton = document.getElementById('start-ppt-button');
    if (startPPTButton) {
        startPPTButton.style.display = 'none';
    }
}

// Start PPT generation from outline
function startPPTGenerationFromOutline() {

    if (confirm('确认开始生成PPT？这将跳转到模板选择页面。')) {
        // Redirect to template selection page
        window.location.href = `/projects/${currentProjectId}/template-selection`;
    }
}

// 重试流式大纲生成函数
function retryStreamingOutlineGeneration() {
    console.log('Retrying streaming outline generation');

    // 重置状态 - 这里不需要重置outlineGenerationStarted，因为流式生成有自己的逻辑

    // 清除错误内容
    const stageId = 'outline_generation';
    const contentDiv = document.getElementById(`outline-content-${stageId}`);
    if (contentDiv) {
        contentDiv.innerHTML = '';
        console.log('Cleared streaming outline content for retry');
    } else {
        console.error('Streaming outline content div not found!');
    }

    // 调用生成函数
    startOutlineGeneration();
}

// Start outline generation with streaming
async function startOutlineGeneration() {
    console.log('Starting outline generation with streaming');

    const stageId = 'outline_generation';
    const outputDiv = document.getElementById(`outline-output-${stageId}`);
    const contentDiv = document.getElementById(`outline-content-${stageId}`);
    const cursorDiv = document.getElementById(`outline-cursor-${stageId}`);

    if (!outputDiv || !contentDiv || !cursorDiv) {
        console.error('Outline output elements not found');
        return;
    }

    // Show output area
    outputDiv.style.display = 'block';
    contentDiv.textContent = '';
    cursorDiv.style.display = 'inline-block';

    // Update stage status to running
    const stageElement = document.querySelector(`[data-stage-id="${stageId}"]`);
    if (stageElement) {
        const statusIcon = stageElement.querySelector('.stage-status-icon');
        if (statusIcon) {
            statusIcon.innerHTML = '<div style="display: inline-block; width: 12px; height: 12px; border: 2px solid #f3f3f3; border-top: 2px solid #f39c12; border-radius: 50%; animation: spin 1s linear infinite;"></div>';
        }
    }

    try {
        const response = await fetch(`/projects/${currentProjectId}/outline-stream`);
        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
            const { done, value } = await reader.read();
            if (done) break;

            const chunk = decoder.decode(value);
            const lines = chunk.split('\n');

            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    try {
                        const data = JSON.parse(line.slice(6));

                        if (data.error) {
                            // 显示错误信息和重新生成按钮
                            contentDiv.innerHTML = `
                                <div style="color: #e74c3c; text-align: center; padding: 20px;">
                                    <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                                    <div style="margin-bottom: 15px;">大纲生成失败</div>
                                    <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">${data.error}</div>
                                    <button onclick="retryStreamingOutlineGeneration()" class="btn btn-warning btn-sm">
                                        <i class="fas fa-sync"></i> 重新生成大纲
                                    </button>
                                </div>
                            `;
                            cursorDiv.style.display = 'none';
                            if (stageElement) {
                                const statusIcon = stageElement.querySelector('.stage-status-icon');
                                if (statusIcon) statusIcon.textContent = '❌';
                            }
                            return;
                        }

                        if (data.content) {
                            contentDiv.textContent += data.content;
                            contentDiv.scrollTop = contentDiv.scrollHeight;
                        }

                        if (data.done) {
                            cursorDiv.style.display = 'none';
                            if (stageElement) {
                                const statusIcon = stageElement.querySelector('.stage-status-icon');
                                if (statusIcon) statusIcon.textContent = '✓';
                            }

                            // 格式化JSON内容并用pre元素包装
                            try {
                                const jsonContent = contentDiv.textContent;
                                const parsed = JSON.parse(jsonContent);
                                const formattedContent = JSON.stringify(parsed, null, 2);

                                // 创建pre元素来正确显示JSON
                                const preElement = document.createElement('pre');
                                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                preElement.textContent = formattedContent;
                                contentDiv.innerHTML = '';
                                contentDiv.appendChild(preElement);

                                console.log('Successfully formatted JSON outline with', parsed.slides ? parsed.slides.length : 0, 'slides');
                            } catch (e) {
                                console.warn('Failed to parse JSON content for formatting:', e);
                                // 保持原始内容，但仍然用pre包装
                                const preElement = document.createElement('pre');
                                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                preElement.textContent = contentDiv.textContent;
                                contentDiv.innerHTML = '';
                                contentDiv.appendChild(preElement);
                            }

                            // Update the header to show completion
                            const outputDiv = document.getElementById(`outline-output-${stageId}`);
                            if (outputDiv) {
                                const header = outputDiv.querySelector('h6');
                                if (header && !header.querySelector('.completion-badge')) {
                                    const badge = document.createElement('span');
                                    badge.className = 'completion-badge';
                                    badge.style.cssText = 'color: #27ae60; font-size: 0.8em; margin-left: 10px;';
                                    badge.textContent = '✅ 生成完成';
                                    header.appendChild(badge);
                                }
                            }

                            // 延迟刷新页面，让用户有时间看到格式化的内容
                            setTimeout(() => {
                                window.location.reload();
                            }, 3000);
                            return;
                        }
                    } catch (e) {
                        console.error('Error parsing outline stream data:', e);
                    }
                }
            }
        }
    } catch (error) {
        console.error('Error streaming outline generation:', error);
        // 显示连接错误和重新生成按钮
        contentDiv.innerHTML = `
            <div style="color: #e74c3c; text-align: center; padding: 20px;">
                <i class="fas fa-exclamation-triangle" style="font-size: 24px; margin-bottom: 10px;"></i>
                <div style="margin-bottom: 15px;">连接失败</div>
                <div style="font-size: 14px; margin-bottom: 20px; color: #7f8c8d;">连接错误: ${error.message}</div>
                <button onclick="retryStreamingOutlineGeneration()" class="btn btn-warning btn-sm">
                    <i class="fas fa-sync"></i> 重新生成大纲
                </button>
            </div>
        `;
        cursorDiv.style.display = 'none';
        if (stageElement) {
            const statusIcon = stageElement.querySelector('.stage-status-icon');
            if (statusIcon) statusIcon.textContent = '❌';
        }
    }
}

// Start execution for a complete stage
async function startStageExecution(stageId) {
    console.log(`Starting stage execution for: ${stageId}`);

    // Special handling for outline generation
    if (stageId === 'outline_generation') {
        // 检查是否已经开始了新的大纲生成
        if (outlineGenerationStarted) {
            console.log('Outline generation already started via new method, skipping stage execution...');
            return;
        }
        return startOutlineGeneration();
    }

    const taskItem = document.querySelector(`[data-stage-id="${stageId}"]`);
    if (!taskItem) {
        console.error(`Task item not found for stage: ${stageId}`);
        return;
    }

    // Check if stage is already running or completed
    const stageStatusIcon = taskItem.querySelector('.stage-status-icon');
    if (stageStatusIcon && (stageStatusIcon.textContent === '✓' || stageStatusIcon.innerHTML.includes('spin'))) {
        console.log(`Stage ${stageId} is already running or completed`);
        return;
    }

    const statusIcon = taskItem.querySelector('.task-status');
    const outputDiv = taskItem.querySelector('.task-output');
    const outputContent = taskItem.querySelector('.output-content');
    const outputCursor = taskItem.querySelector('.output-cursor');
    const streamBtn = taskItem.querySelector('.btn-stream');

    // Update UI
    taskItem.classList.add('active');
    statusIcon.textContent = '🔄';
    outputDiv.style.display = 'block';
    outputContent.textContent = '';
    outputCursor.classList.remove('hidden');
    streamBtn.disabled = true;
    streamBtn.textContent = '处理中...';

    // If this is PPT creation stage, show editor button immediately
    if (stageId === 'ppt_creation') {
        // Show the existing editor button if it exists
        const existingEditorBtn = document.getElementById(`editor-btn-${stageId}`);
        if (existingEditorBtn) {
            existingEditorBtn.style.display = 'inline-block';
            console.log('Editor button shown for PPT creation stage');
        } else {
            // Create new editor button if not exists
            const editorBtn = document.createElement('button');
            editorBtn.onclick = openEditor;
            editorBtn.className = 'editor-btn';
            editorBtn.style.cssText = 'background: #27ae60; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 0.8em; cursor: pointer; margin-left: 8px;';
            editorBtn.innerHTML = '<i class="fas fa-edit"></i> 打开编辑器';

            // Insert after the stream button
            if (streamBtn && streamBtn.parentNode) {
                streamBtn.parentNode.insertBefore(editorBtn, streamBtn.nextSibling);
            }

            console.log('Editor button created for PPT creation stage');
        }
    }

    try {
        const response = await fetch(`/projects/${currentProjectId}/stage-stream/${stageId}`);
        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
            const { done, value } = await reader.read();
            if (done) break;

            const chunk = decoder.decode(value);
            const lines = chunk.split('\n');

            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    try {
                        const data = JSON.parse(line.slice(6));

                        if (data.error) {
                            outputContent.textContent = `错误: ${data.error}`;
                            statusIcon.textContent = '❌';
                            streamBtn.disabled = false;
                            streamBtn.textContent = '重试';

                            // If stage is already running or completed, don't show as error
                            if (data.error.includes('already running') || data.error.includes('already completed')) {
                                outputContent.textContent = `提示: ${data.error}`;
                                statusIcon.textContent = '⚠️';
                                streamBtn.style.display = 'none';
                            }
                            break;
                        }

                        if (data.content) {
                            outputContent.textContent += data.content;
                            outputDiv.scrollTop = outputDiv.scrollHeight;
                        }

                        if (data.done) {
                            outputCursor.classList.add('hidden');
                            statusIcon.textContent = '✅';
                            streamBtn.textContent = '完成';
                            streamBtn.style.display = 'none';

                            // 如果是大纲生成阶段，格式化JSON内容
                            if (stageId === 'outline_generation') {
                                try {
                                    const jsonContent = outputContent.textContent;
                                    const parsed = JSON.parse(jsonContent);
                                    const formattedContent = JSON.stringify(parsed, null, 2);

                                    // 创建pre元素来正确显示JSON
                                    const preElement = document.createElement('pre');
                                    preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                    preElement.textContent = formattedContent;
                                    outputContent.innerHTML = '';
                                    outputContent.appendChild(preElement);

                                    console.log('Successfully formatted JSON outline with', parsed.slides ? parsed.slides.length : 0, 'slides');
                                } catch (e) {
                                    console.warn('Failed to parse JSON content for formatting:', e);
                                    // 保持原始内容，但仍然用pre包装
                                    const preElement = document.createElement('pre');
                                    preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                    preElement.textContent = outputContent.textContent;
                                    outputContent.innerHTML = '';
                                    outputContent.appendChild(preElement);
                                }
                            }

                            // If this is PPT creation stage, update editor button text
                            if (stageId === 'ppt_creation') {
                                const existingEditorBtn = taskItem.querySelector('.editor-btn');
                                if (existingEditorBtn) {
                                    existingEditorBtn.innerHTML = '<i class="fas fa-edit"></i> 查看PPT';
                                    console.log('Updated editor button text to "查看PPT"');
                                }
                            }

                            // Refresh the page to show updated progress
                            setTimeout(() => {
                                window.location.reload();
                            }, 2000);
                            break;
                        }
                    } catch (e) {
                        console.error('Error parsing stream data:', e);
                    }
                }
            }
        }
    } catch (error) {
        console.error('Error streaming stage:', error);
        outputContent.textContent = `连接错误: ${error.message}`;
        statusIcon.textContent = '❌';
    } finally {
        streamBtn.disabled = false;
        if (streamBtn.textContent === '处理中...') {
            streamBtn.textContent = '重试';
        }
    }
}

function startStage(stageId) {
    updateStageStatus(stageId, 'running');
}

function completeStage(stageId) {
    updateStageStatus(stageId, 'completed', 100);
}

function retryStage(stageId) {
    updateStageStatus(stageId, 'running', 0);
}

// Continue from a specific stage - reset all subsequent stages and start from the selected stage
async function continueFromStage(stageId) {
    console.log(`Continue from stage: ${stageId}`);

    // Show confirmation dialog
    const confirmMessage = `确定要从"${getStageDisplayName(stageId)}"步骤重新开始吗？\n\n这将重置该步骤及之后的所有步骤，并重新执行工作流程。`;

    if (!confirm(confirmMessage)) {
        return;
    }

    try {
        // Call backend API to reset stages from the selected stage
        const response = await fetch(`/api/projects/${currentProjectId}/continue-from-stage`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                stage_id: stageId
            })
        });

        if (response.ok) {
            const result = await response.json();

            // Show success message
            alert(`已从"${getStageDisplayName(stageId)}"步骤重新开始，正在重新执行工作流程...`);

            // Reload page to show updated status
            setTimeout(() => {
                window.location.reload();
            }, 1000);
        } else {
            const error = await response.json();
            throw new Error(error.detail || '重新开始失败');
        }
    } catch (error) {
        console.error('Error continuing from stage:', error);
        alert('重新开始失败: ' + error.message);
    }
}

// Get display name for stage ID
function getStageDisplayName(stageId) {
    const stageNames = {
        'requirements_confirmation': '需求确认',
        'outline_generation': '大纲生成',
        'theme_configuration': '主题配置',
        'content_enhancement': '内容增强',
        'ppt_creation': 'PPT生成',
        'quality_review': '质量审核'
    };

    return stageNames[stageId] || stageId;
}

async function updateStageStatus(stageId, status, progress = null) {
    try {
        const response = await fetch(`/api/projects/${currentProjectId}/stages/${stageId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                status: status,
                progress: progress
            })
        });

        if (response.ok) {
            // Reload page to show updated status
            setTimeout(() => {
                window.location.reload();
            }, 500);
        } else {
            alert('更新失败，请重试');
        }
    } catch (error) {
        console.error('Error updating stage:', error);
        alert('更新失败: ' + error.message);
    }
}

// Silent version that doesn't reload the page (for regeneration scenarios)
async function updateStageStatusSilent(stageId, status, progress = null) {
    try {
        const response = await fetch(`/api/projects/${currentProjectId}/stages/${stageId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                status: status,
                progress: progress
            })
        });

        if (!response.ok) {
            console.warn('Failed to update stage status silently');
        }
    } catch (error) {
        console.error('Error updating stage silently:', error);
    }
}

// Subtask management functions removed - now using complete stage execution

// Real-time updates
setInterval(async function() {
    try {
        const response = await fetch(`/api/projects/${currentProjectId}/todo`);
        const todoData = await response.json();

        // Update overall progress
        const progressBar = document.querySelector('.overall-progress-bar');
        const progressText = document.querySelector('.overall-progress-text');
        const progressDetails = document.querySelector('.progress-details');

        if (progressBar && progressText && todoData.overall_progress !== undefined) {
            progressBar.style.width = todoData.overall_progress + '%';
            progressText.textContent = `总体进度: ${todoData.overall_progress.toFixed(1)}%`;
        }

        if (progressDetails && todoData.stages && Array.isArray(todoData.stages)) {
            const completedStages = todoData.stages.filter(s => s.status === 'completed').length;
            progressDetails.textContent = `已完成 ${completedStages} / ${todoData.stages.length} 个阶段`;
        }

        // Hide connection error if update is successful
        const errorElement = document.getElementById('connection-error');
        if (errorElement) {
            errorElement.style.display = 'none';
        }

        // Update stage indicators
        if (todoData.stages && Array.isArray(todoData.stages)) {
            todoData.stages.forEach(stage => {
            const stageElement = document.querySelector(`[data-stage-id="${stage.id}"]`);
            if (stageElement) {
                const icon = stageElement.querySelector('.stage-status-icon');
                const progressBar = stageElement.querySelector('.stage-progress-bar');
                const progressText = stageElement.querySelector('.stage-progress-text');
                const taskStatus = stageElement.querySelector('.task-status');

                // Update status icon
                if (stage.status === 'completed') {
                    icon.textContent = '✓';
                    icon.parentElement.style.background = '#27ae60';
                    if (taskStatus) taskStatus.textContent = '✅';

                    // Auto-start outline generation when requirements confirmation is completed
                    if (stage.id === 'requirements_confirmation') {
                        const outlineStage = document.querySelector('[data-stage-id="outline_generation"]');
                        const outlineStatus = outlineStage?.querySelector('.stage-status-icon')?.textContent;
                        if (outlineStatus === '⏳') {
                            console.log('Requirements just completed, starting outline generation');
                            setTimeout(() => {
                                startStageExecution('outline_generation');
                            }, 2000); // Wait 2 seconds for UI to update
                        }
                    }
                } else if (stage.status === 'running') {
                    icon.innerHTML = '<div style="width: 16px; height: 16px; border: 2px solid white; border-top: 2px solid transparent; border-radius: 50%; animation: spin 1s linear infinite;"></div>';
                    icon.parentElement.style.background = '#3498db';
                    if (taskStatus) taskStatus.textContent = '🔄';

                    // Show editor button for PPT creation stage when it starts running
                    if (stage.id === 'ppt_creation') {
                        const editorBtn = document.getElementById(`editor-btn-${stage.id}`);
                        if (editorBtn) {
                            editorBtn.style.display = 'inline-block';
                        }
                    }
                } else if (stage.status === 'failed') {
                    icon.textContent = '✗';
                    icon.parentElement.style.background = '#e74c3c';
                    if (taskStatus) taskStatus.textContent = '❌';
                }

                // Update progress bar
                if (progressBar && progressText && stage.status === 'running') {
                    progressBar.style.width = stage.progress + '%';
                    progressText.textContent = stage.progress.toFixed(1) + '%';
                }
            }
        });
        }

    } catch (error) {
        console.error('Error updating TODO board:', error);
        // Show connection error message
        const errorElement = document.getElementById('connection-error');
        if (errorElement) {
            errorElement.style.display = 'block';
            errorElement.textContent = '连接错误，请刷新页面重试';
        }
    }
}, 3000); // Update every 3 seconds

// Modal functionality removed - using direct stage execution

// Open editor function
function openEditor() {
    console.log(`Opening editor for project: ${currentProjectId}`);
    const editorUrl = `/projects/${currentProjectId}/edit`;
    console.log(`Editor URL: ${editorUrl}`);
    window.open(editorUrl, '_blank');
}

// Auto-start workflow when page loads
document.addEventListener('DOMContentLoaded', function() {
    // Check if we just came from requirements confirmation (URL parameter or session storage)
    const urlParams = new URLSearchParams(window.location.search);
    const fromRequirements = urlParams.get('from_requirements') === 'true' ||
                            sessionStorage.getItem('requirements_just_confirmed') === 'true';

    // Clear the session storage flag
    sessionStorage.removeItem('requirements_just_confirmed');

    // Check requirements confirmation status and outline generation status
    const requirementsStage = document.querySelector('[data-stage-id="requirements_confirmation"]');
    const outlineStage = document.querySelector('[data-stage-id="outline_generation"]');

    const requirementsCompleted = requirementsStage?.querySelector('.stage-status-icon')?.textContent === '✓';
    const outlineStatus = outlineStage?.querySelector('.stage-status-icon')?.textContent;

    // Auto-start outline generation if requirements just confirmed or if requirements completed and outline pending
    if ((fromRequirements || requirementsCompleted) && outlineStatus === '⏳') {
        // Requirements confirmed, automatically start outline generation (second step)
        console.log('Requirements confirmed, starting outline generation automatically');
        // 只有在不是来自需求确认页面时才调用，避免重复调用
        if (!fromRequirements) {
            setTimeout(() => {
                startOutlineGenerationNew();
            }, 1000);
        }
    } else if (!requirementsCompleted) {
        // Check if this is a new project (all stages are pending)
        const stages = document.querySelectorAll('.todo-stage');
        let allPending = true;

        stages.forEach(stage => {
            const statusIcon = stage.querySelector('.stage-status-icon');
            if (statusIcon && statusIcon.textContent !== '⏳') {
                allPending = false;
            }
        });

        if (allPending) {
            // Start the workflow automatically for requirements confirmation
            setTimeout(() => {
                fetch(`/projects/${currentProjectId}/start-workflow`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    }
                }).then(response => {
                    if (response.ok) {
                        console.log('Workflow started automatically');
                    } else {
                        console.error('Failed to start workflow');
                    }
                }).catch(error => {
                    console.error('Error starting workflow:', error);
                });
            }, 2000); // Wait 2 seconds after page load
        }
    }
});

// Sequential stage execution - simplified to not interfere with backend workflow
async function startSequentialStageExecution() {
    console.log('Workflow started automatically');
    // The backend workflow will handle the actual execution
    // Frontend just monitors progress through real-time updates
}

// Execute a single stage and wait for completion
async function executeStageAndWait(stageId) {
    return new Promise((resolve, reject) => {
        const taskItem = document.querySelector(`[data-stage-id="${stageId}"]`);
        if (!taskItem) {
            resolve();
            return;
        }

        const statusIcon = taskItem.querySelector('.task-status');
        const outputDiv = taskItem.querySelector('.task-output');
        const outputContent = taskItem.querySelector('.output-content');
        const outputCursor = taskItem.querySelector('.output-cursor');
        const streamBtn = taskItem.querySelector('.btn-stream');

        // Update UI
        taskItem.classList.add('active');
        statusIcon.textContent = '🔄';
        outputDiv.style.display = 'block';
        outputContent.textContent = '';
        outputCursor.classList.remove('hidden');
        if (streamBtn) {
            streamBtn.disabled = true;
            streamBtn.textContent = '处理中...';
        }

        // Start streaming
        fetch(`/projects/${currentProjectId}/stage-stream/${stageId}`)
            .then(response => response.body.getReader())
            .then(reader => {
                const decoder = new TextDecoder();

                function readStream() {
                    return reader.read().then(({ done, value }) => {
                        if (done) {
                            // Stream completed
                            outputCursor.classList.add('hidden');
                            statusIcon.textContent = '✅';
                            if (streamBtn) {
                                streamBtn.textContent = '完成';
                                streamBtn.disabled = false;
                                streamBtn.style.display = 'none';
                            }

                            // Small delay before resolving to ensure UI updates
                            setTimeout(() => {
                                resolve();
                            }, 500);
                            return;
                        }

                        const chunk = decoder.decode(value);
                        const lines = chunk.split('\n');

                        for (const line of lines) {
                            if (line.startsWith('data: ')) {
                                try {
                                    const data = JSON.parse(line.slice(6));

                                    if (data.error) {
                                        outputContent.textContent = `错误: ${data.error}`;
                                        statusIcon.textContent = '❌';
                                        reject(new Error(data.error));
                                        return;
                                    }

                                    if (data.content) {
                                        outputContent.textContent += data.content;
                                        outputDiv.scrollTop = outputDiv.scrollHeight;
                                    }

                                    if (data.done) {
                                        outputCursor.classList.add('hidden');
                                        statusIcon.textContent = '✅';
                                        if (streamBtn) {
                                            streamBtn.textContent = '完成';
                                            streamBtn.disabled = false;
                                        }

                                        // 如果是大纲生成相关的流式处理，格式化JSON内容
                                        if (stageId === 'outline_generation' || outputContent.textContent.trim().startsWith('{')) {
                                            try {
                                                const jsonContent = outputContent.textContent;
                                                const parsed = JSON.parse(jsonContent);
                                                const formattedContent = JSON.stringify(parsed, null, 2);

                                                // 创建pre元素来正确显示JSON
                                                const preElement = document.createElement('pre');
                                                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                                preElement.textContent = formattedContent;
                                                outputContent.innerHTML = '';
                                                outputContent.appendChild(preElement);

                                                console.log('Successfully formatted JSON content with', parsed.slides ? parsed.slides.length : 0, 'slides');
                                            } catch (e) {
                                                console.warn('Failed to parse JSON content for formatting:', e);
                                                // 保持原始内容，但仍然用pre包装
                                                const preElement = document.createElement('pre');
                                                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                                                preElement.textContent = outputContent.textContent;
                                                outputContent.innerHTML = '';
                                                outputContent.appendChild(preElement);
                                            }
                                        }

                                        resolve();
                                        return;
                                    }
                                } catch (e) {
                                    console.error('Error parsing stream data:', e);
                                }
                            }
                        }

                        return readStream();
                    });
                }

                return readStream();
            })
            .catch(error => {
                console.error('Error streaming subtask:', error);
                outputContent.textContent = `连接错误: ${error.message}`;
                statusIcon.textContent = '❌';
                if (streamBtn) {
                    streamBtn.disabled = false;
                    streamBtn.textContent = '重试';
                }
                reject(error);
            });
    });
}

// Update stage visual status
function updateStageVisualStatus(stageElement, status) {
    const statusIcon = stageElement.querySelector('.stage-status-icon');
    const progressBar = stageElement.querySelector('.stage-progress-bar');

    if (status === 'running') {
        if (statusIcon) statusIcon.textContent = '🔄';
        if (progressBar) progressBar.style.width = '50%';
        stageElement.style.borderLeft = '4px solid #f39c12';
    } else if (status === 'completed') {
        if (statusIcon) statusIcon.textContent = '✅';
        if (progressBar) progressBar.style.width = '100%';
        stageElement.style.borderLeft = '4px solid #27ae60';
    }
}


let currentView = 'outline';
let mindmapData = null;
let selectedNode = null;
let editingNode = null;
let mindmapSvg = null;
let mindmapZoom = null;

// 切换大纲视图（JSON编辑器 vs 大纲视图）
function switchOutlineView(viewType) {
    const jsonView = document.getElementById('json-view');
    const outlineView = document.getElementById('outline-view');
    const jsonBtn = document.getElementById('json-view-btn');
    const outlineBtn = document.getElementById('outline-view-btn');

    if (viewType === 'json') {
        // 切换到JSON视图
        if (jsonView) jsonView.style.display = 'block';
        if (outlineView) outlineView.style.display = 'none';

        // 更新按钮样式
        if (jsonBtn) {
            jsonBtn.style.background = '#3498db';
            jsonBtn.style.color = 'white';
        }
        if (outlineBtn) {
            outlineBtn.style.background = 'transparent';
            outlineBtn.style.color = '#6c757d';
        }

        currentView = 'json';
    } else if (viewType === 'outline') {
        // 切换到大纲视图
        if (jsonView) jsonView.style.display = 'none';
        if (outlineView) outlineView.style.display = 'block';

        // 更新按钮样式
        if (outlineBtn) {
            outlineBtn.style.background = '#3498db';
            outlineBtn.style.color = 'white';
        }
        if (jsonBtn) {
            jsonBtn.style.background = 'transparent';
            jsonBtn.style.color = '#6c757d';
        }

        currentView = 'outline';

        // 渲染大纲视图
        renderOutlineView();
    }
}

// 渲染大纲视图
function renderOutlineView() {
    const outlineContent = getOutlineContent();
    if (!outlineContent) {
        console.log('No outline content available');
        return;
    }

    try {
        const parsedOutline = JSON.parse(outlineContent);
        if (parsedOutline && parsedOutline.slides) {
            renderOutlinePreview(parsedOutline);
        }
    } catch (e) {
        console.log('Failed to parse outline content for view rendering');
    }
}

// 获取大纲内容
function getOutlineContent() {
    const outlineDisplay = document.getElementById('outline-content-display');
    if (!outlineDisplay) return null;

    const preElement = outlineDisplay.querySelector('pre');
    if (preElement) {
        let content = preElement.textContent || preElement.innerText || '';
        return content.trim();
    }

    // 如果没有pre元素，从整个div获取内容并处理HTML实体
    let content = outlineDisplay.textContent || outlineDisplay.innerText || '';
    content = content.replace(/&nbsp;/g, ' ').replace(/\s+/g, ' ');
    return content.trim();
}


// ========== 大纲预览功能 ==========

let isDetailView = false;
let currentOutlineData = null;

// 切换大纲视图（简洁视图 vs 详细视图）
function toggleOutlineView() {
    const compactView = document.getElementById('compactView');
    const detailView = document.getElementById('detailView');
    const toggleText = document.getElementById('viewToggleText');

    if (isDetailView) {
        compactView.style.display = 'block';
        detailView.style.display = 'none';
        toggleText.textContent = '详细视图';
        isDetailView = false;
    } else {
        compactView.style.display = 'none';
        detailView.style.display = 'block';
        toggleText.textContent = '简洁视图';
        isDetailView = true;
    }
}

// 渲染大纲预览
function renderOutlinePreview(outlineData) {
    if (!outlineData) return;

    currentOutlineData = outlineData;

    // 隐藏空状态，显示内容
    const emptyDiv = document.getElementById('outline-empty');
    const loadingDiv = document.getElementById('outline-loading');
    if (emptyDiv) emptyDiv.style.display = 'none';
    if (loadingDiv) loadingDiv.style.display = 'none';

    // 渲染简洁视图
    renderCompactView(outlineData);

    // 渲染详细视图
    renderDetailView(outlineData);
}

// 渲染简洁视图
function renderCompactView(outlineData) {
    const container = document.getElementById('outline-slides-compact');
    if (!container || !outlineData.slides) return;

    container.innerHTML = '';

    outlineData.slides.forEach((slide, index) => {
        const slideCard = document.createElement('div');
        slideCard.style.cssText = `
            padding: 15px; background: white; border-radius: 8px;
            border-left: 4px solid #3498db; transition: all 0.3s ease;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1); position: relative;
            cursor: pointer;
        `;

        slideCard.onmouseover = function() {
            this.style.transform = 'translateY(-2px)';
            this.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
        };
        slideCard.onmouseout = function() {
            this.style.transform = 'translateY(0)';
            this.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
        };

        const contentPoints = slide.content_points || slide.content || [];
        const firstPoint = Array.isArray(contentPoints) ? contentPoints[0] : contentPoints;
        const remainingCount = Array.isArray(contentPoints) ? Math.max(0, contentPoints.length - 1) : 0;

        slideCard.innerHTML = `
            <div style="display: flex; align-items: center; margin-bottom: 8px;">
                <span style="background: #3498db; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; font-size: 0.8em; font-weight: bold; margin-right: 10px;">
                    ${slide.page_number || index + 1}
                </span>
                <strong style="color: #2c3e50; font-size: 0.9em;">${slide.title || '未命名幻灯片'}</strong>
            </div>
            ${slide.subtitle ? `<p style="color: #7f8c8d; font-size: 0.8em; margin: 5px 0; font-style: italic;">${slide.subtitle}</p>` : ''}
            <div style="color: #666; font-size: 0.8em; line-height: 1.4;">
                ${firstPoint ? (typeof firstPoint === 'string' ? firstPoint.substring(0, 80) + (firstPoint.length > 80 ? '...' : '') : JSON.stringify(firstPoint).substring(0, 80) + '...') : '<span style="color: #95a5a6;">暂无内容</span>'}
                ${remainingCount > 0 ? `<br><span style="color: #95a5a6;">+${remainingCount} 个要点</span>` : ''}
            </div>
        `;

        slideCard.onclick = () => viewSlideDetail(index);
        container.appendChild(slideCard);
    });
}

// 渲染详细视图
function renderDetailView(outlineData) {
    const container = document.getElementById('outline-slides-detail');
    if (!container || !outlineData.slides) return;

    container.innerHTML = '';

    outlineData.slides.forEach((slide, index) => {
        const slideDiv = document.createElement('div');
        slideDiv.style.cssText = `
            padding: 20px; margin-bottom: 15px; background: #f8f9fa;
            border-radius: 10px; border-left: 4px solid #3498db; position: relative;
        `;

        const contentPoints = slide.content_points || slide.content || [];
        let contentHtml = '';

        if (Array.isArray(contentPoints) && contentPoints.length > 0) {
            contentHtml = `
                <div style="margin-top: 10px;">
                    <h5 style="color: #555; margin-bottom: 8px; font-size: 0.9em;">内容要点：</h5>
                    <ul style="margin: 0; padding-left: 20px; color: #555; line-height: 1.6;">
                        ${contentPoints.map(point => `<li style="margin-bottom: 5px;">${point}</li>`).join('')}
                    </ul>
                </div>
            `;
        } else if (contentPoints) {
            contentHtml = `
                <div style="margin-top: 10px;">
                    <h5 style="color: #555; margin-bottom: 8px; font-size: 0.9em;">内容：</h5>
                    <div style="background: white; padding: 15px; border-radius: 6px; color: #555; line-height: 1.6; white-space: pre-wrap;">${contentPoints}</div>
                </div>
            `;
        }

        slideDiv.innerHTML = `
            <div style="display: flex; align-items: center; margin-bottom: 15px;">
                <span style="background: #3498db; color: white; border-radius: 50%; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; font-weight: bold; margin-right: 15px;">
                    ${slide.page_number || index + 1}
                </span>
                <div style="flex: 1;">
                    <strong style="color: #2c3e50; font-size: 1.1em;">${slide.title || '未命名幻灯片'}</strong>
                    ${slide.subtitle ? `<br><em style="color: #7f8c8d; font-size: 0.9em;">${slide.subtitle}</em>` : ''}
                </div>
            </div>
            ${contentHtml}
            ${slide.slide_type ? `<div style="margin-top: 10px;"><span style="background: #e8f4fd; color: #3498db; padding: 4px 8px; border-radius: 4px; font-size: 0.8em;">类型: ${slide.slide_type}</span></div>` : ''}
        `;

        container.appendChild(slideDiv);
    });
}

// 查看幻灯片详情
function viewSlideDetail(slideIndex) {
    if (!currentOutlineData || !currentOutlineData.slides || !currentOutlineData.slides[slideIndex]) return;

    const slide = currentOutlineData.slides[slideIndex];

    // 创建模态框显示详细信息
    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); z-index: 1000; display: flex;
        align-items: center; justify-content: center; padding: 20px;
    `;

    const content = document.createElement('div');
    content.style.cssText = `
        background: white; border-radius: 15px; padding: 30px;
        max-width: 600px; max-height: 80vh; overflow-y: auto;
        box-shadow: 0 10px 30px rgba(0,0,0,0.3);
    `;

    const contentPoints = slide.content_points || slide.content || [];
    let contentHtml = '';

    if (Array.isArray(contentPoints) && contentPoints.length > 0) {
        contentHtml = `
            <h5 style="color: #555; margin: 15px 0 8px 0;">内容要点：</h5>
            <ul style="margin: 0; padding-left: 20px; color: #555; line-height: 1.6;">
                ${contentPoints.map(point => `<li style="margin-bottom: 5px;">${point}</li>`).join('')}
            </ul>
        `;
    } else if (contentPoints) {
        contentHtml = `
            <h5 style="color: #555; margin: 15px 0 8px 0;">内容：</h5>
            <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; color: #555; line-height: 1.6; white-space: pre-wrap;">${contentPoints}</div>
        `;
    }

    content.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
            <h3 style="color: #2c3e50; margin: 0;">第${slide.page_number || slideIndex + 1}页详情</h3>
            <button onclick="this.closest('.modal').remove()" style="background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 16px;">×</button>
        </div>
        <h4 style="color: #3498db; margin-bottom: 10px;">${slide.title || '未命名幻灯片'}</h4>
        ${slide.subtitle ? `<p style="color: #7f8c8d; font-style: italic; margin-bottom: 15px;">${slide.subtitle}</p>` : ''}
        ${contentHtml}
        ${slide.slide_type ? `<div style="margin-top: 15px;"><span style="background: #e8f4fd; color: #3498db; padding: 6px 12px; border-radius: 6px; font-size: 0.9em;">类型: ${slide.slide_type}</span></div>` : ''}
    `;

    modal.className = 'modal';
    modal.appendChild(content);
    document.body.appendChild(modal);

    // 点击背景关闭
    modal.addEventListener('click', (e) => {
        if (e.target === modal) {
            modal.remove();
        }
    });
}

// 编辑大纲内容
function editOutlineContent() {
    // 获取当前大纲内容
    let outlineContent = '';
    if (currentOutlineData) {
        outlineContent = JSON.stringify(currentOutlineData, null, 2);
    } else {
        // 尝试从显示区域获取内容
        const outlineDisplay = document.getElementById('outline-content-display');
        if (outlineDisplay) {
            outlineContent = outlineDisplay.textContent || outlineDisplay.innerText || '';
        }
    }

    // 创建编辑模态框
    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); z-index: 1000; display: flex;
        align-items: center; justify-content: center; padding: 20px;
    `;

    const content = document.createElement('div');
    content.style.cssText = `
        background: white; border-radius: 15px; padding: 30px;
        width: 90%; max-width: 800px; height: 80vh; display: flex;
        flex-direction: column; box-shadow: 0 10px 30px rgba(0,0,0,0.3);
    `;

    content.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
            <h3 style="color: #2c3e50; margin: 0;">编辑PPT大纲</h3>
            <button onclick="this.closest('.modal').remove()" style="background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 16px;">×</button>
        </div>
        <div style="flex: 1; display: flex; flex-direction: column;">
            <textarea id="outlineEditor" style="flex: 1; border: 2px solid #ecf0f1; border-radius: 8px; padding: 15px; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.5; resize: none;" placeholder="编辑大纲JSON...">${outlineContent}</textarea>
            <div style="display: flex; gap: 8px; margin-top: 15px; justify-content: flex-end;">
                <button onclick="this.closest('.modal').remove()" class="btn btn-sm" style="background: #95a5a6; color: white;">取消</button>
                <button onclick="saveOutlineChanges()" class="btn btn-sm btn-primary">保存修改</button>
            </div>
        </div>
    `;

    modal.className = 'modal';
    modal.appendChild(content);
    document.body.appendChild(modal);
}

// 保存大纲修改
function saveOutlineChanges() {
    const editor = document.getElementById('outlineEditor');
    if (!editor) return;

    try {
        const newOutline = JSON.parse(editor.value);

        // 更新当前大纲数据
        currentOutlineData = newOutline;

        // 重新渲染预览
        renderOutlinePreview(newOutline);

        // 更新JSON显示区域
        const outlineDisplay = document.getElementById('outline-content-display');
        if (outlineDisplay) {
            const formattedContent = JSON.stringify(newOutline, null, 2);
            const preElement = document.createElement('pre');
            preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
            preElement.textContent = formattedContent;
            outlineDisplay.innerHTML = '';
            outlineDisplay.appendChild(preElement);
        }

        // 保存到服务器
        fetch(`/projects/${currentProjectId}/update-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                outline_content: JSON.stringify(newOutline, null, 2)
            })
        }).then(response => {
            if (response.ok) {
                alert('大纲修改成功！');
                // 关闭模态框
                document.querySelector('.modal').remove();

                // 立即重新渲染大纲视图，使用最新数据
                setTimeout(() => {
                    // 如果当前是大纲视图，重新渲染
                    if (currentView === 'outline') {
                        renderOutlineView();
                    }

                    // 如果当前是新的大纲视图，使用最新数据重新渲染
                    if (currentViewNew === 'outline') {
                        renderOutlineViewNewWithData(newOutline);
                    }
                }, 100); // 减少延迟
            } else {
                alert('保存失败，请重试');
            }
        }).catch(error => {
            console.error('Error saving outline:', error);
            alert('保存失败: ' + error.message);
        });

    } catch (error) {
        if (error instanceof SyntaxError) {
            alert('JSON格式错误，请检查语法！');
        } else {
            console.error('Error saving outline:', error);
            alert('保存失败: ' + error.message);
        }
    }
}

// 导出大纲为JSON文件
function exportOutlineJSON() {
    if (!currentOutlineData) {
        alert('大纲数据不存在，无法导出');
        return;
    }

    const dataStr = JSON.stringify(currentOutlineData, null, 2);
    const dataBlob = new Blob([dataStr], {type: 'application/json'});

    const link = document.createElement('a');
    link.href = URL.createObjectURL(dataBlob);
    link.download = `${(currentOutlineData.title || 'ppt_outline')}_${new Date().toISOString().split('T')[0]}.json`;

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    console.log('大纲JSON文件已导出');
}


// 大纲视图模式切换（简洁视图 vs 详细视图）
function toggleOutlineViewMode() {
    isDetailView = !isDetailView;
    const toggleText = document.getElementById('viewToggleText');

    if (toggleText) {
        toggleText.textContent = isDetailView ? '简洁视图' : '详细视图';
    }

    // 重新渲染大纲视图
    renderOutlineView();
}



// 更新JSON编辑器内容
function updateJsonEditor(jsonString) {
    const contentDiv = document.getElementById('outline-content-display');
    if (contentDiv) {
        // 尝试格式化JSON
        let formattedContent;
        let parsedOutline = null;
        try {
            parsedOutline = JSON.parse(jsonString);
            formattedContent = JSON.stringify(parsedOutline, null, 2);
        } catch (e) {
            formattedContent = jsonString;
        }

        // 创建pre元素来正确显示JSON
        const preElement = document.createElement('pre');
        preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
        preElement.textContent = formattedContent;
        contentDiv.innerHTML = '';
        contentDiv.appendChild(preElement);

        // 如果当前是大纲视图，立即更新大纲显示
        if (parsedOutline && currentViewNew === 'outline') {
            setTimeout(() => {
                renderOutlineViewNewWithData(parsedOutline);
            }, 100);
        }
    }
}

// 保存大纲到服务器
async function saveOutlineToServer(jsonString) {
    try {
        const response = await fetch(`/projects/${currentProjectId}/update-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                outline_content: jsonString
            })
        });

        if (!response.ok) {
            throw new Error('保存到服务器失败');
        }

        console.log('大纲已保存到服务器');
    } catch (error) {
        console.error('保存到服务器失败:', error);
        throw error;
    }
}

// ========== 辅助函数 ==========

// 隐藏右键菜单
function hideContextMenu() {
    const contextMenu = document.getElementById('mindmap-context-menu');
    if (contextMenu) {
        contextMenu.style.display = 'none';
    }
}

// ========== 事件监听器 ==========

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
    // 隐藏右键菜单当点击其他地方时
    document.addEventListener('click', function(event) {
        if (!event.target.closest('#mindmap-context-menu')) {
            hideContextMenu();
        }
    });

    // 键盘事件处理
    document.addEventListener('keydown', function(event) {
        // ESC键取消编辑
        if (event.key === 'Escape') {
            if (document.getElementById('node-edit-modal').style.display === 'block') {
                cancelNodeEdit();
            }
            hideContextMenu();
            clearNodeSelection();
        }

        // Enter键保存编辑
        if (event.key === 'Enter' && document.getElementById('node-edit-modal').style.display === 'block') {
            saveNodeEdit();
        }
    });

    // 页面加载时检查是否有现有的大纲数据
    setTimeout(function() {
        const outlineDisplay = document.getElementById('outline-content-display');
        if (outlineDisplay) {
            const content = outlineDisplay.textContent || outlineDisplay.innerText || '';
            if (content.trim()) {
                try {
                    const parsedOutline = JSON.parse(content);
                    if (parsedOutline && parsedOutline.slides) {
                        // 渲染大纲预览
                        renderOutlinePreview(parsedOutline);

                        // 如果当前是大纲视图，渲染大纲内容
                        if (currentView === 'outline') {
                            renderOutlineView();
                        }

                        // 如果当前是新的大纲视图，渲染新的大纲内容
                        if (currentViewNew === 'outline') {
                            renderOutlineViewNew();
                        }
                    }
                } catch (e) {
                    console.log('现有内容不是有效的JSON格式');
                }
            }
        }
    }, 500);
});

// ========== 全屏功能 ==========

let isFullscreen = false;
let originalMindmapData = null;




// New view switching functions for the new outline section
let currentViewNew = 'json'; // Default to JSON view for better compatibility
let currentEditInput = null; // Track current editing input to prevent duplicates

function switchOutlineViewNew(view) {
    console.log('Switching to view:', view);

    const jsonViewBtn = document.getElementById('json-view-btn-new');
    const outlineViewBtn = document.getElementById('outline-view-btn-new');
    const jsonView = document.getElementById('outline-content-display');
    const outlineView = document.getElementById('outline-view-new');
    const actionsDiv = document.getElementById('outline-actions');

    if (!jsonViewBtn || !outlineViewBtn || !jsonView || !outlineView) {
        console.error('View elements not found');
        return;
    }

    currentViewNew = view;

    if (view === 'json') {
        // Show JSON view
        jsonView.style.display = 'block';
        outlineView.style.display = 'none';

        // Show action buttons in JSON view
        if (actionsDiv) {
            actionsDiv.style.display = 'block';
        }

        // Update button styles
        jsonViewBtn.style.background = '#3498db';
        jsonViewBtn.style.color = 'white';
        outlineViewBtn.style.background = 'transparent';
        outlineViewBtn.style.color = '#6c757d';
    } else if (view === 'outline') {
        // Show outline view
        jsonView.style.display = 'none';
        outlineView.style.display = 'block';

        // Hide action buttons in outline view
        if (actionsDiv) {
            actionsDiv.style.display = 'none';
        }

        // Update button styles
        outlineViewBtn.style.background = '#3498db';
        outlineViewBtn.style.color = 'white';
        jsonViewBtn.style.background = 'transparent';
        jsonViewBtn.style.color = '#6c757d';

        // Generate outline view if content exists
        renderOutlineViewNew();
    }
}

// 渲染新的大纲视图
function renderOutlineViewNew() {
    let outlineContent = getOutlineContentNew();
    const outlineContainer = document.getElementById('outline-content-new');
    const loadingDiv = document.getElementById('outline-loading-new');
    const errorDiv = document.getElementById('outline-error-new');
    const emptyDiv = document.getElementById('outline-empty-new');

    if (!outlineContainer) {
        console.error('Outline container not found');
        return;
    }

    // 显示加载状态
    if (loadingDiv) loadingDiv.style.display = 'block';
    if (errorDiv) errorDiv.style.display = 'none';
    if (emptyDiv) emptyDiv.style.display = 'none';

    try {
        if (!outlineContent) {
            // 没有内容，显示空状态
            if (loadingDiv) loadingDiv.style.display = 'none';
            if (emptyDiv) emptyDiv.style.display = 'block';
            return;
        }

        // 额外的内容清理，确保JSON格式正确
        outlineContent = outlineContent.trim();

        // 如果内容不是以{开头，尝试查找JSON开始位置
        if (!outlineContent.startsWith('{')) {
            const jsonStart = outlineContent.indexOf('{');
            if (jsonStart > 0) {
                outlineContent = outlineContent.substring(jsonStart);
                console.log('从位置', jsonStart, '开始提取JSON内容');
            }
        }

        // 如果内容不是以}结尾，尝试查找JSON结束位置
        if (!outlineContent.endsWith('}')) {
            const jsonEnd = outlineContent.lastIndexOf('}');
            if (jsonEnd > 0) {
                outlineContent = outlineContent.substring(0, jsonEnd + 1);
                console.log('截取到位置', jsonEnd + 1, '的JSON内容');
            }
        }

        let parsedOutline;
        try {
            parsedOutline = JSON.parse(outlineContent);
        } catch (parseError) {
            console.error('JSON解析失败:', parseError);
            if (loadingDiv) loadingDiv.style.display = 'none';
            if (errorDiv) errorDiv.style.display = 'block';
            return;
        }

        // 使用解析后的数据渲染
        renderOutlineViewNewWithData(parsedOutline);

    } catch (error) {
        console.error('渲染大纲视图时出错:', error);
        if (loadingDiv) loadingDiv.style.display = 'none';
        if (errorDiv) errorDiv.style.display = 'block';
    }
}

// 使用指定数据渲染新的大纲视图
function renderOutlineViewNewWithData(parsedOutline) {
    const outlineContainer = document.getElementById('outline-content-new');
    const loadingDiv = document.getElementById('outline-loading-new');
    const errorDiv = document.getElementById('outline-error-new');
    const emptyDiv = document.getElementById('outline-empty-new');

    if (!outlineContainer) {
        console.error('Outline container not found');
        return;
    }

    try {
        if (!parsedOutline || !parsedOutline.slides) {
            // 没有有效数据，显示空状态
            if (loadingDiv) loadingDiv.style.display = 'none';
            if (errorDiv) errorDiv.style.display = 'none';
            if (emptyDiv) emptyDiv.style.display = 'block';
            return;
        }

        if (!parsedOutline.slides || parsedOutline.slides.length === 0) {
            // 没有slides数据，显示空状态
            if (loadingDiv) loadingDiv.style.display = 'none';
            if (emptyDiv) emptyDiv.style.display = 'block';
            return;
        }

        // 渲染大纲内容
        renderOutlineContentNew(parsedOutline, outlineContainer);

        // 隐藏加载状态
        if (loadingDiv) loadingDiv.style.display = 'none';

    } catch (error) {
        console.error('Error rendering outline view with data:', error);
        if (loadingDiv) loadingDiv.style.display = 'none';
        if (errorDiv) {
            errorDiv.style.display = 'block';
            const errorP = errorDiv.querySelector('p');
            if (errorP) {
                errorP.textContent = '大纲渲染失败：' + error.message;
            }
        }
    }
}

// 大纲视图模式切换（简洁视图 vs 详细视图）
let isDetailViewNew = false;

function toggleOutlineViewModeNew() {
    isDetailViewNew = !isDetailViewNew;
    const toggleText = document.getElementById('viewToggleTextNew');

    if (toggleText) {
        toggleText.textContent = isDetailViewNew ? '简洁视图' : '详细视图';
    }

    // 重新渲染大纲视图
    renderOutlineViewNew();
}

// 渲染大纲内容
function renderOutlineContentNew(outline, container) {
    if (!outline || !outline.slides || !container) {
        return;
    }

    // 清空容器
    container.innerHTML = '';

    // 创建标题区域
    const titleSection = document.createElement('div');
    titleSection.style.cssText = 'text-align: center; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 2px solid #ecf0f1;';
    titleSection.innerHTML = `
        <h4 style="color: #3498db; margin-bottom: 10px;">${outline.title || '未命名大纲'}</h4>
        <p style="color: #7f8c8d; margin: 0;">
            总共 ${outline.slides.length} 页幻灯片 |
            场景: ${outline.metadata?.scenario || '未指定'} |
            语言: ${outline.metadata?.language || 'zh'}
        </p>
    `;
    container.appendChild(titleSection);

    // 创建大纲内容区域
    const contentSection = document.createElement('div');
    contentSection.style.cssText = 'background: #f8f9fa; border-radius: 10px; padding: 20px;';

    if (isDetailViewNew) {
        // 详细视图
        renderDetailedOutlineView(outline.slides, contentSection);
    } else {
        // 简洁视图
        renderCompactOutlineView(outline.slides, contentSection);
    }

    container.appendChild(contentSection);
}

// 渲染简洁视图
function renderCompactOutlineView(slides, container) {
    const gridContainer = document.createElement('div');
    gridContainer.style.cssText = 'display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px;';

    slides.forEach((slide, index) => {
        const slideCard = document.createElement('div');
        slideCard.style.cssText = `
            padding: 15px; background: white; border-radius: 8px;
            border-left: 4px solid #3498db; transition: all 0.3s ease;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1); position: relative; cursor: pointer;
        `;

        // 添加悬停效果
        slideCard.addEventListener('mouseenter', function() {
            this.style.transform = 'translateY(-2px)';
            this.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
        });
        slideCard.addEventListener('mouseleave', function() {
            this.style.transform = 'translateY(0)';
            this.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
        });

        // 操作按钮
        const actionButtons = document.createElement('div');
        actionButtons.style.cssText = 'position: absolute; top: 10px; right: 10px; display: flex; gap: 5px;';
        actionButtons.innerHTML = `
            <button onclick="editSingleSlideNew(${index})" class="btn btn-primary" style="font-size: 0.7em; padding: 4px 8px; border-radius: 4px;" title="编辑此页">
                <i class="fas fa-edit"></i>
            </button>
            <button onclick="viewSlideDetailNew(${index})" class="btn btn-info" style="font-size: 0.7em; padding: 4px 8px; border-radius: 4px;" title="查看详情">
                <i class="fas fa-eye"></i>
            </button>
        `;

        // 内容区域
        const contentArea = document.createElement('div');
        contentArea.style.cssText = 'margin-right: 60px;';
        contentArea.addEventListener('click', () => viewSlideDetailNew(index));

        const header = document.createElement('div');
        header.style.cssText = 'display: flex; align-items: center; margin-bottom: 8px;';
        header.innerHTML = `
            <span style="background: #3498db; color: white; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; font-size: 0.8em; font-weight: bold; margin-right: 10px;">
                ${slide.page_number || index + 1}
            </span>
            <strong style="color: #2c3e50; font-size: 0.9em;">${slide.title || '未命名幻灯片'}</strong>
        `;

        const subtitle = document.createElement('div');
        if (slide.subtitle) {
            subtitle.innerHTML = `<p style="color: #7f8c8d; font-size: 0.8em; margin: 5px 0; font-style: italic;">${slide.subtitle}</p>`;
        }

        const content = document.createElement('div');
        content.style.cssText = 'color: #666; font-size: 0.8em; line-height: 1.4;';

        if (slide.content_points && slide.content_points.length > 0) {
            const firstPoint = slide.content_points[0];
            const truncatedPoint = firstPoint.length > 80 ? firstPoint.substring(0, 80) + '...' : firstPoint;
            content.innerHTML = truncatedPoint;

            if (slide.content_points.length > 1) {
                content.innerHTML += `<br><span style="color: #95a5a6;">+${slide.content_points.length - 1} 个要点</span>`;
            }
        } else if (slide.content) {
            const truncatedContent = slide.content.length > 80 ? slide.content.substring(0, 80) + '...' : slide.content;
            content.innerHTML = truncatedContent;
        } else {
            content.innerHTML = '<span style="color: #95a5a6;">暂无内容</span>';
        }

        contentArea.appendChild(header);
        contentArea.appendChild(subtitle);
        contentArea.appendChild(content);

        slideCard.appendChild(actionButtons);
        slideCard.appendChild(contentArea);
        gridContainer.appendChild(slideCard);
    });

    container.appendChild(gridContainer);
}

// 渲染详细视图
function renderDetailedOutlineView(slides, container) {
    const detailContainer = document.createElement('div');
    detailContainer.style.cssText = 'max-height: 400px; overflow-y: auto;';

    slides.forEach((slide, index) => {
        const slideDetail = document.createElement('div');
        slideDetail.style.cssText = `
            padding: 20px; margin-bottom: 15px; background: white;
            border-radius: 10px; border-left: 4px solid #3498db; position: relative;
        `;

        const header = document.createElement('div');
        header.style.cssText = 'display: flex; align-items: center; margin-bottom: 15px;';
        header.innerHTML = `
            <span style="background: #3498db; color: white; border-radius: 50%; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; font-weight: bold; margin-right: 15px;">
                ${slide.page_number || index + 1}
            </span>
            <div style="flex: 1;">
                <strong style="color: #2c3e50; font-size: 1.1em;">${slide.title || '未命名幻灯片'}</strong>
                ${slide.subtitle ? `<br><em style="color: #7f8c8d; font-size: 0.9em;">${slide.subtitle}</em>` : ''}
            </div>
            <button onclick="editSingleSlideNew(${index})" class="btn btn-primary" style="font-size: 0.8em; padding: 6px 12px;" title="编辑此页">
                <i class="fas fa-edit"></i> 编辑
            </button>
        `;

        const contentSection = document.createElement('div');

        if (slide.content_points && slide.content_points.length > 0) {
            const pointsSection = document.createElement('div');
            pointsSection.style.cssText = 'margin-top: 10px;';
            pointsSection.innerHTML = '<h5 style="color: #555; margin-bottom: 8px; font-size: 0.9em;">内容要点：</h5>';

            const pointsList = document.createElement('ul');
            pointsList.style.cssText = 'margin: 0; padding-left: 20px; color: #555; line-height: 1.6;';

            slide.content_points.forEach(point => {
                const listItem = document.createElement('li');
                listItem.style.cssText = 'margin-bottom: 5px;';
                listItem.textContent = point;
                pointsList.appendChild(listItem);
            });

            pointsSection.appendChild(pointsList);
            contentSection.appendChild(pointsSection);
        } else if (slide.content) {
            const contentDiv = document.createElement('div');
            contentDiv.style.cssText = 'margin-top: 10px;';
            contentDiv.innerHTML = `
                <h5 style="color: #555; margin-bottom: 8px; font-size: 0.9em;">内容：</h5>
                <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; color: #555; line-height: 1.6; white-space: pre-wrap;">${slide.content}</div>
            `;
            contentSection.appendChild(contentDiv);
        }

        if (slide.slide_type) {
            const typeTag = document.createElement('div');
            typeTag.style.cssText = 'margin-top: 10px;';
            typeTag.innerHTML = `
                <span style="background: #e8f4fd; color: #3498db; padding: 4px 8px; border-radius: 4px; font-size: 0.8em;">
                    类型: ${slide.slide_type}
                </span>
            `;
            contentSection.appendChild(typeTag);
        }

        slideDetail.appendChild(header);
        slideDetail.appendChild(contentSection);
        detailContainer.appendChild(slideDetail);
    });

    container.appendChild(detailContainer);
}

// 查看幻灯片详情
function viewSlideDetailNew(slideIndex) {
    const outlineContent = getOutlineContent();
    if (!outlineContent) return;

    try {
        const parsedOutline = JSON.parse(outlineContent);
        const slide = parsedOutline.slides[slideIndex];

        if (!slide) return;

        // 创建模态框显示详细信息
        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); z-index: 1000; display: flex;
            align-items: center; justify-content: center; padding: 20px;
        `;

        const content = document.createElement('div');
        content.style.cssText = `
            background: white; border-radius: 15px; padding: 30px;
            max-width: 600px; max-height: 80vh; overflow-y: auto;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
        `;

        let contentPoints = '';
        if (slide.content_points && slide.content_points.length > 0) {
            contentPoints = '<h5 style="color: #555; margin: 15px 0 8px 0;">内容要点：</h5><ul style="margin: 0; padding-left: 20px; color: #555; line-height: 1.6;">';
            slide.content_points.forEach(point => {
                contentPoints += `<li style="margin-bottom: 5px;">${point}</li>`;
            });
            contentPoints += '</ul>';
        } else if (slide.content) {
            contentPoints = `<h5 style="color: #555; margin: 15px 0 8px 0;">内容：</h5><div style="background: #f8f9fa; padding: 15px; border-radius: 6px; color: #555; line-height: 1.6; white-space: pre-wrap;">${slide.content}</div>`;
        }

        content.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                <h3 style="color: #2c3e50; margin: 0;">第${slide.page_number || slideIndex + 1}页详情</h3>
                <button onclick="this.closest('.modal').remove()" style="background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 16px;">×</button>
            </div>
            <h4 style="color: #3498db; margin-bottom: 10px;">${slide.title || '未命名幻灯片'}</h4>
            ${slide.subtitle ? `<p style="color: #7f8c8d; font-style: italic; margin-bottom: 15px;">${slide.subtitle}</p>` : ''}
            ${contentPoints}
            ${slide.slide_type ? `<div style="margin-top: 15px;"><span style="background: #e8f4fd; color: #3498db; padding: 6px 12px; border-radius: 6px; font-size: 0.9em;">类型: ${slide.slide_type}</span></div>` : ''}
        `;

        modal.className = 'modal';
        modal.appendChild(content);
        document.body.appendChild(modal);

        // 点击背景关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                modal.remove();
            }
        });
    } catch (error) {
        console.error('Error viewing slide detail:', error);
        alert('查看详情失败: ' + error.message);
    }
}

// 编辑大纲
function editOutlineNew() {
    const outlineContent = getOutlineContent();
    if (!outlineContent) {
        alert('大纲数据不存在，无法编辑');
        return;
    }

    // 创建编辑模态框
    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); z-index: 1000; display: flex;
        align-items: center; justify-content: center; padding: 20px;
    `;

    const content = document.createElement('div');
    content.style.cssText = `
        background: white; border-radius: 15px; padding: 30px;
        width: 90%; max-width: 800px; height: 80vh; display: flex;
        flex-direction: column; box-shadow: 0 10px 30px rgba(0,0,0,0.3);
    `;

    content.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
            <h3 style="color: #2c3e50; margin: 0;">编辑PPT大纲</h3>
            <button onclick="this.closest('.modal').remove()" style="background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 16px;">×</button>
        </div>
        <div style="flex: 1; display: flex; flex-direction: column;">
            <textarea id="outlineEditorNew" style="flex: 1; border: 2px solid #ecf0f1; border-radius: 8px; padding: 15px; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.5; resize: none;" placeholder="编辑大纲JSON...">${outlineContent}</textarea>
            <div style="display: flex; gap: 8px; margin-top: 15px; justify-content: flex-end;">
                <button onclick="this.closest('.modal').remove()" class="btn btn-sm" style="background: #95a5a6; color: white;">取消</button>
                <button onclick="saveOutlineChangesNew()" class="btn btn-sm btn-primary">保存修改</button>
            </div>
        </div>
    `;

    modal.className = 'modal';
    modal.appendChild(content);
    document.body.appendChild(modal);
}

// 保存大纲修改
async function saveOutlineChangesNew() {
    const editor = document.getElementById('outlineEditorNew');
    if (!editor) return;

    try {
        const newOutline = JSON.parse(editor.value);

        const response = await fetch(`/projects/${currentProjectId}/update-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ outline_content: editor.value })
        });

        if (response.ok) {
            alert('大纲修改成功！');
            // 关闭模态框
            const modal = editor.closest('.modal');
            if (modal) modal.remove();

            // 更新JSON显示区域
            const outlineDisplay = document.getElementById('outline-content-display');
            if (outlineDisplay) {
                const preElement = document.createElement('pre');
                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                preElement.textContent = editor.value;
                outlineDisplay.innerHTML = '';
                outlineDisplay.appendChild(preElement);
            }

            // 立即重新渲染大纲视图，使用最新数据
            setTimeout(() => {
                renderOutlineViewNewWithData(newOutline);
            }, 100); // 减少延迟
        } else {
            const error = await response.json();
            alert('保存失败: ' + (error.detail || '未知错误'));
        }
    } catch (error) {
        if (error instanceof SyntaxError) {
            alert('JSON格式错误，请检查语法！');
        } else {
            console.error('Error saving outline:', error);
            alert('保存失败: ' + error.message);
        }
    }
}

// 导出大纲为JSON文件
function exportOutlineJSONNew() {
    const outlineContent = getOutlineContent();
    if (!outlineContent) {
        alert('大纲数据不存在，无法导出');
        return;
    }

    try {
        const parsedOutline = JSON.parse(outlineContent);
        const dataStr = JSON.stringify(parsedOutline, null, 2);
        const dataBlob = new Blob([dataStr], {type: 'application/json'});

        const link = document.createElement('a');
        link.href = URL.createObjectURL(dataBlob);
        link.download = `${(parsedOutline.title || 'ppt_outline')}_${new Date().toISOString().split('T')[0]}.json`;

        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);

        // 显示成功提示
        const toast = document.createElement('div');
        toast.style.cssText = `
            position: fixed; top: 20px; right: 20px; background: #27ae60;
            color: white; padding: 15px 20px; border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 1001;
            font-size: 14px; font-weight: bold;
        `;
        toast.textContent = '✅ 大纲JSON文件已导出';
        document.body.appendChild(toast);

        setTimeout(() => {
            toast.remove();
        }, 3000);
    } catch (error) {
        console.error('Error exporting outline:', error);
        alert('导出失败: ' + error.message);
    }
}

// 编辑单页幻灯片
function editSingleSlideNew(slideIndex) {
    const outlineContent = getOutlineContentNew();
    if (!outlineContent) {
        alert('大纲数据不存在，无法编辑');
        return;
    }

    try {
        const parsedOutline = JSON.parse(outlineContent);
        const slide = parsedOutline.slides[slideIndex];

        if (!slide) {
            alert('幻灯片不存在');
            return;
        }

        // 创建单页编辑模态框
        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); z-index: 1000; display: flex;
            align-items: center; justify-content: center; padding: 20px;
        `;

        const content = document.createElement('div');
        content.style.cssText = `
            background: white; border-radius: 15px; padding: 30px;
            width: 90%; max-width: 700px; max-height: 85vh; overflow-y: auto;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
        `;

        // 构建内容要点的编辑界面 - 使用占位符，稍后用JavaScript创建
        let contentPointsHtml = '';
        if (slide.content_points && slide.content_points.length > 0) {
            slide.content_points.forEach((point, index) => {
                contentPointsHtml += `
                    <div class="content-point-item" data-point-index="${index}" style="display: flex; align-items: center; margin-bottom: 10px;">
                        <input type="text" class="content-point-input" data-index="${index}"
                               value="${point.replace(/"/g, '&quot;')}"
                               style="flex: 1; padding: 8px 12px; border: 2px solid #ecf0f1; border-radius: 6px; font-size: 14px;">
                        <button class="remove-point-btn" data-remove-index="${index}"
                                style="background: #e74c3c; color: white; border: none; border-radius: 4px; padding: 6px 10px; margin-left: 8px; cursor: pointer;">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>
                `;
            });
        }

        content.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
                <h3 style="color: #2c3e50; margin: 0;">编辑第${slide.page_number || slideIndex + 1}页</h3>
                <button onclick="this.closest('.modal').remove()"
                        style="background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; cursor: pointer; font-size: 16px;">×</button>
            </div>

            <form id="singleSlideEditForm" style="display: flex; flex-direction: column; gap: 20px;">
                <!-- 页面标题 -->
                <div>
                    <label style="display: block; color: #2c3e50; font-weight: bold; margin-bottom: 8px;">页面标题</label>
                    <input type="text" id="slideTitle" value="${(slide.title || '').replace(/"/g, '&quot;')}"
                           style="width: 100%; padding: 12px; border: 2px solid #ecf0f1; border-radius: 8px; font-size: 16px;">
                </div>

                <!-- 页面副标题 -->
                <div>
                    <label style="display: block; color: #2c3e50; font-weight: bold; margin-bottom: 8px;">副标题（可选）</label>
                    <input type="text" id="slideSubtitle" value="${(slide.subtitle || '').replace(/"/g, '&quot;')}"
                           style="width: 100%; padding: 12px; border: 2px solid #ecf0f1; border-radius: 8px; font-size: 14px;">
                </div>

                <!-- 幻灯片类型 -->
                <div>
                    <label style="display: block; color: #2c3e50; font-weight: bold; margin-bottom: 8px;">幻灯片类型</label>
                    <select id="slideType" style="width: 100%; padding: 12px; border: 2px solid #ecf0f1; border-radius: 8px; font-size: 14px;">
                        <option value="title" ${slide.slide_type === 'title' ? 'selected' : ''}>标题页</option>
                        <option value="content" ${slide.slide_type === 'content' ? 'selected' : ''}>内容页</option>
                        <option value="conclusion" ${slide.slide_type === 'conclusion' ? 'selected' : ''}>结论页</option>
                        <option value="thankyou" ${slide.slide_type === 'thankyou' ? 'selected' : ''}>感谢页</option>
                    </select>
                </div>

                <!-- 内容要点 -->
                <div>
                    <label style="display: block; color: #2c3e50; font-weight: bold; margin-bottom: 8px;">内容要点</label>
                    <div id="contentPointsContainer" style="margin-bottom: 10px;">
                        ${contentPointsHtml}
                    </div>
                    <button type="button" onclick="addSingleContentPoint()"
                            style="background: #3498db; color: white; border: none; border-radius: 6px; padding: 8px 16px; cursor: pointer;">
                        <i class="fas fa-plus"></i> 添加要点
                    </button>
                </div>

                <!-- 页面描述 -->
                <div>
                    <label style="display: block; color: #2c3e50; font-weight: bold; margin-bottom: 8px;">页面描述（可选）</label>
                    <textarea id="slideDescription" rows="3"
                              style="width: 100%; padding: 12px; border: 2px solid #ecf0f1; border-radius: 8px; font-size: 14px; resize: vertical;">${slide.description || ''}</textarea>
                </div>

                <!-- 操作按钮 -->
                <div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px;">
                    <button type="button" onclick="this.closest('.modal').remove()"
                            class="btn" style="background: #95a5a6; color: white; padding: 12px 24px;">取消</button>
                    <button type="button" onclick="saveSingleSlideEdit(${slideIndex})"
                            class="btn btn-primary" style="padding: 12px 24px;">保存修改</button>
                </div>
            </form>
        `;

        modal.className = 'modal';
        modal.appendChild(content);
        document.body.appendChild(modal);

        // 为删除按钮添加事件监听器
        const removeButtons = modal.querySelectorAll('.remove-point-btn');
        removeButtons.forEach(button => {
            button.addEventListener('click', function() {
                const index = parseInt(this.getAttribute('data-remove-index'));
                removeSingleContentPointByElement(this.parentElement);
            });
        });

        // 点击背景关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                modal.remove();
            }
        });

    } catch (error) {
        console.error('Error editing single slide:', error);
        alert('编辑失败: ' + error.message);
    }
}

// 添加内容要点
function addSingleContentPoint() {
    const container = document.getElementById('contentPointsContainer');
    if (!container) return;

    const currentPoints = container.querySelectorAll('.content-point-item');
    const newIndex = currentPoints.length;

    const pointDiv = document.createElement('div');
    pointDiv.className = 'content-point-item';
    pointDiv.style.cssText = 'display: flex; align-items: center; margin-bottom: 10px;';

    // 创建输入框
    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'content-point-input';
    input.setAttribute('data-index', newIndex);
    input.placeholder = '输入新的内容要点...';
    input.style.cssText = 'flex: 1; padding: 8px 12px; border: 2px solid #ecf0f1; border-radius: 6px; font-size: 14px;';

    // 创建删除按钮
    const button = document.createElement('button');
    button.className = 'remove-point-btn';
    button.setAttribute('data-remove-index', newIndex);
    button.addEventListener('click', function() {
        removeSingleContentPointByElement(this.parentElement);
    });
    button.style.cssText = 'background: #e74c3c; color: white; border: none; border-radius: 4px; padding: 6px 10px; margin-left: 8px; cursor: pointer;';
    button.innerHTML = '<i class="fas fa-trash"></i>';

    pointDiv.appendChild(input);
    pointDiv.appendChild(button);

    container.appendChild(pointDiv);

    // 聚焦到新添加的输入框
    const newInput = pointDiv.querySelector('.content-point-input');
    if (newInput) {
        newInput.focus();
    }
}

// 删除内容要点（通过索引）
function removeSingleContentPoint(index) {
    const container = document.getElementById('contentPointsContainer');
    if (!container) return;

    const pointItems = container.querySelectorAll('.content-point-item');
    if (pointItems[index]) {
        removeSingleContentPointByElement(pointItems[index]);
    }
}

// 删除内容要点（通过元素）
function removeSingleContentPointByElement(element) {
    if (!element) return;

    element.remove();

    // 重新编号剩余的要点
    const container = document.getElementById('contentPointsContainer');
    if (!container) return;

    const remainingItems = container.querySelectorAll('.content-point-item');
    remainingItems.forEach((item, newIndex) => {
        const input = item.querySelector('.content-point-input');
        const button = item.querySelector('.remove-point-btn, button');
        if (input) input.setAttribute('data-index', newIndex);
        if (button) {
            if (button.classList.contains('remove-point-btn')) {
                button.setAttribute('data-remove-index', newIndex);
            } else {
                // 重新创建按钮以更新事件处理
                const newButton = document.createElement('button');
                newButton.onclick = () => removeSingleContentPoint(newIndex);
                newButton.style.cssText = 'background: #e74c3c; color: white; border: none; border-radius: 4px; padding: 6px 10px; margin-left: 8px; cursor: pointer;';
                newButton.innerHTML = '<i class="fas fa-trash"></i>';
                button.parentNode.replaceChild(newButton, button);
            }
        }
    });
}

// 保存单页编辑
async function saveSingleSlideEdit(slideIndex) {
    try {
        // 获取表单数据
        const title = document.getElementById('slideTitle').value.trim();
        const subtitle = document.getElementById('slideSubtitle').value.trim();
        const slideType = document.getElementById('slideType').value;
        const description = document.getElementById('slideDescription').value.trim();

        // 获取所有内容要点
        const contentPointInputs = document.querySelectorAll('.content-point-input');
        const contentPoints = Array.from(contentPointInputs)
            .map(input => input.value.trim())
            .filter(point => point.length > 0);

        if (!title) {
            alert('页面标题不能为空');
            return;
        }

        if (contentPoints.length === 0) {
            alert('至少需要一个内容要点');
            return;
        }

        // 获取当前大纲
        const outlineContent = getOutlineContentNew();
        const parsedOutline = JSON.parse(outlineContent);

        // 更新指定的幻灯片
        const updatedSlide = {
            page_number: parsedOutline.slides[slideIndex].page_number || slideIndex + 1,
            title: title,
            content_points: contentPoints,
            slide_type: slideType,
            type: slideType // 保持兼容性
        };

        // 添加可选字段
        if (subtitle) {
            updatedSlide.subtitle = subtitle;
        }
        if (description) {
            updatedSlide.description = description;
        }

        // 保留原有的图表配置（如果存在）
        if (parsedOutline.slides[slideIndex].chart_config) {
            updatedSlide.chart_config = parsedOutline.slides[slideIndex].chart_config;
        }

        // 更新大纲
        parsedOutline.slides[slideIndex] = updatedSlide;

        // 保存到服务器
        const response = await fetch(`/projects/${currentProjectId}/update-outline`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                outline_content: JSON.stringify(parsedOutline, null, 2)
            })
        });

        if (response.ok) {
            // 关闭模态框
            const modal = document.querySelector('.modal');
            if (modal) modal.remove();

            // 更新JSON显示区域
            const outlineDisplay = document.getElementById('outline-content-display');
            if (outlineDisplay) {
                const formattedContent = JSON.stringify(parsedOutline, null, 2);
                const preElement = document.createElement('pre');
                preElement.style.cssText = 'margin: 0; font-family: "Consolas", "Monaco", "Courier New", monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word;';
                preElement.textContent = formattedContent;
                outlineDisplay.innerHTML = '';
                outlineDisplay.appendChild(preElement);
            }

            // 显示成功消息
            const toast = document.createElement('div');
            toast.style.cssText = `
                position: fixed; top: 20px; right: 20px; background: #27ae60;
                color: white; padding: 15px 20px; border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 1001;
                font-size: 14px; font-weight: bold;
            `;
            toast.textContent = `✅ 第${slideIndex + 1}页已更新`;
            document.body.appendChild(toast);

            setTimeout(() => {
                toast.remove();
            }, 3000);

            // 立即重新渲染大纲视图，使用最新数据
            setTimeout(() => {
                renderOutlineViewNewWithData(parsedOutline);
            }, 100);

        } else {
            const error = await response.json();
            alert('保存失败: ' + (error.detail || '未知错误'));
        }

    } catch (error) {
        console.error('Error saving single slide:', error);
        alert('保存失败: ' + error.message);
    }
}



// Get outline content for new section
function getOutlineContentNew() {
    const contentDiv = document.getElementById('outline-content-display');
    if (!contentDiv) return null;

    // 首先尝试从pre元素中获取原始文本内容
    const preElement = contentDiv.querySelector('pre');
    if (preElement) {
        let content = preElement.textContent || preElement.innerText || '';

        // Remove placeholder text
        if (content.includes('正在生成大纲') || content.includes('等待大纲生成')) {
            return null;
        }

        return content.trim();
    }

    // 如果没有pre元素，尝试从整个div获取内容
    let content = contentDiv.textContent || contentDiv.innerText || '';

    // 处理HTML实体和格式问题
    content = content.replace(/&nbsp;/g, ' ')
                    .replace(/&lt;/g, '<')
                    .replace(/&gt;/g, '>')
                    .replace(/&amp;/g, '&')
                    .replace(/&quot;/g, '"')
                    .replace(/&#39;/g, "'")
                    .replace(/<br\s*\/?>/gi, '\n')
                    .replace(/\s+/g, ' ')
                    .trim();

    // Remove placeholder text
    if (content.includes('正在生成大纲') || content.includes('等待大纲生成')) {
        return null;
    }

    return content;
}

// 调试大纲内容的函数
function debugOutlineContent() {
    const outlineContent = getOutlineContentNew();

    console.log('=== 大纲内容调试信息 ===');
    console.log('原始内容长度：', outlineContent ? outlineContent.length : 0);
    console.log('原始内容（前500字符）：', outlineContent ? outlineContent.substring(0, 500) : 'null');
    console.log('原始内容（后100字符）：', outlineContent ? outlineContent.substring(Math.max(0, outlineContent.length - 100)) : 'null');

    // 检查常见的JSON格式问题
    if (outlineContent) {
        console.log('首字符：', outlineContent.charAt(0), '(ASCII:', outlineContent.charCodeAt(0), ')');
        console.log('末字符：', outlineContent.charAt(outlineContent.length - 1), '(ASCII:', outlineContent.charCodeAt(outlineContent.length - 1), ')');

        // 检查是否包含HTML实体
        if (outlineContent.includes('&nbsp;')) {
            console.log('⚠️ 发现HTML实体 &nbsp;');
        }
        if (outlineContent.includes('<br>')) {
            console.log('⚠️ 发现HTML标签 <br>');
        }

        // 尝试清理内容
        let cleanedContent = outlineContent.replace(/&nbsp;/g, ' ').replace(/<br>/g, '\n').trim();
        console.log('清理后内容（前200字符）：', cleanedContent.substring(0, 200));

        try {
            JSON.parse(cleanedContent);
            console.log('✅ 清理后的内容可以正确解析为JSON');
        } catch (e) {
            console.log('❌ 清理后仍然无法解析：', e.message);
        }
    }

    // 显示调试信息弹窗
    alert('调试信息已输出到控制台，请按F12查看');
}

// Convert JSON to mindmap data for new section
function convertJsonToMindmapNew(jsonData) {
    const mindmapData = {
        name: jsonData.title || 'PPT大纲',
        children: []
    };

    if (jsonData.slides && Array.isArray(jsonData.slides)) {
        jsonData.slides.forEach(slide => {
            const slideNode = {
                name: `${slide.page_number}. ${slide.title}`,
                children: []
            };

            if (slide.content_points && Array.isArray(slide.content_points)) {
                slide.content_points.forEach(point => {
                    slideNode.children.push({
                        name: point,
                        children: []
                    });
                });
            }

            mindmapData.children.push(slideNode);
        });
    }

    return mindmapData;
}


// 文件上传相关函数
function toggleContentSourceTodo() {
    const fileSection = document.getElementById('file-upload-section-todo');
    const processingOptions = document.getElementById('file-processing-options-todo');
    const pdfProcessingMode = document.getElementById('pdf-processing-mode-todo');
    const manualRadio = document.querySelector('input[name="content_source"][value="manual"]');
    const fileRadio = document.querySelector('input[name="content_source"][value="file"]');
    const topicInput = document.getElementById('topic');

    if (fileRadio && fileRadio.checked) {
        if (fileSection) fileSection.style.display = 'block';
        if (topicInput) {
            topicInput.required = false;
            topicInput.placeholder = '可选：自定义标题（留空则从文件自动提取）';
        }
        // 检查当前选择的文件，决定是否显示处理选项
        const fileInput = document.getElementById('file_upload_todo');
        if (fileInput && fileInput.files[0]) {
            const fileExt = '.' + fileInput.files[0].name.split('.').pop().toLowerCase();
            // 对所有文件类型显示处理选项容器
            if (processingOptions) {
                processingOptions.style.display = 'block';
            }
            // 只对PDF文件显示处理方式选项
            if (pdfProcessingMode) {
                pdfProcessingMode.style.display = fileExt === '.pdf' ? 'block' : 'none';
            }
        }
    } else {
        if (fileSection) fileSection.style.display = 'none';
        if (processingOptions) processingOptions.style.display = 'none';
        if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
        if (topicInput) {
            topicInput.required = true;
            topicInput.placeholder = '请输入PPT主题';
        }
    }
}

// 受众选择相关函数
function toggleCustomAudience() {
    const audienceSelect = document.getElementById('audience_type');
    const customSection = document.getElementById('custom-audience-section');
    const customInput = document.getElementById('custom_audience');

    if (audienceSelect && customSection && customInput) {
        if (audienceSelect.value === '自定义') {
            customSection.style.display = 'block';
            customInput.required = true;
        } else {
            customSection.style.display = 'none';
            customInput.required = false;
            customInput.value = ''; // 清空自定义输入
        }
    }
}

// 文件上传验证和预览
document.addEventListener('DOMContentLoaded', function() {
    const fileInput = document.getElementById('file_upload_todo');
    if (fileInput) {
        fileInput.addEventListener('change', function(e) {
            const file = e.target.files[0];
            const processingOptions = document.getElementById('file-processing-options-todo');
            const pdfProcessingMode = document.getElementById('pdf-processing-mode-todo');

            if (file) {
                // 验证文件大小 (100MB 限制)
                if (file.size > 100 * 1024 * 1024) {
                    alert('文件大小不能超过 100MB');
                    e.target.value = '';
                    if (processingOptions) processingOptions.style.display = 'none';
                    if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
                    return;
                }

                // 验证文件类型
                const allowedTypes = ['.pdf', '.docx', '.txt', '.md'];
                const fileExt = '.' + file.name.split('.').pop().toLowerCase();
                if (!allowedTypes.includes(fileExt)) {
                    alert('只支持 PDF、DOCX、TXT、MD 格式的文件');
                    e.target.value = '';
                    if (processingOptions) processingOptions.style.display = 'none';
                    if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
                    return;
                }

                // 显示文件处理选项（对所有文件类型）
                if (processingOptions) {
                    processingOptions.style.display = 'block';
                }

                // 根据文件类型显示或隐藏PDF专用处理方式选项
                if (pdfProcessingMode) {
                    if (fileExt === '.pdf') {
                        pdfProcessingMode.style.display = 'block';
                    } else {
                        pdfProcessingMode.style.display = 'none';
                    }
                }

                // 显示文件信息
                const fileInfo = document.createElement('div');
                fileInfo.style.marginTop = '10px';
                fileInfo.style.padding = '10px';
                fileInfo.style.background = '#e8f5e8';
                fileInfo.style.borderRadius = '5px';
                fileInfo.style.color = '#2d5a2d';
                fileInfo.innerHTML = `
                    <strong>已选择文件：</strong>${file.name}<br>
                    <strong>文件大小：</strong>${(file.size / 1024 / 1024).toFixed(2)} MB<br>
                    <strong>文件类型：</strong>${fileExt.toUpperCase()}
                `;

                // 移除现有文件信息
                const existingInfo = e.target.parentNode.querySelector('.file-info-todo');
                if (existingInfo) {
                    existingInfo.remove();
                }

                fileInfo.className = 'file-info-todo';
                e.target.parentNode.appendChild(fileInfo);

                // 自动填充主题（如果为空）
                const topicInput = document.getElementById('topic');
                if (topicInput && !topicInput.value.trim()) {
                    const baseName = file.name.replace(/\.[^/.]+$/, "");
                    topicInput.value = baseName;
                }
            } else {
                // 如果没有选择文件，隐藏处理选项
                if (processingOptions) processingOptions.style.display = 'none';
                if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
            }
        });
    }
});

// 清除所有已选择的文件
function clearAllFiles() {
    const fileInput = document.getElementById('file_upload_todo');
    if (fileInput) {
        fileInput.value = '';
        updateFilesList();
    }
}

// 移除单个文件
function removeFile(index) {
    const fileInput = document.getElementById('file_upload_todo');
    if (!fileInput || !fileInput.files) return;

    const dt = new DataTransfer();
    const files = Array.from(fileInput.files);

    files.forEach((file, i) => {
        if (i !== index) {
            dt.items.add(file);
        }
    });

    fileInput.files = dt.files;
    updateFilesList();
}

// 更新文件列表显示
function updateFilesList() {
    const fileInput = document.getElementById('file_upload_todo');
    const filesList = document.getElementById('selected-files-list-todo');
    const filesContainer = document.getElementById('files-list-container-todo');
    const processingOptions = document.getElementById('file-processing-options-todo');
    const pdfProcessingMode = document.getElementById('pdf-processing-mode-todo');

    if (!fileInput || !filesList || !filesContainer) return;

    const files = fileInput.files;

    if (files.length === 0) {
        filesList.style.display = 'none';
        if (processingOptions) processingOptions.style.display = 'none';
        if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
        return;
    }

    // 显示文件列表
    filesList.style.display = 'block';

    // 显示文件处理选项
    if (processingOptions) {
        processingOptions.style.display = 'block';
    }

    // 检查是否有PDF文件
    let hasPdf = false;
    for (let i = 0; i < files.length; i++) {
        const fileExt = '.' + files[i].name.split('.').pop().toLowerCase();
        if (fileExt === '.pdf') {
            hasPdf = true;
            break;
        }
    }

    // 根据是否有PDF显示/隐藏PDF处理选项
    if (pdfProcessingMode) {
        pdfProcessingMode.style.display = hasPdf ? 'block' : 'none';
    }

    // 生成文件列表HTML
    let html = '';
    let totalSize = 0;

    for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const fileExt = '.' + file.name.split('.').pop().toLowerCase();
        const sizeInMB = (file.size / 1024 / 1024).toFixed(2);
        totalSize += file.size;

        html += `
            <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px; background: #f8f9fa; border-radius: 4px; margin-bottom: 5px; border-left: 3px solid #3498db;">
                <div style="flex: 1;">
                    <div style="font-weight: 500; color: #2c3e50;">${i + 1}. ${file.name}</div>
                    <div style="font-size: 12px; color: #7f8c8d;">
                        <span>${fileExt.toUpperCase()}</span> |
                        <span>${sizeInMB} MB</span>
                    </div>
                </div>
                <button type="button" onclick="removeFile(${i})"
                        style="padding: 4px 8px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;">
                    删除
                </button>
            </div>
        `;
    }

    // 添加总计信息
    html += `
        <div style="margin-top: 10px; padding: 8px; background: #e8f5e9; border-radius: 4px; text-align: center;">
            <strong style="color: #2c3e50;">共 ${files.length} 个文件 | 总大小: ${(totalSize / 1024 / 1024).toFixed(2)} MB</strong>
        </div>
    `;

    filesContainer.innerHTML = html;

    // 自动填充主题（如果为空且只有一个文件）
    const topicInput = document.getElementById('topic');
    if (topicInput && !topicInput.value.trim() && files.length === 1) {
        const baseName = files[0].name.replace(/\.[^/.]+$/, "");
        topicInput.value = baseName;
    } else if (topicInput && !topicInput.value.trim() && files.length > 1) {
        topicInput.value = `合并文档 (${files.length}个文件)`;
    }
}

// 监听文件选择变化 - 支持多文件
document.addEventListener('DOMContentLoaded', function() {
    const fileInput = document.getElementById('file_upload_todo');
    if (fileInput) {
        fileInput.addEventListener('change', function(e) {
            const files = e.target.files;
            const processingOptions = document.getElementById('file-processing-options-todo');
            const pdfProcessingMode = document.getElementById('pdf-processing-mode-todo');

            if (files && files.length > 0) {
                // 验证所有文件
                const allowedTypes = ['.pdf', '.docx', '.txt', '.md', '.jpg', '.jpeg', '.png', '.xlsx', '.csv'];
                let hasInvalidFile = false;
                let hasOversizedFile = false;

                for (let i = 0; i < files.length; i++) {
                    const file = files[i];
                    const fileExt = '.' + file.name.split('.').pop().toLowerCase();

                    // 验证文件大小
                    if (file.size > 100 * 1024 * 1024) {
                        alert(`文件 "${file.name}" 大小超过100MB限制`);
                        hasOversizedFile = true;
                        break;
                    }

                    // 验证文件类型
                    if (!allowedTypes.includes(fileExt)) {
                        alert(`文件 "${file.name}" 格式不支持\n支持的格式: ${allowedTypes.join(', ')}`);
                        hasInvalidFile = true;
                        break;
                    }
                }

                if (hasInvalidFile || hasOversizedFile) {
                    e.target.value = '';
                    if (processingOptions) processingOptions.style.display = 'none';
                    if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
                    return;
                }

                // 更新文件列表显示
                updateFilesList();
            } else {
                // 如果没有选择文件，隐藏处理选项
                const filesList = document.getElementById('selected-files-list-todo');
                if (filesList) filesList.style.display = 'none';
                if (processingOptions) processingOptions.style.display = 'none';
                if (pdfProcessingMode) pdfProcessingMode.style.display = 'none';
            }
        });
    }
});

// 表单提交处理
document.addEventListener('DOMContentLoaded', function() {
    const form = document.getElementById('requirements-form');
    if (form) {
        form.addEventListener('submit', function(e) {
            const fileRadio = document.querySelector('input[name="content_source"][value="file"]');
            const fileInput = document.getElementById('file_upload_todo');

            if (fileRadio && fileRadio.checked && fileInput && fileInput.files.length === 0) {
                e.preventDefault();
                alert('请选择要上传的文件');
                return false;
            }

            // 显示加载状态
            const submitBtn = document.getElementById('confirm-requirements-btn');
            if (submitBtn) {
                submitBtn.disabled = true;
                submitBtn.innerHTML = '⏳ 处理中...';
            }
        });
    }
});
</script>

{% endblock %}
