<!DOCTYPE html>
<html lang="{{ current_lang }}">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ShouChao (手抄) v{{ version }}</title>
    <style>
        :root {
            --primary: #6366f1;
            --primary-dark: #4f46e5;
            --primary-light: #818cf8;
            --primary-50: #eef2ff;
            --success: #10b981;
            --success-bg: #d1fae5;
            --warning: #f59e0b;
            --warning-bg: #fef3c7;
            --danger: #ef4444;
            --danger-bg: #fee2e2;
            --bg-main: #f8fafc;
            --bg-sidebar: #ffffff;
            --bg-card: #ffffff;
            --bg-input: #ffffff;
            --bg-hover: #f1f5f9;
            --text-primary: #1e293b;
            --text-secondary: #64748b;
            --text-muted: #94a3b8;
            --border-light: #e2e8f0;
            --border: #cbd5e1;
            --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
            --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
            --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
            --radius: 8px;
            --radius-lg: 12px;
        }

        [data-theme="dark"] {
            --bg-main: #0f172a;
            --bg-sidebar: #1e293b;
            --bg-card: #1e293b;
            --bg-input: #334155;
            --bg-hover: #334155;
            --text-primary: #f1f5f9;
            --text-secondary: #94a3b8;
            --text-muted: #64748b;
            --border-light: #334155;
            --border: #475569;
            --primary-50: #1e1b4b;
            --success-bg: #064e3b;
            --warning-bg: #451a03;
            --danger-bg: #450a0a;
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background: var(--bg-main);
            color: var(--text-primary);
            line-height: 1.6;
            min-height: 100vh;
        }

        .app-container { display: flex; min-height: 100vh; }

        .sidebar {
            width: 240px;
            min-width: 240px;
            background: var(--bg-sidebar);
            border-right: 1px solid var(--border-light);
            position: fixed;
            top: 0; left: 0;
            height: 100vh;
            display: flex;
            flex-direction: column;
            z-index: 100;
        }

        .sidebar-header {
            padding: 16px;
            border-bottom: 1px solid var(--border-light);
        }

        .logo { display: flex; align-items: center; gap: 10px; }

        .logo-icon {
            width: 36px; height: 36px;
            background: linear-gradient(135deg, var(--primary), var(--primary-light));
            border-radius: 10px;
            display: flex; align-items: center; justify-content: center;
            color: white; font-weight: 700; font-size: 16px;
        }

        .logo-text h2 { font-size: 16px; font-weight: 700; }
        .logo-text span { font-size: 11px; color: var(--text-secondary); }

        .workflow-steps { padding: 12px; flex: 1; overflow-y: auto; }

        .step-item {
            display: flex; align-items: center; gap: 10px;
            padding: 10px 12px;
            border-radius: var(--radius);
            cursor: pointer;
            color: var(--text-secondary);
            font-size: 13px;
            font-weight: 500;
            transition: all 0.2s ease;
        }

        .step-item:hover { background: var(--bg-hover); color: var(--text-primary); }
        .step-item.active { background: var(--primary-50); color: var(--primary); }
        .step-item.completed .step-number { background: var(--success); color: white; }

        .step-number {
            width: 24px; height: 24px;
            border-radius: 6px;
            background: var(--bg-hover);
            display: flex; align-items: center; justify-content: center;
            font-size: 12px; font-weight: 700;
            flex-shrink: 0;
        }

        .step-item.active .step-number { background: var(--primary); color: white; }

        .sidebar-footer {
            padding: 12px;
            border-top: 1px solid var(--border-light);
        }

        .model-status {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 12px;
            background: var(--bg-hover);
            border-radius: var(--radius);
            font-size: 12px;
            cursor: pointer;
            transition: all 0.2s;
        }

        .model-status:hover { background: var(--primary-50); }

        .model-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: var(--danger);
        }

        .model-dot.connected { background: var(--success); }

        .main-content {
            margin-left: 240px;
            padding: 24px;
            width: calc(100% - 240px);
            max-width: 1200px;
        }

        .page-header { margin-bottom: 20px; display: flex; justify-content: space-between; align-items: flex-start; }
        .page-title { font-size: 24px; font-weight: 700; margin-bottom: 4px; }
        .page-subtitle { color: var(--text-secondary); font-size: 14px; }

        .card {
            background: var(--bg-card);
            border: 1px solid var(--border-light);
            border-radius: var(--radius-lg);
            padding: 20px;
            margin-bottom: 16px;
            box-shadow: var(--shadow-sm);
        }

        .card-title {
            font-size: 15px; font-weight: 600;
            margin-bottom: 16px;
            display: flex; align-items: center; gap: 8px;
        }
        .card-title::before {
            content: "";
            width: 3px; height: 16px;
            background: var(--primary);
            border-radius: 2px;
        }

        .form-group { margin-bottom: 14px; }
        .form-label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
        .form-input, .form-select {
            width: 100%; padding: 8px 12px;
            background: var(--bg-input);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            color: var(--text-primary);
            font-size: 13px;
        }
        .form-input:focus, .form-select:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 2px var(--primary-50);
        }
        .form-row { display: flex; gap: 12px; }
        .form-row .form-group { flex: 1; margin-bottom: 0; }

        .btn {
            display: inline-flex; align-items: center; justify-content: center; gap: 6px;
            padding: 8px 16px;
            border-radius: var(--radius);
            border: none;
            font-size: 13px; font-weight: 600;
            cursor: pointer;
            transition: all 0.2s ease;
        }
        .btn-primary { background: var(--primary); color: white; }
        .btn-primary:hover { background: var(--primary-dark); }
        .btn-secondary { background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border); }
        .btn-secondary:hover { background: var(--bg-hover); }
        .btn-success { background: var(--success); color: white; }
        .btn-sm { padding: 6px 12px; font-size: 12px; }
        .btn-lg { padding: 12px 24px; font-size: 14px; }
        .btn:disabled { opacity: 0.5; cursor: not-allowed; }
        .btn-group { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; }

        .badge {
            display: inline-flex; align-items: center; gap: 4px;
            padding: 3px 8px;
            border-radius: 10px;
            font-size: 11px; font-weight: 600;
        }
        .badge-success { background: var(--success-bg); color: var(--success); }
        .badge-warning { background: var(--warning-bg); color: var(--warning); }
        .badge-danger { background: var(--danger-bg); color: var(--danger); }

        /* 素材来源卡片 */
        .source-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 16px;
            margin-bottom: 16px;
        }

        .source-card {
            background: var(--bg-card);
            border: 2px solid var(--border-light);
            border-radius: var(--radius-lg);
            padding: 20px;
            cursor: pointer;
            transition: all 0.2s ease;
            position: relative;
        }

        .source-card:hover { border-color: var(--primary-light); transform: translateY(-2px); }
        .source-card.selected { border-color: var(--primary); background: var(--primary-50); }

        .source-card-header {
            display: flex;
            align-items: center;
            gap: 12px;
            margin-bottom: 12px;
        }

        .source-icon {
            width: 48px;
            height: 48px;
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
        }

        .source-icon.news { background: linear-gradient(135deg, #3b82f6, #60a5fa); }
        .source-icon.github { background: linear-gradient(135deg, #1f2937, #4b5563); }
        .source-icon.market { background: linear-gradient(135deg, #10b981, #34d399); }

        .source-title { font-size: 16px; font-weight: 700; }
        .source-desc { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }

        .source-content {
            margin-top: 12px;
            padding-top: 12px;
            border-top: 1px solid var(--border-light);
            display: none;
        }

        .source-card.selected .source-content { display: block; }

        .source-check {
            position: absolute;
            top: 12px;
            right: 12px;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: var(--bg-hover);
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--text-muted);
            font-size: 14px;
            font-weight: 700;
        }

        .source-card.selected .source-check {
            background: var(--primary);
            color: white;
        }

        /* 文章列表 */
        .article-list {
            max-height: 400px;
            overflow-y: auto;
            border: 1px solid var(--border-light);
            border-radius: var(--radius);
        }

        .article-item {
            display: flex;
            align-items: flex-start;
            gap: 12px;
            padding: 12px;
            border-bottom: 1px solid var(--border-light);
            cursor: pointer;
        }

        .article-item:last-child { border-bottom: none; }
        .article-item:hover { background: var(--bg-hover); }
        .article-item.selected { background: var(--primary-50); }

        .article-checkbox { width: 16px; height: 16px; accent-color: var(--primary); margin-top: 2px; flex-shrink: 0; }
        .article-info { flex: 1; min-width: 0; }
        .article-title { font-size: 13px; font-weight: 600; line-height: 1.4; }
        .article-meta { font-size: 11px; color: var(--text-secondary); margin-top: 4px; }

        /* GitHub 趋势项 */
        .github-item {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px;
            border-bottom: 1px solid var(--border-light);
            cursor: pointer;
        }

        .github-item:hover { background: var(--bg-hover); }
        .github-item.selected { background: var(--primary-50); }

        .github-rank {
            width: 28px;
            height: 28px;
            border-radius: 6px;
            background: var(--bg-hover);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: 700;
            flex-shrink: 0;
        }

        .github-rank.top3 { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: white; }

        .github-info { flex: 1; min-width: 0; }
        .github-name { font-size: 13px; font-weight: 600; color: var(--primary); }
        .github-desc { font-size: 11px; color: var(--text-secondary); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .github-stats { font-size: 11px; color: var(--text-muted); margin-top: 4px; display: flex; gap: 12px; }

        /* 股票项 */
        .stock-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            gap: 8px;
        }

        .stock-item {
            padding: 10px;
            border-radius: var(--radius);
            cursor: pointer;
            text-align: center;
            transition: all 0.2s;
        }

        .stock-item:hover { transform: scale(1.02); }
        .stock-item.up { background: var(--success-bg); }
        .stock-item.down { background: var(--danger-bg); }

        .stock-name { font-size: 12px; font-weight: 600; }
        .stock-change { font-size: 14px; font-weight: 700; margin-top: 4px; }
        .stock-item.up .stock-change { color: var(--success); }
        .stock-item.down .stock-change { color: var(--danger); }

        /* 简报输出 */
        .briefing-output {
            background: var(--bg-card);
            border: 1px solid var(--border-light);
            border-radius: var(--radius-lg);
            padding: 24px;
            min-height: 400px;
            max-height: 600px;
            overflow-y: auto;
            font-size: 14px;
            line-height: 1.8;
        }

        .briefing-output h1 { font-size: 24px; font-weight: 700; margin: 0 0 16px 0; padding-bottom: 12px; border-bottom: 2px solid var(--primary); }
        .briefing-output h2 { font-size: 18px; font-weight: 600; margin: 24px 0 12px 0; padding-bottom: 6px; border-bottom: 1px solid var(--border-light); }
        .briefing-output h3 { font-size: 16px; font-weight: 600; margin: 20px 0 10px 0; }
        .briefing-output p { margin: 12px 0; }
        .briefing-output strong { font-weight: 600; color: var(--primary); }
        .briefing-output ul, .briefing-output ol { margin: 12px 0; padding-left: 24px; }
        .briefing-output li { margin: 6px 0; }
        .briefing-output blockquote { margin: 16px 0; padding: 12px 16px; border-left: 3px solid var(--primary); background: var(--primary-50); border-radius: 0 var(--radius) var(--radius) 0; }
        .briefing-output code { background: var(--bg-hover); padding: 2px 6px; border-radius: 4px; font-size: 12px; }

        /* TTS 内容预览 */
        .tts-preview {
            background: var(--bg-card);
            border: 1px solid var(--border-light);
            border-radius: var(--radius);
            padding: 16px;
            min-height: 120px;
            max-height: 300px;
            overflow-y: auto;
            font-size: 14px;
            line-height: 1.7;
        }
        
        .tts-preview h1 { font-size: 18px; font-weight: 700; margin: 0 0 12px 0; color: var(--primary); }
        .tts-preview h2 { font-size: 16px; font-weight: 600; margin: 16px 0 8px 0; }
        .tts-preview h3 { font-size: 14px; font-weight: 600; margin: 12px 0 6px 0; }
        .tts-preview p { margin: 8px 0; }
        .tts-preview strong { font-weight: 600; color: var(--primary); }
        .tts-preview ul, .tts-preview ol { margin: 8px 0; padding-left: 20px; }
        .tts-preview li { margin: 4px 0; }
        .tts-preview blockquote { margin: 12px 0; padding: 8px 12px; border-left: 3px solid var(--primary); background: var(--primary-50); border-radius: 0 var(--radius) var(--radius) 0; }
        .tts-preview code { background: var(--bg-hover); padding: 2px 4px; border-radius: 3px; font-size: 12px; }
        .tts-preview hr { border: none; border-top: 1px solid var(--border-light); margin: 16px 0; }
        
        .tts-toolbar {
            display: flex;
            gap: 8px;
            margin-bottom: 8px;
        }
        
        .tts-toolbar .btn-sm {
            padding: 4px 10px;
            font-size: 11px;
        }

        /* 进度条 */
        .progress-bar {
            height: 6px;
            background: var(--bg-hover);
            border-radius: 3px;
            overflow: hidden;
            margin: 12px 0;
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--primary), var(--primary-light));
            border-radius: 3px;
            transition: width 0.3s ease;
        }

        .progress-status {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 12px;
            color: var(--text-secondary);
        }

        .progress-spinner {
            width: 16px;
            height: 16px;
            border: 2px solid var(--border);
            border-top-color: var(--primary);
            border-radius: 50%;
            animation: spin 0.8s linear infinite;
        }

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

        .hidden { display: none !important; }

        .step-content { display: none; }
        .step-content.active { display: block; }

        /* Toast */
        .toast-container {
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 1000;
        }

        .toast {
            padding: 12px 20px;
            border-radius: var(--radius);
            margin-top: 8px;
            font-size: 13px;
            font-weight: 500;
            animation: slideIn 0.3s ease;
            box-shadow: var(--shadow-md);
        }

        .toast.success { background: var(--success); color: white; }
        .toast.error { background: var(--danger); color: white; }
        .toast.warning { background: var(--warning); color: white; }

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

        /* 设置弹窗 */
        .modal-overlay {
            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: 200;
        }

        .modal {
            background: var(--bg-card);
            border-radius: var(--radius-lg);
            padding: 24px;
            width: 90%;
            max-width: 500px;
            max-height: 80vh;
            overflow-y: auto;
        }

        .modal-title {
            font-size: 18px;
            font-weight: 700;
            margin-bottom: 16px;
        }

        .lang-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
            gap: 6px;
        }

        .lang-item {
            display: flex;
            align-items: center;
            gap: 6px;
            padding: 8px 10px;
            background: var(--bg-input);
            border: 2px solid var(--border-light);
            border-radius: var(--radius);
            cursor: pointer;
            font-size: 12px;
        }

        .lang-item:hover { border-color: var(--primary); }
        .lang-item.selected { border-color: var(--primary); background: var(--primary-50); }
    </style>
</head>
<body>
    <div class="app-container">
        <nav class="sidebar">
            <div class="sidebar-header">
                <div class="logo">
                    <div class="logo-icon">手</div>
                    <div class="logo-text">
                        <h2>ShouChao</h2>
                        <span>v{{ version }}</span>
                    </div>
                </div>
            </div>

            <div class="workflow-steps">
                <div class="step-item active" data-step="1" onclick="goToStep(1)">
                    <div class="step-number">1</div>
                    <span>素材来源</span>
                </div>
                <div class="step-item" data-step="2" onclick="goToStep(2)">
                    <div class="step-number">2</div>
                    <span>内容选择</span>
                </div>
                <div class="step-item" data-step="3" onclick="goToStep(3)">
                    <div class="step-number">3</div>
                    <span>生成简报</span>
                </div>
                <div class="step-item" data-step="4" onclick="goToStep(4)">
                    <div class="step-number">4</div>
                    <span>TTS 播报</span>
                </div>
            </div>

            <div class="sidebar-footer">
                <div class="model-status" onclick="showSettingsModal()">
                    <div class="model-dot" id="modelDot"></div>
                    <span id="modelStatusText">检测中...</span>
                </div>
                <select id="langSelect" class="form-select" style="font-size: 12px; margin-top: 8px;" onchange="changeLanguage()">
                    {% for code, name in languages.items() %}
                    <option value="{{ code }}" {% if code == current_lang %}selected{% endif %}>{{ name }}</option>
                    {% endfor %}
                </select>
            </div>
        </nav>

        <main class="main-content">
            <!-- Step 1: 素材来源 -->
            <section id="step-1" class="step-content active">
                <div class="page-header">
                    <div>
                        <h1 class="page-title">Step 1: 素材来源</h1>
                        <p class="page-subtitle">选择内容来源，可多选</p>
                    </div>
                </div>

                <div class="source-grid">
                    <!-- 新闻源 -->
                    <div class="source-card selected" data-source="news" onclick="toggleSource(this)">
                        <div class="source-check">✓</div>
                        <div class="source-card-header">
                            <div class="source-icon news">📰</div>
                            <div>
                                <div class="source-title">新闻 RSS</div>
                                <div class="source-desc">109 个多语言新闻源</div>
                            </div>
                        </div>
                        <div class="source-content">
                            <div class="form-group">
                                <label class="form-label">选择语言</label>
                                <div class="lang-grid" id="newsLangGrid">
                                    {% for code, name in languages.items() %}
                                    <div class="lang-item" data-lang="{{ code }}" onclick="toggleNewsLang(this, event)">
                                        <span>{{ name }}</span>
                                    </div>
                                    {% endfor %}
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-label">每源最大文章数</label>
                                <input type="number" id="maxArticles" class="form-input" value="20" min="5" max="100" style="width: 100px;">
                            </div>
                        </div>
                    </div>

                    <!-- GitHub 趋势 -->
                    <div class="source-card" data-source="github" onclick="toggleSource(this)">
                        <div class="source-check"></div>
                        <div class="source-card-header">
                            <div class="source-icon github">🐙</div>
                            <div>
                                <div class="source-title">GitHub 趋势</div>
                                <div class="source-desc">热门开源项目动态</div>
                            </div>
                        </div>
                        <div class="source-content">
                            <div class="form-group">
                                <label class="form-label">时间范围</label>
                                <select id="githubSince" class="form-select">
                                    <option value="daily">今日</option>
                                    <option value="weekly">本周</option>
                                    <option value="monthly">本月</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label class="form-label">编程语言</label>
                                <select id="githubLang" class="form-select">
                                    <option value="">全部</option>
                                    <option value="python">Python</option>
                                    <option value="javascript">JavaScript</option>
                                    <option value="typescript">TypeScript</option>
                                    <option value="go">Go</option>
                                    <option value="rust">Rust</option>
                                    <option value="java">Java</option>
                                </select>
                            </div>
                        </div>
                    </div>

                    <!-- 股市热力图 -->
                    <div class="source-card" data-source="market" onclick="toggleSource(this)">
                        <div class="source-check"></div>
                        <div class="source-card-header">
                            <div class="source-icon market">📊</div>
                            <div>
                                <div class="source-title">股市热力图</div>
                                <div class="source-desc">A 股市场行情概览</div>
                            </div>
                        </div>
                        <div class="source-content">
                            <div class="form-group">
                                <label class="form-label">市场</label>
                                <select id="marketType" class="form-select">
                                    <option value="ashare">A 股</option>
                                    <option value="hk">港股</option>
                                    <option value="us">美股</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label class="form-label">显示数量</label>
                                <input type="number" id="marketTopN" class="form-input" value="50" min="10" max="200" style="width: 100px;">
                            </div>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <h3 class="card-title">已选择内容</h3>
                    <div id="selectedStats" class="stats-row" style="display: none;">
                        <div class="stat-item">
                            <div class="stat-value" id="statNews">0</div>
                            <div class="stat-label">新闻</div>
                        </div>
                        <div class="stat-item">
                            <div class="stat-value" id="statGithub">0</div>
                            <div class="stat-label">GitHub</div>
                        </div>
                        <div class="stat-item">
                            <div class="stat-value" id="statMarket">0</div>
                            <div class="stat-label">股票</div>
                        </div>
                    </div>
                    <p id="noSourceHint" style="color: var(--text-secondary); font-size: 13px;">请选择至少一个素材来源</p>
                </div>

                <div class="btn-group">
                    <button class="btn btn-primary btn-lg" onclick="fetchContent()">📥 抓取内容</button>
                </div>
            </section>

            <!-- Step 2: 内容选择 -->
            <section id="step-2" class="step-content">
                <div class="page-header">
                    <div>
                        <h1 class="page-title">Step 2: 内容选择</h1>
                        <p class="page-subtitle">选择要包含在简报中的内容</p>
                    </div>
                    <button class="btn btn-secondary" onclick="goToStep(1)">← 返回修改来源</button>
                </div>

                <!-- 新闻内容 -->
                <div class="card" id="newsSelectCard" style="display: none;">
                    <h3 class="card-title">
                        📰 新闻文章
                        <span id="newsCount" class="badge badge-success" style="margin-left: auto;">0 篇</span>
                    </h3>
                    <div class="btn-group" style="margin-top: 0; margin-bottom: 12px;">
                        <button class="btn btn-secondary btn-sm" onclick="selectAllNews()">全选</button>
                        <button class="btn btn-secondary btn-sm" onclick="deselectAllNews()">清除</button>
                    </div>
                    <div class="article-list" id="newsList"></div>
                </div>

                <!-- GitHub 内容 -->
                <div class="card" id="githubSelectCard" style="display: none;">
                    <h3 class="card-title">
                        🐙 GitHub 趋势
                        <span id="githubCount" class="badge badge-success" style="margin-left: auto;">0 个</span>
                    </h3>
                    <div id="githubList" style="max-height: 400px; overflow-y: auto;"></div>
                </div>

                <!-- 股市内容 -->
                <div class="card" id="marketSelectCard" style="display: none;">
                    <h3 class="card-title">
                        📊 股市行情
                        <span id="marketCount" class="badge badge-success" style="margin-left: auto;">0 只</span>
                    </h3>
                    <div id="marketList" style="max-height: 400px; overflow-y: auto;"></div>
                </div>

                <div class="btn-group">
                    <button class="btn btn-secondary" onclick="goToStep(1)">← 上一步</button>
                    <button class="btn btn-primary btn-lg" id="nextToBriefing" onclick="goToStep(3)">✓ 确认选择</button>
                </div>
            </section>

            <!-- Step 3: 生成简报 -->
            <section id="step-3" class="step-content">
                <div class="page-header">
                    <div>
                        <h1 class="page-title">Step 3: 生成简报</h1>
                        <p class="page-subtitle">AI 智能生成综合简报</p>
                    </div>
                </div>

                <div class="card">
                    <h3 class="card-title">简报设置</h3>
                    <div class="form-row">
                        <div class="form-group">
                            <label class="form-label">输出语言</label>
                            <select id="outputLang" class="form-select">
                                <option value="zh">中文</option>
                                <option value="en">English</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <label class="form-label">风格</label>
                            <select id="briefingStyle" class="form-select">
                                <option value="detailed">详细</option>
                                <option value="brief">简洁</option>
                                <option value="bullet">要点</option>
                            </select>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <div class="progress-bar" id="briefingProgress" style="display: none;">
                        <div class="progress-fill" style="width: 0%;"></div>
                    </div>
                    <div id="briefingStatus"></div>
                    <div class="briefing-output" id="briefingOutput">
                        <div style="color: var(--text-secondary); text-align: center; padding: 60px;">
                            <div style="font-size: 48px; margin-bottom: 16px;">📝</div>
                            点击"生成简报"开始
                        </div>
                    </div>
                </div>

                <div class="btn-group">
                    <button class="btn btn-secondary" onclick="goToStep(2)">← 上一步</button>
                    <button class="btn btn-primary btn-lg" id="generateBtn" onclick="generateBriefing()">✨ 生成简报</button>
                    <button class="btn btn-secondary" id="nextToTTS" style="display: none;" onclick="goToStep(4)">继续 →</button>
                </div>
            </section>

            <!-- Step 4: TTS 播报 -->
            <section id="step-4" class="step-content">
                <div class="page-header">
                    <div>
                        <h1 class="page-title">Step 4: TTS 播报</h1>
                        <p class="page-subtitle">将简报转换为语音</p>
                    </div>
                </div>

                <div class="card">
                    <h3 class="card-title">语音设置</h3>
                    <div class="form-row">
                        <div class="form-group">
                            <label class="form-label">TTS 引擎</label>
                            <select id="ttsEngine" class="form-select" onchange="onEngineChange()"></select>
                        </div>
                        <div class="form-group">
                            <label class="form-label">播报语言</label>
                            <select id="ttsLanguage" class="form-select" onchange="loadVoices()">
                                <option value="zh">中文</option>
                                <option value="en">English</option>
                                <option value="ja">日本語</option>
                                <option value="ko">한국어</option>
                                <option value="fr">Français</option>
                                <option value="de">Deutsch</option>
                                <option value="es">Español</option>
                                <option value="it">Italiano</option>
                                <option value="pt">Português</option>
                                <option value="hi">हिन्दी</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <label class="form-label">语音</label>
                            <select id="ttsVoice" class="form-select"></select>
                        </div>
                    </div>
                    <div class="form-row">
                        <div class="form-group">
                            <label class="form-label">语速</label>
                            <select id="ttsSpeed" class="form-select">
                                <option value="0.8">0.8x 慢速</option>
                                <option value="1.0" selected>1.0x 正常</option>
                                <option value="1.2">1.2x 快速</option>
                                <option value="1.5">1.5x 极速</option>
                            </select>
                        </div>
                </div>

                <div class="card">
                    <h3 class="card-title">播报内容</h3>
                    <div class="tts-toolbar">
                        <button class="btn btn-secondary btn-sm active" id="previewBtn" onclick="toggleTtsMode('preview')">📄 预览</button>
                        <button class="btn btn-secondary btn-sm" id="editBtn" onclick="toggleTtsMode('edit')">✏️ 编辑</button>
                    </div>
                    <div id="ttsPreviewMode">
                        <div id="ttsPreview" class="tts-preview">
                            <div style="color: var(--text-secondary); text-align: center; padding: 40px;">暂无内容</div>
                        </div>
                    </div>
                    <div id="ttsEditMode" style="display: none;">
                        <textarea id="ttsContent" class="form-input" rows="8" style="resize: vertical; font-size: 13px;" placeholder="输入或粘贴要播报的内容..."></textarea>
                    </div>
                </div>

                <div class="card">
                    <h3 class="card-title">音频播放</h3>
                    <audio id="audioPlayer" controls style="width: 100%; margin-bottom: 12px;"></audio>
                    <div class="btn-group">
                        <button class="btn btn-primary btn-lg" id="ttsBtn" onclick="generateAudio()">🎵 生成音频</button>
                        <button class="btn btn-success" id="playBtn" onclick="playAudio()" disabled>▶️ 播放</button>
                        <button class="btn btn-secondary" id="saveBtn" onclick="saveAudio()" disabled>💾 保存</button>
                    </div>
                    <div id="ttsStatus" style="margin-top: 12px; font-size: 12px; color: var(--text-secondary);">准备就绪</div>
                </div>

                <div class="btn-group">
                    <button class="btn btn-secondary" onclick="goToStep(3)">← 上一步</button>
                    <button class="btn btn-success btn-lg" onclick="startOver()">🔄 重新开始</button>
                </div>
            </section>
        </main>
    </div>

    <!-- 设置弹窗 -->
    <div class="modal-overlay hidden" id="settingsModal">
        <div class="modal">
            <h2 class="modal-title">⚙️ 模型设置</h2>
            <div class="form-group">
                <label class="form-label">Ollama 服务地址</label>
                <div class="form-row">
                    <input type="text" id="ollamaUrl" class="form-input" value="{{ config.ollama_url }}" placeholder="http://localhost:11434">
                    <button class="btn btn-secondary" onclick="testOllama()">测试</button>
                </div>
                <span id="ollamaStatus" style="font-size: 11px;"></span>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label class="form-label">聊天模型</label>
                    <select id="chatModel" class="form-select"><option value="">加载中...</option></select>
                </div>
                <div class="form-group">
                    <label class="form-label">嵌入模型</label>
                    <select id="embedModel" class="form-select"><option value="">加载中...</option></select>
                </div>
            </div>
            <div class="btn-group">
                <button class="btn btn-secondary" onclick="hideSettingsModal()">取消</button>
                <button class="btn btn-primary" onclick="saveSettings()">保存</button>
            </div>
        </div>
    </div>

    <div class="toast-container" id="toastContainer"></div>

    <script>
        // 状态
        let currentStep = 1;
        let selectedSources = ['news'];
        let selectedNewsLangs = ['zh', 'en'];
        let newsArticles = [];
        let githubRepos = [];
        let marketStocks = [];
        let selectedArticles = [];
        let selectedRepos = [];
        let selectedStocks = [];
        let currentBriefing = '';
        let currentAudioPath = '';
        let modelConnected = false;

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            loadModels();
            loadTtsEngines();
            checkModelStatus();
            
            // 预选中文和英文
            document.querySelectorAll('#newsLangGrid .lang-item').forEach(item => {
                if (selectedNewsLangs.includes(item.dataset.lang)) {
                    item.classList.add('selected');
                }
            });
        });

        // 步骤导航
        function goToStep(step) {
            document.querySelectorAll('.step-item').forEach(item => item.classList.remove('active'));
            document.querySelector(`.step-item[data-step="${step}"]`).classList.add('active');
            document.querySelectorAll('.step-content').forEach(s => s.classList.remove('active'));
            document.getElementById(`step-${step}`).classList.add('active');
            currentStep = step;
        }

        // 素材来源选择
        function toggleSource(el) {
            const source = el.dataset.source;
            if (selectedSources.includes(source)) {
                if (selectedSources.length > 1) {
                    selectedSources = selectedSources.filter(s => s !== source);
                    el.classList.remove('selected');
                }
            } else {
                selectedSources.push(source);
                el.classList.add('selected');
            }
            updateSourceStats();
        }

        function toggleNewsLang(el, event) {
            event.stopPropagation();
            const lang = el.dataset.lang;
            if (selectedNewsLangs.includes(lang)) {
                selectedNewsLangs = selectedNewsLangs.filter(l => l !== lang);
                el.classList.remove('selected');
            } else {
                selectedNewsLangs.push(lang);
                el.classList.add('selected');
            }
        }

        function updateSourceStats() {
            const stats = document.getElementById('selectedStats');
            const hint = document.getElementById('noSourceHint');
            if (selectedSources.length > 0) {
                stats.style.display = 'grid';
                hint.style.display = 'none';
                document.getElementById('statNews').textContent = selectedSources.includes('news') ? '✓' : '-';
                document.getElementById('statGithub').textContent = selectedSources.includes('github') ? '✓' : '-';
                document.getElementById('statMarket').textContent = selectedSources.includes('market') ? '✓' : '-';
            } else {
                stats.style.display = 'none';
                hint.style.display = 'block';
            }
        }

        // 抓取内容
        async function fetchContent() {
            showToast('开始抓取内容...', 'success');
            
            // 抓取新闻
            if (selectedSources.includes('news')) {
                await fetchNews();
            }
            
            // 抓取 GitHub
            if (selectedSources.includes('github')) {
                await fetchGithub();
            }
            
            // 抓取股市
            if (selectedSources.includes('market')) {
                await fetchMarket();
            }
            
            goToStep(2);
        }

        async function fetchNews() {
            try {
                const res = await fetch('/api/news/list?language=' + selectedNewsLangs[0] + '&per_page=50');
                const data = await res.json();
                newsArticles = data.articles || [];
                selectedArticles = newsArticles.slice(0, 10).map(a => a.path);
                renderNewsList();
                showToast(`获取 ${newsArticles.length} 篇新闻`, 'success');
            } catch (e) {
                showToast('新闻抓取失败: ' + e.message, 'error');
            }
        }

        async function fetchGithub() {
            try {
                const since = document.getElementById('githubSince').value;
                const lang = document.getElementById('githubLang').value;
                const res = await fetch('/api/github/trending?since=' + since + '&language=' + lang + '&limit=25');
                const data = await res.json();
                githubRepos = data.repos || [];
                selectedRepos = githubRepos.slice(0, 5).map(r => r.name);
                renderGithubList();
                showToast(`获取 ${githubRepos.length} 个 GitHub 项目`, 'success');
            } catch (e) {
                showToast('GitHub 抓取失败: ' + e.message, 'error');
            }
        }

        async function fetchMarket() {
            try {
                const market = document.getElementById('marketType').value;
                const topN = document.getElementById('marketTopN').value;
                const res = await fetch('/api/market/map?market=' + market + '&top_n=' + topN);
                const data = await res.json();
                marketStocks = data.data?.stocks || [];
                selectedStocks = marketStocks.slice(0, 20).map(s => s.code);
                renderMarketList();
                showToast(`获取 ${marketStocks.length} 只股票数据`, 'success');
            } catch (e) {
                showToast('股市数据获取失败: ' + e.message, 'error');
            }
        }

        // 渲染列表
        function renderNewsList() {
            const card = document.getElementById('newsSelectCard');
            const list = document.getElementById('newsList');
            card.style.display = 'block';
            document.getElementById('newsCount').textContent = selectedArticles.length + ' 篇';
            
            list.innerHTML = newsArticles.map(a => `
                <div class="article-item ${selectedArticles.includes(a.path) ? 'selected' : ''}" onclick="toggleArticle('${a.path}')">
                    <input type="checkbox" class="article-checkbox" ${selectedArticles.includes(a.path) ? 'checked' : ''} onclick="event.stopPropagation()">
                    <div class="article-info">
                        <div class="article-title">${a.title || '无标题'}</div>
                        <div class="article-meta">${a.website || ''} · ${a.date || ''}</div>
                    </div>
                </div>
            `).join('');
        }

        function renderGithubList() {
            const card = document.getElementById('githubSelectCard');
            const list = document.getElementById('githubList');
            card.style.display = 'block';
            document.getElementById('githubCount').textContent = selectedRepos.length + ' 个';
            
            list.innerHTML = githubRepos.map((r, i) => `
                <div class="github-item ${selectedRepos.includes(r.name) ? 'selected' : ''}" onclick="toggleRepo('${r.name}')">
                    <div class="github-rank ${i < 3 ? 'top3' : ''}">${i + 1}</div>
                    <div class="github-info">
                        <div class="github-name">${r.name}</div>
                        <div class="github-desc">${r.description || '无描述'}</div>
                        <div class="github-stats">
                            <span>⭐ ${r.stars?.toLocaleString() || 0}</span>
                            <span>🔀 ${r.forks || 0}</span>
                            <span>+${r.today_stars || 0} 今日</span>
                        </div>
                    </div>
                </div>
            `).join('');
        }

        function renderMarketList() {
            const card = document.getElementById('marketSelectCard');
            const list = document.getElementById('marketList');
            card.style.display = 'block';
            document.getElementById('marketCount').textContent = selectedStocks.length + ' 只';
            
            list.innerHTML = `<div class="stock-grid">${marketStocks.slice(0, 50).map(s => `
                <div class="stock-item ${s.change >= 0 ? 'up' : 'down'}" onclick="toggleStock('${s.code}')">
                    <div class="stock-name">${s.name || s.code}</div>
                    <div class="stock-change">${s.change >= 0 ? '+' : ''}${(s.change || 0).toFixed(2)}%</div>
                </div>
            `).join('')}</div>`;
        }

        function toggleArticle(path) {
            if (selectedArticles.includes(path)) {
                selectedArticles = selectedArticles.filter(p => p !== path);
            } else {
                selectedArticles.push(path);
            }
            renderNewsList();
        }

        function toggleRepo(name) {
            if (selectedRepos.includes(name)) {
                selectedRepos = selectedRepos.filter(n => n !== name);
            } else {
                selectedRepos.push(name);
            }
            renderGithubList();
        }

        function toggleStock(code) {
            if (selectedStocks.includes(code)) {
                selectedStocks = selectedStocks.filter(c => c !== code);
            } else {
                selectedStocks.push(code);
            }
            renderMarketList();
        }

        function selectAllNews() {
            selectedArticles = newsArticles.map(a => a.path);
            renderNewsList();
        }

        function deselectAllNews() {
            selectedArticles = [];
            renderNewsList();
        }

        // 生成简报
        function generateBriefing() {
            if (selectedArticles.length === 0 && selectedRepos.length === 0 && selectedStocks.length === 0) {
                showToast('请选择内容', 'warning');
                return;
            }

            const btn = document.getElementById('generateBtn');
            btn.disabled = true;
            btn.textContent = '生成中...';

            const progress = document.getElementById('briefingProgress');
            const status = document.getElementById('briefingStatus');
            const output = document.getElementById('briefingOutput');

            progress.style.display = 'block';
            status.innerHTML = '<div class="progress-status"><div class="progress-spinner"></div><span>正在生成简报...</span></div>';
            output.innerHTML = '';

            fetch('/api/briefing/from-articles', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({
                    articles: selectedArticles,
                    github_repos: selectedRepos,
                    stocks: selectedStocks,
                    language: document.getElementById('outputLang').value,
                })
            }).then(response => {
                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                let content = '';

                function read() {
                    reader.read().then(({ done, value }) => {
                        if (done) {
                            progress.querySelector('.progress-fill').style.width = '100%';
                            status.innerHTML = '<span class="badge badge-success">✓ 生成完成</span>';
                            btn.disabled = false;
                            btn.textContent = '✨ 生成简报';
                            document.getElementById('nextToTTS').style.display = 'inline-flex';
                            currentBriefing = content;
                            document.getElementById('ttsContent').value = content;
                            updateTtsPreview();
                            showToast('简报生成成功', 'success');
                            return;
                        }

                        const text = decoder.decode(value);
                        text.split('\n').forEach(line => {
                            if (line.startsWith('data: ')) {
                                try {
                                    const data = JSON.parse(line.slice(6));
                                    if (data.content) {
                                        content += data.content;
                                        output.innerHTML = renderMarkdown(content);
                                        output.scrollTop = output.scrollHeight;
                                    }
                                } catch (e) {}
                            }
                        });
                        read();
                    });
                }
                read();
            }).catch(err => {
                btn.disabled = false;
                btn.textContent = '✨ 生成简报';
                status.innerHTML = '<span class="badge badge-danger">✗ 生成失败</span>';
                showToast('生成失败: ' + err.message, 'error');
            });
        }

        function renderMarkdown(text) {
            if (!text) return '';
            return text
                .replace(/\r\n/g, '\n')
                .replace(/^### (.*$)/gim, '<h3>$1</h3>')
                .replace(/^## (.*$)/gim, '<h2>$1</h2>')
                .replace(/^# (.*$)/gim, '<h1>$1</h1>')
                .replace(/\*\*\*(.*?)\*\*\*/gim, '<strong><em>$1</em></strong>')
                .replace(/\*\*(.*?)\*\*/gim, '<strong>$1</strong>')
                .replace(/\*(.*?)\*/gim, '<em>$1</em>')
                .replace(/`([^`]+)`/gim, '<code>$1</code>')
                .replace(/^>\s*(.*$)/gim, '<blockquote>$1</blockquote>')
                .replace(/^- (.*$)/gim, '<li>$1</li>')
                .replace(/\n/gim, '<br>');
        }

        // TTS
        function loadTtsEngines() {
            fetch('/api/tts/engines').then(r => r.json()).then(data => {
                const select = document.getElementById('ttsEngine');
                select.innerHTML = '';
                const engines = data.engines || [];
                if (engines.length === 0) {
                    select.innerHTML = '<option value="">无可用引擎</option>';
                    return;
                }
                engines.forEach(e => {
                    const opt = document.createElement('option');
                    opt.value = e.name;
                    opt.textContent = e.name + (e.offline ? ' (离线)' : ' (在线)');
                    select.appendChild(opt);
                });
                loadVoices();
            }).catch(err => {
                console.error('Failed to load TTS engines:', err);
                document.getElementById('ttsEngine').innerHTML = '<option value="">加载失败</option>';
            });
        }

        function onEngineChange() {
            loadVoices();
        }

        function loadVoices() {
            const engine = document.getElementById('ttsEngine').value;
            const language = document.getElementById('ttsLanguage').value;
            const voiceSelect = document.getElementById('ttsVoice');
            
            if (!engine) {
                voiceSelect.innerHTML = '<option value="">请选择引擎</option>';
                return;
            }
            
            voiceSelect.innerHTML = '<option value="">加载中...</option>';
            
            fetch('/api/tts/voices?engine=' + encodeURIComponent(engine) + '&language=' + encodeURIComponent(language))
                .then(r => r.json())
                .then(data => {
                    voiceSelect.innerHTML = '';
                    const voices = data.voices || [];
                    if (voices.length === 0) {
                        voiceSelect.innerHTML = '<option value="">无可用语音</option>';
                        return;
                    }
                    voices.forEach(v => {
                        const opt = document.createElement('option');
                        opt.value = v.id;
                        opt.textContent = v.name + (v.gender ? ' (' + v.gender + ')' : '');
                        opt.dataset.language = v.language || '';
                        voiceSelect.appendChild(opt);
                    });
                    
                    // 自动选择第一个匹配语言的语音
                    const langPrefix = language.split('-')[0];
                    const matchingVoice = Array.from(voiceSelect.options).find(opt => {
                        const voiceLang = opt.dataset.language || '';
                        return voiceLang.startsWith(langPrefix) || voiceLang.startsWith(language);
                    });
                    if (matchingVoice) {
                        voiceSelect.value = matchingVoice.value;
                    }
                }).catch(err => {
                    console.error('Failed to load voices:', err);
                    voiceSelect.innerHTML = '<option value="">加载失败</option>';
                });
        }

        function toggleTtsMode(mode) {
            const previewBtn = document.getElementById('previewBtn');
            const editBtn = document.getElementById('editBtn');
            const previewMode = document.getElementById('ttsPreviewMode');
            const editMode = document.getElementById('ttsEditMode');
            
            if (mode === 'preview') {
                previewBtn.classList.add('active');
                editBtn.classList.remove('active');
                previewMode.style.display = 'block';
                editMode.style.display = 'none';
                updateTtsPreview();
            } else {
                previewBtn.classList.remove('active');
                editBtn.classList.add('active');
                previewMode.style.display = 'none';
                editMode.style.display = 'block';
            }
        }

        function updateTtsPreview() {
            const content = document.getElementById('ttsContent').value;
            const preview = document.getElementById('ttsPreview');
            
            if (!content || !content.trim()) {
                preview.innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 40px;">暂无内容</div>';
            } else {
                preview.innerHTML = renderMarkdown(content);
            }
        }

        // 监听编辑内容变化
        document.addEventListener('DOMContentLoaded', function() {
            const ttsContent = document.getElementById('ttsContent');
            if (ttsContent) {
                ttsContent.addEventListener('input', function() {
                    // 延迟更新预览，避免频繁渲染
                    clearTimeout(window._ttsPreviewTimer);
                    window._ttsPreviewTimer = setTimeout(updateTtsPreview, 300);
                });
            }
        });

        function generateAudio() {
            const text = document.getElementById('ttsContent').value.trim();
            if (!text) {
                showToast('请输入内容', 'warning');
                return;
            }

            const btn = document.getElementById('ttsBtn');
            const status = document.getElementById('ttsStatus');
            btn.disabled = true;
            btn.textContent = '生成中...';
            status.textContent = '正在生成音频...';

            fetch('/api/tts', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({
                    text: text,
                    engine: document.getElementById('ttsEngine').value,
                    voice: document.getElementById('ttsVoice').value,
                    language: document.getElementById('ttsLanguage').value,
                    rate: parseFloat(document.getElementById('ttsSpeed').value)
                })
            }).then(r => r.json()).then(data => {
                btn.disabled = false;
                btn.textContent = '🎵 生成音频';
                if (data.success) {
                    currentAudioPath = data.audio_path || data.data?.audio_path || '';
                    document.getElementById('audioPlayer').src = '/api/audio?path=' + encodeURIComponent(currentAudioPath);
                    document.getElementById('playBtn').disabled = false;
                    document.getElementById('saveBtn').disabled = false;
                    status.innerHTML = '<span class="badge badge-success">✓ 音频生成成功</span>';
                    showToast('音频生成成功', 'success');
                } else {
                    status.innerHTML = '<span class="badge badge-danger">✗ ' + (data.error || '生成失败') + '</span>';
                    showToast('生成失败: ' + (data.error || '未知错误'), 'error');
                }
            }).catch(err => {
                btn.disabled = false;
                btn.textContent = '🎵 生成音频';
                status.innerHTML = '<span class="badge badge-danger">✗ 网络错误</span>';
                showToast('网络错误: ' + err.message, 'error');
            });
        }

        function playAudio() {
            const player = document.getElementById('audioPlayer');
            if (player.src) player.play();
        }

        function saveAudio() {
            const link = document.createElement('a');
            link.href = '/api/audio?path=' + encodeURIComponent(currentAudioPath);
            link.download = 'briefing_' + new Date().toISOString().slice(0, 10) + '.mp3';
            link.click();
            showToast('保存成功', 'success');
        }

        // 模型设置
        function checkModelStatus() {
            fetch('/api/test-connection').then(r => r.json()).then(data => {
                modelConnected = data.available;
                const dot = document.getElementById('modelDot');
                const text = document.getElementById('modelStatusText');
                if (data.available) {
                    dot.classList.add('connected');
                    text.textContent = '模型已连接';
                } else {
                    dot.classList.remove('connected');
                    text.textContent = '未连接';
                    showSettingsModal();
                }
            });
        }

        function showSettingsModal() {
            document.getElementById('settingsModal').classList.remove('hidden');
            loadModels();
        }

        function hideSettingsModal() {
            document.getElementById('settingsModal').classList.add('hidden');
        }

        function loadModels() {
            const url = document.getElementById('ollamaUrl').value;
            fetch('/api/models?url=' + encodeURIComponent(url))
                .then(r => r.json())
                .then(data => {
                    const chatSelect = document.getElementById('chatModel');
                    const embedSelect = document.getElementById('embedModel');
                    chatSelect.innerHTML = '<option value="">请选择</option>';
                    embedSelect.innerHTML = '<option value="">请选择</option>';
                    (data.chat_models || []).forEach(m => {
                        chatSelect.innerHTML += `<option value="${m}">${m}</option>`;
                    });
                    (data.embedding_models || []).forEach(m => {
                        embedSelect.innerHTML += `<option value="${m}">${m}</option>`;
                    });
                });
        }

        function testOllama() {
            const url = document.getElementById('ollamaUrl').value;
            fetch('/api/test-connection')
                .then(r => r.json())
                .then(data => {
                    document.getElementById('ollamaStatus').textContent = data.available ? '✓ 连接成功' : '✗ 连接失败';
                    document.getElementById('ollamaStatus').style.color = data.available ? 'var(--success)' : 'var(--danger)';
                });
        }

        function saveSettings() {
            const data = {
                ollama_url: document.getElementById('ollamaUrl').value,
                chat_model: document.getElementById('chatModel').value,
                embed_model: document.getElementById('embedModel').value,
            };
            fetch('/api/settings', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify(data)
            }).then(() => {
                hideSettingsModal();
                checkModelStatus();
                showToast('设置已保存', 'success');
            });
        }

        function startOver() {
            selectedArticles = [];
            selectedRepos = [];
            selectedStocks = [];
            currentBriefing = '';
            document.getElementById('briefingOutput').innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 60px;"><div style="font-size: 48px; margin-bottom: 16px;">📝</div>点击"生成简报"开始</div>';
            document.getElementById('ttsContent').value = '';
            document.getElementById('ttsPreview').innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 40px;">暂无内容</div>';
            document.getElementById('audioPlayer').src = '';
            document.getElementById('playBtn').disabled = true;
            document.getElementById('saveBtn').disabled = true;
            document.getElementById('nextToTTS').style.display = 'none';
            toggleTtsMode('preview');
            goToStep(1);
            showToast('已重置', 'info');
        }

        function showToast(message, type = 'success') {
            const container = document.getElementById('toastContainer');
            const toast = document.createElement('div');
            toast.className = 'toast ' + type;
            toast.textContent = message;
            container.appendChild(toast);
            setTimeout(() => toast.remove(), 3000);
        }

        function changeLanguage() {
            const lang = document.getElementById('langSelect').value;
            fetch('/api/settings', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({ language: lang })
            });
        }
    </script>
</body>
</html>