my-works.html
4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>我的作品</title>
<link rel="stylesheet" href="live.css" />
<style>
body { background: var(--bg, #fdf6e3); }
.works-wrap { max-width: 900px; margin: 0 auto; padding: 18px 16px 60px; }
.works-section-title { font: bold 16px Tahoma, sans-serif; margin: 22px 0 10px; }
.works-card {
background: #fff;
border: 3px solid #000;
border-radius: 14px;
padding: 12px;
margin-bottom: 14px;
box-shadow: var(--shadow, 3px 3px 0 #000);
}
.works-card-head { display: flex; gap: 12px; align-items: flex-start; }
.works-card-head img { width: 64px; height: 92px; object-fit: cover; border-radius: 8px; border: 1px solid var(--border, #ddd); flex: none; }
.works-card-title { font: bold 14px Tahoma, sans-serif; }
.works-badge { display: inline-block; font-size: 11px; font-weight: bold; padding: 2px 8px; border-radius: 10px; margin-left: 6px; }
.works-badge.active { background: #d4f7d4; color: #1e7d1e; }
.works-badge.expired { background: #eee; color: #777; }
.works-meta { font-size: 12px; color: var(--muted, #888); margin-top: 4px; }
.works-videos { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.works-videos video { width: 140px; max-height: 190px; background: #000; border-radius: 6px; display: block; }
.works-empty { color: var(--muted, #888); text-align: center; margin-top: 60px; font-size: 13px; }
.works-login-gate { text-align: center; margin-top: 80px; }
.works-login-gate a { font-weight: bold; }
</style>
</head>
<body>
<header class="topbar">
<h1 class="logo">我的作品</h1>
<div class="spacer"></div>
<a class="topbar-pill" href="dance.html">← 返回换装跳舞直播间</a>
</header>
<main class="works-wrap" id="main">
<div class="works-empty">加载中…</div>
</main>
<script>
function escapeHtml(s) {
const div = document.createElement("div");
div.textContent = s || "";
return div.innerHTML;
}
function videoHref(c) {
return `/lib/video/${c.id}`;
}
function renderVideos(videos) {
if (!videos.length) return `<div class="works-meta">还没有生成过视频</div>`;
return `<div class="works-videos">${videos
.map((c) => `<video controls preload="none" src="${videoHref(c)}"></video>`)
.join("")}</div>`;
}
function renderCharacterCard(c) {
const badge = c.status === "expired" ? `<span class="works-badge expired">已下线</span>` : `<span class="works-badge active">播放中</span>`;
const segLine = c.totalSegments != null ? `已播 ${c.totalSegments - (c.remainingSegments ?? 0)} / 购买 ${c.totalSegments} 个 10 秒片段` : "";
return `
<div class="works-card">
<div class="works-card-head">
<img src="${escapeHtml(c.imageUrl)}" />
<div>
<div class="works-card-title">${escapeHtml(c.name)}${badge}</div>
<div class="works-meta">${segLine}</div>
<div class="works-meta">上传于 ${new Date(c.createdAt).toLocaleString()}</div>
</div>
</div>
${renderVideos(c.videos)}
</div>`;
}
function renderGarmentCard(g) {
const badge = g.isActive ? `<span class="works-badge active">衣柜中</span>` : `<span class="works-badge expired">已下架</span>`;
return `
<div class="works-card">
<div class="works-card-head">
<img src="${escapeHtml(g.thumbnailUrl || g.imageUrl)}" />
<div>
<div class="works-card-title">${escapeHtml(g.name)}${badge}</div>
<div class="works-meta">上传于 ${new Date(g.createdAt).toLocaleString()}</div>
</div>
</div>
${renderVideos(g.videos)}
</div>`;
}
async function load() {
const main = document.getElementById("main");
const res = await fetch("/api/dance/my-works");
if (res.status === 401) {
main.innerHTML = `<div class="works-login-gate">请先在<br /><a href="dance.html">换装跳舞直播间</a><br />登录后查看你的作品</div>`;
return;
}
if (!res.ok) {
main.innerHTML = `<div class="works-empty">加载失败,请刷新重试</div>`;
return;
}
const { characters, garments } = await res.json();
if (!characters.length && !garments.length) {
main.innerHTML = `<div class="works-empty">还没有传过衣服或人物——去<a href="dance.html">换装跳舞直播间</a>试试吧</div>`;
return;
}
main.innerHTML =
(characters.length ? `<div class="works-section-title">我的人物</div>${characters.map(renderCharacterCard).join("")}` : "") +
(garments.length ? `<div class="works-section-title">我的衣服</div>${garments.map(renderGarmentCard).join("")}` : "");
}
load();
</script>
</body>
</html>