- 10 个页面 (工作台/项目/商品/流水线/资产/账户/创建向导) - V2.1 Restraint 设计规范 (冷灰底 + #FA5D19 + 8px 圆角) - 完整 design-system.html 组件库参考 - SVG line icon · stroke 1.5 全合规 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
524 lines
25 KiB
HTML
524 lines
25 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>视频项目 · 流·Studio</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/restraint.css">
|
|
<style>
|
|
/* ─── List view ─── */
|
|
.proj-name-cell { display: flex; align-items: center; gap: 12px; }
|
|
.proj-thumb { width: 40px; height: 52px; flex-shrink: 0; border-radius: var(--r-md); }
|
|
.proj-name { font-weight: 600; color: var(--accent-black); font-size: 13.5px; }
|
|
.proj-sub { font-size: 11.5px; color: var(--black-alpha-48); margin-top: 3px; font-family: var(--font-mono); letter-spacing: .02em; }
|
|
.row-action { display: flex; gap: 4px; visibility: hidden; }
|
|
table.t tbody tr:hover .row-action { visibility: visible; }
|
|
.row-action a { width: 28px; height: 28px; display: grid; place-items: center; color: var(--black-alpha-56); border-radius: var(--r-md); }
|
|
.row-action a:hover { background: var(--surface); color: var(--heat); border: 1px solid var(--border-faint); }
|
|
|
|
/* ─── View toggle ─── */
|
|
.view-toggle { display: inline-flex; border: 1px solid var(--border-faint); border-radius: var(--r-md); overflow: hidden; }
|
|
.view-toggle button { padding: 0 14px; background: var(--surface); color: var(--black-alpha-56); font-size: 13px; border-right: 1px solid var(--border-faint); border-radius: 0; height: 36px; cursor: pointer; font-family: inherit; display: flex; align-items: center; gap: 6px; transition: background var(--t-base), color var(--t-base); }
|
|
.view-toggle button:last-child { border-right: 0; }
|
|
.view-toggle button:hover { background: var(--background-lighter); color: var(--accent-black); }
|
|
.view-toggle button.active { background: var(--heat-12); color: var(--heat); font-weight: 600; }
|
|
.view-toggle button svg { width: 13px; height: 13px; }
|
|
|
|
/* ─── Grid view ─── */
|
|
.proj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
|
|
.proj-card { background: var(--surface); border: 1px solid var(--border-faint); border-radius: var(--r-md); cursor: pointer; transition: background .15s; display: flex; flex-direction: column; }
|
|
.proj-card:hover { background: var(--background-lighter); border-color: var(--black-alpha-48); }
|
|
.proj-card .card-thumb { aspect-ratio: 9/16; max-height: 280px; border-radius: var(--r-md) var(--r-md) 0 0; }
|
|
.proj-card .card-body { padding: 14px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
|
|
.proj-card .card-name { font-size: 13.5px; font-weight: 600; color: var(--accent-black); line-height: 1.4; }
|
|
.proj-card .card-sub { font-size: 11.5px; color: var(--black-alpha-48); font-family: var(--font-mono); letter-spacing: .02em; }
|
|
.proj-card .card-foot { display: flex; align-items: center; justify-content: space-between; padding-top: 10px; border-top: 1px solid var(--border-faint); margin-top: auto; }
|
|
.proj-card .card-time { font-family: var(--font-mono); font-size: 10.5px; color: var(--black-alpha-48); letter-spacing: .02em; }
|
|
|
|
/* ─── Empty state ─── */
|
|
.empty-state {
|
|
background: var(--surface);
|
|
border: 1px dashed var(--border-faint);
|
|
border-radius: var(--r-md);
|
|
padding: 80px 40px;
|
|
text-align: center;
|
|
color: var(--black-alpha-56);
|
|
display: none;
|
|
}
|
|
.empty-state.show { display: block; }
|
|
.empty-state .ic-empty {
|
|
width: 48px; height: 48px;
|
|
margin: 0 auto 14px;
|
|
background: var(--background-lighter);
|
|
border: 1px solid var(--border-faint);
|
|
border-radius: var(--r-md);
|
|
display: grid; place-items: center;
|
|
color: var(--black-alpha-48);
|
|
}
|
|
.empty-state h3 { font-size: 14px; font-weight: 600; color: var(--accent-black); margin-bottom: 6px; }
|
|
.empty-state p { font-size: 12.5px; color: var(--black-alpha-48); font-family: var(--font-mono); letter-spacing: .02em; }
|
|
|
|
/* ─── Result count ─── */
|
|
.result-meta {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
color: var(--black-alpha-48);
|
|
margin-bottom: 14px;
|
|
letter-spacing: .04em;
|
|
}
|
|
.result-meta .count { color: var(--heat); font-weight: 600; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="page">
|
|
|
|
<div class="page-head">
|
|
<div>
|
|
<h1>视频项目</h1>
|
|
<div class="sub"><span class="mono">// 12 个 · 3 进行中 · 8 完成 · 1 失败</span></div>
|
|
</div>
|
|
<div class="actions">
|
|
<a class="btn btn-primary btn-lg" href="projects-new.html">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 5v14M5 12h14"/></svg>
|
|
新建项目
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tabs" id="status-tabs">
|
|
<div class="tab active" data-filter="all">全部 <span class="count">12</span></div>
|
|
<div class="tab" data-filter="wip">进行中 <span class="count">3</span></div>
|
|
<div class="tab" data-filter="done">已完成 <span class="count">8</span></div>
|
|
<div class="tab" data-filter="fail">失败 <span class="count">1</span></div>
|
|
</div>
|
|
|
|
<div class="toolbar">
|
|
<div class="search-inline">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
|
<input class="input" id="search-input" placeholder="搜索项目名称、商品">
|
|
</div>
|
|
<button class="chip" onclick="Shell.toast('商品筛选', '/filter/product')">商品 <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 6l4 4 4-4"/></svg></button>
|
|
<button class="chip" onclick="Shell.toast('脚本来源筛选', '/filter/source')">脚本来源 <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 6l4 4 4-4"/></svg></button>
|
|
<button class="chip" onclick="Shell.toast('时间筛选', '/filter/date')">创建时间 <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 6l4 4 4-4"/></svg></button>
|
|
<span class="spacer"></span>
|
|
<div class="view-toggle">
|
|
<button id="view-grid" data-view="grid">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="5" height="5"/><rect x="9" y="2" width="5" height="5"/><rect x="2" y="9" width="5" height="5"/><rect x="9" y="9" width="5" height="5"/></svg>
|
|
网格
|
|
</button>
|
|
<button id="view-list" class="active" data-view="list">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 4h12M2 8h12M2 12h12"/></svg>
|
|
列表
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="result-meta" id="result-meta">// 显示 <span class="count">12</span> / 12 个项目</div>
|
|
|
|
<!-- ============= LIST VIEW ============= -->
|
|
<div id="list-view">
|
|
<table class="t">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:32%">项目</th>
|
|
<th>商品</th>
|
|
<th>脚本来源</th>
|
|
<th style="width:200px">进度</th>
|
|
<th>状态</th>
|
|
<th style="width:120px">更新于</th>
|
|
<th style="width:60px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="list-tbody">
|
|
<tr data-status="wip" data-name="补水面膜 痛点种草" onclick="location.href='pipeline.html#stage-3'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">补水面膜 · 痛点种草 · v3</div><div class="proj-sub">6 镜 · 0-15s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>透真补水面膜</td>
|
|
<td><span class="muted">AI 全生</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="cur"></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">3/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill info"><span class="dot"></span>故事板 待确认</span></td>
|
|
<td class="muted-2">12 分钟前</td>
|
|
<td>
|
|
<div class="row-action">
|
|
<a href="pipeline.html#stage-3" onclick="event.stopPropagation()" title="继续"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M5 4l6 4-6 4z" fill="currentColor"/></svg></a>
|
|
<a onclick="event.stopPropagation();Shell.toast('更多操作')"><svg width="14" height="14" viewBox="0 0 16 16"><circle cx="3" cy="8" r="1.2" fill="currentColor"/><circle cx="8" cy="8" r="1.2" fill="currentColor"/><circle cx="13" cy="8" r="1.2" fill="currentColor"/></svg></a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr data-status="wip" data-name="速食牛肉面 加班治愈" onclick="location.href='pipeline.html#stage-2'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">速食牛肉面 · 加班治愈</div><div class="proj-sub">4 镜 · 0-12s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>滋啦速食 · 6 桶装</td>
|
|
<td><span class="muted">一句话主题</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="cur"></span><span></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">2/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill info"><span class="dot"></span>资产生成中</span></td>
|
|
<td class="muted-2">37 分钟前</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="wip" data-name="透真防晒 通勤对比" onclick="location.href='pipeline.html#stage-4'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">透真防晒 · 通勤对比</div><div class="proj-sub">6 镜 · 0-18s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>透真清透防晒霜</td>
|
|
<td><span class="muted">AI 全生</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="cur"></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">4/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill info"><span class="dot"></span>视频生成 4/6</span></td>
|
|
<td class="muted-2">2 小时前</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="fail" data-name="咖啡冻干 早八剧情" onclick="location.href='pipeline.html#stage-3'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">咖啡冻干 · 早八剧情</div><div class="proj-sub">5 镜 · 0-15s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>三顿半同款冻干</td>
|
|
<td><span class="muted">一句话主题</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="fail"></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">3/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill err"><span class="dot"></span>故事板生成失败</span></td>
|
|
<td class="muted-2">昨天 18:42</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="done" data-name="蓝牙耳机 开箱测评" onclick="location.href='pipeline.html#stage-5'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">蓝牙耳机 · 开箱测评</div><div class="proj-sub">5 镜 · 0-15s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>南卡 Lite Pro</td>
|
|
<td><span class="muted">自带脚本</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">5/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill ok"><span class="dot"></span>已完成</span></td>
|
|
<td class="muted-2">5 月 7 日</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="done" data-name="瑜伽裤 通勤穿搭" onclick="location.href='pipeline.html#stage-5'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">瑜伽裤 · 通勤穿搭</div><div class="proj-sub">5 镜 · 0-15s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>露露同款瑜伽裤</td>
|
|
<td><span class="muted">AI 全生</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">5/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill ok"><span class="dot"></span>已完成</span></td>
|
|
<td class="muted-2">5 月 6 日</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="done" data-name="空气炸锅 小户型" onclick="location.href='pipeline.html#stage-5'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">空气炸锅 · 小户型</div><div class="proj-sub">4 镜 · 0-12s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>小熊 4L 空气炸锅</td>
|
|
<td><span class="muted">一句话主题</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">5/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill ok"><span class="dot"></span>已完成</span></td>
|
|
<td class="muted-2">5 月 4 日</td>
|
|
<td></td>
|
|
</tr>
|
|
<tr data-status="archived" data-name="补水面膜 痛点种草 v1" onclick="location.href='pipeline.html#stage-5'">
|
|
<td>
|
|
<div class="proj-name-cell">
|
|
<div class="placeholder proj-thumb"><span class="ph-frame">9:16</span></div>
|
|
<div><div class="proj-name">补水面膜 · 痛点种草 · v1</div><div class="proj-sub">6 镜 · 0-15s</div></div>
|
|
</div>
|
|
</td>
|
|
<td>透真补水面膜</td>
|
|
<td><span class="muted">AI 全生</span></td>
|
|
<td>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:11px;">5/5</span>
|
|
</div>
|
|
</td>
|
|
<td><span class="pill neutral"><span class="dot"></span>已归档</span></td>
|
|
<td class="muted-2">4 月 28 日</td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- ============= GRID VIEW ============= -->
|
|
<div id="grid-view" style="display:none;">
|
|
<div class="proj-grid" id="grid-body">
|
|
<div class="proj-card" data-status="wip" data-name="补水面膜 痛点种草" onclick="location.href='pipeline.html#stage-3'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 镜 3/6</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">补水面膜 · 痛点种草 · v3</div>
|
|
<div class="card-sub" style="margin-top:4px;">透真补水面膜 · 6 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="cur"></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">3/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill info"><span class="dot"></span>故事板 待确认</span>
|
|
<span class="card-time">12 分钟前</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="wip" data-name="速食牛肉面 加班治愈" onclick="location.href='pipeline.html#stage-2'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 镜 2/4</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">速食牛肉面 · 加班治愈</div>
|
|
<div class="card-sub" style="margin-top:4px;">滋啦速食 · 4 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="cur"></span><span></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">2/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill info"><span class="dot"></span>资产生成中</span>
|
|
<span class="card-time">37 分钟前</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="wip" data-name="透真防晒 通勤对比" onclick="location.href='pipeline.html#stage-4'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 镜 4/6</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">透真防晒 · 通勤对比</div>
|
|
<div class="card-sub" style="margin-top:4px;">透真清透防晒霜 · 6 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="cur"></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">4/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill info"><span class="dot"></span>视频 4/6</span>
|
|
<span class="card-time">2 小时前</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="fail" data-name="咖啡冻干 早八剧情" onclick="location.href='pipeline.html#stage-3'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 镜 3/5</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">咖啡冻干 · 早八剧情</div>
|
|
<div class="card-sub" style="margin-top:4px;">三顿半同款 · 5 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="fail"></span><span></span><span></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">3/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill err"><span class="dot"></span>故事板失败</span>
|
|
<span class="card-time">昨天 18:42</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="done" data-name="蓝牙耳机 开箱测评" onclick="location.href='pipeline.html#stage-5'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 5/5 ✓</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">蓝牙耳机 · 开箱测评</div>
|
|
<div class="card-sub" style="margin-top:4px;">南卡 Lite Pro · 5 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">5/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill ok"><span class="dot"></span>已完成</span>
|
|
<span class="card-time">5 月 7 日</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="done" data-name="瑜伽裤 通勤穿搭" onclick="location.href='pipeline.html#stage-5'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 5/5 ✓</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">瑜伽裤 · 通勤穿搭</div>
|
|
<div class="card-sub" style="margin-top:4px;">露露同款 · 5 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">5/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill ok"><span class="dot"></span>已完成</span>
|
|
<span class="card-time">5 月 6 日</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="done" data-name="空气炸锅 小户型" onclick="location.href='pipeline.html#stage-5'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 5/5 ✓</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">空气炸锅 · 小户型</div>
|
|
<div class="card-sub" style="margin-top:4px;">小熊 4L · 4 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">5/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill ok"><span class="dot"></span>已完成</span>
|
|
<span class="card-time">5 月 4 日</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="proj-card" data-status="archived" data-name="补水面膜 痛点种草 v1" onclick="location.href='pipeline.html#stage-5'">
|
|
<div class="placeholder card-thumb"><span class="ph-frame">9:16 · 5/5 ✓</span></div>
|
|
<div class="card-body">
|
|
<div>
|
|
<div class="card-name">补水面膜 · 痛点种草 · v1</div>
|
|
<div class="card-sub" style="margin-top:4px;">透真补水面膜 · 6 镜</div>
|
|
</div>
|
|
<div class="hstack">
|
|
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
|
|
<span class="muted-2 mono" style="font-size:10.5px;">5/5</span>
|
|
</div>
|
|
<div class="card-foot">
|
|
<span class="pill neutral"><span class="dot"></span>已归档</span>
|
|
<span class="card-time">4 月 28 日</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Empty state -->
|
|
<div class="empty-state" id="empty">
|
|
<div class="ic-empty">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
|
</div>
|
|
<h3>没有匹配的项目</h3>
|
|
<p>// 试试切换 tab 或修改搜索词</p>
|
|
</div>
|
|
|
|
</div>
|
|
<script src="assets/shell.js"></script>
|
|
<script>
|
|
Shell.render({ active: 'projects', crumbs: [{ label: '工作台', href: 'index.html' }, { label: '视频项目' }] });
|
|
|
|
// ============== Tab + search filter + view toggle ==============
|
|
const state = { filter: 'all', view: 'list', search: '' };
|
|
const TOTAL = 8; // 实际渲染的样本数
|
|
|
|
function applyFilter() {
|
|
const isList = state.view === 'list';
|
|
document.getElementById('list-view').style.display = isList ? '' : 'none';
|
|
document.getElementById('grid-view').style.display = isList ? 'none' : '';
|
|
|
|
const items = document.querySelectorAll(isList ? '#list-tbody tr' : '.proj-card');
|
|
let visible = 0;
|
|
items.forEach(el => {
|
|
const status = el.dataset.status || '';
|
|
const name = (el.dataset.name || '').toLowerCase();
|
|
const matchFilter = state.filter === 'all' || status.split(' ').includes(state.filter);
|
|
const matchSearch = !state.search || name.includes(state.search.toLowerCase());
|
|
const show = matchFilter && matchSearch;
|
|
el.style.display = show ? '' : 'none';
|
|
if (show) visible++;
|
|
});
|
|
|
|
// empty state
|
|
const empty = document.getElementById('empty');
|
|
if (visible === 0) {
|
|
empty.classList.add('show');
|
|
document.getElementById('list-view').style.display = 'none';
|
|
document.getElementById('grid-view').style.display = 'none';
|
|
} else {
|
|
empty.classList.remove('show');
|
|
}
|
|
|
|
// result meta
|
|
document.getElementById('result-meta').innerHTML = `// 显示 <span class="count">${visible}</span> / ${TOTAL} 个项目`;
|
|
}
|
|
|
|
// Tab clicks
|
|
document.querySelectorAll('#status-tabs .tab').forEach(t => {
|
|
t.addEventListener('click', () => {
|
|
document.querySelectorAll('#status-tabs .tab').forEach(x => x.classList.remove('active'));
|
|
t.classList.add('active');
|
|
state.filter = t.dataset.filter;
|
|
applyFilter();
|
|
Shell.toast('筛选: ' + t.textContent.trim().split(' ')[0], 'filter=' + state.filter);
|
|
});
|
|
});
|
|
|
|
// View toggle
|
|
document.querySelectorAll('.view-toggle button').forEach(b => {
|
|
b.addEventListener('click', () => {
|
|
document.querySelectorAll('.view-toggle button').forEach(x => x.classList.remove('active'));
|
|
b.classList.add('active');
|
|
state.view = b.dataset.view;
|
|
applyFilter();
|
|
Shell.toast('视图切换: ' + (state.view === 'list' ? '列表' : '网格'), 'view=' + state.view);
|
|
});
|
|
});
|
|
|
|
// Search
|
|
document.getElementById('search-input').addEventListener('input', e => {
|
|
state.search = e.target.value.trim();
|
|
applyFilter();
|
|
});
|
|
|
|
applyFilter();
|
|
</script>
|
|
</body>
|
|
</html>
|