@@ -46,6 +53,13 @@
+
+
+
+
@@ -70,6 +84,7 @@
名称(英) |
Prompt |
视频地址 |
+
直播间 |
溯源(人物×衣服×参考视频) |
时长 |
点赞 |
@@ -103,6 +118,13 @@ let danceRefs = [];
let editingId = null;
let sortKey = "createdAt";
let sortDir = -1;
+// 视频直播间(live.html) / 跳舞直播间(dance.html) 是两条独立的产品线,
+// 素材各自的排播池互不共享(architecture.md 2.1),所以后台也分开管理。
+let activeChannel = "video";
+
+function inChannel(c) {
+ return activeChannel === "dance" ? c.channel === "dance" : c.channel !== "dance";
+}
function escapeHtml(s) {
const div = document.createElement("div");
@@ -142,7 +164,7 @@ function traceability(c) {
function filteredSorted() {
const q = document.getElementById("searchInput").value.trim().toLowerCase();
const source = document.getElementById("sourceFilter").value;
- let rows = library.slice();
+ let rows = library.filter(inChannel);
if (q) rows = rows.filter((c) => c.prompt.toLowerCase().includes(q) || (c.promptEn || "").toLowerCase().includes(q) || (c.fullPrompt || "").toLowerCase().includes(q) || c.id.toLowerCase().includes(q));
if (source) rows = rows.filter((c) => c.source === source);
rows.sort((a, b) => {
@@ -160,7 +182,10 @@ function videoHref(c) {
function render() {
const rows = filteredSorted();
- document.getElementById("countHint").textContent = `共 ${library.length} 条,当前筛选 ${rows.length} 条`;
+ const channelTotal = library.filter(inChannel).length;
+ document.getElementById("countHint").textContent = `本直播间共 ${channelTotal} 条,当前筛选 ${rows.length} 条`;
+ document.getElementById("tabVideo").classList.toggle("active", activeChannel === "video");
+ document.getElementById("tabDance").classList.toggle("active", activeChannel === "dance");
document.querySelectorAll("th[data-sort]").forEach((th) => {
th.innerHTML = th.textContent.replace(/ ?[▲▼]$/, "") + (th.dataset.sort === sortKey ? `
${sortDir === 1 ? "▲" : "▼"}` : "");
});
@@ -175,6 +200,12 @@ function render() {
|
|
|
+
+
+ |
${escapeHtml(traceability(c))} |
${c.duration ?? "-"}s |
${c.likes || 0} |
@@ -193,6 +224,7 @@ function render() {
${escapeHtml(c.promptEn || "")} |
${escapeHtml((c.fullPrompt || "").slice(0, 80))}${(c.fullPrompt || "").length > 80 ? "…" : ""} |
${videoHref(c)} |
+
${c.channel === "dance" ? "跳舞直播间" : "视频直播间"} |
${escapeHtml(traceability(c))} |
${c.duration ?? "-"}s |
${c.likes || 0} |
@@ -248,6 +280,17 @@ document.querySelectorAll("th[data-sort]").forEach((th) => {
document.getElementById("searchInput").addEventListener("input", render);
document.getElementById("sourceFilter").addEventListener("change", render);
+document.getElementById("tabVideo").addEventListener("click", () => {
+ activeChannel = "video";
+ document.getElementById("newChannel").value = "video";
+ render();
+});
+document.getElementById("tabDance").addEventListener("click", () => {
+ activeChannel = "dance";
+ document.getElementById("newChannel").value = "dance";
+ render();
+});
+
document.getElementById("addBtn").addEventListener("click", async () => {
const errorBox = document.getElementById("addError");
errorBox.hidden = true;
@@ -256,6 +299,7 @@ document.getElementById("addBtn").addEventListener("click", async () => {
const videoUrl = document.getElementById("newVideoUrl").value.trim();
const fullPrompt = document.getElementById("newFullPrompt").value.trim();
const duration = Number(document.getElementById("newDuration").value) || null;
+ const channel = document.getElementById("newChannel").value;
if (!prompt || !videoUrl) {
errorBox.hidden = false;
errorBox.textContent = "名称和视频地址必填";
@@ -264,7 +308,7 @@ document.getElementById("addBtn").addEventListener("click", async () => {
const res = await fetch("/api/admin/library", {
method: "POST",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ prompt, promptEn, videoUrl, fullPrompt, duration }),
+ body: JSON.stringify({ prompt, promptEn, videoUrl, fullPrompt, duration, channel }),
});
if (res.ok) {
document.getElementById("newPrompt").value = "";