All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 6s
页面 (电商AI平台/) - account / team / settings / index / products / projects: 累积迭代 - restraint.css: 设计 token 补充 - login.html / register.html: 新增登录注册页 - _ARCHIVE.md: 归档说明 Next.js 工程骨架 - app/ + components/: 新一代 SPA 雏形 (page / layout / sidebar / topbar / GridBg / Icon) - package.json / package-lock.json / next.config.mjs / tsconfig.json / postcss.config.mjs / next-env.d.ts 历史归档 / 文档 - v1/: 原 V1 静态稿镜像 (含 mockup-A/B/C) - PRD.md / deployment-guide.md / _check.html - ui参考/ / screenshots/ 杂项 - .gitignore 调整 - 删除根 README.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
522 lines
25 KiB
HTML
522 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; }
|
|
.proj-name { font-weight: 600; color: var(--ink); font-size: 13.5px; }
|
|
.proj-sub { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; font-family: 'JetBrains Mono', monospace; 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(--ink-2); }
|
|
.row-action a:hover { background: var(--card); color: var(--orange); border: 1px solid var(--border); }
|
|
|
|
/* ─── View toggle ─── */
|
|
.view-toggle { display: inline-flex; border: 1px solid var(--border); }
|
|
.view-toggle button { padding: 6px 12px; background: var(--card); color: var(--ink-2); font-size: 12px; border-right: 1px solid var(--border); border-radius: 0; height: 32px; cursor: pointer; font-family: inherit; display: flex; align-items: center; gap: 5px; }
|
|
.view-toggle button:last-child { border-right: 0; }
|
|
.view-toggle button:hover { background: var(--bg-soft); color: var(--ink); }
|
|
.view-toggle button.active { background: var(--orange-tint); color: var(--orange); 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(--card); border: 1px solid var(--border); cursor: pointer; transition: background .15s; display: flex; flex-direction: column; }
|
|
.proj-card:hover { background: var(--bg-soft); border-color: var(--ink-3); }
|
|
.proj-card .card-thumb { aspect-ratio: 9/16; max-height: 280px; }
|
|
.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(--ink); line-height: 1.4; }
|
|
.proj-card .card-sub { font-size: 11.5px; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; 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); margin-top: auto; }
|
|
.proj-card .card-time { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .02em; }
|
|
|
|
/* ─── Empty state ─── */
|
|
.empty-state {
|
|
background: var(--card);
|
|
border: 1px dashed var(--border);
|
|
padding: 80px 40px;
|
|
text-align: center;
|
|
color: var(--ink-2);
|
|
display: none;
|
|
}
|
|
.empty-state.show { display: block; }
|
|
.empty-state .ic-empty {
|
|
width: 48px; height: 48px;
|
|
margin: 0 auto 14px;
|
|
background: var(--bg-soft);
|
|
border: 1px solid var(--border);
|
|
display: grid; place-items: center;
|
|
color: var(--ink-3);
|
|
}
|
|
.empty-state h3 { font-size: 14px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
|
|
.empty-state p { font-size: 12.5px; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
|
|
|
/* ─── Result count ─── */
|
|
.result-meta {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 11px;
|
|
color: var(--ink-3);
|
|
margin-bottom: 14px;
|
|
letter-spacing: .04em;
|
|
}
|
|
.result-meta .count { color: var(--orange); 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="2.4"><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="2"><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.6"><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.6"><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.6"><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.6"><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.6"><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.6"><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>
|