mcp-demo/index.html.current
GoMrStone 1a7567231a feat: 录音素材管理系统 - 完整功能
- 视频分析: MiMo 2.5 大模型直接分析
- 场景检测: AI 视觉模型识别分镜头
- 语音识别: 每个场景单独 ASR
- 语音克隆: MiMo TTS 语音克隆
- 下载功能: 单文件/批量 ZIP 下载
- 系统设置: API 密钥配置
- 文件夹管理: 创建/移动/筛选
- 扁平化 UI: 简约按钮样式
2026-07-10 17:26:53 +08:00

280 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拍摄素材管理</title>
<link rel="stylesheet" href="/static/style.css?v=36">
</head>
<body>
<div class="app-layout">
<!-- Left Sidebar -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<span class="sidebar-logo">🎬</span>
<span class="sidebar-title">拍摄剪辑</span>
</div>
<nav class="sidebar-nav">
<div class="nav-section">
<div class="nav-item" onclick="showCreateFolderModal()" style="cursor:pointer;color:#1a73e8">
<span class="nav-icon"></span>
<span class="nav-label">新建文件夹</span>
</div>
<div class="nav-item active" data-filter="" onclick="filterByNav(this, 'all')">
<span class="nav-icon">📁</span>
<span class="nav-label">全部</span>
<span class="nav-count" id="countAll">0</span>
</div>
<div class="nav-item" data-filter="未分析" onclick="filterByNav(this, 'unanalyzed')">
<span class="nav-icon">🏷️</span>
<span class="nav-label">未标签</span>
<span class="nav-count" id="countUnanalyzed">0</span>
</div>
<div class="nav-item" data-filter="已分析" onclick="filterByNav(this, 'analyzed')">
<span class="nav-icon">✅</span>
<span class="nav-label">待拉片</span>
<span class="nav-count" id="countAnalyzed">0</span>
</div>
<div class="nav-item" data-filter="已剪辑" onclick="filterByNav(this, 'clipped')">
<span class="nav-icon">🎬</span>
<span class="nav-label">已拉片</span>
<span class="nav-count" id="countClipped">0</span>
</div>
<div class="nav-item" data-filter="recycle" onclick="filterByNav(this, 'recycle')">
<span class="nav-icon">🗑️</span>
<span class="nav-label">回收站</span>
<span class="nav-count" id="countRecycle">0</span>
</div>
</div>
<div class="nav-divider"></div>
<div class="nav-section">
<div class="nav-section-title">任务管理</div>
<div id="taskList">
<div class="nav-item" onclick="showTasks()">
<span class="nav-icon">📋</span>
<span class="nav-label">分析任务</span>
<span class="nav-count" id="countRunning">0</span>
</div>
</div>
</div>
<div class="nav-divider"></div>
<div class="nav-section">
<div class="nav-section-title">智能文件夹</div>
<div id="categoryList"></div>
</div>
</nav>
<div class="sidebar-footer">
<button class="btn btn-block btn-upload" onclick="openUploadModal()">📤 上传素材</button>
</div>
</aside>
<!-- Main Area -->
<div class="main-area">
<!-- Top Bar -->
<div class="topbar">
<div class="topbar-left">
<button class="btn btn-icon" id="btnToggleSidebar" onclick="toggleSidebar()">☰</button>
<div class="breadcrumb">
<span class="breadcrumb-item" id="breadcrumbRoot">拍摄剪辑</span>
<span class="breadcrumb-sep"></span>
<span class="breadcrumb-item active" id="breadcrumbCurrent">全部</span>
</div>
</div>
<div class="topbar-center">
<div class="slider-group">
<span class="slider-label">小</span>
<input type="range" id="cardSizeSlider" min="160" max="360" value="240" oninput="setCardSize(this.value)">
<span class="slider-label">大</span>
</div>
</div>
<div class="topbar-right">
<div class="view-toggle">
<button class="view-btn active" id="btnGrid" onclick="setView('grid')">▦</button>
<button class="view-btn" id="btnList" onclick="setView('list')">☰</button>
</div>
<div class="search-box">
<input type="text" id="search" placeholder="搜索文件名或AI描述..." oninput="applyFilters()">
</div>
<button class="btn btn-analyze" id="btnAnalyze" onclick="startAnalysis()">🔍 分析</button>
</div>
</div>
<!-- Filter Bar -->
<div class="filterbar">
<div class="filter-group">
<label>时长:</label>
<input type="number" id="minDur" placeholder="最小" min="0" step="1" style="width:55px">
<span>-</span>
<input type="number" id="maxDur" placeholder="最大" min="0" step="1" style="width:55px">
<span>秒</span>
</div>
<div class="filter-group">
<label>分辨率:</label>
<select id="resolutionFilter" onchange="applyFilters()">
<option value="">全部</option>
<option value="4k">4K</option>
<option value="1080p">1080P</option>
<option value="vertical">竖屏</option>
</select>
</div>
<div class="filter-results" id="filterResults"></div>
<button class="btn btn-select-all" onclick="selectAllPage()">☑ 全选本页</button>
</div>
<!-- Grid -->
<div class="content-area">
<div class="grid-container">
<div class="grid" id="grid"></div>
<div class="empty-state" id="emptyState" style="display:none">
<p>📭 没有找到匹配的素材</p>
</div>
</div>
<!-- Pagination -->
<div class="pagination" id="pagination"></div>
</div>
</div>
</div>
<!-- Upload Modal -->
<div class="modal" id="uploadModal">
<div class="modal-overlay" onclick="closeUploadModal()"></div>
<div class="modal-content" style="max-width:600px">
<button class="modal-close" onclick="event.stopPropagation();closeUploadModal()">✕</button>
<div class="upload-header">
<h2>📤 上传视频素材</h2>
<p>支持 MP4、MOV、AVI、MKV 等格式,最大 4GB</p>
</div>
<div class="upload-body">
<div class="upload-dropzone" id="dropzone">
<div class="dropzone-icon">📁</div>
<p>拖拽文件到此处,或点击选择文件</p>
<input type="file" id="fileInput" multiple accept="video/*,.mp4,.mov,.avi,.mkv,.mts,.mxf,.wmv" style="position:absolute;width:100%;height:100%;top:0;left:0;opacity:0;cursor:pointer;z-index:10">
</div>
<div class="upload-category">
<label>分类:</label>
<input type="text" id="uploadCategory" value="上传素材" placeholder="输入分类名称">
</div>
<div class="upload-filelist" id="uploadFilelist"></div>
<div class="upload-progress" id="uploadProgress" style="display:none">
<div class="progress-bar">
<div class="progress-fill" id="uploadProgressFill"></div>
</div>
<span class="progress-text" id="uploadProgressText">上传中...</span>
</div>
<div class="upload-result" id="uploadResult" style="display:none"></div>
<button class="btn btn-upload-submit" id="btnUploadSubmit" onclick="submitUpload()" disabled>开始上传</button>
</div>
</div>
</div>
<!-- Task Panel -->
<div class="task-panel" id="taskPanel" style="display:none">
<div class="task-panel-header">
<span>📋 分析任务</span>
<button class="btn btn-icon" onclick="hideTasks()">✕</button>
</div>
<div class="task-panel-body" id="taskPanelBody"></div>
</div>
<!-- Analysis Progress -->
<div class="progress-overlay" id="progressBar" style="display:none">
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<span class="progress-text" id="progressText">分析中...</span>
</div>
<!-- Video Preview Modal -->
<div class="modal" id="modal">
<div class="modal-overlay" onclick="closeModal()"></div>
<div class="modal-content">
<button class="modal-close" onclick="event.stopPropagation();closeModal()">✕</button>
<div class="modal-tabs">
<button class="modal-tab active" onclick="switchModalTab('preview', this)">🎬 预览</button>
<button class="modal-tab" onclick="switchModalTab('report', this)">📊 分析报告</button>
</div>
<div class="modal-tab-content" id="tabPreview">
<video id="videoPlayer" controls preload="auto"></video>
<div class="clip-toolbar" id="clipToolbar">
<div class="clip-timeline-wrapper">
<div class="clip-timeline" id="clipTimeline">
<div class="clip-played" id="clipPlayed"></div>
<div class="clip-selection" id="clipSelection"></div>
<div class="clip-marker clip-marker-in" id="clipMarkerIn"></div>
<div class="clip-marker clip-marker-out" id="clipMarkerOut"></div>
<div class="clip-playhead" id="clipPlayhead"></div>
</div>
<div class="clip-timeaxis" id="clipTimeaxis"></div>
</div>
<div class="clip-row">
<button class="btn btn-clip-set" onclick="setClipStart()">📍 入点</button>
<span class="clip-time" id="clipStart">00:00.000</span>
<span class="clip-sep">→</span>
<button class="btn btn-clip-set" onclick="setClipEnd()">📍 出点</button>
<span class="clip-time" id="clipEnd">00:00.000</span>
<span class="clip-duration" id="clipDuration">时长: 0s</span>
<button class="btn btn-clip-play" onclick="playClipRange()">▶ 播放选区</button>
<button class="btn btn-clip-split" onclick="splitClip()">✂️ 分割</button>
<button class="btn btn-clip-save" onclick="saveClip()">💾 保存片段</button>
<button class="btn btn-clip-add" onclick="addClipToList()"> 添加到列表</button>
</div>
<div class="clip-list" id="clipList"></div>
</div>
<div class="modal-info" id="modalInfo"></div>
</div>
<div class="modal-tab-content" id="tabReport" style="display:none">
<div class="report-container" id="reportContainer"></div>
<div class="scene-section" id="sceneSection" style="display:none">
<div id="sceneResults"></div>
</div>
</div>
<div class="modal-actions">
<button class="btn btn-analyze-modal" id="modalAnalyzeBtn" onclick="analyzeFromModal()">🔍 分析</button>
<button class="btn btn-prev" onclick="navigateModal(-1)">◀ 上一个</button>
<button class="btn btn-next" onclick="navigateModal(1)">下一个 ▶</button>
</div>
</div>
</div>
<!-- 新建文件夹模态框 -->
<div class="modal" id="createFolderModal">
<div class="modal-overlay" onclick="closeCreateFolderModal()"></div>
<div class="modal-content" style="max-width:400px">
<button class="modal-close" onclick="closeCreateFolderModal()">✕</button>
<h3 style="margin:0 0 16px 0">新建文件夹</h3>
<input type="text" id="newFolderName" placeholder="输入文件夹名称" maxlength="50" style="width:100%;padding:10px;border:1px solid #ddd;border-radius:6px;font-size:14px;box-sizing:border-box">
<div style="margin-top:16px;display:flex;gap:8px;justify-content:flex-end">
<button class="btn btn-clear" onclick="closeCreateFolderModal()">取消</button>
<button class="btn btn-upload" onclick="createFolder()">创建</button>
</div>
</div>
</div>
<!-- Selected Bar -->
<div class="selected-bar" id="selectedBar" style="display:none">
<span>已选择 <strong id="selectedCount">0</strong> 个素材</span>
<div id="normalActions">
<button class="btn btn-export" onclick="exportSelected()">📥 导出报告</button>
<button class="btn btn-analyze-selected" onclick="analyzeSelected()">🔍 分析选中</button>
<button class="btn btn-move" onclick="showMoveMenu()">📁 移动到文件夹</button>
<button class="btn btn-delete-selected" onclick="deleteSelected()">🗑 移入回收站</button>
</div>
<div id="recycleActions" style="display:none">
<button class="btn btn-restore" onclick="restoreSelected()">♻️ 恢复选中</button>
<button class="btn btn-permanent-delete" onclick="permanentDeleteSelected()">🔥 彻底删除</button>
</div>
<button class="btn btn-clear" onclick="clearSelection()">✕ 清空</button>
</div>
<script src="/static/folder_functions.js"></script>
<script src="/static/app.js?v=99"></script>
</body>
</html>