feat(web): refresh palette, simplify ranking toolbar and drop export
This commit is contained in:
1 parent
6a053bdfe8
commit
c2ef998720
16 files changed
+141
-206
No files matched your search
@@ -49,10 +49,10 @@ export async function renderCandidates(root) {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="notice-row">
|
||||
<strong>Web 看板只读</strong>
|
||||
<span>${data.telegram_enabled ? "请在 Telegram 消息中处理候选。" : "Telegram 未启用,请使用 CLI 或数据库处理候选。"}</span>
|
||||
</div>
|
||||
${data.items.length ? `<div class="notice-row">
|
||||
<strong>候选处理</strong>
|
||||
<span>${data.telegram_enabled ? "请在 Telegram 消息中收藏、忽略或拉黑。" : "Telegram 未启用,请使用 CLI 或数据库处理候选。"}</span>
|
||||
</div>` : ""}
|
||||
|
||||
<section class="panel">
|
||||
${sectionHeader("待确认")}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { api } from "../api.js";
|
||||
import { centerActiveChips, emptyState, sectionHeader } from "../components.js";
|
||||
import { lineChart } from "../charts.js";
|
||||
import { lineChart, themeColor } from "../charts.js";
|
||||
import {
|
||||
escapeAttr, escapeHtml, formatCount, formatDate, formatDelta,
|
||||
} from "../format.js";
|
||||
@@ -82,7 +82,7 @@ export async function renderFans(root, { query }) {
|
||||
dates: fans.dates || [],
|
||||
values: fans.series || [],
|
||||
name: "粉丝",
|
||||
color: "#9b7bff",
|
||||
color: themeColor("accent"),
|
||||
scale: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { api, apiUrl } from "../api.js";
|
||||
import { api } from "../api.js";
|
||||
import {
|
||||
centerActiveChips, chip, emptyState, pager, sectionHeader, upCard, videoCard,
|
||||
} from "../components.js";
|
||||
@@ -8,7 +8,7 @@ import { replaceQuery } from "../router.js";
|
||||
const VIDEO_SORTS = [
|
||||
["heat", "综合热度"], ["view", "播放"], ["like", "点赞"], ["coin", "投币"],
|
||||
["favorite", "收藏"], ["share", "转发"], ["reply", "评论"], ["danmaku", "弹幕"],
|
||||
["interaction", "互动率"], ["growth", "增长"], ["growth_rate", "增速"],
|
||||
["interaction", "互动率"], ["growth", "播放增量"], ["growth_rate", "播放增速"],
|
||||
];
|
||||
const UP_SORTS = [
|
||||
["avg_views", "平均播放"], ["avg_interaction", "平均互动"],
|
||||
@@ -20,18 +20,20 @@ const METRIC_PRIMARY = new Set(["view", "like", "coin", "favorite", "share", "re
|
||||
function controls({ scope, sort, within, growthDays, q, folder, minVideos, folders }) {
|
||||
const sorts = scope === "up" ? UP_SORTS : VIDEO_SORTS;
|
||||
return `
|
||||
<div class="segmented" role="tablist">
|
||||
<button type="button" class="${scope === "video" ? "active" : ""}" data-scope="video">视频</button>
|
||||
<button type="button" class="${scope === "up" ? "active" : ""}" data-scope="up">UP</button>
|
||||
<div class="rank-toolbar">
|
||||
<div class="segmented" role="tablist">
|
||||
<button type="button" class="${scope === "video" ? "active" : ""}" data-scope="video">视频</button>
|
||||
<button type="button" class="${scope === "up" ? "active" : ""}" data-scope="up">UP</button>
|
||||
</div>
|
||||
<form class="rank-search" id="rank-filter">
|
||||
<input class="search-input" type="search" name="q" value="${escapeAttr(q || "")}"
|
||||
placeholder="${scope === "up" ? "搜索 UP 名" : "搜索标题或 UP"}" autocomplete="off">
|
||||
<button class="button" type="submit">搜索</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="chip-row scroll-x">
|
||||
${sorts.map(([value, label]) => chip(label, sort === value, "sort", value)).join("")}
|
||||
</div>
|
||||
<form class="filter-bar" id="rank-filter">
|
||||
<input class="search-input" type="search" name="q" value="${escapeAttr(q || "")}"
|
||||
placeholder="${scope === "up" ? "搜索 UP 名" : "搜索标题或 UP"}" autocomplete="off">
|
||||
<button class="button" type="submit">搜索</button>
|
||||
</form>
|
||||
<div class="filter-row">
|
||||
<div class="chip-row scroll-x">
|
||||
${[["all", "全部发布时间"], ["7", "近 7 天"], ["30", "近 30 天"], ["90", "近 90 天"]]
|
||||
@@ -106,12 +108,6 @@ export async function renderRankings(root, { query }) {
|
||||
}
|
||||
|
||||
const startRank = (data.page - 1) * data.page_size + 1;
|
||||
const exportParams = {
|
||||
...params, folder: folder || null, scope,
|
||||
min_videos: scope === "up" ? minVideos : null,
|
||||
};
|
||||
delete exportParams.page;
|
||||
delete exportParams.page_size;
|
||||
|
||||
root.innerHTML = `<section class="page rankings-page">
|
||||
<header class="page-head">
|
||||
@@ -119,9 +115,6 @@ export async function renderRankings(root, { query }) {
|
||||
<h1>榜单</h1>
|
||||
<p class="page-sub">共 ${formatCount(data.total)} ${scope === "up" ? "个 UP" : "条视频"}</p>
|
||||
</div>
|
||||
${scope === "video"
|
||||
? `<a class="button ghost" href="${escapeAttr(apiUrl("/api/export.csv", exportParams))}">导出 CSV</a>`
|
||||
: ""}
|
||||
</header>
|
||||
${controls({ scope, sort, within, growthDays, q, folder, minVideos, folders })}
|
||||
${data.available === false ? `<div class="notice-row warning">
|
||||
|
||||
@@ -104,7 +104,7 @@ export async function renderSystem(root) {
|
||||
|
||||
<section class="panel">
|
||||
${sectionHeader("UP 黑名单")}
|
||||
<p class="section-note">只影响未来搜索发现;已入库视频继续追踪。Web 只读,移除请使用 CLI 或数据库。</p>
|
||||
<p class="section-note">只影响未来搜索发现;已入库视频继续追踪。移除请使用 CLI 或数据库。</p>
|
||||
${(system.blacklist || []).length ? `<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<thead><tr><th>mid</th><th>昵称</th><th>原因</th><th>在库视频</th></tr></thead>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { api } from "../api.js";
|
||||
import {
|
||||
badge, emptyState, sectionHeader, videoCard,
|
||||
} from "../components.js";
|
||||
import { barChart, lineChart } from "../charts.js";
|
||||
import { barChart, lineChart, themeColor } from "../charts.js";
|
||||
import {
|
||||
escapeAttr, escapeHtml, formatCount, formatDate, formatPercent,
|
||||
} from "../format.js";
|
||||
@@ -89,7 +89,7 @@ export async function renderUp(root, { params, query }) {
|
||||
dates: up.series.dates,
|
||||
values: up.series.views,
|
||||
name: "总播放",
|
||||
color: "#fb7299",
|
||||
color: themeColor("accent"),
|
||||
scale: true,
|
||||
});
|
||||
}
|
||||
@@ -99,7 +99,7 @@ export async function renderUp(root, { params, query }) {
|
||||
labels: topForBar.map((item) => (item.title || `#${item.aid}`).slice(0, 12)),
|
||||
values: topForBar.map((item) => item.metrics?.view || 0),
|
||||
name: "播放",
|
||||
color: "#00aeec",
|
||||
color: themeColor("blue"),
|
||||
});
|
||||
}
|
||||
root.querySelector("#up-sort")?.addEventListener("change", (event) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
badge, centerActiveChips, cover, emptyState, metricChips, metricGrid,
|
||||
sectionHeader, videoCard,
|
||||
} from "../components.js";
|
||||
import { lineChart, emptyChart } from "../charts.js";
|
||||
import { lineChart, themeColor } from "../charts.js";
|
||||
import {
|
||||
escapeAttr, escapeHtml, formatCount, formatDate, formatDelta,
|
||||
formatDuration, formatPercent, formatScore, metricLabel, statusLabel,
|
||||
@@ -119,7 +119,7 @@ export async function renderVideo(root, { params, query }) {
|
||||
dates: trend.dates || [],
|
||||
values: trend.series?.[metric] || [],
|
||||
name: metricLabel(metric),
|
||||
color: metric === "view" ? "#fb7299" : "#00aeec",
|
||||
color: metric === "view" ? themeColor("accent") : themeColor("blue"),
|
||||
scale: true,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user