Files
xiaoxia-saas/frontend-v21-ui-prototype-final.html
T
CI Bot cdf0cbdfef
Downgrade New Runners to v0.2.6 / downgrade (push) Failing after 1s
fix: use python script for downgrade to avoid heredoc issues
2026-07-13 18:15:05 +08:00

6433 lines
308 KiB
HTML
Executable File
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"/>
<title>小虾智剪 - AI智能视频创作平台</title>
<style>
:root{
--primary:#4f46e5;
--primary-dark:#4338ca;
--primary-soft:#eef2ff;
--primary-light:#818cf8;
--slate:#0f172a;
--muted:#64748b;
--line:#e2e8f0;
--bg:#f8fafc;
--green:#10b981;
--amber:#f59e0b;
--red:#ef4444;
--shadow-sm:0 10px 30px rgba(15,23,42,.06);
--shadow-md:0 24px 70px rgba(15,23,42,.09);
--radius-sm:14px;
--radius-md:18px;
--radius-lg:24px;
--radius-xl:28px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",Arial,sans-serif;color:var(--slate);background:var(--bg);line-height:1.6;min-height:100vh}
/* 背景装饰 */
.bg{position:fixed;inset:0;z-index:-2;background:radial-gradient(circle at 18% 20%,rgba(79,70,229,.11),transparent 30%),radial-gradient(circle at 86% 14%,rgba(16,185,129,.08),transparent 28%),radial-gradient(circle at 48% 80%,rgba(99,102,241,.08),transparent 34%),#f8fafc}
.dots{position:fixed;inset:0;z-index:-1;background-image:radial-gradient(circle,rgba(79,70,229,.1) 1px,transparent 1px);background-size:38px 38px;opacity:.32}
/* 通用组件 */
.tag{display:inline-flex;padding:6px 12px;border-radius:999px;border:1px solid #c7d2fe;background:#eef2ff;color:#4338ca;font-weight:700;font-size:13px}
.card{background:rgba(255,255,255,.94);border:1px solid rgba(226,232,240,.95);border-radius:var(--radius-xl);box-shadow:var(--shadow-md);padding:28px}
.btn{border:0;border-radius:var(--radius-sm);padding:11px 18px;font-weight:700;cursor:pointer;transition:.18s ease;display:inline-flex;align-items:center;justify-content:center;gap:7px;font-size:14px}
.btn.primary{background:linear-gradient(135deg,#6366f1,#4f46e5);color:#fff;box-shadow:0 14px 26px rgba(79,70,229,.22)}
.btn.primary:hover{transform:translateY(-2px);box-shadow:0 18px 34px rgba(79,70,229,.28)}
.btn.ghost{background:#fff;border:1px solid var(--line);color:#475569}
.btn.ghost:hover{border-color:#c7d2fe;color:#4338ca;background:#f8faff}
.btn.sm{padding:8px 14px;font-size:13px}
.btn:active{transform:translateY(0)}
.pill{font-size:11px;padding:4px 8px;border-radius:999px;font-weight:700;display:inline-block}
.pill.ok{background:#dcfce7;color:#166534}
.pill.warn{background:#ffedd5;color:#c2410c}
.pill.bad{background:#ffe4e6;color:#be123c}
.pill.info{background:#dbeafe;color:#1d4ed8}
.pill.muted{background:#f1f5f9;color:#64748b}
.icon{width:44px;height:44px;border-radius:16px;display:grid;place-items:center;font-size:20px}
/* 页面视图 */
.view{display:none}
.view.active{display:block}
.wrap{max-width:1440px;margin:0 auto;padding:0 24px 60px}
.page-head{display:flex;justify-content:space-between;align-items:flex-start;gap:18px;margin-bottom:22px;padding-top:32px}
.page-head h2{font-size:26px;margin:0 0 6px;letter-spacing:-.02em}
.page-head p{margin:0;color:var(--muted);line-height:1.7}
.section{padding:24px 0;border-top:1px solid #edf2f7}
.section:first-child{border-top:0;padding-top:0}
.section-title{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}
.section-title h3{margin:0;font-size:18px;font-weight:700}
.hint{border:1px solid var(--line);background:#f8fafc;color:var(--muted);border-radius:999px;padding:6px 10px;font-size:12px}
/* 顶部导航(公开页面) */
.nav{height:68px;position:sticky;top:0;z-index:50;background:rgba(255,255,255,.86);backdrop-filter:blur(18px);border-bottom:1px solid rgba(226,232,240,.92);box-shadow:0 8px 28px rgba(15,23,42,.04)}
.nav-in{max-width:1440px;margin:0 auto;height:100%;padding:0 24px;display:flex;align-items:center;justify-content:space-between}
.brand{display:flex;gap:10px;align-items:center;font-size:20px;font-weight:900}
.logo{width:38px;height:38px;border-radius:14px;background:linear-gradient(135deg,#818cf8,#4f46e5);display:grid;place-items:center;color:#fff;box-shadow:0 12px 26px rgba(79,70,229,.24);font-size:20px}
.nav-links{display:flex;gap:22px;color:var(--muted);font-weight:600}
.nav-links span{cursor:pointer;padding:8px 0;position:relative}
.nav-links .active{color:var(--primary)}
.nav-links .active::after{content:"";position:absolute;left:0;right:0;bottom:-18px;height:3px;border-radius:999px;background:var(--primary)}
.avatar-btn{width:36px;height:36px;border-radius:50%;background:var(--primary-soft);color:var(--primary-dark);display:grid;place-items:center;font-weight:800;cursor:pointer;position:relative}
.avatar-menu{position:absolute;top:48px;right:0;background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);box-shadow:var(--shadow-md);padding:8px;min-width:180px;display:none;z-index:100}
.avatar-btn:hover .avatar-menu{display:block}
.avatar-menu span{display:block;padding:10px 12px;border-radius:10px;cursor:pointer;font-size:14px}
.avatar-menu span:hover{background:var(--primary-soft);color:var(--primary-dark)}
/* 用户下拉菜单 */
.user-dropdown{display:flex;align-items:center;gap:10px;position:relative;cursor:pointer}
.user-dropdown .name{font-weight:600;font-size:14px}
.user-dropdown .role{font-size:12px;color:var(--muted)}
/* Hero区域 */
.hero{display:grid;grid-template-columns:1fr 420px;gap:48px;align-items:center;padding:60px 0 50px}
.hero h1{font-size:44px;line-height:1.1;margin:16px 0 14px;letter-spacing:-.04em}
.hero p{font-size:17px;line-height:1.8;color:var(--muted);margin:0 0 22px}
.hero-actions{display:flex;gap:12px;margin-top:8px}
.hero-actions .btn{padding:14px 24px;font-size:15px}
.hero-visual{border-radius:28px;background:#fff;border:1px solid var(--line);box-shadow:0 30px 90px rgba(15,23,42,.15);padding:18px;position:relative;overflow:hidden}
.hero-video{height:260px;border-radius:22px;background:linear-gradient(135deg,#111827,#312e81);position:relative;overflow:hidden;display:grid;place-items:center;color:#fff}
.hero-video::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 72% 28%,rgba(255,255,255,.22),transparent 24%),linear-gradient(0deg,rgba(0,0,0,.42),transparent)}
.play-btn{position:relative;z-index:1;width:72px;height:72px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.18);border:1px solid rgba(255,255,255,.25);backdrop-filter:blur(8px);font-size:28px}
.hero-info{margin-top:14px;display:flex;justify-content:space-between;align-items:center}
.hero-badge{display:flex;gap:10px}
.demo-badge{background:linear-gradient(135deg,#fef3c7,#fde68a);color:#92400e;padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600}
/* 功能卡片 */
.feature-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin:30px 0}
.feature{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:22px;transition:.18s ease}
.feature:hover{transform:translateY(-3px);box-shadow:var(--shadow-sm)}
.feature .icon{margin-bottom:14px}
.feature h3{margin:0 0 8px;font-size:16px}
.feature p{margin:0;color:var(--muted);line-height:1.6;font-size:13px}
/* 工作流程 */
.workflow{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:30px 0}
.workflow-step{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:18px;text-align:center;position:relative}
.workflow-step:not(:last-child)::after{content:"→";position:absolute;right:-18px;top:50%;transform:translateY(-50%);color:var(--primary-light);font-size:20px;font-weight:700}
.workflow-step .step-num{width:32px;height:32px;border-radius:10px;background:var(--primary);color:#fff;display:inline-grid;place-items:center;font-weight:800;margin-bottom:10px}
.workflow-step h4{margin:0 0 6px;font-size:15px}
.workflow-step p{margin:0;color:var(--muted);font-size:12px}
/* 定价卡片 */
.pricing-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin:30px 0}
.pricing-card{background:#fff;border:2px solid var(--line);border-radius:var(--radius-lg);padding:26px;text-align:center;transition:.18s ease;position:relative}
.pricing-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-sm)}
.pricing-card.popular{border-color:var(--primary);background:linear-gradient(180deg,#fff,#f5f7ff)}
.pricing-card .icon{margin:0 auto 14px}
.pricing-card h3{margin:0 0 4px;font-size:18px}
.pricing-card .desc{color:var(--muted);font-size:13px;margin:0 0 16px}
.pricing-card .price{font-size:32px;font-weight:800;color:var(--slate)}
.pricing-card .price span{font-size:14px;font-weight:400;color:var(--muted)}
.pricing-card .features{text-align:left;margin:18px 0;color:#475569;font-size:13px;line-height:2}
.pricing-card .features div{padding:2px 0}
.pricing-card .btn{width:100%;margin-top:16px}
.pricing-card .popular-tag{position:absolute;top:-12px;left:50%;transform:translateX(-50%);background:var(--primary);color:#fff;padding:4px 14px;border-radius:999px;font-size:12px;font-weight:700}
/* KPI卡片 */
.kpi-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.kpi{background:linear-gradient(180deg,#fff,#f8fafc);border:1px solid var(--line);border-radius:var(--radius-lg);padding:20px;transition:.18s ease}
.kpi:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.kpi .value{font-size:30px;font-weight:800;color:var(--slate)}
.kpi .label{color:var(--muted);font-size:13px;margin-top:4px}
.kpi .trend{font-size:12px;margin-top:8px}
.kpi .trend.up{color:var(--green)}
.kpi .trend.down{color:var(--red)}
/* 侧边栏布局 */
.app-layout{display:grid;grid-template-columns:240px 1fr;gap:24px;min-height:calc(100vh - 68px)}
.sidebar{background:rgba(255,255,255,.88);backdrop-filter:blur(18px);border-right:1px solid rgba(226,232,240,.9);padding:24px 16px;position:sticky;top:68px;height:calc(100vh - 68px);overflow-y:auto}
.sidebar-logo{display:flex;gap:10px;align-items:center;font-size:18px;font-weight:800;margin-bottom:28px;padding:0 8px}
.sidebar-nav{display:flex;flex-direction:column;gap:4px}
.sidebar-item{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:var(--radius-sm);color:var(--muted);cursor:pointer;font-weight:600;font-size:14px;transition:.15s ease}
.sidebar-item:hover{background:var(--primary-soft);color:var(--primary)}
.sidebar-item.active{background:var(--primary-soft);color:var(--primary);font-weight:700}
.sidebar-item .icon{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;font-size:18px;background:#f1f5f9}
.sidebar-item.active .icon{background:var(--primary);color:#fff}
.sidebar-divider{height:1px;background:var(--line);margin:16px 0}
.sidebar-bottom{margin-top:auto;padding-top:20px;border-top:1px solid var(--line)}
/* 主内容区 */
.main-content{padding:0}
.main-content .page-head{padding-top:24px}
/* 标题库 */
.titles-layout{display:grid;grid-template-columns:220px 1fr;gap:20px}
.category-list{display:flex;flex-direction:column;gap:8px}
.category-item{border:1px solid var(--line);background:#fff;border-radius:var(--radius-sm);padding:14px;cursor:pointer;transition:.15s ease}
.category-item:hover{transform:translateX(4px)}
.category-item.active{border-color:var(--primary);background:var(--primary-soft)}
.category-item h4{margin:0 0 4px;font-size:14px}
.category-item span{font-size:12px;color:var(--muted)}
.titles-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.title-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:16px;cursor:pointer;transition:.18s ease}
.title-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.title-card .content{font-size:14px;font-weight:600;margin-bottom:10px;line-height:1.5}
.title-card .meta{display:flex;justify-content:space-between;align-items:center}
.title-card .stats{font-size:12px;color:var(--muted)}
.favorite{color:var(--amber);font-size:16px;cursor:pointer}
/* 素材库 */
.assets-layout{display:grid;grid-template-columns:260px 1fr;gap:20px}
.asset-library-list{display:flex;flex-direction:column;gap:8px}
.asset-library-item{border:1px solid var(--line);background:#fff;border-radius:var(--radius-sm);padding:14px;cursor:pointer;transition:.15s ease}
.asset-library-item.active{border-color:var(--primary);background:var(--primary-soft)}
.asset-library-item h4{margin:0 0 4px;font-size:14px}
.asset-library-item span{font-size:12px;color:var(--muted)}
.asset-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.asset-card{border:1px solid var(--line);background:#fff;border-radius:var(--radius-md);overflow:hidden;cursor:pointer;transition:.18s ease}
.asset-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-sm)}
.asset-thumb{aspect-ratio:9/16;border-radius:var(--radius-sm) var(--radius-sm) 0 0;position:relative;overflow:hidden;display:grid;place-items:center;color:#fff}
.asset-thumb .play{position:absolute;width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.25);display:grid;place-items:center;backdrop-filter:blur(4px)}
.asset-info{padding:12px}
.asset-info h4{margin:0 0 6px;font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.asset-info .meta{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--muted)}
/* 配音库 */
.voices-layout{display:grid;grid-template-columns:220px 1fr;gap:20px}
.voice-list{display:flex;flex-direction:column;gap:10px}
.voice-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:16px;display:grid;grid-template-columns:50px 1fr auto;gap:14px;align-items:center;transition:.18s ease}
.voice-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.voice-icon{width:50px;height:50px;border-radius:50%;display:grid;place-items:center;color:#fff;font-size:22px}
.voice-info h4{margin:0 0 4px;font-size:14px;font-weight:600}
.voice-info .meta{font-size:12px;color:var(--muted)}
.voice-wave{height:24px;width:120px;border-radius:999px;background:repeating-linear-gradient(90deg,#c7d2fe 0 5px,transparent 5px 10px)}
.voice-actions{display:flex;gap:8px}
/* 模板库 */
.template-toolbar{display:flex;justify-content:space-between;align-items:center;gap:16px;margin-bottom:20px}
.search-box{display:flex;align-items:center;gap:10px;background:#fff;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;flex:1;max-width:400px}
.search-box input{border:0;outline:0;padding:12px 0;font-size:14px;width:100%}
.template-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.template-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);overflow:hidden;cursor:pointer;transition:.18s ease}
.template-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-sm)}
.template-thumb{aspect-ratio:16/9;display:grid;place-items:center;color:#fff;font-size:28px;font-weight:700;position:relative}
.template-thumb::after{content:"";position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.3),transparent)}
.template-thumb span{position:relative;z-index:1}
.template-info{padding:14px}
.template-info h4{margin:0 0 6px;font-size:14px;font-weight:600}
.template-info .meta{font-size:12px;color:var(--muted);display:flex;justify-content:space-between}
/* 一键生成 */
.generate-layout{display:grid;grid-template-columns:1fr 320px;gap:24px}
.steps-bar{display:flex;justify-content:center;gap:8px;margin-bottom:28px}
.step-item{display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:var(--radius-sm);color:var(--muted);font-weight:600;font-size:14px}
.step-item.active{background:var(--primary-soft);color:var(--primary)}
.step-item.done{color:var(--green)}
.step-item .num{width:26px;height:26px;border-radius:50%;background:#f1f5f9;display:grid;place-items:center;font-size:12px;font-weight:700}
.step-item.active .num{background:var(--primary);color:#fff}
.step-item.done .num{background:var(--green);color:#fff}
.step-item .arrow{color:#cbd5e1}
.generate-form{display:flex;flex-direction:column;gap:16px}
.form-section{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:20px}
.form-section h3{margin:0 0 14px;font-size:15px}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.form-field label{display:block;font-weight:600;margin-bottom:8px;font-size:13px}
.form-field input,.form-field select{width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);background:#fff;padding:0 14px;font-size:14px;outline:0;transition:.15s ease}
.form-field input:focus,.form-field select:focus{border-color:var(--primary);box-shadow:0 0 0 3px rgba(79,70,229,.1)}
.choice-list{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.choice-item{background:#fff;border:2px solid var(--line);border-radius:var(--radius-md);padding:14px;cursor:pointer;transition:.18s ease;text-align:center}
.choice-item:hover{border-color:#c7d2fe}
.choice-item.selected{border-color:var(--primary);background:var(--primary-soft)}
.choice-item .thumb{height:60px;border-radius:var(--radius-sm);display:grid;place-items:center;color:#fff;font-size:24px;margin-bottom:10px}
.choice-item h4{margin:0 0 4px;font-size:13px;font-weight:600}
.choice-item p{margin:0;font-size:11px;color:var(--muted)}
.choice-item .check-icon{width:22px;height:22px;border-radius:50%;background:var(--primary);color:#fff;display:none;place-items:center;font-size:12px;position:absolute;right:-6px;top:-6px}
.choice-item{position:relative}
.choice-item.selected .check-icon{display:grid}
.generate-preview{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:20px;position:sticky;top:92px}
.preview-video{aspect-ratio:9/16;max-height:400px;border-radius:var(--radius-md);background:linear-gradient(135deg,#111827,#312e81);display:grid;place-items:center;color:#fff;font-size:36px;position:relative;overflow:hidden;margin-bottom:16px}
.preview-video::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 72% 28%,rgba(255,255,255,.2),transparent 40%)}
.preview-video .play{position:relative;z-index:1;width:60px;height:60px;border-radius:50%;background:rgba(255,255,255,.2);display:grid;place-items:center;backdrop-filter:blur(8px)}
.preview-caption{background:rgba(255,255,255,.95);color:var(--slate);border-radius:10px;padding:10px;text-align:center;font-weight:600;font-size:14px;margin-bottom:14px}
.preview-title{font-weight:600;margin-bottom:10px}
.preview-timeline{display:flex;flex-direction:column;gap:8px}
.timeline-item{display:flex;align-items:center;gap:10px;padding:10px;background:#f8fafc;border-radius:10px;font-size:13px}
.timeline-item .num{width:24px;height:24px;border-radius:8px;background:var(--primary-soft);color:var(--primary);display:grid;place-items:center;font-weight:700;font-size:11px}
.timeline-item span{color:var(--muted);margin-left:auto;font-size:12px}
.generate-actions{display:flex;gap:10px;margin-top:16px}
.generate-actions .btn{flex:1}
/* 成片库 */
.products-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.product-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);overflow:hidden;cursor:pointer;transition:.18s ease;position:relative}
.product-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-sm)}
.product-card.selected{border-color:var(--primary);box-shadow:0 0 0 2px var(--primary-soft)}
.product-thumb{aspect-ratio:9/16;position:relative;overflow:hidden;display:grid;place-items:center;color:#fff}
.product-thumb .play{position:absolute;width:48px;height:48px;border-radius:50%;background:rgba(255,255,255,.25);display:grid;place-items:center;backdrop-filter:blur(4px)}
.product-thumb .duration{position:absolute;bottom:8px;right:8px;background:rgba(0,0,0,.6);padding:2px 8px;border-radius:6px;font-size:11px}
.product-info{padding:14px}
.product-info h4{margin:0 0 8px;font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.product-info .status{display:flex;justify-content:space-between;align-items:center}
.product-select-checkbox{position:absolute;top:12px;left:12px;z-index:10}
/* 任务历史 */
.tabs{display:flex;gap:6px;margin-bottom:20px;border-bottom:1px solid var(--line);padding-bottom:12px}
.tab{padding:8px 16px;border-radius:var(--radius-sm);cursor:pointer;font-weight:600;font-size:14px;color:var(--muted);transition:.15s ease}
.tab:hover{background:#f1f5f9}
.tab.active{background:var(--primary-soft);color:var(--primary)}
.task-list{display:flex;flex-direction:column;gap:10px}
.task-item{background:#fff;border:1px solid var(--line);border-radius:var(--radius-md);padding:16px;display:grid;grid-template-columns:1fr auto auto auto;gap:16px;align-items:center;transition:.15s ease}
.task-item:hover{box-shadow:var(--shadow-sm)}
.task-info h4{margin:0 0 4px;font-size:14px;font-weight:600}
.task-info .meta{font-size:12px;color:var(--muted)}
.task-time{text-align:right;font-size:12px;color:var(--muted)}
.task-time .date{display:block;margin-bottom:2px}
/* 查重检测 */
.duplication-layout{display:grid;grid-template-columns:1fr 1fr;gap:24px}
.upload-zone{border:2px dashed var(--line);border-radius:var(--radius-lg);padding:60px;text-align:center;background:linear-gradient(180deg,#fff,#f8fafc);transition:.18s ease;cursor:pointer}
.upload-zone:hover{border-color:var(--primary-light);background:linear-gradient(180deg,#fff,var(--primary-soft))}
.upload-zone .icon{width:64px;height:64px;border-radius:20px;background:var(--primary-soft);margin:0 auto 16px;display:grid;place-items:center;font-size:28px;color:var(--primary)}
.upload-zone h3{margin:0 0 8px;font-size:18px}
.upload-zone p{margin:0;color:var(--muted);font-size:13px}
.upload-zone .formats{margin-top:12px;font-size:12px;color:var(--muted)}
.result-zone{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:24px}
.result-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}
.result-score{text-align:center;padding:30px}
.result-circle{width:140px;height:140px;border-radius:50%;margin:0 auto 16px;display:grid;place-items:center;flex-direction:column}
.result-circle .percent{font-size:36px;font-weight:800}
.result-circle .label{font-size:14px;opacity:.8}
.result-circle.low{background:linear-gradient(135deg,#dcfce7,#bbf7d0);color:#15803d}
.result-circle.mid{background:linear-gradient(135deg,#fef3c7,#fde68a);color:#92400e}
.result-circle.high{background:linear-gradient(135deg,#fee2e2,#fecaca);color:#dc2626}
.result-list{margin-top:20px}
.result-item{display:flex;align-items:center;gap:14px;padding:14px;background:#f8fafc;border-radius:var(--radius-sm);margin-bottom:10px}
.result-item .thumb{width:60px;height:80px;border-radius:8px;background:linear-gradient(135deg,#64748b,#334155);display:grid;place-items:center;color:#fff}
.result-item .info h4{margin:0 0 4px;font-size:14px;font-weight:600}
.result-item .info p{font-size:12px;color:var(--muted);margin:0}
.result-item .similarity{margin-left:auto;font-weight:700;color:var(--amber)}
/* 空状态 */
.empty-state{border:1px dashed #cbd5e1;background:linear-gradient(180deg,#fff,#f8fafc);border-radius:var(--radius-lg);padding:48px;text-align:center;color:var(--muted)}
.empty-state .icon{width:60px;height:60px;border-radius:18px;background:var(--primary-soft);margin:0 auto 16px;display:grid;place-items:center;color:var(--primary);font-size:28px;font-weight:800}
.empty-state h3{color:var(--slate);margin:0 0 8px;font-size:16px}
.empty-state p{margin:0 0 16px;font-size:14px}
/* 登录页 */
.login-page{min-height:100vh;display:grid;place-items:center;padding:40px 24px}
.login-card{background:rgba(255,255,255,.95);border:1px solid var(--line);border-radius:var(--radius-xl);box-shadow:var(--shadow-md);padding:48px;width:100%;max-width:420px}
.login-header{text-align:center;margin-bottom:32px}
.login-header .brand{display:flex;gap:10px;align-items:center;justify-content:center;font-size:24px;font-weight:900;margin-bottom:12px}
.login-header p{color:var(--muted);font-size:14px}
.login-form{display:flex;flex-direction:column;gap:16px}
.login-form .form-field label{display:block;font-weight:600;margin-bottom:8px;font-size:13px}
.login-form .form-field input{width:100%;height:48px;border:1px solid var(--line);border-radius:var(--radius-sm);background:#fff;padding:0 16px;font-size:14px;outline:0;transition:.15s ease}
.login-form .form-field input:focus{border-color:var(--primary);box-shadow:0 0 0 3px rgba(79,70,229,.1)}
.login-form .btn{width:100%;padding:14px;margin-top:8px}
.login-footer{text-align:center;margin-top:20px;font-size:14px;color:var(--muted)}
.login-footer a{color:var(--primary);font-weight:600;text-decoration:none}
.login-divider{display:flex;align-items:center;gap:16px;margin:20px 0;color:var(--muted);font-size:13px}
.login-divider::before,.login-divider::after{content:"";flex:1;height:1px;background:var(--line)}
/* 订阅页 */
.subscription-page{}
/* 模态框 */
.modal-overlay{display:none;position:fixed;inset:0;z-index:200;background:rgba(15,23,42,.5);backdrop-filter:blur(8px);place-items:center;padding:24px}
.modal-overlay.show{display:grid}
.modal{background:#fff;border-radius:var(--radius-xl);padding:32px;width:min(480px,100%);box-shadow:0 40px 120px rgba(15,23,42,.3);text-align:center}
.modal h3{font-size:22px;margin:0 0 8px}
.modal p{color:var(--muted);margin:0 0 20px;line-height:1.7}
.progress-bar{height:8px;background:#e2e8f0;border-radius:999px;overflow:hidden;margin:16px 0}
.progress-bar .fill{height:100%;background:linear-gradient(90deg,#6366f1,#4f46e5);border-radius:999px;transition:width .4s ease}
.spinner{width:64px;height:64px;border-radius:50%;margin:0 auto 18px;border:5px solid #e0e7ff;border-top-color:var(--primary);animation:spin 1s linear infinite}
.success-icon{width:64px;height:64px;border-radius:50%;background:var(--green);color:#fff;font-size:32px;display:none;place-items:center;margin:0 auto 18px}
.modal.done .spinner{display:none}
.modal.done .success-icon{display:grid}
.modal-step{font-size:13px;color:var(--muted);margin-top:12px}
@keyframes spin{to{transform:rotate(360deg)}}
/* 响应式 */
@media(max-width:1200px){
.hero{grid-template-columns:1fr}
.feature-grid,.pricing-grid,.kpi-grid{grid-template-columns:repeat(2,1fr)}
.template-grid{grid-template-columns:repeat(3,1fr)}
.products-grid{grid-template-columns:repeat(3,1fr)}
}
@media(max-width:980px){
.app-layout{grid-template-columns:1fr}
.sidebar{position:fixed;left:0;top:68px;width:260px;height:calc(100vh - 68px);transform:translateX(-100%);z-index:40}
.sidebar.open{transform:translateX(0)}
.titles-layout,.assets-layout,.voices-layout,.generate-layout,.duplication-layout{grid-template-columns:1fr}
.feature-grid,.pricing-grid,.kpi-grid,.template-grid,.products-grid{grid-template-columns:repeat(2,1fr)}
.workflow{grid-template-columns:repeat(2,1fr)}
.workflow-step:not(:last-child)::after{display:none}
}
@media(max-width:720px){
.wrap{padding:0 16px 60px}
.hero h1{font-size:32px}
.feature-grid,.pricing-grid,.kpi-grid,.template-grid,.products-grid,.workflow{grid-template-columns:1fr}
.choice-list{grid-template-columns:repeat(2,1fr)}
.task-item{grid-template-columns:1fr;gap:10px}
.tabs{flex-wrap:wrap}
.form-row{grid-template-columns:1fr}
.step-item .label{display:none}
}
/* 隐藏导航 */
.nav-hidden{display:none}
</style>
</head>
<body>
<div class="bg"></div>
<div class="dots"></div>
<!-- 顶部导航 -->
<nav class="nav" id="topNav">
<div class="nav-in">
<div class="brand">
<div class="logo">🦐</div>
<span>小虾智剪</span>
</div>
<div class="nav-links" id="navLinks">
<span class="active" data-view="home">首页</span>
<span data-view="subscription">订阅</span>
<span>帮助中心</span>
<span>联系我们</span>
</div>
<div id="authButtons">
<button class="btn ghost" onclick="showView('login')">登录</button>
<button class="btn primary" onclick="showView('login')">免费开始</button>
</div>
<div id="userMenu" class="user-dropdown" style="display:none">
<div class="avatar-btn">
<div class="avatar-menu">
<span>个人设置</span>
<span>工作空间</span>
<span onclick="logout()">退出登录</span>
</div>
</div>
<div>
<div class="name">演示用户</div>
<div class="role">标准版</div>
</div>
</div>
</div>
</nav>
<!-- 主内容 -->
<main>
<!-- 首页 -->
<section id="view-home" class="view active">
<div class="wrap">
<div class="hero">
<div>
<span class="tag">🦐 小虾智剪 · AI智能视频创作平台</span>
<h1>上传素材,AI自动剪辑<br/>一键生成短视频</h1>
<p>面向口播、产品介绍、直播切片和企业宣传的智能视频创作平台。素材管理、智能分类、一键生成、成片查重,全流程自动化处理。</p>
<div class="hero-actions">
<button class="btn primary" onclick="login()">立即免费开始</button>
<button class="btn ghost" onclick="showView('subscription')">查看定价方案</button>
</div>
</div>
<div class="hero-visual">
<div class="hero-video">
<div class="play-btn"></div>
</div>
<div class="hero-info">
<div class="hero-badge">
<span class="demo-badge">✨ AI智能剪辑</span>
<span class="demo-badge">⚡ 30秒生成</span>
</div>
<span class="pill ok">可发布</span>
</div>
<p style="color:#64748b;line-height:1.6;margin:12px 0 0;font-size:13px">小虾智剪 让视频创作变得简单高效</p>
</div>
</div>
<div class="feature-grid">
<div class="feature">
<div class="icon" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">🎬</div>
<h3>AI智能剪辑</h3>
<p>智能分析素材内容,自动匹配最佳剪辑方案,一键生成专业级短视频。</p>
</div>
<div class="feature">
<div class="icon" style="background:linear-gradient(135deg,#10b981,#059669)">📦</div>
<h3>素材自动分类</h3>
<p>AI自动识别素材内容,智能打标签,支持视频、音频、图片统一管理。</p>
</div>
<div class="feature">
<div class="icon" style="background:linear-gradient(135deg,#6366f1,#4f46e5)"></div>
<h3>一键生成视频</h3>
<p>选择模板和素材,系统自动完成剪辑、配音、字幕,30秒快速出片。</p>
</div>
<div class="feature">
<div class="icon" style="background:linear-gradient(135deg,#f59e0b,#d97706)">🔍</div>
<h3>成片查重检测</h3>
<p>智能检测视频相似度,支持MP4/AVI/MOV/MKV格式,确保内容原创性。</p>
</div>
</div>
<div class="section">
<div class="section-title">
<h3>工作流程</h3>
</div>
<div class="workflow">
<div class="workflow-step">
<div class="step-num">1</div>
<h4>上传素材</h4>
<p>上传视频、音频、图片素材</p>
</div>
<div class="workflow-step">
<div class="step-num">2</div>
<h4>AI分析</h4>
<p>智能识别内容自动分类</p>
</div>
<div class="workflow-step">
<div class="step-num">3</div>
<h4>智能剪辑</h4>
<p>选择模板自动生成剪辑方案</p>
</div>
<div class="workflow-step">
<div class="step-num">4</div>
<h4>一键导出</h4>
<p>快速导出高质量成片</p>
</div>
</div>
</div>
<div class="section" id="pricing-home">
<div class="section-title">
<h3>定价方案</h3>
<button class="btn ghost sm" onclick="showView('subscription')">查看全部方案 →</button>
</div>
<div class="pricing-grid">
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#94a3b8,#64748b);margin:0 auto"></div>
<h3>体验版</h3>
<p class="desc">免费体验基础功能</p>
<div class="price">¥0 <span>/ 永久</span></div>
<div class="features">
<div>✓ 1个工作空间</div>
<div>✓ 基础素材库管理</div>
<div>✓ 每月10次视频生成</div>
</div>
<button class="btn ghost" onclick="login()">开始体验</button>
</div>
<div class="pricing-card popular">
<span class="popular-tag">推荐</span>
<div class="icon" style="background:linear-gradient(135deg,#6366f1,#4f46e5);margin:0 auto"></div>
<h3>标准版</h3>
<p class="desc">适合个人创作者</p>
<div class="price">¥99 <span>/ 月</span></div>
<div class="features">
<div>✓ 3个项目空间</div>
<div>✓ 500条素材管理</div>
<div>✓ 每月200次视频生成</div>
</div>
<button class="btn primary" onclick="login()">立即开通</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#10b981,#059669);margin:0 auto"></div>
<h3>专业版</h3>
<p class="desc">适合团队高频创作</p>
<div class="price">¥299 <span>/ 月</span></div>
<div class="features">
<div>✓ 20个项目空间</div>
<div>✓ 5000条素材管理</div>
<div>✓ 每月1000次视频生成</div>
</div>
<button class="btn ghost" onclick="login()">了解详情</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#f59e0b,#d97706);margin:0 auto"></div>
<h3>企业版</h3>
<p class="desc">专属定制服务</p>
<div class="price">定制 <span>/ 方案</span></div>
<div class="features">
<div>✓ 无限项目空间</div>
<div>✓ 私有化部署</div>
<div>✓ 专属技术支持</div>
</div>
<button class="btn ghost" onclick="login()">联系销售</button>
</div>
</div>
</div>
<div class="section" style="text-align:center;padding:40px 0">
<h2 style="font-size:28px;margin-bottom:12px">准备好开始了吗?</h2>
<p style="color:var(--muted);margin-bottom:24px">立即注册,体验AI智能视频创作的便捷</p>
<button class="btn primary" style="padding:16px 32px;font-size:16px" onclick="login()">免费开始使用 →</button>
</div>
</div>
</section>
<!-- 登录页 -->
<section id="view-login" class="view">
<div class="login-page">
<div class="login-card">
<div class="login-header">
<div class="brand">
<div class="logo">🦐</div>
<span>小虾智剪</span>
</div>
<p>登录到您的账户,开始智能视频创作</p>
</div>
<div class="login-form">
<div class="form-field">
<label>邮箱地址</label>
<input type="email" placeholder="请输入邮箱"/>
</div>
<div class="form-field">
<label>密码</label>
<input type="password" placeholder="请输入密码"/>
</div>
<button class="btn primary" onclick="doLogin()">登录</button>
</div>
<div class="login-divider"></div>
<button class="btn ghost" style="width:100%" onclick="doLogin()">微信登录</button>
<div class="login-footer">
还没有账户?<a href="#" onclick="doLogin()">立即注册</a>
</div>
</div>
</div>
</section>
<!-- 订阅页 -->
<section id="view-subscription" class="view">
<div class="wrap subscription-page">
<div class="page-head">
<div>
<span class="tag">订阅与定价</span>
<h2>选择适合你的方案</h2>
<p>从个人试用到团队批量生产,灵活选择,按需升级</p>
</div>
</div>
<div class="pricing-grid">
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#94a3b8,#64748b);margin:0 auto"></div>
<h3>体验版</h3>
<p class="desc">适合先体验基础功能</p>
<div class="price">¥0 <span>/ 永久免费</span></div>
<div class="features">
<div>✓ 1个工作空间</div>
<div>✓ 基础素材库 / 标题库</div>
<div>✓ 每月10次视频生成</div>
<div>✓ 成片预览与下载</div>
<div>✓ 不含团队协作</div>
</div>
<button class="btn ghost" onclick="showView('login')">开始体验</button>
</div>
<div class="pricing-card popular">
<span class="popular-tag">推荐</span>
<div class="icon" style="background:linear-gradient(135deg,#6366f1,#4f46e5);margin:0 auto"></div>
<h3>标准版</h3>
<p class="desc">适合个人创作者</p>
<div class="price">¥99 <span>/ 月</span></div>
<div class="features">
<div>✓ 3个项目空间</div>
<div>✓ 500条素材管理</div>
<div>✓ 每月200次视频生成</div>
<div>✓ 标题库 / 配音库 / 成片库</div>
<div>✓ 签名下载与批量地址</div>
</div>
<button class="btn primary" onclick="showView('login')">选择标准版</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#10b981,#059669);margin:0 auto"></div>
<h3>专业版</h3>
<p class="desc">适合高频创作团队</p>
<div class="price">¥299 <span>/ 月</span></div>
<div class="features">
<div>✓ 20个项目空间</div>
<div>✓ 5000条素材管理</div>
<div>✓ 每月1000次视频生成</div>
<div>✓ 高风险素材诊断</div>
<div>✓ 失败任务重试与协作</div>
</div>
<button class="btn ghost" onclick="showView('login')">选择专业版</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:linear-gradient(135deg,#f59e0b,#d97706);margin:0 auto"></div>
<h3>企业版</h3>
<p class="desc">适合品牌和机构</p>
<div class="price">定制 <span>/ 专属报价</span></div>
<div class="features">
<div>✓ 无限项目与团队席位</div>
<div>✓ 私有化部署 / 专属存储</div>
<div>✓ 专属模板与品牌素材库</div>
<div>✓ API对接与权限审计</div>
<div>✓ 运维支持与SLA</div>
</div>
<button class="btn ghost" onclick="showView('login')">联系销售</button>
</div>
</div>
</div>
</section>
<!-- Dashboard -->
<section id="view-dashboard" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item active" data-view="dashboard">
<div class="icon" style="background:var(--primary);color:#fff">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="generate">
<div class="icon" style="background:var(--primary);color:#fff"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>欢迎回来,演示用户 👋</h2>
<p>今天是2024年,您有3个任务正在进行中</p>
</div>
<button class="btn primary" onclick="showView('generate')">✨ 一键生成视频</button>
</div>
<div class="kpi-grid">
<div class="kpi">
<div class="value">12</div>
<div class="label">项目总数</div>
<div class="trend up">↑ 2 本月新增</div>
</div>
<div class="kpi">
<div class="value">486</div>
<div class="label">素材总数</div>
<div class="trend up">↑ 38 本月上传</div>
</div>
<div class="kpi">
<div class="value">156</div>
<div class="label">本月生成数</div>
<div class="trend up">↑ 23% vs 上月</div>
</div>
<div class="kpi">
<div class="value">2.4GB</div>
<div class="label">存储空间</div>
<div class="trend">已用 24%</div>
</div>
</div>
<div class="section">
<div class="section-title">
<h3>最近任务</h3>
<button class="btn ghost sm" onclick="showView('history')">查看全部 →</button>
</div>
<div class="task-list">
<div class="task-item">
<div class="task-info">
<h4>产品卖点混剪视频</h4>
<div class="meta">一键生成 · 模板:画中画混剪</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">今天 14:32</span>
耗时 28秒
</div>
</div>
<div class="task-item">
<div class="task-info">
<h4>直播切片成片</h4>
<div class="meta">一键生成 · 模板:人物口播</div>
</div>
<span class="pill warn">进行中</span>
<div class="task-time">
<span class="date">今天 14:28</span>
已耗时 2分钟
</div>
</div>
<div class="task-item">
<div class="task-info">
<h4>新品上市宣传片</h4>
<div class="meta">一键生成 · 模板:品牌宣传</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">昨天 16:45</span>
耗时 35秒
</div>
</div>
</div>
</div>
<div class="section">
<div class="section-title">
<h3>快速入口</h3>
</div>
<div class="feature-grid" style="margin:0">
<div class="feature" style="cursor:pointer" onclick="showView('titles')">
<div class="icon" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">📝</div>
<h3>标题库</h3>
<p>24条标题 · 5个分类</p>
</div>
<div class="feature" style="cursor:pointer" onclick="showView('assets')">
<div class="icon" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">📦</div>
<h3>素材库</h3>
<p>486个素材 · 3个素材库</p>
</div>
<div class="feature" style="cursor:pointer" onclick="showView('generate')">
<div class="icon" style="background:linear-gradient(135deg,#10b981,#059669)"></div>
<h3>一键生成</h3>
<p>开始创作新视频</p>
</div>
<div class="feature" style="cursor:pointer" onclick="showView('products')">
<div class="icon" style="background:linear-gradient(135deg,#f59e0b,#d97706)">🎬</div>
<h3>成片库</h3>
<p>89个成片 · 3个待复核</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 标题库 -->
<section id="view-titles" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item active" data-view="titles">
<div class="icon" style="background:var(--primary);color:#fff">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>标题库</h2>
<p>管理常用标题,生成时直接选择使用</p>
</div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="openBatchImportModal()">批量导入</button>
<button class="btn primary" onclick="openNewTitleModal()">+ 新增标题</button>
</div>
</div>
<div class="titles-layout">
<div class="category-list">
<div class="category-item active">
<h4>全部标题</h4>
<span>24 条</span>
</div>
<div class="category-item">
<h4>口播开场</h4>
<span>8 条</span>
</div>
<div class="category-item">
<h4>产品介绍</h4>
<span>6 条</span>
</div>
<div class="category-item">
<h4>教程类</h4>
<span>5 条</span>
</div>
<div class="category-item">
<h4>种草推荐</h4>
<span>3 条</span>
</div>
<div class="category-item">
<h4>直播引流</h4>
<span>2 条</span>
</div>
</div>
<div class="titles-grid">
<div class="title-card">
<div class="content">3秒抓住注意力,30秒讲清卖点</div>
<div class="meta">
<div>
<span class="pill info" style="margin-right:6px">口播开场</span>
<span class="stats">使用 6 次</span>
</div>
<div style="display:flex;align-items:center;gap:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();openEditTitleModal(this.parentElement.parentElement.parentElement)">✏️ 编辑</button>
<button class="btn ghost sm" onclick="event.stopPropagation();openDeleteTitleModal(this.parentElement.parentElement.parentElement)" style="color:var(--red)">🗑️</button>
<span class="favorite favorited" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
</div>
<div class="title-card">
<div class="content">新手也能看懂的自动剪辑教程</div>
<div class="meta">
<div>
<span class="pill info" style="margin-right:6px">教程类</span>
<span class="stats">使用 3 次</span>
</div>
<span class="favorite" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">这款产品让效率提升10倍的秘密</div>
<div class="meta">
<div>
<span class="pill ok" style="margin-right:6px">种草推荐</span>
<span class="stats">使用 4 次</span>
</div>
<span class="favorite favorited" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">直播预告:今晚8点准时开始</div>
<div class="meta">
<div>
<span class="pill warn" style="margin-right:6px">直播引流</span>
<span class="stats">使用 2 次</span>
</div>
<span class="favorite" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">产品功能详解,看这一期就够了</div>
<div class="meta">
<div>
<span class="pill info" style="margin-right:6px">产品介绍</span>
<span class="stats">使用 5 次</span>
</div>
<span class="favorite favorited" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">揭秘!达人都在用的剪辑技巧</div>
<div class="meta">
<div>
<span class="pill info" style="margin-right:6px">口播开场</span>
<span class="stats">使用 3 次</span>
</div>
<span class="favorite" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">实测对比:传统方法VS智能剪辑</div>
<div class="meta">
<div>
<span class="pill ok" style="margin-right:6px">种草推荐</span>
<span class="stats">使用 2 次</span>
</div>
<span class="favorite favorited" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">如何使用小虾智剪快速生成视频</div>
<div class="meta">
<div>
<span class="pill info" style="margin-right:6px">教程类</span>
<span class="stats">使用 4 次</span>
</div>
<span class="favorite" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
<div class="title-card">
<div class="content">限时福利!今天下单立减100元</div>
<div class="meta">
<div>
<span class="pill warn" style="margin-right:6px">直播引流</span>
<span class="stats">使用 1 次</span>
</div>
<span class="favorite" onclick="event.stopPropagation();toggleFavorite(this)"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 素材库 -->
<section id="view-assets" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item active" data-view="assets">
<div class="icon" style="background:var(--primary);color:#fff">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>素材库</h2>
<p>管理视频、音频、图片素材,AI自动分类</p>
</div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="openNewAssetLibModal()">+ 新建素材库</button>
<button class="btn primary" onclick="openUploadModal()">上传素材</button>
</div>
</div>
<div class="assets-layout">
<div class="asset-library-list">
<div class="asset-library-item active">
<h4>直播切片素材库</h4>
<span>186 个素材 · 1.2GB</span>
</div>
<div class="asset-library-item">
<h4>产品展示素材库</h4>
<span>156 个素材 · 980MB</span>
</div>
<div class="asset-library-item">
<h4>用户反馈素材库</h4>
<span>144 个素材 · 320MB</span>
</div>
</div>
<div class="asset-grid">
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>主播口播开场.mp4</h4>
<div class="meta">
<span class="pill info">视频</span>
<span>00:32</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#f59e0b,#d97706)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>产品特写镜头.mp4</h4>
<div class="meta">
<span class="pill warn">待复核</span>
<span>00:18</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#10b981,#059669)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>用户评价片段.mp4</h4>
<div class="meta">
<span class="pill ok">已通过</span>
<span>00:25</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>开箱展示.mp4</h4>
<div class="meta">
<span class="pill info">视频</span>
<span>00:16</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#ec4899,#db2777)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>使用场景演示.mp4</h4>
<div class="meta">
<span class="pill ok">已通过</span>
<span>00:22</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#64748b,#475569)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>低清素材片段.mp4</h4>
<div class="meta">
<span class="pill bad">高风险</span>
<span>00:09</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#14b8a6,#0d9488)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>直播高光时刻.mp4</h4>
<div class="meta">
<span class="pill ok">已通过</span>
<span>01:15</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
<div class="asset-card">
<div class="asset-thumb" style="background:linear-gradient(135deg,#8b5cf6,#7c3aed)">
<div class="play"></div>
</div>
<div class="asset-info">
<h4>产品细节特写.mp4</h4>
<div class="meta">
<span class="pill info">视频</span>
<span>00:14</span>
</div>
<button class="btn ghost sm" onclick="event.stopPropagation();openDiagnoseModal(this.closest('.asset-card'))" style="width:100%;margin-top:8px;padding:6px;font-size:12px">🔍 诊断</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 配音库 -->
<section id="view-voices" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item active" data-view="voices">
<div class="icon" style="background:var(--primary);color:#fff">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>配音库</h2>
<p>管理配音素材,支持AI生成和手动创建</p>
</div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="openNewVoiceModal()">+ 新建配音库</button>
<button class="btn ghost" onclick="openAIGenerateModal()">🎙️ AI生成配音</button>
<button class="btn primary" onclick="openManualVoiceModal()">+ 上传配音</button>
</div>
</div>
<div class="voices-layout">
<div class="asset-library-list">
<div class="asset-library-item active">
<h4>短视频带货配音</h4>
<span>8 条配音</span>
</div>
<div class="asset-library-item">
<h4>知识分享配音</h4>
<span>5 条配音</span>
</div>
<div class="asset-library-item">
<h4>品牌宣传配音</h4>
<span>3 条配音</span>
</div>
</div>
<div class="voice-list">
<div class="voice-card">
<div class="voice-icon" style="background:linear-gradient(135deg,#ec4899,#db2777)">🎙️</div>
<div class="voice-info">
<h4>温柔女声 - 轻松种草</h4>
<div class="meta">短视频带货配音 · 00:28 · 女声</div>
</div>
<div class="voice-wave"></div>
<div class="voice-actions">
<button class="btn ghost sm">▶ 试听</button>
</div>
</div>
<div class="voice-card">
<div class="voice-icon" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">🎙️</div>
<div class="voice-info">
<h4>专业男声 - 产品介绍</h4>
<div class="meta">品牌宣传配音 · 00:35 · 男声</div>
</div>
<div class="voice-wave"></div>
<div class="voice-actions">
<button class="btn ghost sm">▶ 试听</button>
</div>
</div>
<div class="voice-card">
<div class="voice-icon" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">🎙️</div>
<div class="voice-info">
<h4>活力女声 - 直播预告</h4>
<div class="meta">短视频带货配音 · 00:15 · 女声</div>
</div>
<div class="voice-wave"></div>
<div class="voice-actions">
<button class="btn ghost sm">▶ 试听</button>
</div>
</div>
<div class="voice-card">
<div class="voice-icon" style="background:linear-gradient(135deg,#10b981,#059669)">🎙️</div>
<div class="voice-info">
<h4>知性女声 - 知识讲解</h4>
<div class="meta">知识分享配音 · 00:42 · 女声</div>
</div>
<div class="voice-wave"></div>
<div class="voice-actions">
<button class="btn ghost sm">▶ 试听</button>
</div>
</div>
<div class="voice-card">
<div class="voice-icon" style="background:linear-gradient(135deg,#f59e0b,#d97706)">🎙️</div>
<div class="voice-info">
<h4>磁性男声 - 深度测评</h4>
<div class="meta">知识分享配音 · 00:55 · 男声</div>
</div>
<div class="voice-wave"></div>
<div class="voice-actions">
<button class="btn ghost sm">▶ 试听</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 模板库 -->
<section id="view-templates" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item active" data-view="templates">
<div class="icon" style="background:var(--primary);color:#fff">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>模板库</h2>
<p>选择适合的模板,快速生成专业视频</p>
</div>
<button class="btn ghost" onclick="showView('editing-planner')">+ 创建模板</button>
</div>
<div class="template-toolbar">
<div class="search-box">
<span>🔍</span>
<input type="text" placeholder="搜索模板..."/>
</div>
<div style="display:flex;gap:8px">
<button class="btn ghost sm active">全部</button>
<button class="btn ghost sm">口播</button>
<button class="btn ghost sm">种草</button>
<button class="btn ghost sm">产品</button>
<button class="btn ghost sm">品牌</button>
</div>
</div>
<div class="template-grid">
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#fbbf24,#f59e0b)">
<span>PIP</span>
</div>
<div class="template-info">
<h4>画中画混剪</h4>
<div class="meta">
<span class="pill muted">产品展示</span>
<span>使用 56 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#3b82f6,#1d4ed8)">
<span>ONE</span>
</div>
<div class="template-info">
<h4>一镜到底</h4>
<div class="meta">
<span class="pill info">口播</span>
<span>使用 42 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">
<span>PER</span>
</div>
<div class="template-info">
<h4>人物口播</h4>
<div class="meta">
<span class="pill info">口播</span>
<span>使用 38 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#10b981,#059669)">
<span>SUP</span>
</div>
<div class="template-info">
<h4>种草推荐</h4>
<div class="meta">
<span class="pill ok">种草</span>
<span>使用 35 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#ec4899,#db2777)">
<span>REV</span>
</div>
<div class="template-info">
<h4>产品评测</h4>
<div class="meta">
<span class="pill warn">产品</span>
<span>使用 28 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#8b5cf6,#7c3aed)">
<span>BRD</span>
</div>
<div class="template-info">
<h4>品牌宣传</h4>
<div class="meta">
<span class="pill muted">品牌</span>
<span>使用 22 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#f97316,#ea580c)">
<span>LIV</span>
</div>
<div class="template-info">
<h4>直播切片</h4>
<div class="meta">
<span class="pill warn">直播</span>
<span>使用 48 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
<div class="template-card">
<div class="template-thumb" style="background:linear-gradient(135deg,#64748b,#475569)">
<span>TIP</span>
</div>
<div class="template-info">
<h4>技巧教程</h4>
<div class="meta">
<span class="pill info">教程</span>
<span>使用 18 次</span>
</div>
<button class="btn primary sm" style="width:100%;margin-top:10px" onclick="event.stopPropagation();useTemplate(this.parentElement.parentElement)">使用此模板</button>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 一键生成 -->
<section id="view-generate" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item active" data-view="generate">
<div class="icon" style="background:var(--primary);color:#fff"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>一键生成视频</h2>
<p>选择模板和素材,系统自动完成剪辑</p>
</div>
<button class="btn ghost">💾 保存草稿</button>
</div>
<div class="steps-bar">
<div class="step-item active" data-step="1">
<div class="num">1</div>
<span class="label">选择模板</span>
</div>
<span class="arrow"></span>
<div class="step-item" data-step="2">
<div class="num">2</div>
<span class="label">选择素材</span>
</div>
<span class="arrow"></span>
<div class="step-item" data-step="3">
<div class="num">3</div>
<span class="label">选择标题</span>
</div>
<span class="arrow"></span>
<div class="step-item" data-step="4">
<div class="num">4</div>
<span class="label">选择配音</span>
</div>
</div>
<div class="generate-layout">
<div class="generate-form">
<div class="form-section" id="step-1">
<h3>🎨 选择模板</h3>
<div class="choice-list">
<div class="choice-item selected" onclick="selectChoice(this)">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#fbbf24,#f59e0b)">PIP</div>
<h4>画中画混剪</h4>
<p>产品展示 · 30秒</p>
</div>
<div class="choice-item" onclick="selectChoice(this)">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#3b82f6,#1d4ed8)">ONE</div>
<h4>一镜到底</h4>
<p>口播 · 45秒</p>
</div>
<div class="choice-item" onclick="selectChoice(this)">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">PER</div>
<h4>人物口播</h4>
<p>知识分享 · 60秒</p>
</div>
</div>
</div>
<div class="form-section" id="step-2" style="display:none">
<h3>📦 选择素材</h3>
<div class="form-field">
<label>选择素材库</label>
<select>
<option>直播切片素材库</option>
<option>产品展示素材库</option>
<option>用户反馈素材库</option>
</select>
</div>
<div style="margin-top:14px">
<span class="pill ok" style="margin-right:8px">已选 12 个素材</span>
<span style="color:var(--muted);font-size:13px">系统将自动选择最合适的素材</span>
</div>
</div>
<div class="form-section" id="step-3" style="display:none">
<h3>📝 选择标题</h3>
<div class="form-field">
<label>选择标题</label>
<select>
<option>3秒抓住注意力,30秒讲清卖点</option>
<option>新手也能看懂的自动剪辑教程</option>
<option>这款产品让效率提升10倍的秘密</option>
</select>
</div>
</div>
<div class="form-section" id="step-4" style="display:none">
<h3>🎙️ 选择配音</h3>
<div class="choice-list" id="voice-choice-list" style="grid-template-columns:repeat(4,1fr);margin-bottom:16px">
<div class="choice-item" onclick="selectVoiceChoice(this, 'douyin')">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#ec4899,#db2777)">🎙️</div>
<h4>温柔女声</h4>
<p>轻松种草</p>
</div>
<div class="choice-item" onclick="selectVoiceChoice(this, 'male1')">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">🎙️</div>
<h4>专业男声</h4>
<p>产品介绍</p>
</div>
<div class="choice-item" onclick="selectVoiceChoice(this, 'female2')">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">🎙️</div>
<h4>活力女声</h4>
<p>直播预告</p>
</div>
<div class="choice-item" onclick="selectVoiceChoice(this, 'clone')" id="clone-voice-option">
<span class="check-icon"></span>
<div class="thumb" style="background:linear-gradient(135deg,#f59e0b,#d97706)">🎤</div>
<h4>克隆我的声音</h4>
<p>上传/录制</p>
</div>
</div>
<!-- 克隆声音展开区域 -->
<div id="clone-voice-expand" style="display:none;margin-top:16px;padding:20px;background:#fff;border:1px solid var(--line);border-radius:var(--radius-md)">
<h4 style="margin:0 0 12px;font-size:14px">🎤 克隆我的声音</h4>
<p style="margin:0 0 12px;font-size:12px;color:var(--muted)">上传你的声音,AI将用你的音色生成配音</p>
<div id="clone-voice-upload-area" style="border:2px dashed var(--line);border-radius:var(--radius-sm);padding:30px;text-align:center;background:#f8fafc;cursor:pointer;margin-bottom:12px" onclick="document.getElementById('clone-audio-input').click()">
<div style="font-size:28px;margin-bottom:8px">🎵</div>
<p style="margin:0;font-size:13px">拖拽或点击上传音频文件(MP3/WAV,10秒以上)</p>
<p style="margin:8px 0 0;font-size:11px;color:var(--muted)">支持格式:MP3、WAV · 建议时长:10秒~3分钟</p>
<input type="file" id="clone-audio-input" accept=".mp3,.wav" style="display:none" onchange="handleCloneAudioUpload(this)"/>
</div>
<div style="display:flex;gap:10px;margin-bottom:12px">
<button class="btn ghost" style="flex:1" onclick="openRecordModal()">🎙️ 直接录制</button>
</div>
<p style="margin:0;font-size:11px;color:var(--muted);background:#f8fafc;padding:8px 12px;border-radius:8px">💡 建议上传10秒~3分钟的清晰语音,环境安静、语速均匀效果最佳</p>
<!-- 音频预览区域 -->
<div id="clone-audio-preview" style="display:none;margin-top:12px;padding:16px;background:#f8fafc;border-radius:var(--radius-sm)">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:10px">
<button class="btn ghost sm" onclick="playCloneAudio()">▶ 播放</button>
<div style="flex:1">
<div style="height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden">
<div id="clone-audio-progress" style="height:100%;background:var(--primary);width:0%;transition:width .3s"></div>
</div>
</div>
<span id="clone-audio-duration" style="font-size:12px;color:var(--muted)">00:00 / 00:00</span>
</div>
<p id="clone-audio-name" style="margin:0;font-size:12px;color:var(--muted)">已上传音频.mp3</p>
</div>
<!-- 已克隆音色选择区域 -->
<div id="cloned-voices-select" style="margin-top:16px">
<p style="margin:0 0 8px;font-size:12px;font-weight:600;color:var(--muted)">或选择已克隆的音色:</p>
<div id="cloned-voice-list-step4" style="display:flex;flex-direction:column;gap:8px">
<!-- 动态渲染已克隆音色 -->
</div>
<button class="btn ghost sm" style="margin-top:8px" onclick="showView('voiceClone')"> 克隆新音色</button>
</div>
<button id="start-clone-btn" class="btn primary" style="width:100%;margin-top:16px" onclick="startVoiceClone()">🎤 开始克隆</button>
<!-- 克隆进度 -->
<div id="clone-progress-area" style="display:none;margin-top:16px;text-align:center">
<div style="font-size:13px;color:var(--muted);margin-bottom:8px">正在克隆音色...</div>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden;margin-bottom:8px">
<div id="clone-progress-bar" style="height:100%;background:linear-gradient(90deg,var(--primary),var(--primary-light));width:0%;transition:width .4s"></div>
</div>
<p id="clone-progress-text" style="margin:0;font-size:12px;color:var(--primary)">准备就绪</p>
</div>
<!-- 克隆成功提示 -->
<div id="clone-success-area" style="display:none;margin-top:16px;text-align:center;padding:16px;background:#dcfce7;border-radius:var(--radius-sm)">
<p style="margin:0;font-size:14px;color:#166534">✅ 音色克隆成功,可继续使用</p>
</div>
</div>
<div id="selected-voice-display" style="display:none;font-size:13px;color:var(--green);margin-bottom:12px">已选择配音</div>
</div>
<div style="display:flex;gap:12px;margin-top:8px">
<button class="btn ghost" onclick="prevStep()">← 上一步</button>
<button class="btn primary" style="flex:1" onclick="nextStep()">下一步 →</button>
</div>
</div>
<div class="generate-preview">
<div class="preview-video">
<div class="play"></div>
</div>
<div id="preview-caption" class="preview-caption">3秒抓住注意力,30秒讲清卖点</div>
<div class="preview-title">剪辑计划预览</div>
<div id="preview-timeline" class="preview-timeline">
<div class="timeline-item">
<div class="num">1</div>
<span>主讲口播 · 开场钩子</span>
<span>0-8s</span>
</div>
<div class="timeline-item">
<div class="num">2</div>
<span>产品特写 · B-roll</span>
<span>8-20s</span>
</div>
<div class="timeline-item">
<div class="num">3</div>
<span>用户反馈 · 结尾</span>
<span>20-30s</span>
</div>
</div>
<div class="generate-actions">
<button class="btn ghost">重新生成</button>
<button class="btn primary" onclick="startGeneration()">✨ 确认生成</button>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 成片库 -->
<section id="view-products" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item active" data-view="products">
<div class="icon" style="background:var(--primary);color:#fff">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>成片库</h2>
<p>查看和管理生成的视频成品</p>
</div>
<div style="display:flex;align-items:center;gap:12px">
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-size:14px;font-weight:600;color:var(--muted)">
<input type="checkbox" id="select-all-products" onchange="toggleSelectAllProducts()" style="width:16px;height:16px;accent-color:var(--primary)"/>
全选
</label>
<span id="selected-count" style="font-size:13px;color:var(--muted)">已选 <span style="color:var(--primary);font-weight:700">0</span> 个视频</span>
<button id="batch-publish-btn" class="btn primary" onclick="openBatchPublishModal()" disabled style="opacity:0.5;cursor:not-allowed">📢 批量发布</button>
<button class="btn ghost">批量下载</button>
</div>
</div>
<div class="products-grid">
<div class="product-card" data-product-id="2" data-product-name="产品卖点混剪">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#f59e0b,#d97706)">
<div class="play"></div>
<span class="duration">00:28</span>
</div>
<div class="product-info">
<h4>产品卖点混剪</h4>
<div class="status">
<span class="pill warn">待复核</span>
<span style="font-size:12px;color:var(--muted)">今天 14:28</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="3" data-product-name="种草推荐视频">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#10b981,#059669)">
<div class="play"></div>
<span class="duration">00:35</span>
</div>
<div class="product-info">
<h4>种草推荐视频</h4>
<div class="status">
<span class="pill ok">可发布</span>
<span style="font-size:12px;color:var(--muted)">昨天 16:45</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="4" data-product-name="品牌宣传片">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">
<div class="play"></div>
<span class="duration">00:45</span>
</div>
<div class="product-info">
<h4>品牌宣传片</h4>
<div class="status">
<span class="pill ok">可发布</span>
<span style="font-size:12px;color:var(--muted)">昨天 11:20</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="5" data-product-name="新品上市预告">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#ec4899,#db2777)">
<div class="play"></div>
<span class="duration">00:30</span>
</div>
<div class="product-info">
<h4>新品上市预告</h4>
<div class="status">
<span class="pill bad">已下载</span>
<span style="font-size:12px;color:var(--muted)">3天前</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="6" data-product-name="技巧教程第一期">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#8b5cf6,#7c3aed)">
<div class="play"></div>
<span class="duration">00:22</span>
</div>
<div class="product-info">
<h4>技巧教程第一期</h4>
<div class="status">
<span class="pill ok">可发布</span>
<span style="font-size:12px;color:var(--muted)">5天前</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="7" data-product-name="产品评测视频">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" onchange="toggleProductSelect(this.closest('.product-card'))" style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10"/>
</label>
<div class="product-thumb" style="background:linear-gradient(135deg,#64748b,#475569)">
<div class="play"></div>
<span class="duration">00:18</span>
</div>
<div class="product-info">
<h4>产品评测视频</h4>
<div class="status">
<span class="pill bad">已下载</span>
<span style="font-size:12px;color:var(--muted)">1周前</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
<div class="product-card" data-product-id="1" data-product-name="直播切片成片_v2" data-published="true" style="opacity:0.65">
<label class="product-select-checkbox" onclick="event.stopPropagation()">
<input type="checkbox" disabled style="width:18px;height:18px;accent-color:var(--primary);position:absolute;top:12px;left:12px;z-index:10;opacity:0.4"/>
</label>
<div style="position:absolute;top:12px;right:12px;background:var(--green);color:#fff;font-size:11px;font-weight:700;padding:3px 8px;border-radius:6px;z-index:10">已发布</div>
<div class="product-thumb" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)">
<div class="play"></div>
<span class="duration">00:32</span>
</div>
<div class="product-info">
<h4>直播切片成片_v2</h4>
<div class="status">
<span class="pill ok">可发布</span>
<span style="font-size:12px;color:var(--muted)">今天 14:32</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<span class="pill ok" style="flex:1;padding:6px 4px;font-size:12px;text-align:center;display:inline-block">✅ 已发布</span>
</div>
</div>
</div>
<div class="product-card">
<div class="product-thumb" style="background:linear-gradient(135deg,#14b8a6,#0d9488)">
<div class="play"></div>
<span class="duration">00:40</span>
</div>
<div class="product-info">
<h4>直播高光合集</h4>
<div class="status">
<span class="pill ok">可发布</span>
<span style="font-size:12px;color:var(--muted)">1周前</span>
</div>
<div style="display:flex;gap:6px;margin-top:8px">
<button class="btn ghost sm" onclick="event.stopPropagation();downloadProduct(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📥 下载</button>
<button class="btn primary sm" onclick="event.stopPropagation();openPublishModal(this.closest('.product-card'))" style="flex:1;padding:6px 4px;font-size:12px">📢 发布</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 任务历史 -->
<section id="view-history" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item active" data-view="history">
<div class="icon" style="background:var(--primary);color:#fff">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>任务历史</h2>
<p>查看所有视频生成任务的执行记录</p>
</div>
</div>
<div class="tabs">
<div class="tab active" onclick="filterTasks('all')">全部 (156)</div>
<div class="tab" onclick="filterTasks('running')">进行中 (3)</div>
<div class="tab" onclick="filterTasks('done')">已完成 (150)</div>
<div class="tab" onclick="filterTasks('failed')">失败 (3)</div>
</div>
<div class="task-list">
<div class="task-item">
<div class="task-info">
<h4>产品卖点混剪视频</h4>
<div class="meta">一键生成 · 模板:画中画混剪</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">今天 14:32</span>
耗时 28秒
</div>
<button class="btn ghost sm">查看</button>
</div>
<div class="task-item">
<div class="task-info">
<h4>直播切片成片</h4>
<div class="meta">一键生成 · 模板:人物口播</div>
</div>
<span class="pill warn">进行中</span>
<div class="task-time">
<span class="date">今天 14:28</span>
已耗时 2分钟
</div>
<button class="btn ghost sm">查看</button>
</div>
<div class="task-item">
<div class="task-info">
<h4>新品上市宣传片</h4>
<div class="meta">一键生成 · 模板:品牌宣传</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">昨天 16:45</span>
耗时 35秒
</div>
<button class="btn ghost sm">查看</button>
</div>
<div class="task-item">
<div class="task-info">
<h4>产品评测视频</h4>
<div class="meta">一键生成 · 模板:产品评测</div>
</div>
<span class="pill bad">失败</span>
<div class="task-time">
<span class="date">昨天 10:30</span>
失败
</div>
<button class="btn ghost sm">重试</button>
</div>
<div class="task-item">
<div class="task-info">
<h4>技巧教程第一期</h4>
<div class="meta">一键生成 · 模板:技巧教程</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">3天前 15:20</span>
耗时 42秒
</div>
<button class="btn ghost sm">查看</button>
</div>
<div class="task-item">
<div class="task-info">
<h4>直播高光合集</h4>
<div class="meta">一键生成 · 模板:直播切片</div>
</div>
<span class="pill ok">已完成</span>
<div class="task-time">
<span class="date">5天前 11:15</span>
耗时 55秒
</div>
<button class="btn ghost sm">查看</button>
</div>
</div>
</div>
</div>
</section>
<!-- 查重检测 -->
<section id="view-duplication" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item active" data-view="duplication">
<div class="icon" style="background:var(--primary);color:#fff">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>视频查重检测</h2>
<p>上传视频文件,检测与现有视频的相似度</p>
</div>
</div>
<div class="duplication-layout">
<div>
<div class="upload-zone" onclick="simulateUpload()">
<div class="icon">📤</div>
<h3>拖拽上传视频文件</h3>
<p>或点击选择文件上传</p>
<div class="formats">支持格式:MP4 / AVI / MOV / MKV,单文件 ≤ 2GB</div>
</div>
<div style="margin-top:16px;display:flex;gap:10px">
<button class="btn primary" style="flex:1" onclick="simulateUpload()">📤 选择文件</button>
<button class="btn ghost">📷 摄像头录制</button>
</div>
</div>
<div class="result-zone">
<div class="result-header">
<h3 style="margin:0">查重结果</h3>
<span class="pill warn">待检测</span>
</div>
<div class="result-score">
<div class="result-circle low">
<div class="percent">12%</div>
<div class="label">相似度</div>
</div>
<p style="color:var(--muted);font-size:14px;margin-top:12px">该视频相似度较低,原创性良好</p>
</div>
<div class="result-list">
<h4 style="margin:0 0 12px;font-size:14px">匹配的视频片段</h4>
<div class="result-item">
<div class="thumb"></div>
<div class="info">
<h4>直播切片成片_v1.mp4</h4>
<p>相似片段:0:08-0:12</p>
</div>
<span class="similarity">8%</span>
</div>
<div class="result-item">
<div class="thumb" style="background:linear-gradient(135deg,#0ea5e9,#0284c7)"></div>
<div class="info">
<h4>产品卖点混剪.mp4</h4>
<p>相似片段:0:22-0:25</p>
</div>
<span class="similarity">4%</span>
</div>
</div>
<button class="btn primary" style="width:100%;margin-top:16px">📥 下载检测报告</button>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- 我的音色库 -->
<section id="view-voiceClone" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon" style="background:var(--primary);color:#fff">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>🎤 我的音色库</h2>
<p>克隆和管理你的专属音色,用AI生成个性化配音</p>
</div>
<button class="btn primary" onclick="openCloneVoiceModal()">✨ 克隆新音色</button>
</div>
<!-- 音色卡片列表 -->
<div id="voice-clone-list" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;margin-top:20px">
<!-- 示例音色卡片 -->
<div class="voice-clone-card" style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:20px;position:relative">
<div style="position:absolute;top:16px;right:16px">
<button class="btn ghost sm" onclick="deleteVoiceClone(this)" style="padding:4px 8px;font-size:11px">🗑️</button>
<button class="btn ghost sm" onclick="renameVoiceClone(this)" style="padding:4px 8px;font-size:11px">✏️</button>
</div>
<div style="display:flex;align-items:center;gap:14px;margin-bottom:14px">
<div style="width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#f59e0b,#d97706);display:grid;place-items:center;color:#fff;font-size:24px">🎤</div>
<div>
<h4 style="margin:0 0 4px;font-size:15px;font-weight:600">我的默认音色</h4>
<span class="pill ok">已就绪</span>
</div>
</div>
<div style="font-size:13px;color:var(--muted);margin-bottom:12px">
<div style="margin-bottom:4px">🎵 时长:15秒</div>
<div>📅 创建于:2024年6月15日</div>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#f8fafc;border-radius:10px">
<button class="btn ghost sm" onclick="playVoiceClone(this)" style="flex:1">▶ 试听</button>
<button class="btn primary sm" onclick="useVoiceClone(this)" style="flex:1">✨ 使用此音色</button>
</div>
</div>
<!-- 更多音色卡片可通过JS动态添加 -->
</div>
<!-- 空状态 -->
<div id="voice-clone-empty" style="display:none;margin-top:40px;text-align:center;padding:48px">
<div style="font-size:64px;margin-bottom:16px">🎤</div>
<h3 style="margin:0 0 8px;font-size:18px">还没有克隆音色</h3>
<p style="margin:0 0 20px;color:var(--muted)">上传你的声音,AI将克隆你的专属音色</p>
<button class="btn primary" onclick="openCloneVoiceModal()">✨ 立即克隆</button>
</div>
</div>
</div>
</section>
<!-- 订阅管理(登录后版本) -->
<section id="view-subscription-logged" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item" data-view="accounts">
<div class="icon">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item active" data-view="subscription-logged">
<div class="icon" style="background:var(--primary);color:#fff">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>订阅管理</h2>
<p>查看和管理您的订阅套餐</p>
</div>
</div>
<!-- 当前套餐信息 -->
<div class="card" style="margin-bottom:24px">
<div style="display:flex;justify-content:space-between;align-items:center">
<div>
<div style="display:flex;align-items:center;gap:12px;margin-bottom:8px">
<span class="tag">专业版</span>
<span class="pill ok">已激活</span>
</div>
<p style="margin:0;color:var(--muted);font-size:14px">到期时间:2025年6月15日 · 自动续费</p>
</div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="openRenewModal()">续费</button>
<button class="btn ghost" onclick="openDowngradeModal()">降级</button>
<button class="btn primary" onclick="openUpgradeModal('旗舰版')">升级</button>
</div>
</div>
</div>
<!-- 套餐卡片 -->
<div class="pricing-grid">
<div class="pricing-card">
<div class="icon" style="background:#f1f5f9;margin:0 auto 14px">🆓</div>
<h3>免费版</h3>
<p class="desc">入门体验</p>
<div class="price">¥0<span>/月</span></div>
<div class="features">
<div>✓ 5个视频/月</div>
<div>✓ 基础剪辑功能</div>
<div>✓ 标准画质导出</div>
<div>✗ 无AI高级功能</div>
</div>
<button class="btn ghost" onclick="alert('当前已是免费版')">当前版本</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:var(--primary-soft);margin:0 auto 14px"></div>
<h3>个人进阶版</h3>
<p class="desc">创作者首选</p>
<div class="price">¥299<span>/月</span></div>
<div class="features">
<div>✓ 50个视频/月</div>
<div>✓ 高级剪辑功能</div>
<div>✓ 1080P高清导出</div>
<div>✓ AI智能剪辑</div>
</div>
<button class="btn ghost" onclick="openUpgradeModal('个人进阶版')">升级</button>
</div>
<div class="pricing-card popular">
<div class="popular-tag">推荐</div>
<div class="icon" style="background:var(--primary);color:#fff;margin:0 auto 14px">💎</div>
<h3>个人旗舰版</h3>
<p class="desc">专业创作者</p>
<div class="price">¥599<span>/月</span></div>
<div class="features">
<div>✓ 无限视频生成</div>
<div>✓ 4K超清导出</div>
<div>✓ 全AI功能</div>
<div>✓ 优先处理队列</div>
</div>
<button class="btn ghost" onclick="openUpgradeModal('个人旗舰版')">升级</button>
</div>
<div class="pricing-card">
<div class="icon" style="background:#fef3c7;margin:0 auto 14px">🏢</div>
<h3>企业版</h3>
<p class="desc">团队协作</p>
<div class="price">¥1999<span>/月</span></div>
<div class="features">
<div>✓ 无限视频生成</div>
<div>✓ 团队协作空间</div>
<div>✓ API接口调用</div>
<div>✓ 专属客服支持</div>
</div>
<button class="btn ghost" onclick="openUpgradeModal('企业版')">升级</button>
</div>
</div>
<!-- 账单记录 -->
<div class="section">
<div class="section-title">
<h3>账单记录</h3>
</div>
<div style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden">
<table style="width:100%;border-collapse:collapse">
<thead>
<tr style="background:#f8fafc">
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">订单号</th>
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">套餐</th>
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">金额</th>
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">支付方式</th>
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">时间</th>
<th style="padding:14px 16px;text-align:left;font-size:13px;color:var(--muted)">状态</th>
</tr>
</thead>
<tbody>
<tr style="border-top:1px solid var(--line)">
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">ORD20240615001</td>
<td style="padding:14px 16px;font-size:13px">专业版(年付)</td>
<td style="padding:14px 16px;font-size:13px;font-weight:600">¥1,299</td>
<td style="padding:14px 16px;font-size:13px">支付宝</td>
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">2024-06-15</td>
<td style="padding:14px 16px"><span class="pill ok">已支付</span></td>
</tr>
<tr style="border-top:1px solid var(--line)">
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">ORD20240615001</td>
<td style="padding:14px 16px;font-size:13px">专业版(年付)</td>
<td style="padding:14px 16px;font-size:13px;font-weight:600">¥1,299</td>
<td style="padding:14px 16px;font-size:13px">支付宝</td>
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">2024-06-15</td>
<td style="padding:14px 16px"><span class="pill ok">已支付</span></td>
</tr>
<tr style="border-top:1px solid var(--line)">
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">ORD20230615001</td>
<td style="padding:14px 16px;font-size:13px">专业版(年付)</td>
<td style="padding:14px 16px;font-size:13px;font-weight:600">¥1,199</td>
<td style="padding:14px 16px;font-size:13px">微信支付</td>
<td style="padding:14px 16px;font-size:13px;color:var(--muted)">2023-06-15</td>
<td style="padding:14px 16px"><span class="pill ok">已支付</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
<!-- 账号管理 -->
<section id="view-accounts" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="editing-planner">
<div class="icon">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-item active" data-view="accounts">
<div class="icon" style="background:var(--primary);color:#fff">🔑</div>
<span>账号管理</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<div class="main-content">
<div class="page-head">
<div>
<h2>🔑 账号管理</h2>
<p>绑定您的社交平台账号,用于视频一键发布到各平台</p>
</div>
</div>
<div class="section">
<div style="display:grid;grid-template-columns:repeat(2,1fr);gap:20px">
<!-- 抖音 -->
<div style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:24px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px">
<span style="font-size:28px">📱</span>
<div>
<h3 style="margin:0;font-size:18px">抖音</h3>
<p style="margin:4px 0 0;font-size:13px;color:var(--muted)">Douyin</p>
</div>
</div>
<div id="accounts-douyin-list" style="display:flex;flex-direction:column;gap:10px;margin-bottom:16px">
<!-- 账号1 -->
<div style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:12px">
<div style="width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#fe2c55,#25f4ee);display:grid;place-items:center;color:#fff;font-weight:700;font-size:14px">🎬</div>
<div style="flex:1">
<div style="font-weight:600;font-size:14px">小虾智剪-官方号</div>
<span class="pill ok" style="font-size:10px;padding:2px 6px">已连接</span>
</div>
<button class="btn ghost sm" onclick="openUnbindModal('douyin', '小虾智剪-官方号')" style="padding:6px 10px;font-size:12px">解绑</button>
</div>
<!-- 账号2 -->
<div style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:12px">
<div style="width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#fe2c55,#25f4ee);display:grid;place-items:center;color:#fff;font-weight:700;font-size:14px"></div>
<div style="flex:1">
<div style="font-weight:600;font-size:14px">小虾智剪-好物推荐</div>
<span class="pill ok" style="font-size:10px;padding:2px 6px">已连接</span>
</div>
<button class="btn ghost sm" onclick="openUnbindModal('douyin', '小虾智剪-好物推荐')" style="padding:6px 10px;font-size:12px">解绑</button>
</div>
</div>
<button class="btn ghost" onclick="openBindAccountModal('douyin')" style="width:100%">+ 绑定新账号</button>
</div>
<!-- 快手 -->
<div style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:24px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px">
<span style="font-size:28px">🎬</span>
<div>
<h3 style="margin:0;font-size:18px">快手</h3>
<p style="margin:4px 0 0;font-size:13px;color:var(--muted)">Kuaishou</p>
</div>
</div>
<div id="accounts-kuaishou-list" style="display:flex;flex-direction:column;gap:10px;margin-bottom:16px">
<!-- 账号1 -->
<div style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:12px">
<div style="width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#ff4906,#ffba00);display:grid;place-items:center;color:#fff;font-weight:700;font-size:14px"></div>
<div style="flex:1">
<div style="font-weight:600;font-size:14px">小虾智剪-快手</div>
<span class="pill ok" style="font-size:10px;padding:2px 6px">已连接</span>
</div>
<button class="btn ghost sm" onclick="openUnbindModal('kuaishou', '小虾智剪-快手')" style="padding:6px 10px;font-size:12px">解绑</button>
</div>
</div>
<button class="btn ghost" onclick="openBindAccountModal('kuaishou')" style="width:100%">+ 绑定新账号</button>
</div>
<!-- 小红书 -->
<div style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:24px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px">
<span style="font-size:28px">📕</span>
<div>
<h3 style="margin:0;font-size:18px">小红书</h3>
<p style="margin:4px 0 0;font-size:13px;color:var(--muted)">Xiaohongshu</p>
</div>
</div>
<div id="accounts-xiaohongshu-list" style="display:flex;flex-direction:column;gap:10px;margin-bottom:16px">
<!-- 账号1 -->
<div style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:12px">
<div style="width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#ff2442,#ff6b6b);display:grid;place-items:center;color:#fff;font-weight:700;font-size:14px">📕</div>
<div style="flex:1">
<div style="font-weight:600;font-size:14px">小虾智剪-种草号</div>
<span class="pill ok" style="font-size:10px;padding:2px 6px">已连接</span>
</div>
<button class="btn ghost sm" onclick="openUnbindModal('xiaohongshu', '小虾智剪-种草号')" style="padding:6px 10px;font-size:12px">解绑</button>
</div>
</div>
<button class="btn ghost" onclick="openBindAccountModal('xiaohongshu')" style="width:100%">+ 绑定新账号</button>
</div>
<!-- 微信视频号 -->
<div style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:24px">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:20px">
<span style="font-size:28px">💬</span>
<div>
<h3 style="margin:0;font-size:18px">微信视频号</h3>
<p style="margin:4px 0 0;font-size:13px;color:var(--muted)">WeChat Channels</p>
</div>
</div>
<div id="accounts-wechat-list" style="display:flex;flex-direction:column;gap:10px;margin-bottom:16px">
<!-- 空状态 -->
<div style="padding:20px;text-align:center;color:var(--muted);font-size:14px">
<div style="font-size:32px;margin-bottom:8px">🔓</div>
<p style="margin:0">暂未绑定账号</p>
</div>
</div>
<button class="btn ghost" onclick="openBindAccountModal('wechat')" style="width:100%">+ 绑定新账号</button>
</div>
</div>
<!-- 底部统计 -->
<div style="margin-top:24px;padding:16px 20px;background:#f8fafc;border-radius:var(--radius-md);display:flex;align-items:center;justify-content:center;gap:8px">
<span style="font-size:16px">📊</span>
<span style="font-weight:600">已绑定 <span style="color:var(--primary)">4</span> 个账号 / 支持 <span style="color:var(--primary)">4</span> 个平台</span>
</div>
</div>
</div>
</div>
</section>
<!-- ==================== 音色克隆模态框 ==================== -->
<div id="modal-cloneVoice" class="modal-overlay">
<div class="modal" style="max-width:520px;max-height:90vh;overflow-y:auto;text-align:left">
<h3 style="margin:0 0 20px;font-size:20px">🎤 克隆新音色</h3>
<!-- 音色名称 -->
<div style="margin-bottom:20px">
<label style="display:block;margin-bottom:8px;font-weight:600;font-size:14px">音色名称</label>
<input type="text" id="clone-voice-name" value="我的声音 1" placeholder="输入音色名称" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px"/>
</div>
<!-- 上传音频区域 -->
<div style="margin-bottom:20px">
<label style="display:block;margin-bottom:8px;font-weight:600;font-size:14px">上传音频</label>
<div id="clone-upload-area" style="border:2px dashed var(--line);border-radius:var(--radius-md);padding:30px;text-align:center;background:#f8fafc;cursor:pointer;transition:all .2s" onclick="document.getElementById('clone-upload-input').click()">
<div style="font-size:36px;margin-bottom:10px">🎵</div>
<p style="margin:0;font-size:14px;font-weight:600">拖拽音频文件到此处</p>
<p style="margin:8px 0 0;font-size:13px;color:var(--muted)">或点击选择文件</p>
<p style="margin:6px 0 0;font-size:11px;color:var(--muted)">支持 MP3、WAV 格式,建议时长 10秒~3分钟</p>
<input type="file" id="clone-upload-input" accept=".mp3,.wav" style="display:none" onchange="handleCloneFileUpload(this)"/>
</div>
</div>
<!-- 或分隔符 -->
<div style="display:flex;align-items:center;gap:16px;margin:20px 0">
<div style="flex:1;height:1px;background:var(--line)"></div>
<span style="font-size:13px;color:var(--muted)"></span>
<div style="flex:1;height:1px;background:var(--line)"></div>
</div>
<!-- 直接录制 -->
<div style="margin-bottom:20px">
<label style="display:block;margin-bottom:8px;font-weight:600;font-size:14px">直接录制</label>
<div id="clone-record-area" style="border:1px solid var(--line);border-radius:var(--radius-md);padding:24px;text-align:center;background:#fff">
<div id="clone-record-idle">
<p style="margin:0 0 12px;font-size:13px;color:var(--muted)">点击按钮开始录制你的声音</p>
<button id="clone-record-btn" class="btn primary" onclick="startCloneRecording()" style="width:80px;height:80px;border-radius:50%;font-size:32px;padding:0;background:linear-gradient(135deg,#ef4444,#dc2626)">🎙️</button>
<p style="margin:12px 0 0;font-size:12px;color:var(--muted)">建议录制10秒以上</p>
</div>
<div id="clone-record-recording" style="display:none">
<p style="margin:0 0 12px;font-size:14px;color:var(--red);font-weight:600">🔴 录音中...</p>
<div style="font-size:36px;font-weight:700;color:var(--red);margin-bottom:12px" id="clone-record-timer">00:00</div>
<button class="btn" onclick="stopCloneRecording()" style="width:80px;height:80px;border-radius:50%;font-size:32px;padding:0;background:var(--red);color:#fff;border:none"></button>
</div>
<div id="clone-record-preview" style="display:none">
<p style="margin:0 0 12px;font-size:14px;color:var(--green);font-weight:600">✅ 录制完成</p>
<div style="display:flex;align-items:center;justify-content:center;gap:12px">
<button class="btn ghost" onclick="reRecordClone()">🔄 重新录制</button>
<button class="btn primary" onclick="useCloneRecording()">✓ 使用此录音</button>
</div>
</div>
</div>
</div>
<!-- 音频预览 -->
<div id="clone-audio-preview-modal" style="display:none;margin-bottom:20px;padding:16px;background:#f8fafc;border-radius:var(--radius-md)">
<div style="display:flex;align-items:center;gap:12px;margin-bottom:10px">
<button class="btn ghost sm" onclick="playClonePreview()">▶ 播放</button>
<div style="flex:1">
<div style="height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden">
<div id="clone-preview-progress" style="height:100%;background:var(--primary);width:0%;transition:width .3s"></div>
</div>
</div>
<span id="clone-preview-duration" style="font-size:12px;color:var(--muted)">00:00 / 00:00</span>
</div>
<p id="clone-preview-name" style="margin:0;font-size:12px;color:var(--muted)">已上传音频.mp3</p>
<button onclick="removeCloneAudio()" style="margin-top:8px;background:none;border:none;color:var(--red);font-size:12px;cursor:pointer">🗑️ 移除</button>
</div>
<!-- 提示 -->
<div style="padding:12px 16px;background:#fef3c7;border-radius:var(--radius-sm);margin-bottom:20px;font-size:13px;color:#92400e">
💡 建议上传10秒~3分钟的清晰语音,环境安静、语速均匀效果最佳
</div>
<!-- 克隆进度 -->
<div id="clone-modal-progress" style="display:none;margin-bottom:20px;text-align:center">
<div style="font-size:14px;color:var(--muted);margin-bottom:12px">正在克隆音色...</div>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden;margin-bottom:12px">
<div id="clone-modal-progress-bar" style="height:100%;background:linear-gradient(90deg,var(--primary),var(--primary-light));width:0%;transition:width .4s"></div>
</div>
<p id="clone-modal-progress-text" style="margin:0;font-size:12px;color:var(--primary)">准备就绪</p>
</div>
<!-- 克隆成功 -->
<div id="clone-modal-success" style="display:none;margin-bottom:20px;text-align:center;padding:20px;background:#dcfce7;border-radius:var(--radius-md)">
<p style="margin:0;font-size:16px;color:#166534">🎉 音色克隆成功!</p>
<p style="margin:8px 0 0;font-size:13px;color:#15803d">你的专属音色已保存到音色库</p>
</div>
<!-- 按钮 -->
<div style="display:flex;gap:12px" id="clone-modal-buttons">
<button class="btn ghost" onclick="closeModal('modal-cloneVoice')" style="flex:1">取消</button>
<button id="clone-start-btn" class="btn primary" onclick="startCloneVoiceProcess()" style="flex:1" disabled>🎤 开始克隆</button>
</div>
<div style="display:flex;gap:12px" id="clone-modal-done" style="display:none">
<button class="btn primary" onclick="closeModal('modal-cloneVoice')" style="flex:1">完成</button>
</div>
</div>
</div>
<!-- 生成进度模态框 -->
<div id="modalOverlay" class="modal-overlay">
<div id="generationModal" class="modal">
<div class="spinner"></div>
<div class="success-icon"></div>
<h3 id="modalTitle">正在生成视频</h3>
<p id="modalText">小虾智剪正在按剪辑计划合成成片,生成完成后会自动进入成片库。</p>
<div class="progress-bar">
<div id="progressFill" class="fill" style="width:0%"></div>
</div>
<div id="modalStep" class="modal-step">正在读取素材...</div>
</div>
</div>
<script>
// ==================== 状态管理 ====================
let currentView = 'home';
let isLoggedIn = false;
let currentStep = 1;
let currentPlayingVoice = null;
let playbackTimer = null;
// 模板剪辑计划数据
const templatePlans = {
'画中画混剪': [
{ scene: '主讲口播 · 开场钩子', time: '0-8s' },
{ scene: '产品特写 · B-roll', time: '8-20s' },
{ scene: '用户反馈 · 结尾', time: '20-30s' }
],
'一镜到底': [
{ scene: '场景建立 · 环境展示', time: '0-10s' },
{ scene: '核心讲解 · 过程演示', time: '10-30s' },
{ scene: '总结收尾 · 行动号召', time: '30-45s' }
],
'人物口播': [
{ scene: '人物出场 · 自我介绍', time: '0-10s' },
{ scene: '知识要点一', time: '10-25s' },
{ scene: '知识要点二', time: '25-40s' },
{ scene: '知识要点三', time: '40-55s' },
{ scene: '总结 · 引导关注', time: '55-60s' }
],
'种草推荐': [
{ scene: '痛点切入 · 引起共鸣', time: '0-5s' },
{ scene: '产品介绍 · 核心卖点', time: '5-20s' },
{ scene: '使用体验 · 效果展示', time: '20-35s' },
{ scene: '限时优惠 · 行动号召', time: '35-45s' }
],
'产品评测': [
{ scene: '开箱亮相 · 第一印象', time: '0-8s' },
{ scene: '外观设计 · 细节展示', time: '8-20s' },
{ scene: '功能测试 · 实际体验', time: '20-35s' },
{ scene: '优缺点总结 · 购买建议', time: '35-45s' }
],
'品牌宣传': [
{ scene: '品牌理念 · 价值观', time: '0-8s' },
{ scene: '产品特色 · 差异化', time: '8-25s' },
{ scene: '用户见证 · 社会认可', time: '25-38s' },
{ scene: '品牌号召 · 情感共鸣', time: '38-45s' }
]
};
// 更新预览区
function updatePreview() {
// 更新标题
const titleEl = document.querySelector('#step-3 select');
const title = titleEl ? titleEl.value : '3秒抓住注意力,30秒讲清卖点';
const captionEl = document.getElementById('preview-caption');
if (captionEl) captionEl.textContent = title;
// 更新剪辑计划时间线
const timelineEl = document.getElementById('preview-timeline');
if (!timelineEl) return;
// 获取当前选中的模板
const selectedTemplate = document.querySelector('#step-1 .choice-item.selected h4');
const templateName = selectedTemplate ? selectedTemplate.textContent : '画中画混剪';
// 获取对应的剪辑计划
const plan = templatePlans[templateName] || templatePlans['画中画混剪'];
// 更新时间线HTML
let timelineHTML = '';
plan.forEach((item, idx) => {
timelineHTML += `
<div class="timeline-item">
<div class="num">${idx + 1}</div>
<span>${item.scene}</span>
<span>${item.time}</span>
</div>
`;
});
timelineEl.innerHTML = timelineHTML;
}
// ==================== 模态框通用函数 ====================
function openModal(modalId) {
document.getElementById(modalId).classList.add('show');
}
function closeModal(modalId) {
document.getElementById(modalId).classList.remove('show');
}
function closeAllModals() {
document.querySelectorAll('.modal-overlay.show').forEach(m => m.classList.remove('show'));
}
// ESC关闭和点击遮罩关闭
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeAllModals();
});
document.addEventListener('click', (e) => {
if (e.target.classList.contains('modal-overlay')) {
e.target.classList.remove('show');
}
});
// ==================== 显示视图 ====================
function showView(viewId) {
document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
const targetView = document.getElementById('view-' + viewId);
if (targetView) {
targetView.classList.add('active');
currentView = viewId;
}
// 更新导航高亮
document.querySelectorAll('.nav-links span, .sidebar-item').forEach(item => {
item.classList.remove('active');
});
// Handle subscription-logged highlighting for subscription
const viewForHighlight = viewId === 'subscription-logged' ? 'subscription' : viewId;
document.querySelectorAll('.nav-links span[data-view="' + viewId + '"], .sidebar-item[data-view="' + viewId + '"], .sidebar-item[data-view="' + viewForHighlight + '"]').forEach(item => {
item.classList.add('active');
});
window.scrollTo({ top: 0, behavior: 'smooth' });
}
// ==================== 登录登出 ====================
function login() { showView('login'); }
function doLogin() {
isLoggedIn = true;
document.getElementById('authButtons').style.display = 'none';
document.getElementById('userMenu').style.display = 'flex';
showView('dashboard');
}
function logout() {
isLoggedIn = false;
document.getElementById('authButtons').style.display = 'flex';
document.getElementById('userMenu').style.display = 'none';
showView('home');
}
// ==================== 标题库交互 ====================
// 新建标题
function openNewTitleModal() { openModal('modal-new-title'); }
function saveNewTitle() {
const content = document.getElementById('new-title-content').value;
const category = document.getElementById('new-title-category').value;
if (content.trim()) {
alert('标题创建成功!');
closeModal('modal-new-title');
document.getElementById('new-title-content').value = '';
}
}
// 批量导入
function openBatchImportModal() { openModal('modal-batch-import'); }
function startBatchImport() {
alert('批量导入已开始,请等待处理完成...');
closeModal('modal-batch-import');
}
// 编辑标题
function openEditTitleModal(card) {
const titleContent = card.querySelector('.content').textContent;
document.getElementById('edit-title-content').value = titleContent;
openModal('modal-edit-title');
window.currentEditingTitle = card;
}
function saveEditTitle() {
const newContent = document.getElementById('edit-title-content').value;
if (newContent.trim() && window.currentEditingTitle) {
window.currentEditingTitle.querySelector('.content').textContent = newContent;
closeModal('modal-edit-title');
alert('标题已更新!');
}
}
// 删除标题
function openDeleteTitleModal(card) {
window.currentDeletingTitle = card;
openModal('modal-delete-title');
}
function confirmDeleteTitle() {
if (window.currentDeletingTitle) {
window.currentDeletingTitle.style.transform = 'scale(0)';
window.currentDeletingTitle.style.opacity = '0';
setTimeout(() => {
window.currentDeletingTitle.remove();
closeModal('modal-delete-title');
}, 300);
}
}
// 收藏切换
function toggleFavorite(btn) {
btn.classList.toggle('favorited');
if (btn.classList.contains('favorited')) {
btn.textContent = '★';
} else {
btn.textContent = '☆';
}
}
// ==================== 素材库交互 ====================
// 新建素材库
function openNewAssetLibModal() { openModal('modal-new-assetlib'); }
function saveNewAssetLib() {
const name = document.getElementById('new-assetlib-name').value;
if (name.trim()) {
alert('素材库创建成功!');
closeModal('modal-new-assetlib');
document.getElementById('new-assetlib-name').value = '';
document.getElementById('new-assetlib-desc').value = '';
}
}
// 上传素材
function openUploadModal() { openModal('modal-upload'); }
// 诊断
function openDiagnoseModal(card) {
openModal('modal-diagnose');
const title = card.querySelector('h4').textContent;
document.getElementById('diagnose-score').textContent = '0%';
document.getElementById('diagnose-result').style.display = 'none';
// 模拟诊断过程
let progress = 0;
const interval = setInterval(() => {
progress += 20;
document.getElementById('diagnose-score').textContent = progress + '%';
if (progress >= 100) {
clearInterval(interval);
document.getElementById('diagnose-score').textContent = '85%';
document.getElementById('diagnose-result').style.display = 'block';
}
}, 200);
}
// ==================== 配音库交互 ====================
// AI生成配音
function openAIGenerateModal() { openModal('modal-ai-generate'); }
function startAIGenerate() {
const text = document.getElementById('ai-voice-text').value;
if (!text.trim()) {
alert('请输入配音文本');
return;
}
let progress = 0;
document.getElementById('ai-generate-status').textContent = '生成中...';
const interval = setInterval(() => {
progress += 10;
document.getElementById('ai-generate-progress').style.width = progress + '%';
if (progress >= 100) {
clearInterval(interval);
document.getElementById('ai-generate-status').textContent = '生成完成';
alert('配音生成成功!');
closeModal('modal-ai-generate');
document.getElementById('ai-voice-text').value = '';
document.getElementById('ai-generate-progress').style.width = '0%';
}
}, 300);
}
// 新建配音
function openNewVoiceModal() { openModal('modal-new-voice'); }
function saveNewVoice() {
const name = document.getElementById('new-voice-name').value;
if (name.trim()) {
alert('配音创建成功!');
closeModal('modal-new-voice');
document.getElementById('new-voice-name').value = '';
}
}
// 手动创建配音
function openManualVoiceModal() { openModal('modal-manual-voice'); }
function saveManualVoice() {
const text = document.getElementById('manual-voice-text').value;
if (text.trim()) {
alert('配音已提交审核!');
closeModal('modal-manual-voice');
document.getElementById('manual-voice-text').value = '';
}
}
// ==================== 模板库交互 ====================
// 打开模板编辑器
function openTemplateEditor() { openModal('modal-template-editor'); }
function saveTemplate() {
const name = document.getElementById('template-name').value;
if (name.trim()) {
alert('模板保存成功!');
closeModal('modal-template-editor');
} else {
alert('请输入模板名称');
}
}
// 使用模板 - 跳转到剪辑计划编辑器并预选模板
function useTemplate(card) {
const title = card.querySelector('h4').textContent;
// 跳转到剪辑计划编辑器
showView('editing-planner');
// 尝试预选模板
setTimeout(() => {
const templateItems = document.querySelectorAll('#ep-templates .template-card');
templateItems.forEach(item => {
if (item.querySelector('h4')?.textContent === title) {
item.click();
}
});
}, 100);
}
// 选择模板
function selectTemplate(el) {
document.querySelectorAll('#modal-select-template .choice-item').forEach(item => item.classList.remove('selected'));
el.classList.add('selected');
}
// 选择素材
function selectMaterial(el) {
el.classList.toggle('selected');
}
// 确认选择素材
function confirmSelectMaterial() {
const selected = document.querySelectorAll('#modal-select-material .choice-item.selected').length;
if (selected > 0) {
alert('已选择 ' + selected + ' 个素材');
}
closeModal('modal-select-material');
}
// 选择标题
function selectTitle(el) {
document.querySelectorAll('#modal-select-title .choice-item').forEach(item => item.classList.remove('selected'));
el.classList.add('selected');
}
// 选择配音
function selectVoice(el) {
document.querySelectorAll('#modal-select-voice .choice-item').forEach(item => item.classList.remove('selected'));
el.classList.add('selected');
}
// ==================== 一键生成交互 ====================
function selectChoice(el) {
// 单选:先取消所有选中,再选中当前
el.parentElement.querySelectorAll('.choice-item').forEach(item => item.classList.remove('selected'));
el.classList.add('selected');
// 切换模板时更新预览
updatePreview();
}
function prevStep() {
if (currentStep > 1) {
currentStep--;
updateStepUI();
}
}
function nextStep() {
if (currentStep < 4) {
currentStep++;
updateStepUI();
} else if (currentStep === 4) {
// 第4步完成后弹出确认生成弹窗
openConfirmGenerateModal();
}
}
function updateStepUI() {
document.querySelectorAll('.step-item').forEach(item => {
const step = parseInt(item.dataset.step);
item.classList.remove('active', 'done');
if (step < currentStep) item.classList.add('done');
if (step === currentStep) item.classList.add('active');
});
// 只显示当前步骤的表单区域
document.querySelectorAll('.form-section').forEach((section, idx) => {
section.style.display = (idx + 1 === currentStep) ? 'block' : 'none';
});
// 更新按钮文字
const prevBtn = document.querySelector('.generate-form .btn.ghost');
const nextBtn = document.querySelector('.generate-form .btn.primary:not(.sm)');
if (prevBtn) prevBtn.style.display = currentStep > 1 ? 'inline-flex' : 'none';
if (nextBtn) nextBtn.textContent = currentStep === 4 ? '✨ 确认生成' : '下一步 →';
}
// 打开确认生成弹窗
function openConfirmGenerateModal() {
// 读取当前选择的值
const templateEl = document.querySelector('#step-1 .choice-item.selected h4');
const materialEl = document.querySelector('#step-2 select');
const titleEl = document.querySelector('#step-3 select');
const voiceEl = document.querySelector('#step-4 select:last-of-type') || document.querySelector('#step-4 select');
const templateName = templateEl ? templateEl.textContent : '未选择';
const materialName = materialEl ? materialEl.value : '未选择';
const titleName = titleEl ? titleEl.value : '未选择';
const voiceName = voiceEl ? voiceEl.value : '未选择';
// 更新弹窗内容
document.getElementById('confirm-template').textContent = templateName;
document.getElementById('confirm-material').textContent = materialName;
document.getElementById('confirm-title').textContent = titleName;
document.getElementById('confirm-voice').textContent = voiceName;
openModal('modal-confirm-generate');
}
// 确认生成
function confirmGenerate() {
closeModal('modal-confirm-generate');
startGeneration();
}
function openSelectVoice() { openModal('modal-select-voice'); }
function startGeneration() {
openModal('modalOverlay');
const modal = document.getElementById('generationModal');
modal.classList.remove('done');
let progress = 0;
const steps = ['正在读取素材...', '正在分析内容...', '正在生成剪辑计划...', '正在合成视频...', '即将完成...'];
const progressFill = document.getElementById('progressFill');
const modalStep = document.getElementById('modalStep');
const interval = setInterval(() => {
progress += 2;
progressFill.style.width = progress + '%';
modalStep.textContent = steps[Math.min(Math.floor(progress / 20), steps.length - 1)];
if (progress >= 100) {
clearInterval(interval);
modal.classList.add('done');
document.getElementById('modalTitle').textContent = '生成完成!';
document.getElementById('modalText').textContent = '视频已保存到成片库,可以开始下载或发布了。';
modalStep.textContent = '准备就绪';
setTimeout(() => {
closeModal('modalOverlay');
showView('products');
}, 1500);
}
}, 100);
}
// ==================== 成片库交互 ====================
function downloadProduct(card) {
const name = card.querySelector('h4').textContent;
openModal('modal-download');
document.getElementById('download-product-name').textContent = name + '.mp4';
let progress = 0;
const interval = setInterval(() => {
progress += 15;
document.getElementById('download-progress-bar').style.width = progress + '%';
if (progress >= 100) {
clearInterval(interval);
setTimeout(() => {
closeModal('modal-download');
alert('下载完成!');
}, 500);
}
}, 300);
}
// 平台对应的账号数据
const platformAccounts = {
douyin: ['小虾智剪-官方号', '小虾智剪-产品号', '小虾智剪-运营号'],
kuaishou: ['小虾智剪-官方号', '小虾智剪-带货号'],
xiaohongshu: ['小虾智剪-种草号', '小虾智剪-品牌号'],
wechat: ['小虾智剪-视频号']
};
const platformNames = { douyin:'抖音', kuaishou:'快手', xiaohongshu:'小红书', wechat:'微信视频号' };
let publishTags = ['产品推荐', '短视频'];
// 打开发布弹窗
function openPublishModal(card) {
// 保存当前发布的卡片引用
window.currentPublishCard = card;
// 重置表单
const title = card ? card.querySelector('h4')?.textContent || '' : '';
document.getElementById('publish-title').value = title;
document.getElementById('publish-desc').value = '';
document.getElementById('publish-tag-input').value = '';
publishTags = [];
renderPublishTags();
renderRecentTopics();
// 默认选中抖音,更新账号列表
updateAccountSelect('douyin');
openModal('modal-publish');
}
// 选择发布平台
function selectPublishPlatform(el) {
document.querySelectorAll('.publish-platform-item').forEach(item => {
item.style.border = '1px solid var(--line)';
item.style.background = '';
item.classList.remove('selected');
});
el.style.border = '2px solid var(--primary)';
el.style.background = 'var(--primary-soft)';
el.classList.add('selected');
el.querySelector('input[type="radio"]').checked = true;
const platform = el.dataset.platform;
updateAccountSelect(platform);
}
// 更新账号下拉
function updateAccountSelect(platform) {
const select = document.getElementById('publish-account');
const accounts = platformAccounts[platform] || [];
select.innerHTML = '<option value="">请选择账号</option>';
accounts.forEach(acc => {
const opt = document.createElement('option');
opt.value = acc;
opt.textContent = acc;
select.appendChild(opt);
});
if (accounts.length > 0) select.value = accounts[0];
}
// 渲染标签
function renderPublishTags() {
const container = document.getElementById('publish-tags-container');
container.innerHTML = publishTags.map(tag =>
'<span style="display:inline-flex;align-items:center;gap:4px;padding:4px 10px;background:var(--primary-soft);color:var(--primary);border-radius:999px;font-size:12px;font-weight:600">' +
'#' + tag + ' <span onclick="removePublishTag(\'' + tag + '\')" style="cursor:pointer;margin-left:2px;font-size:14px;color:#94a3b8">×</span></span>'
).join('');
}
// 添加标签
function addPublishTag() {
const input = document.getElementById('publish-tag-input');
const tag = input.value.trim();
if (tag && !publishTags.includes(tag)) {
publishTags.push(tag);
renderPublishTags();
renderRecentTopics();
input.value = '';
}
}
// 删除标签
function removePublishTag(tag) {
publishTags = publishTags.filter(t => t !== tag);
renderPublishTags();
renderRecentTopics();
}
// 常用话题(历史使用过的)
const recentTopics = ['产品推荐', '好物分享', '短视频', '直播切片', '开箱测评', '日常分享', '教程', '干货分享', '种草', '避坑指南', '数码', '科技'];
// 渲染常用话题列表
function renderRecentTopics() {
const container = document.getElementById('publish-recent-topics');
container.innerHTML = recentTopics.map(topic => {
const isSelected = publishTags.includes(topic);
if (isSelected) {
return '<span style="padding:4px 10px;background:#f1f5f9;color:#94a3b8;border-radius:999px;font-size:12px;cursor:default;text-decoration:line-through">#' + topic + '</span>';
}
return '<span onclick="toggleRecentTopic(\'' + topic + '\')" style="padding:4px 10px;background:#fff;border:1px dashed var(--line);color:var(--text);border-radius:999px;font-size:12px;cursor:pointer;transition:all .15s" onmouseover="this.style.borderColor=\'var(--primary)\';this.style.color=\'var(--primary)\'" onmouseout="this.style.borderColor=\'var(--line)\';this.style.color=\'var(--text)\'">+ #' + topic + '</span>';
}).join('');
}
// 点击常用话题直接添加
function toggleRecentTopic(topic) {
if (!publishTags.includes(topic)) {
publishTags.push(topic);
renderPublishTags();
renderRecentTopics();
}
}
// 确认发布
function confirmPublish() {
const platform = document.querySelector('input[name="platform"]:checked').value;
const platformName = platformNames[platform] || platform;
const account = document.getElementById('publish-account').value;
const title = document.getElementById('publish-title').value || '(使用默认标题)';
const tags = publishTags.length > 0 ? publishTags.map(t => '#' + t).join(' ') : '(无话题)';
if (!account) {
alert('请选择发布账号');
return;
}
closeModal('modal-publish');
// 显示"正在发布"弹窗
document.getElementById('publish-progress-text').textContent = '正在发布到' + platformName + '...';
document.getElementById('publish-progress-bar').style.width = '0%';
document.getElementById('publish-progress-icon').innerHTML = '<div class="spinner"></div>';
openModal('modal-publishProgress');
// 模拟发布进度
let progress = 0;
const progressInterval = setInterval(() => {
progress += Math.random() * 30 + 15;
if (progress >= 100) {
progress = 100;
clearInterval(progressInterval);
setTimeout(() => {
document.getElementById('publish-progress-icon').innerHTML = '<div class="success-icon">✓</div>';
document.getElementById('publish-progress-text').textContent = '发布成功!';
// 标记当前视频为已发布
if (window.currentPublishCard) {
markProductPublished(window.currentPublishCard.dataset.productId);
}
// 2秒后自动关闭
setTimeout(() => {
closeModal('modal-publishProgress');
}, 2000);
}, 500);
}
document.getElementById('publish-progress-bar').style.width = progress + '%';
}, 400);
}
// ==================== 账号管理 ====================
// 已绑定账号数据
const boundAccounts = {
douyin: ['小虾智剪-官方号', '小虾智剪-好物推荐'],
kuaishou: ['小虾智剪-快手'],
xiaohongshu: ['小虾智剪-种草号'],
wechat: []
};
// 当前解绑的账号信息
let currentUnbindInfo = { platform: '', account: '' };
// 打开绑定账号弹窗
function openBindAccountModal(platform) {
document.getElementById('bind-platform').value = platform || 'douyin';
openModal('modal-bindAccount');
}
// 确认绑定账号
function confirmBindAccount() {
const platform = document.getElementById('bind-platform').value;
const platformName = platformNames[platform] || platform;
closeModal('modal-bindAccount');
alert('✅ 授权成功!\n\n已成功绑定' + platformName + '账号。\n您现在可以通过小虾智剪发布视频到该平台。');
// 实际应用中这里应该刷新账号列表
}
// 打开解绑确认弹窗
function openUnbindModal(platform, account) {
currentUnbindInfo = { platform, account };
document.getElementById('unbind-account-name').textContent = account;
openModal('modal-unbindAccount');
}
// 确认解绑
function confirmUnbind() {
const { platform, account } = currentUnbindInfo;
const platformName = platformNames[platform] || platform;
// 从数据中移除
const idx = boundAccounts[platform].indexOf(account);
if (idx > -1) {
boundAccounts[platform].splice(idx, 1);
}
closeModal('modal-unbindAccount');
alert('✅ 解绑成功!\n\n已解除绑定:' + platformName + ' - ' + account);
// 刷新账号列表(简单模拟)
refreshAccountList(platform);
}
// 刷新账号列表(模拟)
function refreshAccountList(platform) {
const listId = 'accounts-' + platform + '-list';
const container = document.getElementById(listId);
if (!container) return;
const accounts = boundAccounts[platform] || [];
if (accounts.length === 0) {
container.innerHTML = '<div style="padding:20px;text-align:center;color:var(--muted);font-size:14px"><div style="font-size:32px;margin-bottom:8px">🔓</div><p style="margin:0">暂未绑定账号</p></div>';
} else {
const colors = {
douyin: 'linear-gradient(135deg,#fe2c55,#25f4ee)',
kuaishou: 'linear-gradient(135deg,#ff4906,#ffba00)',
xiaohongshu: 'linear-gradient(135deg,#ff2442,#ff6b6b)',
wechat: 'linear-gradient(135deg,#07c160,#4ade80)'
};
const icons = { douyin: '🎬', kuaishou: '快', xiaohongshu: '📕', wechat: '💬' };
container.innerHTML = accounts.map(acc => {
const icon = icons[platform] || '📱';
const color = colors[platform] || '#6366f1';
return '<div style="display:flex;align-items:center;gap:10px;padding:12px;background:#f8fafc;border-radius:12px">' +
'<div style="width:36px;height:36px;border-radius:50%;background:' + color + ';display:grid;place-items:center;color:#fff;font-weight:700;font-size:14px">' + icon + '</div>' +
'<div style="flex:1"><div style="font-weight:600;font-size:14px">' + acc + '</div><span class="pill ok" style="font-size:10px;padding:2px 6px">已连接</span></div>' +
'<button class="btn ghost sm" onclick="openUnbindModal(\'' + platform + '\', \'' + acc + '\')" style="padding:6px 10px;font-size:12px">解绑</button></div>';
}).join('');
}
// 更新底部统计
updateAccountsStats();
}
// 更新账号统计
function updateAccountsStats() {
let totalAccounts = 0;
Object.values(boundAccounts).forEach(accs => totalAccounts += accs.length);
// 找到统计元素并更新
const statsEl = document.querySelector('#view-accounts .section:last-child .page-head + .section span[style*="color:var(--primary)"]');
if (statsEl) {
statsEl.textContent = totalAccounts;
}
}
// ==================== 已发布视频管理 ====================
// 标记视频为已发布状态
function markProductPublished(productId) {
const card = document.querySelector('.product-card[data-product-id="' + productId + '"]');
if (!card) return;
card.dataset.published = 'true';
card.style.opacity = '0.65';
// 禁用checkbox
const cb = card.querySelector('input[type="checkbox"]');
if (cb) {
cb.checked = false;
cb.disabled = true;
cb.style.opacity = '0.4';
}
card.classList.remove('selected');
selectedProducts.delete(productId);
// 替换发布按钮为"已发布"标签
const publishBtn = card.querySelector('button[onclick*="openPublishModal"]');
if (publishBtn) {
const badge = document.createElement('span');
badge.className = 'pill ok';
badge.textContent = '✅ 已发布';
badge.style.cssText = 'flex:1;padding:6px 4px;font-size:12px;text-align:center;display:inline-block';
publishBtn.replaceWith(badge);
}
// 添加"已发布"角标
if (!card.querySelector('.published-badge')) {
const badge = document.createElement('div');
badge.className = 'published-badge';
badge.textContent = '已发布';
badge.style.cssText = 'position:absolute;top:12px;right:12px;background:var(--green);color:#fff;font-size:11px;font-weight:700;padding:3px 8px;border-radius:6px;z-index:10';
card.appendChild(badge);
}
// 把卡片移到最后(排序到最下面)
const parent = card.parentNode;
parent.appendChild(card);
updateBatchPublishUI();
}
// ==================== 批量发布 ====================
// 选中的视频
let selectedProducts = new Set();
// 批量发布的话题标签
let batchPublishTags = [];
// 切换视频选中状态
function toggleProductSelect(card) {
const productId = card.dataset.productId;
const checkbox = card.querySelector('input[type="checkbox"]');
if (checkbox.checked) {
selectedProducts.add(productId);
card.classList.add('selected');
} else {
selectedProducts.delete(productId);
card.classList.remove('selected');
}
updateBatchPublishUI();
}
// 全选/取消全选
function toggleSelectAllProducts() {
const selectAllCheckbox = document.getElementById('select-all-products');
const allCards = document.querySelectorAll('.product-card');
if (selectAllCheckbox.checked) {
allCards.forEach(card => {
// 跳过已发布的视频
if (card.dataset.published === 'true') return;
const cb = card.querySelector('input[type="checkbox"]');
if (cb && !cb.disabled) {
selectedProducts.add(card.dataset.productId);
card.classList.add('selected');
cb.checked = true;
}
});
} else {
selectedProducts.clear();
allCards.forEach(card => {
card.classList.remove('selected');
const cb = card.querySelector('input[type="checkbox"]');
if (cb && !cb.disabled) cb.checked = false;
});
}
updateBatchPublishUI();
}
// 更新批量发布UI状态
function updateBatchPublishUI() {
const count = selectedProducts.size;
const countEl = document.querySelector('#selected-count span');
const batchBtn = document.getElementById('batch-publish-btn');
const selectAll = document.getElementById('select-all-products');
if (countEl) countEl.textContent = count;
if (batchBtn) {
if (count > 0) {
batchBtn.disabled = false;
batchBtn.style.opacity = '1';
batchBtn.style.cursor = 'pointer';
} else {
batchBtn.disabled = true;
batchBtn.style.opacity = '0.5';
batchBtn.style.cursor = 'not-allowed';
}
}
// 更新全选框状态
const allCards = document.querySelectorAll('.product-card');
if (selectAll && allCards.length > 0) {
selectAll.checked = count === allCards.length;
selectAll.indeterminate = count > 0 && count < allCards.length;
}
}
// 打开批量发布弹窗
function openBatchPublishModal() {
if (selectedProducts.size === 0) {
alert('请先选择要发布的视频');
return;
}
// 获取选中的视频信息
const selectedCards = [];
selectedProducts.forEach(id => {
const card = document.querySelector('.product-card[data-product-id="' + id + '"]');
if (card) {
selectedCards.push({
id: id,
name: card.dataset.productName || card.querySelector('h4')?.textContent || '未命名视频'
});
}
});
// 渲染视频列表
const videoList = document.getElementById('batch-video-list');
videoList.innerHTML = selectedCards.map((video, idx) =>
'<div style="display:flex;align-items:center;gap:12px;padding:12px;background:#f8fafc;border-radius:12px">' +
'<div style="flex:1;min-width:0"><div style="font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + video.name + '</div></div>' +
'<select id="batch-platform-' + idx + '" onchange="updateBatchAccountSelect(' + idx + ', this.value)" style="height:36px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 10px;font-size:13px;min-width:100px">' +
'<option value="">选择平台</option>' +
'<option value="douyin">📱 抖音</option>' +
'<option value="kuaishou">🎬 快手</option>' +
'<option value="xiaohongshu">📕 小红书</option>' +
'<option value="wechat">💬 视频号</option>' +
'</select>' +
'<select id="batch-account-' + idx + '" onchange="refreshAllBatchAccounts()" style="height:36px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 10px;font-size:13px;min-width:120px">' +
'<option value="">先选平台</option>' +
'</select>' +
'</div>'
).join('');
// 重置批量标签
batchPublishTags = [];
renderBatchPublishTags();
renderBatchRecentTopics();
// 更新统计
updateBatchPublishStats();
openModal('modal-batchPublish');
}
// 批量发布中平台→账号联动
function getBatchSelectedAccounts() {
const selected = new Set();
document.querySelectorAll('[id^="batch-account-"]').forEach(sel => {
if (sel.value) selected.add(sel.value);
});
return selected;
}
function refreshAllBatchAccounts() {
document.querySelectorAll('[id^="batch-platform-"]').forEach((platformSel, idx) => {
if (platformSel.value) {
updateBatchAccountSelect(idx, platformSel.value);
}
});
}
function updateBatchAccountSelect(videoIndex, platform) {
const accountSelect = document.getElementById('batch-account-' + videoIndex);
if (!accountSelect) return;
if (!platform) {
accountSelect.innerHTML = '<option value="">先选平台</option>';
return;
}
const accounts = boundAccounts[platform] || [];
const alreadySelected = getBatchSelectedAccounts();
const currentAccount = accountSelect.value; // 保留当前选中
if (accounts.length === 0) {
accountSelect.innerHTML = '<option value="">暂无可用账号</option>';
} else {
const available = accounts.filter(acc => !alreadySelected.has(acc) || acc === currentAccount);
if (available.length === 0) {
accountSelect.innerHTML = '<option value="">所有账号已被分配</option>';
} else {
accountSelect.innerHTML = '<option value="">选择账号</option>' +
available.map(acc => '<option value="' + acc + '"' + (acc === currentAccount ? ' selected' : '') + '>' + acc + '</option>').join('');
}
}
// 刷新所有其他视频的账号下拉(因为当前选择变了)
document.querySelectorAll('[id^="batch-platform-"]').forEach((platformSel, idx) => {
if (idx !== videoIndex && platformSel.value) {
const otherAccountSel = document.getElementById('batch-account-' + idx);
if (otherAccountSel) {
const otherAccounts = boundAccounts[platformSel.value] || [];
const selected2 = getBatchSelectedAccounts();
const currentVal = otherAccountSel.value;
const avail = otherAccounts.filter(acc => !selected2.has(acc) || acc === currentVal);
otherAccountSel.innerHTML = '<option value="">选择账号</option>' +
avail.map(acc => '<option value="' + acc + '"' + (acc === currentVal ? ' selected' : '') + '>' + acc + '</option>').join('');
}
}
});
updateBatchPublishStats();
}
// 渲染批量发布标签
function renderBatchPublishTags() {
const container = document.getElementById('batch-tags-container');
container.innerHTML = batchPublishTags.map(tag =>
'<span style="display:inline-flex;align-items:center;gap:4px;padding:4px 10px;background:var(--primary-soft);color:var(--primary);border-radius:999px;font-size:12px;font-weight:600">' +
'#' + tag + ' <span onclick="removeBatchTag(\'' + tag + '\')" style="cursor:pointer;margin-left:2px;font-size:14px;color:#94a3b8">×</span></span>'
).join('');
}
// 添加批量发布标签
function addBatchTag() {
const input = document.getElementById('batch-tag-input');
const tag = input.value.trim();
if (tag && !batchPublishTags.includes(tag)) {
batchPublishTags.push(tag);
renderBatchPublishTags();
renderBatchRecentTopics();
input.value = '';
}
}
// 删除批量发布标签
function removeBatchTag(tag) {
batchPublishTags = batchPublishTags.filter(t => t !== tag);
renderBatchPublishTags();
renderBatchRecentTopics();
}
// 渲染批量发布常用话题
function renderBatchRecentTopics() {
const container = document.getElementById('batch-recent-topics');
container.innerHTML = recentTopics.map(topic => {
const isSelected = batchPublishTags.includes(topic);
if (isSelected) {
return '<span style="padding:4px 10px;background:#f1f5f9;color:#94a3b8;border-radius:999px;font-size:12px;cursor:default;text-decoration:line-through">#' + topic + '</span>';
}
return '<span onclick="addBatchTopic(\'' + topic + '\')" style="padding:4px 10px;background:#fff;border:1px dashed var(--line);color:var(--text);border-radius:999px;font-size:12px;cursor:pointer">+ #' + topic + '</span>';
}).join('');
}
// 添加批量话题
function addBatchTopic(topic) {
if (!batchPublishTags.includes(topic)) {
batchPublishTags.push(topic);
renderBatchPublishTags();
renderBatchRecentTopics();
}
}
// 更新批量发布统计
function updateBatchPublishStats() {
const videoCount = selectedProducts.size;
const platformSet = new Set();
// 统计已选平台数
document.querySelectorAll('[id^="batch-platform-"]').forEach(sel => {
if (sel.value) platformSet.add(sel.value);
});
document.getElementById('batch-video-count').textContent = videoCount;
document.getElementById('batch-platform-count').textContent = platformSet.size;
}
// 确认批量发布
function confirmBatchPublish() {
// 收集发布信息(保持原有逻辑)
const videoCount = selectedProducts.size;
const videos = [];
let validCount = 0;
document.querySelectorAll('[id^="batch-platform-"]').forEach((platformSel, idx) => {
const accountSel = document.getElementById('batch-account-' + idx);
const productId = Array.from(selectedProducts)[idx];
const card = document.querySelector('.product-card[data-product-id="' + productId + '"]');
const videoName = card ? (card.dataset.productName || card.querySelector('h4')?.textContent) : '视频' + (idx + 1);
videos.push({
productId: productId,
name: videoName,
platform: platformSel.value,
account: accountSel ? accountSel.value : ''
});
if (platformSel.value && accountSel && accountSel.value) {
validCount++;
}
});
if (validCount === 0) {
alert('请至少选择一个平台和账号');
return;
}
closeModal('modal-batchPublish');
// 显示"正在发布"弹窗
document.getElementById('publish-progress-text').textContent = '正在发布 ' + validCount + ' 个视频...';
document.getElementById('publish-progress-bar').style.width = '0%';
document.getElementById('publish-progress-icon').innerHTML = '<div class="spinner"></div>';
openModal('modal-publishProgress');
// 模拟发布进度
let progress = 0;
const progressInterval = setInterval(() => {
progress += Math.random() * 25 + 10;
if (progress >= 100) {
progress = 100;
clearInterval(progressInterval);
// 发布完成
setTimeout(() => {
document.getElementById('publish-progress-icon').innerHTML = '<div class="success-icon">✓</div>';
document.getElementById('publish-progress-text').textContent = '发布成功!';
// 标记已发布的视频
videos.forEach(v => {
if (v.platform && v.account) {
markProductPublished(v.productId);
}
});
// 2秒后自动关闭进度弹窗
setTimeout(() => {
closeModal('modal-publishProgress');
}, 2000);
}, 500);
}
document.getElementById('publish-progress-bar').style.width = progress + '%';
}, 400);
// 清除选中状态
selectedProducts.clear();
document.querySelectorAll('.product-card').forEach(card => {
card.classList.remove('selected');
const cb = card.querySelector('input[type="checkbox"]');
if (cb) cb.checked = false;
});
updateBatchPublishUI();
}
// ==================== 任务历史交互 ====================
function filterTasks(filter) {
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
event.target.classList.add('active');
}
// ==================== 查重检测交互 ====================
function simulateUpload() {
alert('模拟上传功能:请在真实环境中选择视频文件');
}
// ==================== 订阅管理交互 ====================
function openUpgradeModal(planName) {
document.getElementById('upgrade-plan-name').textContent = planName;
openModal('modal-upgrade');
}
function confirmUpgrade() {
alert('升级成功!');
closeModal('modal-upgrade');
}
function openDowngradeModal() { openModal('modal-downgrade'); }
function confirmDowngrade() {
alert('降级申请已提交,将在当前周期结束后生效');
closeModal('modal-downgrade');
}
function openRenewModal() { openModal('modal-renew'); }
function confirmRenew() {
alert('正在跳转到支付页面...');
closeModal('modal-renew');
}
// 侧边栏导航点击
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.sidebar-item[data-view], .nav-links span[data-view]').forEach(item => {
item.addEventListener('click', function() {
const viewId = this.dataset.view;
if (viewId) showView(viewId);
});
});
// 一键生成步骤初始化 - 只显示第1步
updateStepUI();
// 初始化预览区
updatePreview();
});
</script>
<!-- ==================== 标题库模态框 ==================== -->
<!-- 新建标题模态框 -->
<div id="modal-new-title" class="modal-overlay">
<div class="modal" style="max-width:520px">
<h3 style="margin:0 0 20px;font-size:20px">📝 新建标题</h3>
<div class="form-field">
<label>标题内容</label>
<textarea id="new-title-content" style="width:100%;height:100px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none" placeholder="输入标题内容..."></textarea>
</div>
<div class="form-field" style="margin-top:16px">
<label>选择分类</label>
<select id="new-title-category" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>口播开场</option>
<option>产品介绍</option>
<option>教程类</option>
<option>种草推荐</option>
<option>直播引流</option>
</select>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-new-title')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveNewTitle()" style="flex:1">保存</button>
</div>
</div>
</div>
<!-- 批量导入模态框 -->
<div id="modal-batch-import" class="modal-overlay">
<div class="modal" style="max-width:560px">
<h3 style="margin:0 0 20px;font-size:20px">📥 批量导入标题</h3>
<div style="border:2px dashed var(--line);border-radius:var(--radius-md);padding:40px;text-align:center;background:#f8fafc;cursor:pointer;margin-bottom:16px">
<div style="font-size:40px;margin-bottom:12px">📁</div>
<p style="margin:0;color:var(--muted)">拖拽文件到此处,或点击选择文件</p>
<p style="margin:8px 0 0;color:var(--muted);font-size:12px">支持格式:TXT、CSV、Excel</p>
</div>
<div style="background:#f8fafc;border-radius:var(--radius-sm);padding:14px;font-size:13px;color:var(--muted)">
<p style="margin:0 0 8px">📋 导入说明:</p>
<ul style="margin:0;padding-left:18px">
<li>每行一个标题</li>
<li>CSV/Excel首行需包含"标题"列</li>
<li>单次最多导入500条</li>
</ul>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-batch-import')" style="flex:1">取消</button>
<button class="btn primary" onclick="startBatchImport()" style="flex:1">开始导入</button>
</div>
</div>
</div>
<!-- 编辑标题模态框 -->
<div id="modal-edit-title" class="modal-overlay">
<div class="modal" style="max-width:520px">
<h3 style="margin:0 0 20px;font-size:20px">✏️ 编辑标题</h3>
<div class="form-field">
<label>标题内容</label>
<textarea id="edit-title-content" style="width:100%;height:100px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none"></textarea>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-edit-title')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveEditTitle()" style="flex:1">保存</button>
</div>
</div>
</div>
<!-- 删除确认模态框 -->
<div id="modal-delete-title" class="modal-overlay">
<div class="modal" style="max-width:400px;text-align:center">
<div style="width:60px;height:60px;border-radius:50%;background:#fee2e2;margin:0 auto 16px;display:grid;place-items:center;font-size:28px">⚠️</div>
<h3 style="margin:0 0 8px;font-size:18px">确认删除</h3>
<p style="margin:0;color:var(--muted)">确定要删除这个标题吗?此操作无法撤销。</p>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-delete-title')" style="flex:1">取消</button>
<button class="btn" onclick="confirmDeleteTitle()" style="flex:1;background:#ef4444;color:#fff">删除</button>
</div>
</div>
</div>
<!-- ==================== 素材库模态框 ==================== -->
<!-- 新建素材库模态框 -->
<div id="modal-new-assetlib" class="modal-overlay">
<div class="modal" style="max-width:480px">
<h3 style="margin:0 0 20px;font-size:20px">📦 新建素材库</h3>
<div class="form-field">
<label>素材库名称</label>
<input id="new-assetlib-name" type="text" placeholder="输入素材库名称" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px"/>
</div>
<div class="form-field" style="margin-top:16px">
<label>描述(可选)</label>
<textarea id="new-assetlib-desc" style="width:100%;height:80px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none" placeholder="简短描述素材库用途..."></textarea>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-new-assetlib')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveNewAssetLib()" style="flex:1">创建</button>
</div>
</div>
</div>
<!-- 上传素材模态框 -->
<div id="modal-upload" class="modal-overlay">
<div class="modal" style="max-width:500px">
<h3 style="margin:0 0 20px;font-size:20px">📤 上传素材</h3>
<div style="border:2px dashed var(--line);border-radius:var(--radius-md);padding:40px;text-align:center;background:linear-gradient(180deg,#fff,#f8fafc);cursor:pointer;margin-bottom:16px">
<div style="font-size:48px;margin-bottom:12px">🖼️</div>
<p style="margin:0;font-weight:600">拖拽文件到此处上传</p>
<p style="margin:8px 0 0;color:var(--muted)">或点击选择文件</p>
<p style="margin:8px 0 0;color:var(--muted);font-size:12px">支持:MP4、MOV、AVI、MKV、图片、音频</p>
</div>
<div style="margin-bottom:12px">
<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:6px">
<span>上传进度</span>
<span id="upload-status">准备上传...</span>
</div>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden">
<div id="upload-progress" style="height:100%;background:linear-gradient(90deg,var(--primary),var(--primary-light));width:0%;transition:width .3s"></div>
</div>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-upload')" style="flex:1">取消</button>
<button class="btn primary" style="flex:1">开始上传</button>
</div>
</div>
</div>
<!-- 素材详情模态框 -->
<div id="modal-asset-detail" class="modal-overlay">
<div class="modal" style="max-width:600px">
<h3 style="margin:0 0 16px;font-size:20px">📦 素材详情</h3>
<div style="display:grid;grid-template-columns:200px 1fr;gap:20px">
<div style="aspect-ratio:9/16;background:linear-gradient(135deg,#0ea5e9,#0284c7);border-radius:var(--radius-md);display:grid;place-items:center;color:#fff;font-size:40px"></div>
<div>
<h4 id="detail-asset-title" style="margin:0 0 12px;font-size:16px">主播口播开场.mp4</h4>
<div id="detail-asset-meta" style="font-size:13px;color:var(--muted)"></div>
<div style="margin-top:16px;padding:12px;background:#f8fafc;border-radius:var(--radius-sm)">
<div style="display:flex;justify-content:space-between;margin-bottom:8px">
<span style="color:var(--muted)">文件大小</span>
<span>12.5 MB</span>
</div>
<div style="display:flex;justify-content:space-between;margin-bottom:8px">
<span style="color:var(--muted)">分辨率</span>
<span>1920 × 1080</span>
</div>
<div style="display:flex;justify-content:space-between;margin-bottom:8px">
<span style="color:var(--muted)">时长</span>
<span>00:32</span>
</div>
<div style="display:flex;justify-content:space-between">
<span style="color:var(--muted)">AI分类</span>
<span>口播开场</span>
</div>
</div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-asset-detail')" style="flex:1">关闭</button>
<button class="btn primary" onclick="closeModal('modal-asset-detail')" style="flex:1">下载素材</button>
</div>
</div>
</div>
<!-- 诊断结果模态框 -->
<div id="modal-diagnose" class="modal-overlay">
<div class="modal" style="max-width:500px">
<h3 style="margin:0 0 20px;font-size:20px">🔍 素材诊断</h3>
<div style="text-align:center;padding:20px 0">
<p style="margin:0 0 12px;color:var(--muted)">正在分析素材质量...</p>
<div style="font-size:48px;font-weight:800;color:var(--primary)" id="diagnose-score">0%</div>
</div>
<div id="diagnose-result" style="display:none;padding:20px;background:#f8fafc;border-radius:var(--radius-md)">
<h4 style="margin:0 0 12px;font-size:15px">诊断结果</h4>
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<span style="width:36px;height:36px;border-radius:50%;background:#dcfce7;color:#166534;display:grid;place-items:center"></span>
<span>画质清晰度:良好</span>
</div>
<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">
<span style="width:36px;height:36px;border-radius:50%;background:#fef3c7;color:#92400e;display:grid;place-items:center">!</span>
<span>建议:适当裁剪边缘区域</span>
</div>
<div style="display:flex;align-items:center;gap:12px">
<span style="width:36px;height:36px;border-radius:50%;background:#dcfce7;color:#166534;display:grid;place-items:center"></span>
<span>音频质量:正常</span>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-diagnose')" style="flex:1">关闭</button>
<button class="btn primary" onclick="closeModal('modal-diagnose')" style="flex:1">查看详情</button>
</div>
</div>
</div>
<!-- ==================== 配音库模态框 ==================== -->
<!-- AI生成配音模态框 -->
<div id="modal-ai-generate" class="modal-overlay">
<div class="modal" style="max-width:560px">
<h3 style="margin:0 0 20px;font-size:20px">🎙️ AI生成配音</h3>
<div class="form-field">
<label>配音文本</label>
<textarea id="ai-voice-text" style="width:100%;height:120px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none" placeholder="输入需要转换的文本..."></textarea>
</div>
<div class="form-row" style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px">
<div class="form-field">
<label>选择音色</label>
<select id="ai-voice-select" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>温柔女声</option>
<option>专业男声</option>
<option>活力女声</option>
<option>磁性男声</option>
</select>
</div>
<div class="form-field">
<label>语速调节</label>
<select style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>0.75x(慢速)</option>
<option>1.0x(正常)</option>
<option>1.25x(快速)</option>
</select>
</div>
</div>
<div style="margin-top:16px">
<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:6px">
<span>生成进度</span>
<span id="ai-generate-status">准备就绪</span>
</div>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden">
<div id="ai-generate-progress" style="height:100%;background:linear-gradient(90deg,var(--primary),var(--primary-light));width:0%;transition:width .3s"></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-ai-generate')" style="flex:1">取消</button>
<button class="btn primary" onclick="startAIGenerate()" style="flex:1">开始生成</button>
</div>
</div>
</div>
<!-- 新建配音模态框 -->
<div id="modal-new-voice" class="modal-overlay">
<div class="modal" style="max-width:480px">
<h3 style="margin:0 0 20px;font-size:20px">🎵 新建配音</h3>
<div class="form-field">
<label>配音名称</label>
<input id="new-voice-name" type="text" placeholder="输入配音名称" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px"/>
</div>
<div class="form-field" style="margin-top:16px">
<label>上传音频文件</label>
<div style="border:2px dashed var(--line);border-radius:var(--radius-sm);padding:30px;text-align:center;background:#f8fafc;cursor:pointer">
<p style="margin:0;color:var(--muted)">点击选择音频文件</p>
<p style="margin:8px 0 0;color:var(--muted);font-size:12px">支持:MP3、WAV、M4A</p>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-new-voice')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveNewVoice()" style="flex:1">创建</button>
</div>
</div>
</div>
<!-- 手动创建配音模态框 -->
<div id="modal-manual-voice" class="modal-overlay">
<div class="modal" style="max-width:560px">
<h3 style="margin:0 0 20px;font-size:20px">✍️ 手动创建配音</h3>
<div class="form-field">
<label>配音文本</label>
<textarea id="manual-voice-text" style="width:100%;height:150px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none" placeholder="输入配音文本内容..."></textarea>
</div>
<div style="background:#f8fafc;border-radius:var(--radius-sm);padding:14px;margin-top:16px;font-size:13px;color:var(--muted)">
<p style="margin:0">💡 提示:手动创建的配音会进入审核队列,审核通过后即可使用。</p>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-manual-voice')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveManualVoice()" style="flex:1">提交审核</button>
</div>
</div>
</div>
<!-- 配音播放模态框 -->
<div id="modal-voice-play" class="modal-overlay">
<div class="modal" style="max-width:400px;text-align:center">
<h3 style="margin:0 0 20px;font-size:20px">🎧 正在播放</h3>
<p id="playing-voice-name" style="font-weight:600;margin:0 0 16px">温柔女声 - 轻松种草</p>
<div style="width:80px;height:80px;border-radius:50%;background:var(--primary-soft);margin:0 auto 20px;display:grid;place-items:center;font-size:36px;color:var(--primary)">🎙️</div>
<div style="margin-bottom:8px">
<span id="voice-play-time" style="font-size:14px;color:var(--muted)">00:00 / 00:28</span>
</div>
<div style="height:6px;background:#f1f5f9;border-radius:999px;overflow:hidden;margin-bottom:20px">
<div id="voice-play-progress" style="height:100%;background:var(--primary);width:0%;transition:width .5s"></div>
</div>
<button class="btn ghost" onclick="closeModal('modal-voice-play')" style="width:100%">关闭</button>
</div>
</div>
<!-- ==================== 模板库模态框 ==================== -->
<!-- 模板编辑器模态框 -->
<div id="modal-template-editor" class="modal-overlay" style="padding:40px">
<div class="modal" style="max-width:1000px;max-height:90vh;overflow-y:auto">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px">
<h3 style="margin:0;font-size:20px">🎨 模板编辑器</h3>
<button onclick="closeModal('modal-template-editor')" style="background:none;border:none;font-size:24px;cursor:pointer">×</button>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:24px">
<!-- 左侧:参数配置 -->
<div>
<div class="form-field">
<label>模板名称</label>
<input id="template-name" type="text" placeholder="输入模板名称" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px"/>
</div>
<div class="form-field" style="margin-top:16px">
<label>剪辑模式</label>
<select style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>一镜到底</option>
<option>画中画</option>
<option>口播</option>
<option>口播+画中画</option>
</select>
</div>
<div class="form-field" style="margin-top:16px">
<label>片段数量</label>
<div style="display:flex;align-items:center;gap:12px">
<input type="range" min="1" max="10" value="3" style="flex:1"/>
<span style="font-weight:600;min-width:30px;text-align:center">3</span>
</div>
</div>
<div class="form-field" style="margin-top:16px">
<label>字幕样式</label>
<select style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>底部居中白字</option>
<option>顶部居中白字</option>
<option>底部描边字</option>
<option>动感字幕</option>
</select>
</div>
<div class="form-field" style="margin-top:16px">
<label>背景音乐</label>
<select style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px">
<option>不使用</option>
<option>轻快背景音乐</option>
<option>激情背景音乐</option>
<option>舒缓背景音乐</option>
</select>
</div>
</div>
<!-- 右侧:预览 -->
<div>
<div style="background:#1a1a2e;border-radius:var(--radius-md);padding:16px;text-align:center">
<p style="color:#fff;margin:0 0 12px;font-size:14px">模板预览</p>
<div style="aspect-ratio:9/16;max-height:300px;margin:0 auto;border-radius:var(--radius-sm);background:linear-gradient(180deg,#2d2d44,#1a1a2e);display:grid;place-items:center;color:#fff;font-size:48px">
🎬
</div>
</div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-template-editor')" style="flex:1">取消</button>
<button class="btn primary" onclick="saveTemplate()" style="flex:1">保存模板</button>
</div>
</div>
</div>
<!-- 模板详情模态框 -->
<div id="modal-template-detail" class="modal-overlay">
<div class="modal" style="max-width:600px">
<h3 style="margin:0 0 16px;font-size:20px">🎨 模板详情</h3>
<div style="aspect-ratio:16/9;background:linear-gradient(135deg,#fbbf24,#f59e0b);border-radius:var(--radius-md);display:grid;place-items:center;color:#fff;font-size:60px;margin-bottom:16px">PIP</div>
<h4 id="detail-template-title" style="margin:0 0 12px;font-size:16px">画中画混剪</h4>
<div id="detail-template-meta" style="font-size:13px;color:var(--muted);margin-bottom:16px"></div>
<div style="padding:16px;background:#f8fafc;border-radius:var(--radius-md)">
<h5 style="margin:0 0 12px;font-size:14px">参数配置</h5>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;font-size:13px">
<div><span style="color:var(--muted)">剪辑模式:</span>画中画</div>
<div><span style="color:var(--muted)">片段数量:</span>5个</div>
<div><span style="color:var(--muted)">字幕样式:</span>底部居中</div>
<div><span style="color:var(--muted)">背景音乐:</span>轻快BGM</div>
<div><span style="color:var(--muted)">使用次数:</span>56次</div>
<div><span style="color:var(--muted)">创建时间:</span>2024-01-15</div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-template-detail')" style="flex:1">关闭</button>
<button class="btn primary" onclick="closeModal('modal-template-detail');showView('generate')" style="flex:1">使用此模板</button>
</div>
</div>
</div>
<!-- ==================== 一键生成选择弹窗 ==================== -->
<!-- 选择模板弹窗 -->
<div id="modal-select-template" class="modal-overlay">
<div class="modal" style="max-width:700px">
<h3 style="margin:0 0 20px;font-size:20px">🎨 选择模板</h3>
<div class="choice-list" style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px">
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#fbbf24,#f59e0b)">PIP</div>
<h4>画中画混剪</h4>
<p>产品展示</p>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#3b82f6,#1d4ed8)">ONE</div>
<h4>一镜到底</h4>
<p>口播</p>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#6366f1,#4f46e5)">PER</div>
<h4>人物口播</h4>
<p>口播</p>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#10b981,#059669)">SUP</div>
<h4>种草推荐</h4>
<p>种草</p>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#ec4899,#db2777)">REV</div>
<h4>产品评测</h4>
<p>产品</p>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTemplate(this)">
<div class="thumb" style="background:linear-gradient(135deg,#8b5cf6,#7c3aed)">BRD</div>
<h4>品牌宣传</h4>
<p>品牌</p>
<div class="check-icon"></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-select-template')" style="flex:1">取消</button>
<button class="btn primary" onclick="closeModal('modal-select-template')" style="flex:1">确认选择</button>
</div>
</div>
</div>
<!-- 选择素材弹窗 -->
<div id="modal-select-material" class="modal-overlay">
<div class="modal" style="max-width:800px">
<h3 style="margin:0 0 20px;font-size:20px">📦 选择素材</h3>
<div class="asset-grid" style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px">
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#0ea5e9,#0284c7);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">主播口播开场</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#f59e0b,#d97706);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">产品特写镜头</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#10b981,#059669);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">用户评价片段</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#6366f1,#4f46e5);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">开箱展示</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#ec4899,#db2777);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">使用场景演示</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectMaterial(this)">
<div class="thumb" style="height:60px;background:linear-gradient(135deg,#14b8a6,#0d9488);border-radius:8px"></div>
<h4 style="font-size:12px;margin:8px 0 0">直播高光时刻</h4>
<div class="check-icon"></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-select-material')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmSelectMaterial()" style="flex:1">确认选择</button>
</div>
</div>
</div>
<!-- 选择标题弹窗 -->
<div id="modal-select-title" class="modal-overlay">
<div class="modal" style="max-width:600px">
<h3 style="margin:0 0 20px;font-size:20px">📝 选择标题</h3>
<div style="display:flex;flex-direction:column;gap:10px">
<div class="choice-item" onclick="selectTitle(this)" style="padding:14px">
<h4 style="margin:0;font-size:14px">3秒抓住注意力,30秒讲清卖点</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTitle(this)" style="padding:14px">
<h4 style="margin:0;font-size:14px">新手也能看懂的自动剪辑教程</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTitle(this)" style="padding:14px">
<h4 style="margin:0;font-size:14px">这款产品让效率提升10倍的秘密</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTitle(this)" style="padding:14px">
<h4 style="margin:0;font-size:14px">产品功能详解,看这一期就够了</h4>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectTitle(this)" style="padding:14px">
<h4 style="margin:0;font-size:14px">如何使用小虾智剪快速生成视频</h4>
<div class="check-icon"></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-select-title')" style="flex:1">取消</button>
<button class="btn primary" onclick="closeModal('modal-select-title')" style="flex:1">确认选择</button>
</div>
</div>
</div>
<!-- 选择配音弹窗 -->
<div id="modal-select-voice" class="modal-overlay">
<div class="modal" style="max-width:600px">
<h3 style="margin:0 0 20px;font-size:20px">🎙️ 选择配音</h3>
<div style="display:flex;flex-direction:column;gap:10px">
<div class="choice-item" onclick="selectVoice(this)" style="padding:14px;display:flex;align-items:center;gap:12px">
<div style="width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,#ec4899,#db2777);display:grid;place-items:center;color:#fff;font-size:18px">🎙️</div>
<div>
<h4 style="margin:0;font-size:14px">温柔女声 - 轻松种草</h4>
<p style="margin:4px 0 0;font-size:12px;color:var(--muted)">短视频带货配音</p>
</div>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectVoice(this)" style="padding:14px;display:flex;align-items:center;gap:12px">
<div style="width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,#6366f1,#4f46e5);display:grid;place-items:center;color:#fff;font-size:18px">🎙️</div>
<div>
<h4 style="margin:0;font-size:14px">专业男声 - 产品介绍</h4>
<p style="margin:4px 0 0;font-size:12px;color:var(--muted)">品牌宣传配音</p>
</div>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectVoice(this)" style="padding:14px;display:flex;align-items:center;gap:12px">
<div style="width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,#0ea5e9,#0284c7);display:grid;place-items:center;color:#fff;font-size:18px">🎙️</div>
<div>
<h4 style="margin:0;font-size:14px">活力女声 - 直播预告</h4>
<p style="margin:4px 0 0;font-size:12px;color:var(--muted)">短视频带货配音</p>
</div>
<div class="check-icon"></div>
</div>
<div class="choice-item" onclick="selectVoice(this)" style="padding:14px;display:flex;align-items:center;gap:12px">
<div style="width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,#10b981,#059669);display:grid;place-items:center;color:#fff;font-size:18px">🎙️</div>
<div>
<h4 style="margin:0;font-size:14px">知性女声 - 知识讲解</h4>
<p style="margin:4px 0 0;font-size:12px;color:var(--muted)">知识分享配音</p>
</div>
<div class="check-icon"></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-select-voice')" style="flex:1">取消</button>
<button class="btn primary" onclick="closeModal('modal-select-voice')" style="flex:1">确认选择</button>
</div>
</div>
</div>
<!-- 确认生成弹窗 -->
<div id="modal-confirm-generate" class="modal-overlay">
<div class="modal" style="max-width:480px">
<h3 style="margin:0 0 20px;font-size:20px;text-align:center">✨ 确认生成视频</h3>
<div style="background:#f8fafc;border-radius:16px;padding:20px;margin-bottom:20px">
<div style="display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #e2e8f0">
<span style="color:var(--muted);font-size:14px">模板</span>
<span id="confirm-template" style="font-weight:600;font-size:14px;color:var(--slate)">画中画混剪</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #e2e8f0">
<span style="color:var(--muted);font-size:14px">素材</span>
<span id="confirm-material" style="font-weight:600;font-size:14px;color:var(--slate)">直播切片素材库</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #e2e8f0">
<span style="color:var(--muted);font-size:14px">标题</span>
<span id="confirm-title" style="font-weight:600;font-size:14px;color:var(--slate);max-width:220px;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">3秒抓住注意力,30秒讲清卖点</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:10px 0">
<span style="color:var(--muted);font-size:14px">配音</span>
<span id="confirm-voice" style="font-weight:600;font-size:14px;color:var(--slate)">温柔女声 - 轻松种草</span>
</div>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-confirm-generate')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmGenerate()" style="flex:1">确认生成</button>
</div>
</div>
</div>
<!-- ==================== 成片库模态框 ==================== -->
<!-- 成片预览模态框 -->
<div id="modal-product-preview" class="modal-overlay">
<div class="modal" style="max-width:700px">
<h3 style="margin:0 0 16px;font-size:20px">🎬 视频预览</h3>
<div style="aspect-ratio:9/16;max-height:400px;margin:0 auto;border-radius:var(--radius-md);background:linear-gradient(135deg,#0ea5e9,#0284c7);display:grid;place-items:center;color:#fff;font-size:80px;position:relative;overflow:hidden">
<div style="position:absolute;inset:0;background:radial-gradient(circle at 72% 28%,rgba(255,255,255,.2),transparent 40%)"></div>
<div style="position:relative;width:80px;height:80px;border-radius:50%;background:rgba(255,255,255,.2);display:grid;place-items:center;backdrop-filter:blur(8px)"></div>
</div>
<div style="margin-top:16px">
<h4 id="preview-product-title" style="margin:0 0 12px;font-size:16px">直播切片成片_v2</h4>
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;font-size:13px">
<div><span style="color:var(--muted)">时长:</span>00:32</div>
<div><span style="color:var(--muted)">分辨率:</span>1080P</div>
<div><span style="color:var(--muted)">大小:</span>25.6 MB</div>
<div><span style="color:var(--muted)">生成时间:</span>今天 14:32</div>
<div><span style="color:var(--muted)">模板:</span>画中画混剪</div>
<div><span style="color:var(--muted)">状态:</span><span class="pill ok">可发布</span></div>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-product-preview')" style="flex:1">关闭</button>
<button class="btn ghost" onclick="closeModal('modal-product-preview');downloadProduct()" style="flex:1">下载</button>
<button class="btn primary" onclick="closeModal('modal-product-preview');openPublishModal()" style="flex:1">发布</button>
</div>
</div>
</div>
<!-- 发布视频模态框 -->
<div id="modal-publish" class="modal-overlay">
<div class="modal" style="max-width:520px;max-height:90vh;overflow-y:auto;text-align:left">
<h3 style="margin:0 0 20px;font-size:20px">📢 发布视频</h3>
<!-- 第1步:选择平台 -->
<div id="publish-step-platform">
<p style="margin:0 0 12px;font-weight:600;font-size:14px">选择发布平台</p>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px">
<label class="publish-platform-item selected" onclick="selectPublishPlatform(this)" data-platform="douyin" style="display:flex;align-items:center;gap:10px;padding:14px;border:2px solid var(--primary);border-radius:var(--radius-sm);cursor:pointer;background:var(--primary-soft)">
<input type="radio" name="platform" value="douyin" checked style="width:16px;height:16px;accent-color:var(--primary)"/>
<span style="font-size:22px">📱</span>
<span style="font-weight:600">抖音</span>
</label>
<label class="publish-platform-item" onclick="selectPublishPlatform(this)" data-platform="kuaishou" style="display:flex;align-items:center;gap:10px;padding:14px;border:1px solid var(--line);border-radius:var(--radius-sm);cursor:pointer">
<input type="radio" name="platform" value="kuaishou" style="width:16px;height:16px"/>
<span style="font-size:22px">🎬</span>
<span style="font-weight:600">快手</span>
</label>
<label class="publish-platform-item" onclick="selectPublishPlatform(this)" data-platform="xiaohongshu" style="display:flex;align-items:center;gap:10px;padding:14px;border:1px solid var(--line);border-radius:var(--radius-sm);cursor:pointer">
<input type="radio" name="platform" value="xiaohongshu" style="width:16px;height:16px"/>
<span style="font-size:22px">📕</span>
<span style="font-weight:600">小红书</span>
</label>
<label class="publish-platform-item" onclick="selectPublishPlatform(this)" data-platform="wechat" style="display:flex;align-items:center;gap:10px;padding:14px;border:1px solid var(--line);border-radius:var(--radius-sm);cursor:pointer">
<input type="radio" name="platform" value="wechat" style="width:16px;height:16px"/>
<span style="font-size:22px">💬</span>
<span style="font-weight:600">微信视频号</span>
</label>
</div>
</div>
<!-- 第2步:选择账号 -->
<div id="publish-step-account" style="margin-bottom:16px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">选择发布账号</p>
<select id="publish-account" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px;background:#fff">
<option value="">请选择账号</option>
</select>
</div>
<!-- 视频信息 -->
<div style="margin-bottom:16px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">视频标题 <span style="color:var(--muted);font-weight:400;font-size:12px">(可选,不填则使用默认标题)</span></p>
<input id="publish-title" type="text" placeholder="输入视频标题(选填)" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px"/>
</div>
<div style="margin-bottom:16px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">话题标签 <span style="color:var(--muted);font-weight:400;font-size:12px">(发布时的话题 #</span></p>
<div id="publish-tags-container" style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px"></div>
<div style="display:flex;gap:8px;margin-bottom:10px">
<input id="publish-tag-input" type="text" placeholder="输入话题后按回车添加" style="flex:1;height:36px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 12px;font-size:13px" onkeydown="if(event.key==='Enter'){event.preventDefault();addPublishTag()}"/>
<button class="btn ghost sm" onclick="addPublishTag()">+ 添加</button>
</div>
<div>
<p style="margin:0 0 6px;font-size:12px;color:var(--muted)">💡 常用话题(点击直接添加)</p>
<div id="publish-recent-topics" style="display:flex;flex-wrap:wrap;gap:6px"></div>
</div>
</div>
<div style="margin-bottom:20px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">视频描述 <span style="color:var(--muted);font-weight:400;font-size:12px">(可选)</span></p>
<textarea id="publish-desc" style="width:100%;height:80px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;font-size:14px;resize:none" placeholder="添加视频描述..."></textarea>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-publish')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmPublish()" style="flex:1">🚀 确认发布</button>
</div>
</div>
</div>
<!-- 下载进度模态框 -->
<div id="modal-download" class="modal-overlay">
<div class="modal" style="max-width:400px;text-align:center">
<h3 style="margin:0 0 16px;font-size:20px">📥 正在下载</h3>
<p id="download-product-name" style="font-weight:600;margin:0 0 16px">直播切片成片_v2.mp4</p>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden;margin-bottom:12px">
<div id="download-progress-bar" style="height:100%;background:linear-gradient(90deg,var(--green),#34d399);width:0%;transition:width .3s"></div>
</div>
<p style="margin:0;font-size:14px;color:var(--muted)">请稍候...</p>
</div>
</div>
<!-- 绑定账号模态框 -->
<div id="modal-bindAccount" class="modal-overlay">
<div class="modal" style="max-width:440px;text-align:left">
<h3 style="margin:0 0 20px;font-size:20px">🔗 绑定新账号</h3>
<div style="margin-bottom:20px">
<label style="display:block;margin-bottom:8px;font-weight:600;font-size:14px">选择平台</label>
<select id="bind-platform" style="width:100%;height:44px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 14px;font-size:14px;background:#fff">
<option value="douyin">📱 抖音</option>
<option value="kuaishou">🎬 快手</option>
<option value="xiaohongshu">📕 小红书</option>
<option value="wechat">💬 微信视频号</option>
</select>
</div>
<div style="background:#f8fafc;border-radius:var(--radius-md);padding:16px;margin-bottom:20px">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
<span style="font-size:18px">💡</span>
<span style="font-weight:600;font-size:14px">授权说明</span>
</div>
<p style="margin:0;font-size:13px;color:var(--muted);line-height:1.6">点击"前往授权"后将跳转到平台授权页面,授权成功后即可通过小虾智剪发布视频到该平台。</p>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-bindAccount')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmBindAccount()" style="flex:1">🚀 前往授权</button>
</div>
</div>
</div>
<!-- 解绑确认模态框 -->
<div id="modal-unbindAccount" class="modal-overlay">
<div class="modal" style="max-width:400px;text-align:center">
<h3 style="margin:0 0 16px;font-size:20px">⚠️ 确认解绑</h3>
<div style="background:#fef2f2;border-radius:16px;padding:20px;margin-bottom:20px">
<p style="margin:0;font-size:14px;color:#991b1b">确定要解除绑定以下账号吗?</p>
<p id="unbind-account-name" style="margin:12px 0 0;font-weight:700;font-size:16px;color:#991b1b">小虾智剪-官方号</p>
</div>
<p style="margin:0 0 20px;font-size:13px;color:var(--muted)">解绑后该账号将无法通过小虾智剪发布视频,但不会影响您在平台上的账号本身。</p>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-unbindAccount')" style="flex:1">取消</button>
<button class="btn" onclick="confirmUnbind()" style="flex:1;background:#ef4444;color:#fff">确认解绑</button>
</div>
</div>
</div>
<!-- 批量发布模态框 -->
<div id="modal-batchPublish" class="modal-overlay">
<div class="modal" style="max-width:640px;max-height:90vh;overflow-y:auto;text-align:left">
<h3 style="margin:0 0 20px;font-size:20px">📢 批量发布</h3>
<div style="margin-bottom:20px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">选择发布的视频</p>
<div id="batch-video-list" style="display:flex;flex-direction:column;gap:10px;max-height:280px;overflow-y:auto">
<!-- 动态填充 -->
</div>
</div>
<div style="margin-bottom:16px">
<p style="margin:0 0 8px;font-weight:600;font-size:14px">统一话题标签 <span style="color:var(--muted);font-weight:400;font-size:12px">(所有视频统一使用)</span></p>
<div id="batch-tags-container" style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px"></div>
<div style="display:flex;gap:8px;margin-bottom:10px">
<input id="batch-tag-input" type="text" placeholder="输入话题后按回车添加" style="flex:1;height:36px;border:1px solid var(--line);border-radius:var(--radius-sm);padding:0 12px;font-size:13px" onkeydown="if(event.key==='Enter'){event.preventDefault();addBatchTag()}"/>
<button class="btn ghost sm" onclick="addBatchTag()">+ 添加</button>
</div>
<div>
<p style="margin:0 0 6px;font-size:12px;color:var(--muted)">💡 常用话题(点击直接添加)</p>
<div id="batch-recent-topics" style="display:flex;flex-wrap:wrap;gap:6px"></div>
</div>
</div>
<div style="padding:14px 16px;background:#f8fafc;border-radius:var(--radius-md);margin-bottom:20px;display:flex;align-items:center;justify-content:center;gap:8px">
<span style="font-size:14px">📊 共 <span id="batch-video-count" style="font-weight:700;color:var(--primary)">0</span> 个视频,将发布到 <span id="batch-platform-count" style="font-weight:700;color:var(--primary)">0</span> 个平台</span>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-batchPublish')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmBatchPublish()" style="flex:1">🚀 确认批量发布</button>
</div>
</div>
</div>
<!-- 发布进度模态框 -->
<div id="modal-publishProgress" class="modal-overlay">
<div class="modal" style="max-width:400px;text-align:center">
<div id="publish-progress-icon" style="margin-bottom:8px"><div class="spinner"></div></div>
<h3 style="margin:0 0 8px;font-size:18px">正在发布</h3>
<p id="publish-progress-text" style="margin:0 0 16px;color:var(--muted);font-size:14px">正在发布视频...</p>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden;margin-bottom:12px">
<div id="publish-progress-bar" style="height:100%;background:linear-gradient(90deg,var(--primary),#38bdf8);width:0%;transition:width .4s;border-radius:999px"></div>
</div>
<p style="margin:0;font-size:12px;color:var(--muted)">请勿关闭页面</p>
</div>
</div>
<style>
.success-icon {
width:56px;
height:56px;
border-radius:50%;
background:#dcfce7;
color:#10b981;
display:inline-flex;
align-items:center;
justify-content:center;
font-size:28px;
font-weight:700;
}
.spinner {
width:56px;
height:56px;
border:4px solid #e2e8f0;
border-top-color:var(--primary);
border-radius:50%;
animation:spin .8s linear infinite;
margin:0 auto;
}
@keyframes spin {
to{transform:rotate(360deg)}
}
</style>
<!-- ==================== 任务历史模态框 ==================== -->
<!-- 任务详情模态框 -->
<div id="modal-task-detail" class="modal-overlay">
<div class="modal" style="max-width:600px">
<h3 style="margin:0 0 20px;font-size:20px">📋 任务详情</h3>
<div style="background:#f8fafc;border-radius:var(--radius-md);padding:20px;margin-bottom:20px">
<h4 id="detail-task-title" style="margin:0 0 8px;font-size:16px">产品卖点混剪视频</h4>
<p id="detail-task-meta" style="margin:0;font-size:13px;color:var(--muted)">一键生成 · 模板:画中画混剪</p>
</div>
<div style="margin-bottom:20px">
<h5 style="margin:0 0 12px;font-size:14px;font-weight:600">执行步骤</h5>
<div style="display:flex;flex-direction:column;gap:8px">
<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#dcfce7;border-radius:8px">
<span style="width:24px;height:24px;border-radius:50%;background:#10b981;color:#fff;display:grid;place-items:center;font-size:12px"></span>
<span>读取素材</span>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#dcfce7;border-radius:8px">
<span style="width:24px;height:24px;border-radius:50%;background:#10b981;color:#fff;display:grid;place-items:center;font-size:12px"></span>
<span>AI内容分析</span>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#dcfce7;border-radius:8px">
<span style="width:24px;height:24px;border-radius:50%;background:#10b981;color:#fff;display:grid;place-items:center;font-size:12px"></span>
<span>生成剪辑计划</span>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#fef3c7;border-radius:8px">
<span style="width:24px;height:24px;border-radius:50%;background:#f59e0b;color:#fff;display:grid;place-items:center;font-size:12px"></span>
<span>合成视频</span>
</div>
</div>
</div>
<div style="padding:14px;background:#f8fafc;border-radius:var(--radius-sm);font-size:13px;color:var(--muted)">
<div style="display:flex;justify-content:space-between">
<span>开始时间</span>
<span>今天 14:32:15</span>
</div>
<div style="display:flex;justify-content:space-between;margin-top:8px">
<span>总耗时</span>
<span>28秒</span>
</div>
</div>
<div style="display:flex;gap:12px;margin-top:24px">
<button class="btn ghost" onclick="closeModal('modal-task-detail')" style="flex:1">关闭</button>
<button class="btn primary" onclick="closeModal('modal-task-detail');showView('products')" style="flex:1">查看成片</button>
</div>
</div>
</div>
<!-- ==================== 查重检测模态框 ==================== -->
<div id="dup-upload-progress" class="modal-overlay" style="display:none" style="display:none;pointer-events:none">
<div class="modal" style="max-width:400px;text-align:center;pointer-events:auto">
<h3 style="margin:0 0 16px;font-size:20px">📤 上传进度</h3>
<p id="dup-upload-status" style="margin:0 0 12px;color:var(--muted)">上传中... 0%</p>
<div style="height:8px;background:#f1f5f9;border-radius:999px;overflow:hidden">
<div style="height:100%;background:var(--primary);width:0%;transition:width .3s"></div>
</div>
</div>
</div>
<!-- ==================== 订阅管理模态框 ==================== -->
<!-- 升级确认 -->
<div id="modal-upgrade" class="modal-overlay">
<div class="modal" style="max-width:420px;text-align:center">
<div style="width:60px;height:60px;border-radius:50%;background:var(--primary-soft);margin:0 auto 16px;display:grid;place-items:center;font-size:28px;color:var(--primary)">⬆️</div>
<h3 style="margin:0 0 8px;font-size:18px">确认升级套餐</h3>
<p style="margin:0 0 16px;color:var(--muted)">升级到 <strong id="upgrade-plan-name">旗舰版</strong>,立即解锁更多功能</p>
<div style="padding:14px;background:#f8fafc;border-radius:var(--radius-sm);margin-bottom:20px;text-align:left">
<p style="margin:0;font-size:13px">• 无限视频生成</p>
<p style="margin:8px 0 0;font-size:13px">• 优先处理队列</p>
<p style="margin:8px 0 0;font-size:13px">• 高级AI功能</p>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-upgrade')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmUpgrade()" style="flex:1">立即升级</button>
</div>
</div>
</div>
<!-- 降级确认 -->
<div id="modal-downgrade" class="modal-overlay">
<div class="modal" style="max-width:420px;text-align:center">
<div style="width:60px;height:60px;border-radius:50%;background:#fef3c7;margin:0 auto 16px;display:grid;place-items:center;font-size:28px;color:#92400e">⬇️</div>
<h3 style="margin:0 0 8px;font-size:18px">确认降级套餐</h3>
<p style="margin:0 0 16px;color:var(--muted)">降级后,部分高级功能将无法使用。已生成的视频不受影响。</p>
<div style="padding:14px;background:#fef3c7;border-radius:var(--radius-sm);margin-bottom:20px;font-size:13px;color:#92400e">
<p style="margin:0">⚠️ 降级将在当前计费周期结束后生效</p>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-downgrade')" style="flex:1">取消</button>
<button class="btn" onclick="confirmDowngrade()" style="flex:1;background:#f59e0b;color:#fff">确认降级</button>
</div>
</div>
</div>
<!-- 续费确认 -->
<div id="modal-renew" class="modal-overlay">
<div class="modal" style="max-width:420px;text-align:center">
<div style="width:60px;height:60px;border-radius:50%;background:#dcfce7;margin:0 auto 16px;display:grid;place-items:center;font-size:28px;color:#166534">💳</div>
<h3 style="margin:0 0 8px;font-size:18px">续费套餐</h3>
<p style="margin:0 0 16px;color:var(--muted)">您的专业版套餐将在 <strong>15天后</strong> 到期</p>
<div style="padding:14px;background:#f8fafc;border-radius:var(--radius-sm);margin-bottom:20px">
<div style="display:flex;justify-content:space-between;margin-bottom:8px">
<span>当前套餐</span>
<span>专业版</span>
</div>
<div style="display:flex;justify-content:space-between;margin-bottom:8px">
<span>续费时长</span>
<span>1年</span>
</div>
<div style="display:flex;justify-content:space-between;font-weight:700">
<span>应付金额</span>
<span style="color:var(--primary)">¥1,299</span>
</div>
</div>
<div style="display:flex;gap:12px">
<button class="btn ghost" onclick="closeModal('modal-renew')" style="flex:1">取消</button>
<button class="btn primary" onclick="confirmRenew()" style="flex:1">前往支付</button>
</div>
</div>
</div>
<!-- ==================== 剪辑计划编辑器视图 ==================== -->
<section id="view-editing-planner" class="view">
<div class="app-layout">
<aside class="sidebar">
<div class="sidebar-logo">
<div class="logo" style="width:34px;height:34px;font-size:18px">🦐</div>
<span>小虾智剪</span>
</div>
<nav class="sidebar-nav">
<div class="sidebar-item" data-view="dashboard">
<div class="icon">📊</div>
<span>控制台</span>
</div>
<div class="sidebar-item" data-view="titles">
<div class="icon">📝</div>
<span>标题库</span>
</div>
<div class="sidebar-item" data-view="assets">
<div class="icon">📦</div>
<span>素材库</span>
</div>
<div class="sidebar-item" data-view="voices">
<div class="icon">🎙️</div>
<span>配音库</span>
</div>
<div class="sidebar-item" data-view="templates">
<div class="icon">🎨</div>
<span>模板库</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item active" data-view="editing-planner">
<div class="icon" style="background:var(--primary);color:#fff">✂️</div>
<span>剪辑计划</span>
</div>
<div class="sidebar-item" data-view="generate">
<div class="icon"></div>
<span>一键生成</span>
</div>
<div class="sidebar-item" data-view="products">
<div class="icon">🎬</div>
<span>成片库</span>
</div>
<div class="sidebar-item" data-view="history">
<div class="icon">📋</div>
<span>任务历史</span>
</div>
<div class="sidebar-item" data-view="duplication">
<div class="icon">🔍</div>
<span>查重检测</span>
</div>
<div class="sidebar-item" data-view="voiceClone">
<div class="icon">🎤</div>
<span>我的音色</span>
</div>
<div class="sidebar-divider"></div>
<div class="sidebar-item" data-view="subscription-logged">
<div class="icon">💎</div>
<span>订阅管理</span>
</div>
</nav>
<div class="sidebar-bottom">
<div class="sidebar-item" onclick="logout()">
<div class="icon">🚪</div>
<span>退出登录</span>
</div>
</div>
</aside>
<!-- 剪辑计划主内容 -->
<div class="main-content" style="display:flex;flex-direction:column;height:calc(100vh - 68px);overflow:hidden">
<!-- 顶部工具栏 -->
<div style="height:52px;background:#fff;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0">
<div style="display:flex;align-items:center;gap:12px">
<span style="font-weight:700;color:var(--primary)">✂️ 剪辑计划编辑器</span>
<span style="color:var(--muted);font-size:13px" id="ep-plan-title">空白模板</span>
<span style="font-size:11px;color:var(--muted)" id="ep-editing-indicator"></span>
</div>
<div style="display:flex;align-items:center;gap:10px">
<button class="btn ghost sm" onclick="epSaveTemplate()">💾 <span id="ep-save-btn-text">保存模板</span></button>
<button class="btn primary sm" onclick="epGenerateVideo()">🎬 使用此模板生成</button>
</div>
</div>
<!-- 剪辑模式切换 -->
<div style="height:56px;background:#fff;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:center;gap:12px;padding:0 20px;flex-shrink:0">
<span style="font-size:12px;color:var(--muted);margin-right:8px">剪辑模式:</span>
<div style="display:flex;gap:8px">
<button class="ep-mode-btn active" data-mode="pip" onclick="switchEpMode('pip')">
<div style="font-size:18px">🎭</div>
<div style="font-size:10px;color:#888">画中画</div>
</button>
<button class="ep-mode-btn" data-mode="voice_over" onclick="switchEpMode('voice_over')">
<div style="font-size:18px">🎙️</div>
<div style="font-size:10px;color:#888">人物口播</div>
</button>
<button class="ep-mode-btn" data-mode="one_take" onclick="switchEpMode('one_take')">
<div style="font-size:18px">🎬</div>
<div style="font-size:10px;color:#888">一镜到底</div>
</button>
<button class="ep-mode-btn" data-mode="voice_pip" onclick="switchEpMode('voice_pip')">
<div style="font-size:18px">🎭🎙️</div>
<div style="font-size:10px;color:#888">口播+画中画</div>
</button>
</div>
</div>
<!-- 三栏主体布局 -->
<div style="flex:1;display:flex;min-height:0;overflow:hidden">
<!-- 左侧:模板面板 -->
<div style="width:240px;background:#fff;border-right:1px solid var(--line);display:flex;flex-direction:column;flex-shrink:0">
<div style="padding:12px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between">
<span style="font-size:12px;font-weight:600;color:var(--muted)">📋 已保存模板</span>
<button style="font-size:10px;color:#aaa;background:none;border:none;cursor:pointer" onclick="epToggleTemplateList()" id="ep-back-btn" hidden>← 返回列表</button>
</div>
<!-- 搜索栏 -->
<div style="padding:10px 12px;border-bottom:1px solid #f1f5f9;position:relative">
<span style="position:absolute;left:20px;top:50%;transform:translateY(-50%);font-size:10px;color:#94a3b8">🔍</span>
<input type="text" id="ep-template-search" placeholder="搜索模板..." oninput="epFilterTemplates()" style="width:100%;padding:6px 8px 6px 28px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
</div>
<!-- 分类筛选 -->
<div style="padding:8px 12px;border-bottom:1px solid #f1f5f9;display:flex;gap:6px;flex-wrap:wrap" id="ep-filter-chips">
<span class="ep-filter-chip active" data-filter="all" onclick="epSetFilter(this)">全部</span>
<span class="ep-filter-chip" data-filter="种草" onclick="epSetFilter(this)">种草</span>
<span class="ep-filter-chip" data-filter="知识" onclick="epSetFilter(this)">知识</span>
<span class="ep-filter-chip" data-filter="日常" onclick="epSetFilter(this)">日常</span>
<span class="ep-filter-chip" data-filter="推荐" onclick="epSetFilter(this)">推荐</span>
</div>
<!-- 模板卡片列表 -->
<div style="flex:1;overflow-y:auto;padding:10px" id="ep-template-cards">
<!-- 动态生成 -->
</div>
</div>
<!-- 中间:预览+时间线 -->
<div style="flex:1;display:flex;flex-direction:column;min-width:0;background:#f8fafc">
<!-- 上部:视频预览+封面预览 -->
<div style="display:flex;align-items:flex-start;justify-content:center;gap:40px;padding:20px;background:#fff;border-bottom:1px solid var(--line);height:320px;flex-shrink:0">
<!-- 视频预览 -->
<div style="display:flex;flex-direction:column;align-items:center">
<div style="font-size:11px;color:#94a3b8;margin-bottom:8px">🎬 视频预览</div>
<div style="width:150px;height:267px;background:#1a1a2e;border-radius:16px;overflow:hidden;box-shadow:0 8px 40px rgba(0,0,0,0.3);border:1px solid #333;position:relative">
<div style="height:20px;background:#0a0a14;display:flex;align-items:center;justify-content:space-between;padding:0 8px;font-size:8px;color:#666">
<span>9:41</span>
<span>📶 🔋</span>
</div>
<div style="flex:1;display:flex;align-items:center;justify-content:center;flex-direction:column;background:linear-gradient(180deg,#2d2d44,#1a1a2e)" id="ep-preview-content">
<div style="font-size:48px;opacity:0.5">🎬</div>
<div style="font-size:9px;color:#666">视频预览区域</div>
<div style="font-size:9px;color:#555;margin-top:4px" id="ep-preview-mode-label">画中画模式</div>
</div>
<div style="position:absolute;bottom:8px;left:0;right:0;display:flex;align-items:center;justify-content:center">
<button onclick="epTogglePreview()" style="width:32px;height:32px;border-radius:50%;background:rgba(99,102,241,0.8);color:#fff;border:none;cursor:pointer;font-size:12px;display:grid;place-items:center"></button>
</div>
<div style="position:absolute;bottom:8px;right:8px;padding:2px 6px;background:rgba(0,0,0,0.5);border-radius:4px;font-size:8px;color:#fff" id="ep-preview-time">00:00/02:00</div>
</div>
<!-- 进度条 -->
<div style="display:flex;align-items:center;gap:8px;margin-top:8px;width:150px">
<span style="font-size:9px;color:#94a3b8" id="ep-current-time">00:00</span>
<div style="flex:1;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden">
<div style="height:100%;background:var(--primary);transition:width .3s" id="ep-progress-bar"></div>
</div>
<span style="font-size:9px;color:#94a3b8" id="ep-total-time">02:00</span>
</div>
</div>
<!-- 封面预览 -->
<div style="display:flex;flex-direction:column;align-items:center">
<div style="font-size:11px;color:#94a3b8;margin-bottom:8px">🖼️ 封面预览</div>
<div style="display:flex;align-items:flex-start;gap:12px">
<div style="width:150px;height:267px;background:linear-gradient(135deg,#2d1f6e,#6366f1,#a29bfe);border-radius:16px;overflow:hidden;box-shadow:0 8px 40px rgba(99,102,241,0.3);border:1px solid #333;position:relative" id="ep-cover-preview-box">
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center">
<div style="text-align:center">
<div style="font-size:36px;opacity:0.5">👤</div>
<div style="font-size:9px;color:rgba(255,255,255,0.6);padding:0 8px">封面预览区</div>
</div>
</div>
<div style="position:absolute;bottom:8px;left:8px;padding:2px 6px;background:rgba(0,0,0,0.6);border-radius:4px;font-size:8px;color:rgba(255,255,255,0.8)" id="ep-cover-source-tag">🤖 AI选帧</div>
</div>
<!-- 封面方案按钮 -->
<div style="display:flex;flex-direction:column;gap:8px" id="ep-cover-tags">
<span class="ep-cover-tag active" data-cover="ai" onclick="epSelectCoverScheme(this)">🤖 AI选帧</span>
<span class="ep-cover-tag" data-cover="manual" onclick="epSelectCoverScheme(this)">👆 手动选</span>
<span class="ep-cover-tag" data-cover="upload" onclick="epSelectCoverScheme(this)">📤 上传</span>
<span class="ep-cover-tag" data-cover="repick" onclick="epSelectCoverScheme(this)">🔄 AI重选</span>
</div>
</div>
</div>
</div>
<!-- 下部:时间线 -->
<div style="flex:1;border-top:1px solid var(--line);display:flex;flex-direction:column;background:#fff;min-height:0">
<div style="display:flex;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid #f1f5f9;flex-shrink:0">
<div style="display:flex;align-items:center;gap:10px">
<span style="font-size:12px;color:#64748b">🎬 时间线</span>
<span style="font-size:12px;color:#f59e0b;font-weight:600" id="ep-total-duration-badge">总时长: 0:00</span>
<span style="font-size:10px;color:#94a3b8;padding:2px 8px;border-radius:4px;background:#f1f5f9;display:none" id="ep-one-take-hint">🔒 一镜到底:固定1个片段</span>
</div>
<div style="display:flex;align-items:center;gap:6px">
<button onclick="epUndo()" style="width:28px;height:28px;border-radius:8px;background:#f8fafc;border:1px solid var(--line);color:#94a3b8;cursor:pointer;font-size:12px;display:grid;place-items:center"></button>
<button onclick="epRedo()" style="width:28px;height:28px;border-radius:8px;background:#f8fafc;border:1px solid var(--line);color:#94a3b8;cursor:pointer;font-size:12px;display:grid;place-items:center"></button>
</div>
</div>
<!-- 时间标尺 -->
<div style="height:24px;background:#f8fafc;border-bottom:1px solid #f1f5f9;position:relative;display:flex;align-items:flex-end;padding:0 16px;flex-shrink:0">
<span style="font-size:9px;color:#cbd5e1;position:absolute;bottom:4px;left:10%">0:00</span>
<span style="font-size:9px;color:#cbd5e1;position:absolute;bottom:4px;left:30%">0:30</span>
<span style="font-size:9px;color:#cbd5e1;position:absolute;bottom:4px;left:55%">1:00</span>
<span style="font-size:9px;color:#cbd5e1;position:absolute;bottom:4px;left:80%">1:30</span>
</div>
<!-- 片段轨道 -->
<div style="flex:1;display:flex;align-items:center;gap:12px;padding:12px 16px;overflow-x:auto" id="ep-timeline-track">
<!-- 动态生成 -->
</div>
</div>
</div>
<!-- 右侧:属性面板 -->
<div style="width:280px;background:#fff;border-left:1px solid var(--line);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto">
<div style="flex:1">
<!-- 标题设置 -->
<div style="padding:14px;border-bottom:1px solid #f1f5f9">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
<span style="font-size:11px;font-weight:600;color:#64748b;text-transform:uppercase">📌 标题设置</span>
<div class="toggle" id="ep-title-ai-toggle" onclick="epToggleTitleAi()"></div>
</div>
<div style="display:flex;flex-direction:column;gap:10px">
<div id="ep-title-ai-hint" style="display:none">
<div style="background:#eef2ff;border:1px solid #c7d2fe;border-radius:8px;padding:8px;text-align:center;font-size:10px;color:#6366f1">🤖 系统将从标题库自动匹配</div>
</div>
<div id="ep-title-input-section">
<input type="text" id="ep-title-input" placeholder="输入视频标题..." style="width:100%;padding:8px 10px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
</div>
<div style="display:flex;align-items:center;gap:8px">
<label style="font-size:11px;color:#94a3b8;width:36px">位置</label>
<select id="ep-title-position" style="flex:1;padding:6px 8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option value="top">顶部</option>
<option value="bottom" selected>底部</option>
</select>
</div>
<div style="display:flex;align-items:center;gap:8px">
<select id="ep-title-font" style="flex:1;padding:6px 8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option>默认字体</option>
<option>思源黑体</option>
<option>阿里巴巴普惠体</option>
</select>
<input type="color" id="ep-title-color" value="#ffffff" style="width:32px;height:32px;border-radius:8px;cursor:pointer;border:1px solid var(--line)">
</div>
<div style="display:flex;align-items:center;gap:8px">
<label style="font-size:11px;color:#94a3b8;width:36px">大小</label>
<input type="range" id="ep-title-size-slider" min="12" max="32" value="18" style="flex:1;accent-color:var(--primary)">
<span id="ep-title-size-value" style="font-size:11px;color:var(--primary);width:32px;text-align:right">18px</span>
</div>
<div style="display:flex;align-items:center;gap:10px">
<label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#64748b;cursor:pointer"><input type="checkbox" checked id="ep-title-bold" style="accent-color:var(--primary)">粗体</label>
<label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#64748b;cursor:pointer"><input type="checkbox" id="ep-title-italic" style="accent-color:var(--primary)">斜体</label>
<label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#64748b;cursor:pointer"><input type="checkbox" checked id="ep-title-stroke" style="accent-color:var(--primary)">描边</label>
<label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#64748b;cursor:pointer"><input type="checkbox" id="ep-title-shadow" style="accent-color:var(--primary)">阴影</label>
</div>
<div style="font-size:10px;color:#94a3b8;font-style:italic">💡 标题将贯穿整个视频显示</div>
</div>
</div>
<!-- 字幕设置 -->
<div style="padding:14px;border-bottom:1px solid #f1f5f9">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
<span style="font-size:11px;font-weight:600;color:#64748b;text-transform:uppercase">💬 字幕设置</span>
<div class="toggle on" onclick="this.classList.toggle('on')"></div>
</div>
<div style="display:flex;flex-direction:column;gap:10px">
<div style="display:flex;align-items:center;gap:8px">
<label style="font-size:11px;color:#94a3b8;width:36px">位置</label>
<select style="flex:1;padding:6px 8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option value="top">顶部</option>
<option value="center">中部</option>
<option value="bottom" selected>底部</option>
</select>
</div>
<div style="display:flex;align-items:center;gap:8px">
<select style="flex:1;padding:6px 8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option>系统默认</option>
<option>思源黑体</option>
</select>
<input type="color" value="#ffff00" style="width:32px;height:32px;border-radius:8px;cursor:pointer;border:1px solid var(--line)">
</div>
<div style="display:flex;align-items:center;gap:8px">
<label style="font-size:11px;color:#94a3b8;width:36px">动画</label>
<select style="flex:1;padding:6px 8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option value="none"></option>
<option value="fade" selected>渐入渐出</option>
<option value="bounce">弹跳</option>
</select>
</div>
</div>
</div>
<!-- BGM设置 -->
<div style="padding:14px;border-bottom:1px solid #f1f5f9">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
<span style="font-size:11px;font-weight:600;color:#64748b;text-transform:uppercase">🎵 BGM设置</span>
<div class="toggle on" onclick="this.classList.toggle('on')"></div>
</div>
<select style="width:100%;padding:8px 10px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<option value="">请选择背景音乐</option>
<option value="1" selected>🎸 活力电子 - 节奏感强</option>
<option value="2">🎹 轻快流行 - 青春活力</option>
<option value="3">🎻 舒缓钢琴 - 安静放松</option>
<option value="4">🥁 励志摇滚 - 激情澎湃</option>
</select>
</div>
</div>
<!-- 片段详情区 -->
<div style="border-top:2px solid var(--line);padding:14px" id="ep-segment-detail" hidden>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
<span style="font-size:12px;font-weight:600" id="ep-segment-detail-title">片段 1</span>
<button onclick="epDeleteCurrentSegment()" style="background:none;border:none;color:#94a3b8;cursor:pointer;font-size:14px">🗑️</button>
</div>
<div id="ep-duration-section" style="margin-bottom:12px">
<label style="font-size:11px;color:#94a3b8;display:block;margin-bottom:6px">片段时长范围</label>
<div style="display:flex;align-items:center;gap:6px">
<input type="number" id="ep-duration-min" value="3" min="1" max="60" style="width:48px;padding:6px;text-align:center;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<span style="font-size:11px;color:#94a3b8">-</span>
<input type="number" id="ep-duration-max" value="8" min="1" max="60" style="width:48px;padding:6px;text-align:center;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none">
<span style="font-size:11px;color:#94a3b8"></span>
</div>
<div style="font-size:10px;color:#94a3b8;margin-top:4px">AI根据素材内容自适应决定具体时长</div>
</div>
<div id="ep-duration-locked" style="margin-bottom:12px;display:none">
<label style="font-size:11px;color:#94a3b8;display:block;margin-bottom:6px">片段时长</label>
<div style="padding:8px 10px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:11px;color:#94a3b8">
🔒 由配音决定
</div>
</div>
<div style="margin-bottom:12px">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px">
<span style="font-size:11px;color:#94a3b8">配音文案</span>
<div style="display:flex;align-items:center;gap:8px">
<span style="font-size:10px;color:#94a3b8" id="ep-script-hint">🔇 使用原声</span>
<div class="toggle" id="ep-script-toggle" onclick="epToggleScript()"></div>
</div>
</div>
<div id="ep-script-input" style="display:none">
<textarea id="ep-script-textarea" rows="2" placeholder="输入配音文案..." style="width:100%;padding:8px;background:#f8fafc;border:1px solid var(--line);border-radius:8px;font-size:12px;outline:none;resize:none"></textarea>
</div>
</div>
<div id="ep-material-type-section" style="display:none;margin-bottom:12px">
<label style="font-size:11px;color:#94a3b8;display:block;margin-bottom:6px">素材类型</label>
<div style="display:flex;gap:8px">
<button class="ep-material-type-btn active" data-type="person" onclick="epSelectMaterialType(this)" style="flex:1;padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-size:10px;cursor:pointer;background:#f8fafc">👤 人物</button>
<button class="ep-material-type-btn" data-type="scene" onclick="epSelectMaterialType(this)" style="flex:1;padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-size:10px;cursor:pointer;background:#f8fafc">🏞️ 场景</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Toast容器 -->
<div id="ep-toast-container" style="position:fixed;top:50px;right:12px;z-index:9999;display:flex;flex-direction:column;gap:4px"></div>
<!-- 保存模板弹窗 -->
<div id="ep-save-template-modal" class="modal-overlay">
<div class="modal" style="max-width:420px">
<h3 style="margin:0 0 16px;font-size:18px" id="ep-save-modal-title">保存为模板</h3>
<div style="text-align:left;margin-bottom:16px">
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px">模板名称</label>
<input type="text" id="ep-template-name-input" placeholder="输入模板名称..." style="width:100%;padding:10px 12px;background:#f8fafc;border:1px solid var(--line);border-radius:10px;font-size:13px;outline:none">
</div>
<div style="text-align:left;margin-bottom:16px">
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:8px">标签分类</label>
<div style="display:flex;flex-wrap:wrap;gap:8px">
<label style="display:flex;align-items:center;gap:4px;font-size:12px;cursor:pointer;color:#64748b"><input type="checkbox" value="种草" style="accent-color:var(--primary)">种草</label>
<label style="display:flex;align-items:center;gap:4px;font-size:12px;cursor:pointer;color:#64748b"><input type="checkbox" value="知识" style="accent-color:var(--primary)">知识</label>
<label style="display:flex;align-items:center;gap:4px;font-size:12px;cursor:pointer;color:#64748b"><input type="checkbox" value="日常" style="accent-color:var(--primary)">日常</label>
<label style="display:flex;align-items:center;gap:4px;font-size:12px;cursor:pointer;color:#64748b"><input type="checkbox" value="推荐" style="accent-color:var(--primary)">推荐</label>
</div>
</div>
<div style="padding:12px;background:#f8fafc;border-radius:10px;font-size:12px;color:#64748b;text-align:left;margin-bottom:16px">
<div>📱 <b>视频格式</b>:竖屏 9:161080×1920</div>
<div>🎭 <b>剪辑模式</b><span id="ep-template-mode-display">画中画</span></div>
<div>🎬 <b>片段数量</b><span id="ep-template-segment-count">0</span></div>
</div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="closeModal('ep-save-template-modal')" style="flex:1">取消</button>
<button class="btn primary" onclick="epConfirmSaveTemplate()" style="flex:1">保存</button>
</div>
</div>
</div>
<!-- 生成视频弹窗 -->
<div id="ep-generate-modal" class="modal-overlay">
<div class="modal" style="max-width:420px">
<h3 style="margin:0 0 16px;font-size:18px">🎬 确认生成视频</h3>
<div id="ep-generate-summary" style="text-align:left;padding:14px;background:#f8fafc;border-radius:10px;font-size:13px;line-height:2;margin-bottom:16px"></div>
<div style="display:flex;gap:10px">
<button class="btn ghost" onclick="closeModal('ep-generate-modal')" style="flex:1">取消</button>
<button class="btn primary" onclick="epStartGenerate()" style="flex:1">开始生成</button>
</div>
</div>
</div>
<style>
/* 剪辑计划编辑器样式 */
.ep-mode-btn{padding:8px 14px;border-radius:10px;border:1px solid var(--line);cursor:pointer;transition:all .2s;background:#fff;display:flex;flex-direction:column;align-items:center;gap:2px;min-width:64px}
.ep-mode-btn:hover{border-color:var(--primary-light);background:#f8faff}
.ep-mode-btn.active{border-color:var(--primary);background:var(--primary-soft)}
.ep-mode-btn.active div:last-child{color:var(--primary)}
.ep-filter-chip{padding:4px 10px;border-radius:20px;font-size:10px;cursor:pointer;border:1px solid var(--line);color:#94a3b8;background:#f8fafc;transition:all .2s}
.ep-filter-chip:hover{border-color:var(--primary-light);color:#64748b}
.ep-filter-chip.active{border-color:var(--primary);color:var(--primary);background:var(--primary-soft)}
.ep-cover-tag{display:inline-flex;align-items:center;gap:4px;padding:6px 10px;border-radius:20px;font-size:10px;cursor:pointer;transition:all .2s;border:1px solid var(--line);color:#94a3b8;background:#f8fafc}
.ep-cover-tag:hover{border-color:var(--primary);color:var(--primary)}
.ep-cover-tag.active{border-color:var(--primary);color:var(--primary);background:var(--primary-soft)}
.ep-material-type-btn.active{border-color:var(--primary);background:var(--primary-soft);color:var(--primary)}
.ep-template-card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px;cursor:pointer;transition:all .2s}
.ep-template-card:hover{border-color:var(--primary-light);box-shadow:0 4px 12px rgba(0,0,0,0.08)}
.ep-timeline-card{min-width:100px;height:100px;border-radius:12px;padding:10px;cursor:grab;position:relative;flex-shrink:0;display:flex;flex-direction:column;transition:all .15s;border:2px solid transparent}
.ep-timeline-card:hover{transform:translateY(-2px);box-shadow:0 4px 16px rgba(0,0,0,0.1)}
.ep-timeline-card.selected{border-color:var(--primary);box-shadow:0 0 12px rgba(99,102,241,0.4)}
.ep-toast{padding:10px 16px;border-radius:8px;font-size:12px;color:#fff;animation:epSlideIn .3s ease}
.ep-toast.hide{animation:epFadeOut .3s ease forwards}
.ep-toast-success{background:#10b981}
.ep-toast-info{background:var(--primary)}
.ep-toast-warning{background:#f59e0b;color:#fff}
@keyframes epSlideIn{from{opacity:0;transform:translateX(20px)}to{opacity:1;transform:translateX(0)}}
@keyframes epFadeOut{from{opacity:1}to{opacity:0}}
</style>
<script>
// ==================== 剪辑计划编辑器 JavaScript ====================
var epCurrentMode = 'pip';
var epSegments = [];
var epSelectedSegmentId = null;
var epCurrentTemplateId = null;
var epTemplates = [
{id:1,name:'产品卖点介绍',mode:'pip',tags:['种草','推荐'],segments:5,duration:'约2分钟'},
{id:2,name:'知识分享口播',mode:'voice_over',tags:['知识'],segments:3,duration:'约1分钟'},
{id:3,name:'一镜到底种草',mode:'one_take',tags:['种草','推荐'],segments:1,duration:'约30秒'},
];
var epCurrentFilter = 'all';
var epSearchQuery = '';
var epCurrentCoverScheme = 'ai';
var epIsPlaying = false;
var epPlayTimer = null;
var epPlayProgress = 0;
var EP_MODE_CONFIG = {
pip:{label:'画中画',icon:'🎭',color:'#6366f1'},
voice_over:{label:'人物口播',icon:'🎙️',color:'#10b981'},
one_take:{label:'一镜到底',icon:'🎬',color:'#f59e0b'},
voice_pip:{label:'口播+画中画',icon:'🎭🎙️',color:'#ec4899'}
};
var EP_COVER_SCHEME_LABELS = {
ai:'🤖 AI选帧',manual:'👆 手动选',upload:'📤 上传',repick:'🔄 AI重选'
};
function epInit(){
epRenderTemplateCards();
epRenderTimeline();
epUpdatePreview();
document.getElementById('ep-title-size-slider').addEventListener('input',function(){
document.getElementById('ep-title-size-value').textContent = this.value + 'px';
});
document.getElementById('ep-duration-min').addEventListener('change',epUpdateSegmentDuration);
document.getElementById('ep-duration-max').addEventListener('change',epUpdateSegmentDuration);
}
function epRenderTemplateCards(){
var container = document.getElementById('ep-template-cards');
if(epTemplates.length === 0){
container.innerHTML = '<div style="text-align:center;padding:20px;font-size:12px;color:#94a3b8">暂无已保存的模板</div>';
return;
}
var filtered = epTemplates;
if(epCurrentFilter !== 'all') filtered = filtered.filter(function(t){return t.tags.indexOf(epCurrentFilter) !== -1});
if(epSearchQuery){
var q = epSearchQuery.toLowerCase();
filtered = filtered.filter(function(t){return t.name.toLowerCase().indexOf(q) !== -1});
}
if(filtered.length === 0){
container.innerHTML = '<div style="text-align:center;padding:20px;font-size:12px;color:#94a3b8">未找到匹配的模板</div>';
return;
}
var html = '';
for(var i=0;i<filtered.length;i++){
var t = filtered[i];
html += '<div class="ep-template-card" onclick="epLoadTemplate(' + t.id + ')" style="margin-bottom:8px">';
html += '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px">';
html += '<div style="font-size:12px;font-weight:600;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + t.name + '</div>';
html += '</div>';
html += '<div style="display:flex;align-items:center;gap:4px;margin-bottom:4px">';
html += '<span style="padding:2px 6px;background:var(--primary-soft);color:var(--primary);border-radius:4px;font-size:9px">' + (t.mode === 'pip' ? '🎭' : t.mode === 'voice_over' ? '🎙️' : '🎬') + '</span>';
html += '<span style="font-size:10px;color:#94a3b8">' + EP_MODE_CONFIG[t.mode].label + '</span>';
html += '</div>';
html += '<div style="font-size:10px;color:#94a3b8">' + t.segments + '个片段 · ' + t.duration + '</div>';
html += '</div>';
}
container.innerHTML = html;
}
function epLoadTemplate(id){
var t = null;
for(var i=0;i<epTemplates.length;i++){if(epTemplates[i].id === id){t = epTemplates[i];break;}}
if(!t) return;
epCurrentTemplateId = id;
switchEpMode(t.mode);
document.getElementById('ep-plan-title').textContent = t.name;
document.getElementById('ep-editing-indicator').textContent = '(编辑中)';
document.getElementById('ep-save-btn-text').textContent = '更新模板';
epShowToast('📋 已加载模板「' + t.name + '」','success');
}
function epFilterTemplates(){
epSearchQuery = document.getElementById('ep-template-search').value.trim();
epRenderTemplateCards();
}
function epSetFilter(el){
epCurrentFilter = el.dataset.filter;
var chips = document.querySelectorAll('#ep-filter-chips .ep-filter-chip');
for(var i=0;i<chips.length;i++) chips[i].classList.remove('active');
el.classList.add('active');
epRenderTemplateCards();
}
function epToggleTemplateList(){
document.getElementById('ep-back-btn').hidden = !document.getElementById('ep-back-btn').hidden;
}
function switchEpMode(mode){
epCurrentMode = mode;
var btns = document.querySelectorAll('.ep-mode-btn');
for(var i=0;i<btns.length;i++){
btns[i].classList.toggle('active', btns[i].dataset.mode === mode);
}
document.getElementById('ep-preview-mode-label').textContent = EP_MODE_CONFIG[mode].icon + ' ' + EP_MODE_CONFIG[mode].label;
document.getElementById('ep-template-mode-display').textContent = EP_MODE_CONFIG[mode].label;
document.getElementById('ep-one-take-hint').style.display = (mode === 'one_take') ? 'inline-block' : 'none';
if(mode === 'one_take' && epSegments.length > 1){
epSegments = [epSegments[0]];
epSelectedSegmentId = null;
document.getElementById('ep-segment-detail').hidden = true;
epShowToast('🔒 一镜到底模式已锁定为1个片段','warning');
}
epUpdateSegmentDetailPanel();
epRenderTimeline();
epUpdatePreview();
}
function epUpdateSegmentDetailPanel(){
var durSec = document.getElementById('ep-duration-section');
var durLock = document.getElementById('ep-duration-locked');
var matType = document.getElementById('ep-material-type-section');
if(epCurrentMode === 'one_take' || epCurrentMode === 'voice_over'){
durSec.style.display = 'none';
durLock.style.display = 'block';
}else{
durSec.style.display = 'block';
durLock.style.display = 'none';
}
if(epCurrentMode === 'voice_pip') matType.style.display = 'block';
else matType.style.display = 'none';
}
function epRenderTimeline(){
var track = document.getElementById('ep-timeline-track');
var html = '';
var cfg = EP_MODE_CONFIG[epCurrentMode];
for(var i=0;i<epSegments.length;i++){
var seg = epSegments[i];
var isSelected = (seg.id === epSelectedSegmentId);
var typeTag = '';
if(epCurrentMode === 'voice_pip'){
typeTag = '<span style="font-size:9px;padding:2px 6px;border-radius:4px;background:' + (seg.materialType === 'person' ? 'rgba(99,102,241,0.2)' : 'rgba(16,185,129,0.2)') + ';color:' + (seg.materialType === 'person' ? '#6366f1' : '#10b981') + '">' + (seg.materialType === 'person' ? '👤' : '🏞️') + '</span>';
}
var scriptIcon = seg.hasScript ? '🎤' : '🔇';
var durText = (epCurrentMode === 'one_take' || epCurrentMode === 'voice_over') ? '🔒 由配音决定' : seg.durationMin + '-' + seg.durationMax + 's';
html += '<div class="ep-timeline-card ' + (isSelected ? 'selected' : '') + '" style="background:' + cfg.color + '22;border-color:' + (isSelected ? '#fff' : cfg.color + '44') + '" draggable="true" data-id="' + seg.id + '" onclick="epSelectSegment(' + seg.id + ')" ondragstart="epDragStart(event,' + seg.id + ')" ondragover="epDragOver(event)" ondrop="epDrop(event,' + seg.id + ')">';
html += '<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px">';
html += '<span style="font-size:11px;font-weight:500">片段' + (i + 1) + '</span>';
html += '<div style="display:flex;align-items:center;gap:4px">' + typeTag + '<span style="font-size:9px">' + scriptIcon + '</span></div>';
html += '</div>';
html += '<div style="font-size:10px;color:rgba(255,255,255,0.7);background:rgba(0,0,0,0.3);padding:4px 8px;border-radius:4px;margin-bottom:auto">' + durText + '</div>';
html += '<div style="display:flex;align-items:center;justify-content:space-between;margin-top:auto;padding-top:6px">';
html += '<span style="font-size:9px;color:rgba(255,255,255,0.5)">👆 拖拽排序</span>';
html += '<button onclick="event.stopPropagation();epDeleteSegment(' + seg.id + ')" style="background:none;border:none;color:rgba(255,255,255,0.5);cursor:pointer;font-size:12px">×</button>';
html += '</div></div>';
}
var isOneTake = (epCurrentMode === 'one_take');
if(!isOneTake){
html += '<div onclick="epAddSegment()" style="min-width:60px;height:100px;border:2px dashed var(--line);border-radius:12px;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:24px;color:#94a3b8;transition:all .2s" onmouseover="this.style.borderColor=\'var(--primary)\';this.style.color=\'var(--primary)\'" onmouseout="this.style.borderColor=\'var(--line)\';this.style.color=\'#94a3b8\'">+</div>';
}else{
html += '<div style="min-width:60px;height:100px;border:2px dashed #e2e8f0;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:20px;color:#cbd5e1">🔒</div>';
}
track.innerHTML = html;
epUpdateDurationBadge();
}
function epUpdateDurationBadge(){
if(epCurrentMode === 'one_take' || epCurrentMode === 'voice_over'){
document.getElementById('ep-total-duration-badge').textContent = '总时长: 由配音决定';
document.getElementById('ep-total-time').textContent = '00:00 / 配音时长';
}else{
var totalMin = 0,totalMax = 0;
for(var i=0;i<epSegments.length;i++){totalMin += epSegments[i].durationMin;totalMax += epSegments[i].durationMax;}
document.getElementById('ep-total-duration-badge').textContent = '总时长: ' + totalMin + '-' + totalMax + 's';
var mm = String(Math.floor(totalMax / 60)).padStart(2,'0');
var ss = String(totalMax % 60).padStart(2,'0');
document.getElementById('ep-total-time').textContent = '00:00 / ' + mm + ':' + ss;
}
}
function epSelectSegment(id){
epSelectedSegmentId = id;
var seg = null;
for(var i=0;i<epSegments.length;i++){if(epSegments[i].id === id){seg = epSegments[i];break;}}
if(!seg) return;
document.getElementById('ep-segment-detail').hidden = false;
var idx = 0;
for(var i=0;i<epSegments.length;i++){if(epSegments[i].id === id){idx = i;break;}}
document.getElementById('ep-segment-detail-title').textContent = '片段 ' + (idx + 1);
document.getElementById('ep-duration-min').value = seg.durationMin;
document.getElementById('ep-duration-max').value = seg.durationMax;
var scriptToggle = document.getElementById('ep-script-toggle');
var scriptHint = document.getElementById('ep-script-hint');
var scriptInput = document.getElementById('ep-script-input');
if(seg.hasScript){
scriptToggle.classList.add('on');
scriptHint.textContent = '🎤 有配音文案';
scriptInput.style.display = 'block';
document.getElementById('ep-script-textarea').value = seg.script || '';
}else{
scriptToggle.classList.remove('on');
scriptHint.textContent = '🔇 使用原声';
scriptInput.style.display = 'none';
}
var btns = document.querySelectorAll('.ep-material-type-btn');
for(var i=0;i<btns.length;i++){
var isActive = (btns[i].dataset.type === seg.materialType);
btns[i].classList.toggle('active',isActive);
btns[i].style.borderColor = isActive ? 'var(--primary)' : 'var(--line)';
}
epRenderTimeline();
}
function epDeleteSegment(id){
if(epCurrentMode === 'one_take') return;
epSegments = epSegments.filter(function(s){return s.id !== id});
if(epSelectedSegmentId === id){epSelectedSegmentId = null;document.getElementById('ep-segment-detail').hidden = true;}
epRenderTimeline();
epShowToast('片段已删除','info');
}
function epDeleteCurrentSegment(){
if(epSelectedSegmentId) epDeleteSegment(epSelectedSegmentId);
}
function epAddSegment(){
if(epCurrentMode === 'one_take') return;
var newId = 1;
for(var i=0;i<epSegments.length;i++) if(epSegments[i].id >= newId) newId = epSegments[i].id + 1;
epSegments.push({id:newId,durationMin:3,durationMax:8,script:'',hasScript:false,materialType:'person'});
epSelectSegment(newId);
epRenderTimeline();
epShowToast('新片段已添加','success');
}
function epUpdateSegmentDuration(){
if(!epSelectedSegmentId) return;
for(var i=0;i<epSegments.length;i++){
if(epSegments[i].id === epSelectedSegmentId){
epSegments[i].durationMin = parseInt(document.getElementById('ep-duration-min').value) || 3;
epSegments[i].durationMax = parseInt(document.getElementById('ep-duration-max').value) || 8;
break;
}
}
epRenderTimeline();
}
function epToggleScript(){
var toggle = document.getElementById('ep-script-toggle');
var hint = document.getElementById('ep-script-hint');
var input = document.getElementById('ep-script-input');
toggle.classList.toggle('on');
var isOn = toggle.classList.contains('on');
if(isOn){
hint.textContent = '🎤 有配音文案';
input.style.display = 'block';
if(epSelectedSegmentId){
for(var i=0;i<epSegments.length;i++){
if(epSegments[i].id === epSelectedSegmentId){epSegments[i].hasScript = true;break;}
}
}
}else{
hint.textContent = '🔇 使用原声';
input.style.display = 'none';
if(epSelectedSegmentId){
for(var i=0;i<epSegments.length;i++){
if(epSegments[i].id === epSelectedSegmentId){epSegments[i].hasScript = false;epSegments[i].script = '';break;}
}
}
}
epRenderTimeline();
}
function epSelectMaterialType(btn){
var type = btn.dataset.type;
var btns = document.querySelectorAll('.ep-material-type-btn');
for(var i=0;i<btns.length;i++){btns[i].classList.remove('active');btns[i].style.borderColor = 'var(--line)';}
btn.classList.add('active');
btn.style.borderColor = 'var(--primary)';
if(epSelectedSegmentId){
for(var i=0;i<epSegments.length;i++){
if(epSegments[i].id === epSelectedSegmentId){epSegments[i].materialType = type;break;}
}
}
epRenderTimeline();
}
function epToggleTitleAi(){
var toggle = document.getElementById('ep-title-ai-toggle');
var hint = document.getElementById('ep-title-ai-hint');
var inputSection = document.getElementById('ep-title-input-section');
toggle.classList.toggle('on');
var isOn = toggle.classList.contains('on');
hint.style.display = isOn ? 'block' : 'none';
inputSection.style.display = isOn ? 'none' : 'block';
}
function epSelectCoverScheme(btn){
var tags = document.querySelectorAll('.ep-cover-tag');
for(var i=0;i<tags.length;i++) tags[i].classList.remove('active');
btn.classList.add('active');
epCurrentCoverScheme = btn.dataset.cover;
document.getElementById('ep-cover-source-tag').textContent = EP_COVER_SCHEME_LABELS[epCurrentCoverScheme];
var box = document.getElementById('ep-cover-preview-box');
if(epCurrentCoverScheme === 'upload'){
box.style.background = 'linear-gradient(135deg,#1a4a2e,#2d7a4e)';
}else if(epCurrentCoverScheme === 'manual'){
box.style.background = 'linear-gradient(135deg,#2a1f6e,#6366f1)';
}else if(epCurrentCoverScheme === 'repick'){
box.style.background = 'linear-gradient(135deg,#6e2d5c,#a29bfe)';
}else{
box.style.background = 'linear-gradient(135deg,#2d1f6e,#6366f1,#a29bfe)';
}
}
function epTogglePreview(){
if(epIsPlaying){epStopPreview();}else{epStartPreview();}
}
function epStartPreview(){
epIsPlaying = true;
var totalDur = 120;
if(epCurrentMode !== 'one_take' && epCurrentMode !== 'voice_over'){
totalDur = 0;
for(var i=0;i<epSegments.length;i++) totalDur += epSegments[i].durationMax;
if(totalDur === 0) totalDur = 120;
}
epPlayProgress = 0;
epPlayTimer = setInterval(function(){
epPlayProgress++;
if(epPlayProgress >= totalDur){epPlayProgress = 0;epStopPreview();return;}
var pct = (epPlayProgress / totalDur) * 100;
document.getElementById('ep-progress-bar').style.width = pct + '%';
document.getElementById('ep-current-time').textContent = epFormatTime(epPlayProgress);
if(epCurrentMode === 'one_take'){
document.getElementById('ep-preview-mode-label').textContent = '🎬 片段1';
}else{
var elapsed = 0;
for(var i=0;i<epSegments.length;i++){
if(epPlayProgress < elapsed + epSegments[i].durationMax){
document.getElementById('ep-preview-mode-label').textContent = '片段' + (i + 1);
break;
}
elapsed += epSegments[i].durationMax;
}
}
},1000);
}
function epStopPreview(){
epIsPlaying = false;
clearInterval(epPlayTimer);
}
function epUpdatePreview(){
var cfg = EP_MODE_CONFIG[epCurrentMode];
document.getElementById('ep-preview-mode-label').textContent = cfg.icon + ' ' + cfg.label;
}
function epUndo(){epShowToast('↩ 撤销','info');}
function epRedo(){epShowToast('↪ 重做','info');}
var epDragSegmentId = null;
function epDragStart(e,id){epDragSegmentId = id;e.target.style.opacity = '0.5';}
function epDragOver(e){e.preventDefault();}
function epDrop(e,targetId){
e.preventDefault();
if(epDragSegmentId === null || epDragSegmentId === targetId) return;
if(epCurrentMode === 'one_take') return;
var fromIdx = -1,toIdx = -1;
for(var i=0;i<epSegments.length;i++){
if(epSegments[i].id === epDragSegmentId) fromIdx = i;
if(epSegments[i].id === targetId) toIdx = i;
}
if(fromIdx !== -1 && toIdx !== -1){
var item = epSegments.splice(fromIdx,1)[0];
epSegments.splice(toIdx,0,item);
epRenderTimeline();
epShowToast('片段顺序已调整','info');
}
epDragSegmentId = null;
}
function epSaveTemplate(){
document.getElementById('ep-template-segment-count').textContent = epSegments.length;
document.getElementById('ep-template-mode-display').textContent = EP_MODE_CONFIG[epCurrentMode].label;
if(epCurrentTemplateId){
for(var i=0;i<epTemplates.length;i++){
if(epTemplates[i].id === epCurrentTemplateId){
document.getElementById('ep-template-name-input').value = epTemplates[i].name;
var cbs = document.querySelectorAll('#ep-save-template-modal input[type="checkbox"]');
for(var j=0;j<cbs.length;j++) cbs[j].checked = (epTemplates[i].tags.indexOf(cbs[j].value) !== -1);
break;
}
}
document.getElementById('ep-save-modal-title').textContent = '更新模板';
}else{
document.getElementById('ep-template-name-input').value = '';
var cbs = document.querySelectorAll('#ep-save-template-modal input[type="checkbox"]');
for(var j=0;j<cbs.length;j++) cbs[j].checked = false;
document.getElementById('ep-save-modal-title').textContent = '保存为模板';
}
openModal('ep-save-template-modal');
}
function epConfirmSaveTemplate(){
var name = document.getElementById('ep-template-name-input').value.trim();
if(!name){epShowToast('请输入模板名称','warning');return;}
var checkedTags = [];
var cbs = document.querySelectorAll('#ep-save-template-modal input[type="checkbox"]:checked');
for(var i=0;i<cbs.length;i++) checkedTags.push(cbs[i].value);
var totalMax = 0;
for(var i=0;i<epSegments.length;i++) totalMax += epSegments[i].durationMax;
var dur = '约' + Math.ceil(totalMax / 60) + '分钟';
if(epCurrentTemplateId){
for(var i=0;i<epTemplates.length;i++){
if(epTemplates[i].id === epCurrentTemplateId){
epTemplates[i].name = name;
epTemplates[i].mode = epCurrentMode;
epTemplates[i].tags = checkedTags.length ? checkedTags : ['未分类'];
epTemplates[i].segments = epSegments.length;
epTemplates[i].duration = dur;
break;
}
}
closeModal('ep-save-template-modal');
document.getElementById('ep-plan-title').textContent = name;
epShowToast('✅ 模板「' + name + '」已更新','success');
}else{
var newId = 1;
for(var i=0;i<epTemplates.length;i++) if(epTemplates[i].id >= newId) newId = epTemplates[i].id + 1;
epTemplates.push({id:newId,name:name,mode:epCurrentMode,tags:checkedTags.length ? checkedTags : ['未分类'],segments:epSegments.length,duration:dur});
epCurrentTemplateId = newId;
closeModal('ep-save-template-modal');
epShowToast('✅ 模板「' + name + '」已保存','success');
}
epRenderTemplateCards();
}
function epGenerateVideo(){
var segsWithScript = 0;
for(var i=0;i<epSegments.length;i++) if(epSegments[i].hasScript) segsWithScript++;
var durationText = '由配音决定';
if(epCurrentMode !== 'one_take' && epCurrentMode !== 'voice_over'){
var totalMin = 0,totalMax = 0;
for(var i=0;i<epSegments.length;i++){totalMin += epSegments[i].durationMin;totalMax += epSegments[i].durationMax;}
durationText = totalMin + '-' + totalMax + '秒';
}
document.getElementById('ep-generate-summary').innerHTML = '<div>📱 <b>视频格式</b>:竖屏 9:161080×1920</div><div>🎭 <b>剪辑模式</b>' + EP_MODE_CONFIG[epCurrentMode].icon + ' ' + EP_MODE_CONFIG[epCurrentMode].label + '</div><div>🎬 <b>片段数量</b>' + epSegments.length + ' 个</div><div>⏱️ <b>预计总时长</b>' + durationText + '</div><div>📝 <b>配音文案</b>' + segsWithScript + ' 段有台词</div>';
openModal('ep-generate-modal');
}
function epStartGenerate(){
closeModal('ep-generate-modal');
epShowToast('🎬 视频生成任务已提交,预计需要3-5分钟...','success');
setTimeout(function(){epShowToast('🔍 正在进行查重检测...','info');},3000);
setTimeout(function(){epShowToast('✅ 查重通过,视频已就绪!','success');},6000);
}
function epFormatTime(seconds){
seconds = Math.max(0,Math.floor(seconds));
var m = Math.floor(seconds / 60);
var s = seconds % 60;
return String(m).padStart(2,'0') + ':' + String(s).padStart(2,'0');
}
function epShowToast(msg,type){
type = type || 'info';
var container = document.getElementById('ep-toast-container');
var toast = document.createElement('div');
toast.className = 'ep-toast ep-toast-' + type;
toast.textContent = msg;
container.appendChild(toast);
setTimeout(function(){
toast.classList.add('hide');
setTimeout(function(){toast.remove();},300);
},2500);
}
document.addEventListener('DOMContentLoaded',epInit);
</script>
<!-- ==================== 音色克隆功能 JavaScript ==================== -->
<script>
// 已克隆音色数据
var clonedVoices = [
{id: 1, name: '我的默认音色', duration: '15秒', createdAt: '2024年6月15日', status: 'ready'}
];
var selectedCloneVoiceId = null;
var currentCloneAudio = null;
var cloneRecordTimer = null;
var cloneRecordSeconds = 0;
var cloneAudioPlayTimer = null;
// 打开克隆音色弹窗
function openCloneVoiceModal() {
// 重置表单状态
document.getElementById('clone-voice-name').value = '我的声音 ' + (clonedVoices.length + 1);
document.getElementById('clone-upload-input').value = '';
document.getElementById('clone-audio-preview-modal').style.display = 'none';
document.getElementById('clone-modal-progress').style.display = 'none';
document.getElementById('clone-modal-success').style.display = 'none';
document.getElementById('clone-modal-buttons').style.display = 'flex';
document.getElementById('clone-modal-done').style.display = 'none';
document.getElementById('clone-start-btn').disabled = true;
document.getElementById('clone-record-idle').style.display = 'block';
document.getElementById('clone-record-recording').style.display = 'none';
document.getElementById('clone-record-preview').style.display = 'none';
currentCloneAudio = null;
openModal('modal-cloneVoice');
}
// 处理文件上传
function handleCloneFileUpload(input) {
if (input.files && input.files[0]) {
var file = input.files[0];
if (!file.name.match(/\.(mp3|wav)$/i)) {
alert('请上传 MP3 或 WAV 格式的音频文件');
return;
}
currentCloneAudio = {
name: file.name,
type: 'upload',
duration: Math.floor(Math.random() * 60) + 10 + '秒'
};
document.getElementById('clone-audio-preview-modal').style.display = 'block';
document.getElementById('clone-preview-name').textContent = file.name;
document.getElementById('clone-preview-duration').textContent = '00:00 / ' + currentCloneAudio.duration;
document.getElementById('clone-start-btn').disabled = false;
}
}
// 处理拖拽上传
function handleCloneDrop(e) {
e.preventDefault();
e.target.style.borderColor = 'var(--line)';
var files = e.dataTransfer.files;
if (files.length > 0) {
var input = document.getElementById('clone-upload-input');
var dt = new DataTransfer();
dt.items.add(files[0]);
input.files = dt.files;
handleCloneFileUpload(input);
}
}
// 移除音频
function removeCloneAudio() {
currentCloneAudio = null;
document.getElementById('clone-upload-input').value = '';
document.getElementById('clone-audio-preview-modal').style.display = 'none';
document.getElementById('clone-start-btn').disabled = true;
document.getElementById('clone-record-idle').style.display = 'block';
document.getElementById('clone-record-recording').style.display = 'none';
document.getElementById('clone-record-preview').style.display = 'none';
}
// 播放音频预览
function playClonePreview() {
// 模拟播放进度
var progress = 0;
var interval = setInterval(function() {
progress += 5;
if (progress >= 100) {
progress = 0;
clearInterval(interval);
}
document.getElementById('clone-preview-progress').style.width = progress + '%';
}, 200);
}
// 开始录音
function startCloneRecording() {
document.getElementById('clone-record-idle').style.display = 'none';
document.getElementById('clone-record-recording').style.display = 'block';
document.getElementById('clone-record-preview').style.display = 'none';
cloneRecordSeconds = 0;
updateCloneRecordTimer();
cloneRecordTimer = setInterval(function() {
cloneRecordSeconds++;
updateCloneRecordTimer();
if (cloneRecordSeconds >= 120) { // 最多2分钟
stopCloneRecording();
}
}, 1000);
}
function updateCloneRecordTimer() {
var m = Math.floor(cloneRecordSeconds / 60);
var s = cloneRecordSeconds % 60;
document.getElementById('clone-record-timer').textContent = String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0');
}
// 停止录音
function stopCloneRecording() {
clearInterval(cloneRecordTimer);
document.getElementById('clone-record-idle').style.display = 'none';
document.getElementById('clone-record-recording').style.display = 'none';
document.getElementById('clone-record-preview').style.display = 'block';
currentCloneAudio = {
name: '录音_' + new Date().toLocaleTimeString() + '.wav',
type: 'record',
duration: Math.floor(cloneRecordSeconds) + '秒'
};
}
// 重新录制
function reRecordClone() {
document.getElementById('clone-record-idle').style.display = 'block';
document.getElementById('clone-record-recording').style.display = 'none';
document.getElementById('clone-record-preview').style.display = 'none';
currentCloneAudio = null;
document.getElementById('clone-start-btn').disabled = true;
}
// 使用录音
function useCloneRecording() {
document.getElementById('clone-audio-preview-modal').style.display = 'block';
document.getElementById('clone-preview-name').textContent = currentCloneAudio.name;
document.getElementById('clone-preview-duration').textContent = '00:00 / ' + currentCloneAudio.duration;
document.getElementById('clone-record-idle').style.display = 'none';
document.getElementById('clone-record-recording').style.display = 'none';
document.getElementById('clone-record-preview').style.display = 'none';
document.getElementById('clone-start-btn').disabled = false;
}
// 开始克隆流程
function startCloneVoiceProcess() {
if (!currentCloneAudio) {
alert('请先上传或录制音频');
return;
}
var voiceName = document.getElementById('clone-voice-name').value || '我的声音';
document.getElementById('clone-modal-buttons').style.display = 'none';
document.getElementById('clone-modal-progress').style.display = 'block';
document.getElementById('clone-modal-progress-text').textContent = '正在处理音频...';
var progress = 0;
var progressBar = document.getElementById('clone-modal-progress-bar');
var progressText = document.getElementById('clone-modal-progress-text');
var steps = ['正在处理音频...', '正在提取音色特征...', '正在训练AI模型...', '正在保存音色...', '即将完成...'];
var interval = setInterval(function() {
progress += 2;
progressBar.style.width = progress + '%';
progressText.textContent = steps[Math.min(Math.floor(progress / 20), steps.length - 1)];
if (progress >= 100) {
clearInterval(interval);
// 克隆成功
document.getElementById('clone-modal-progress').style.display = 'none';
document.getElementById('clone-modal-success').style.display = 'block';
document.getElementById('clone-modal-done').style.display = 'flex';
// 添加到音色列表
var newVoice = {
id: Date.now(),
name: voiceName,
duration: currentCloneAudio.duration,
createdAt: new Date().toLocaleDateString(),
status: 'ready'
};
clonedVoices.push(newVoice);
renderClonedVoices();
}
}, 60);
}
// 渲染音色列表
function renderClonedVoices() {
var container = document.getElementById('voice-clone-list');
if (!container) return;
if (clonedVoices.length === 0) {
document.getElementById('voice-clone-empty').style.display = 'block';
container.innerHTML = '';
return;
}
document.getElementById('voice-clone-empty').style.display = 'none';
var html = '';
clonedVoices.forEach(function(voice) {
var statusClass = voice.status === 'ready' ? 'ok' : (voice.status === 'cloning' ? 'warn' : 'bad');
var statusText = voice.status === 'ready' ? '已就绪' : (voice.status === 'cloning' ? '克隆中' : '失败');
html += '<div class="voice-clone-card" data-voice-id="' + voice.id + '" style="background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:20px;position:relative">';
html += '<div style="position:absolute;top:16px;right:16px">';
html += '<button class="btn ghost sm" onclick="deleteVoiceCloneItem(' + voice.id + ')" style="padding:4px 8px;font-size:11px">🗑️</button>';
html += '<button class="btn ghost sm" onclick="renameVoiceCloneItem(' + voice.id + ')" style="padding:4px 8px;font-size:11px">✏️</button>';
html += '</div>';
html += '<div style="display:flex;align-items:center;gap:14px;margin-bottom:14px">';
html += '<div style="width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#f59e0b,#d97706);display:grid;place-items:center;color:#fff;font-size:24px">🎤</div>';
html += '<div>';
html += '<h4 style="margin:0 0 4px;font-size:15px;font-weight:600">' + voice.name + '</h4>';
html += '<span class="pill ' + statusClass + '">' + statusText + '</span>';
html += '</div></div>';
html += '<div style="font-size:13px;color:var(--muted);margin-bottom:12px">';
html += '<div style="margin-bottom:4px">🎵 时长:' + voice.duration + '</div>';
html += '<div>📅 创建于:' + voice.createdAt + '</div></div>';
html += '<div style="display:flex;align-items:center;gap:10px;padding:10px;background:#f8fafc;border-radius:10px">';
html += '<button class="btn ghost sm" onclick="playVoiceCloneItem(' + voice.id + ')" style="flex:1">▶ 试听</button>';
html += '<button class="btn primary sm" onclick="useVoiceCloneItem(' + voice.id + ')" style="flex:1">✨ 使用此音色</button>';
html += '</div></div>';
});
container.innerHTML = html;
}
// 在一键生成页面渲染已克隆音色列表
function renderClonedVoicesForStep4() {
var container = document.getElementById('cloned-voice-list-step4');
if (!container) return;
if (clonedVoices.length === 0) {
container.innerHTML = '<p style="font-size:12px;color:var(--muted);padding:8px 0">暂无已克隆音色,<a href="#" onclick="showView(\'voiceClone\');return false" style="color:var(--primary)">去克隆</a></p>';
return;
}
var html = '';
clonedVoices.forEach(function(voice) {
html += '<label style="display:flex;align-items:center;gap:10px;padding:10px;background:#f8fafc;border-radius:10px;cursor:pointer">';
html += '<input type="radio" name="cloned-voice-select" value="' + voice.id + '" onclick="selectClonedVoice(' + voice.id + ')" style="width:16px;height:16px;accent-color:var(--primary)"/>';
html += '<div style="flex:1">';
html += '<div style="font-weight:600;font-size:13px">' + voice.name + '</div>';
html += '<div style="font-size:11px;color:var(--muted)">' + voice.duration + '</div></div>';
html += '<span class="pill ok" style="font-size:10px">就绪</span></label>';
});
container.innerHTML = html;
}
// 选择已克隆音色
function selectClonedVoice(voiceId) {
selectedCloneVoiceId = voiceId;
document.getElementById('start-clone-btn').disabled = false;
}
// 在step-4中选择配音选项
function selectVoiceChoice(el, voiceType) {
document.querySelectorAll('#voice-choice-list .choice-item').forEach(function(item) {
item.classList.remove('selected');
});
el.classList.add('selected');
// 隐藏/显示克隆声音展开区域
var expandArea = document.getElementById('clone-voice-expand');
if (voiceType === 'clone') {
expandArea.style.display = 'block';
renderClonedVoicesForStep4();
} else {
expandArea.style.display = 'none';
}
}
// 处理克隆音频上传(step-4中)
function handleCloneAudioUpload(input) {
if (input.files && input.files[0]) {
var file = input.files[0];
document.getElementById('clone-audio-preview').style.display = 'block';
document.getElementById('clone-audio-name').textContent = file.name;
document.getElementById('clone-audio-duration').textContent = '00:00 / 00:' + (Math.floor(Math.random() * 30) + 10);
document.getElementById('start-clone-btn').disabled = false;
}
}
// 播放克隆音频(step-4中)
function playCloneAudio() {
var progress = 0;
var interval = setInterval(function() {
progress += 5;
if (progress >= 100) {
progress = 0;
clearInterval(interval);
}
document.getElementById('clone-audio-progress').style.width = progress + '%';
}, 200);
}
// 开始克隆(step-4中)
function startVoiceClone() {
var progressArea = document.getElementById('clone-progress-area');
var successArea = document.getElementById('clone-success-area');
var progressBar = document.getElementById('clone-progress-bar');
var progressText = document.getElementById('clone-progress-text');
progressArea.style.display = 'block';
successArea.style.display = 'none';
var progress = 0;
var steps = ['正在处理音频...', '正在提取音色...', '正在克隆...', '即将完成...'];
var interval = setInterval(function() {
progress += 3;
progressBar.style.width = progress + '%';
progressText.textContent = steps[Math.min(Math.floor(progress / 25), steps.length - 1)];
if (progress >= 100) {
clearInterval(interval);
progressArea.style.display = 'none';
successArea.style.display = 'block';
}
}, 80);
}
// 音色库页面操作
function deleteVoiceClone(btn) {
var card = btn.closest('.voice-clone-card');
if (card) {
var voiceId = card.dataset.voiceId;
if (confirm('确定要删除这个音色吗?')) {
clonedVoices = clonedVoices.filter(function(v) { return v.id != voiceId; });
renderClonedVoices();
}
}
}
function renameVoiceClone(btn) {
var card = btn.closest('.voice-clone-card');
if (card) {
var voiceId = parseInt(card.dataset.voiceId);
var voice = clonedVoices.find(function(v) { return v.id == voiceId; });
if (voice) {
var newName = prompt('请输入新的音色名称:', voice.name);
if (newName && newName.trim()) {
voice.name = newName.trim();
renderClonedVoices();
}
}
}
}
function playVoiceClone(btn) {
alert('播放音色预览(模拟)');
}
function useVoiceClone(btn) {
var card = btn.closest('.voice-clone-card');
if (card) {
selectedCloneVoiceId = parseInt(card.dataset.voiceId);
alert('已选择音色,正在跳转到一键生成页面...');
showView('generate');
// 自动切换到step-4
currentStep = 4;
updateStepUI();
}
}
// 音色库卡片操作
function deleteVoiceCloneItem(id) {
if (confirm('确定要删除这个音色吗?')) {
clonedVoices = clonedVoices.filter(function(v) { return v.id != id; });
renderClonedVoices();
}
}
function renameVoiceCloneItem(id) {
var voice = clonedVoices.find(function(v) { return v.id == id; });
if (voice) {
var newName = prompt('请输入新的音色名称:', voice.name);
if (newName && newName.trim()) {
voice.name = newName.trim();
renderClonedVoices();
}
}
}
function playVoiceCloneItem(id) {
alert('播放音色预览(模拟)');
}
function useVoiceCloneItem(id) {
selectedCloneVoiceId = id;
alert('已选择音色,正在跳转到一键生成页面...');
showView('generate');
currentStep = 4;
updateStepUI();
}
// 打开录制弹窗(从step-4中)
function openRecordModal() {
openCloneVoiceModal();
}
// 初始化音色列表
document.addEventListener('DOMContentLoaded', function() {
renderClonedVoices();
renderClonedVoicesForStep4();
});
</script>
</body>
</html>