style: optimize mobile discovery and production flows

This commit is contained in:
kris
2026-03-22 12:46:03 +08:00
parent 7500d02730
commit ed5bcaef84
2 changed files with 163 additions and 6 deletions

View File

@@ -1121,8 +1121,33 @@ function renderDiscoveryScreen() {
</div>
</div>
</div>
<div class="mobile-only mobile-account-list">
${accounts.map((account) => {
const active = account.id === appState.selectedAccountId;
return `
<button class="account-select-card ${active ? "is-active" : ""}" type="button" data-action="select-account" data-account-id="${escapeHtml(account.id)}">
<div class="entity-cell">
<div class="avatar-lg">${escapeHtml(initials(account.nickname || account.douyin_id))}</div>
<div>
<div class="cell-title">${escapeHtml(account.nickname || "未命名账号")}</div>
<div class="cell-desc">${escapeHtml(account.douyin_id || "未填抖音号")}</div>
</div>
</div>
<div class="kpi-inline">
<span>作品 ${escapeHtml(formatNumber(account.video_summary?.count))}</span>
<span>均播 ${escapeHtml(formatNumber(account.video_summary?.avg_play))}</span>
<span>均赞 ${escapeHtml(formatNumber(account.video_summary?.avg_like))}</span>
</div>
<div class="task-meta">
<span class="tag ${active ? "green" : "blue"}">${active ? "当前选中" : "点击查看"}</span>
<span class="tag">${escapeHtml(account.sync_status || "ready")}</span>
</div>
</button>
`;
}).join("") || `<div class="empty-state">当前没有抖音账号数据。</div>`}
</div>
<div class="table-wrap">
<table>
<table class="account-table">
<thead>
<tr>
<th>账号</th>
@@ -1167,6 +1192,12 @@ function renderDiscoveryScreen() {
<p>${escapeHtml(selected?.profile_url || selected?.signature || "左侧点一个账号,这里会展示详情。")}</p>
</div>
</div>
<div class="mobile-only compact-summary-row" style="margin-top:14px;">
<span class="tag blue">作品 ${escapeHtml(formatNumber(selected?.video_summary?.count))}</span>
<span class="tag green">高分 ${escapeHtml(formatNumber(topVideos.length))}</span>
<span class="tag">报告 ${escapeHtml(formatNumber(reports.length))}</span>
<span class="tag">对标 ${escapeHtml(formatNumber(linkedAccounts.length))}</span>
</div>
<div class="mini-grid">
<div class="mini-card"><small>作品数</small><strong>${escapeHtml(formatNumber(selected?.video_summary?.count))}</strong></div>
<div class="mini-card"><small>高分作品</small><strong>${escapeHtml(formatNumber(topVideos.length))}</strong></div>
@@ -1298,9 +1329,14 @@ function renderTrackingScreen() {
<div class="side-stack">
<div class="panel pad">
<div class="panel-head"><div><h3>跟踪列表</h3><div class="panel-subtitle"> Agent</div></div><span class="tag">${escapeHtml(formatNumber(trackedAccounts.length))} </span></div>
<div class="mobile-only compact-summary-row">
<span class="tag blue">跟踪 ${escapeHtml(formatNumber(trackedAccounts.length))}</span>
<span class="tag green">日报 ${escapeHtml(formatNumber(digestItems.length))}</span>
<span class="tag">${escapeHtml(daysSince(appState.lastSeenAt))} 天窗口</span>
</div>
<div class="list">
${trackedAccounts.map((item) => `
<div class="task-item">
<div class="task-item compact">
<h4>${escapeHtml(item.account?.nickname || "未命名账号")}</h4>
<p>最近作品 ${escapeHtml(formatNumber(item.account?.video_summary?.count))} 条 · 平均播放 ${escapeHtml(formatNumber(item.account?.video_summary?.avg_play))}</p>
<div class="task-meta">
@@ -1318,7 +1354,7 @@ function renderTrackingScreen() {
<div class="panel-head"><div><h3>更新日报</h3><div class="panel-subtitle"></div></div><span class="tag blue">${escapeHtml(formatNumber(digestItems.length))} </span></div>
<div class="list">
${digestItems.map((item) => `
<div class="review-card">
<div class="review-card compact">
<h4>${escapeHtml(item.account?.nickname || "账号")} · ${escapeHtml(item.video?.title || item.video?.description || "最新作品")}</h4>
<p>${escapeHtml(item.summary || `发布时间 ${formatDateTime(item.video?.published_at)},建议继续判断借鉴点。`)}</p>
<div class="task-meta">
@@ -1491,6 +1527,11 @@ function renderProductionScreen() {
<div class="queue-card"><h4>AI 视频</h4><p> ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))} </p></div>
<div class="queue-card"><h4>内容源同步</h4><p> ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "content_source_sync").length))} </p></div>
</div>
<div class="mobile-only compact-summary-row" style="margin-top:14px;">
<span class="tag blue">分析 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "analysis").length))}</span>
<span class="tag">实拍 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "real_cut").length))}</span>
<span class="tag green">AI 视频 ${escapeHtml(formatNumber(jobs.filter((item) => item.line_type === "ai_video").length))}</span>
</div>
</div>
<div class="layout-grid grid-main" style="margin-top:18px;">
<div class="side-stack">
@@ -1498,7 +1539,7 @@ function renderProductionScreen() {
<div class="panel-head"><div><h3>当前任务</h3><div class="panel-subtitle"> recent_jobs</div></div></div>
<div class="list">
${(activeJobs.length ? activeJobs : jobs.slice(0, 4)).map((job) => `
<div class="task-item">
<div class="task-item compact">
<h4>${escapeHtml(job.title)}</h4>
<p>${escapeHtml(brief(job.style_summary || job.transcript_text || job.error || "暂无摘要", 80))}</p>
<div class="task-meta">
@@ -1518,7 +1559,7 @@ function renderProductionScreen() {
<div class="panel-head"><div><h3>作品与成片</h3><div class="panel-subtitle"></div></div></div>
<div class="list">
${works.map((video) => `
<div class="review-card">
<div class="review-card compact">
<h4>${escapeHtml(describeVideo(video))}</h4>
<p>${escapeHtml(`发布时间 ${formatDateTime(video.published_at)} · 播放 ${formatNumber(video.stats?.play)} · 点赞 ${formatNumber(video.stats?.like)}`)}</p>
<div class="task-meta">
@@ -1529,7 +1570,7 @@ function renderProductionScreen() {
</div>
`).join("")}
${recentDocs.map((doc) => `
<div class="review-card">
<div class="review-card compact">
<h4>${escapeHtml(doc.title)}</h4>
<p>${escapeHtml(brief(doc.style_summary || doc.combined_text || doc.transcript_text, 92))}</p>
<div class="task-meta"><span class="tag">${escapeHtml(doc.source_type || "document")}</span><span class="tag blue">学习素材</span></div>

View File

@@ -680,6 +680,50 @@ select {
cursor: pointer;
}
.mobile-only {
display: none;
}
.desktop-only {
display: initial;
}
.mobile-account-list {
padding: 14px;
border-top: 1px solid var(--line);
background: linear-gradient(180deg, #fbfdff 0%, #f4f9ff 100%);
}
.account-select-card {
width: 100%;
display: grid;
gap: 10px;
text-align: left;
padding: 14px;
border-radius: 18px;
border: 1px solid var(--line);
background: linear-gradient(180deg, #fff 0%, #f7fbff 100%);
color: var(--text);
cursor: pointer;
margin-bottom: 10px;
}
.account-select-card:last-child {
margin-bottom: 0;
}
.account-select-card.is-active {
border-color: rgba(79, 143, 238, 0.24);
background: linear-gradient(180deg, #f8fbff 0%, #eef6ff 100%);
box-shadow: inset 0 0 0 1px rgba(79, 143, 238, 0.08);
}
.compact-summary-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.sheet-html {
border: 1px solid var(--line);
border-radius: 16px;
@@ -1120,6 +1164,14 @@ tbody tr:hover {
}
@media (max-width: 760px) {
.mobile-only {
display: block;
}
.desktop-only {
display: none !important;
}
.sidebar {
padding: 14px 14px 12px;
}
@@ -1235,6 +1287,10 @@ tbody tr:hover {
font-size: 24px;
}
.screen-head p {
font-size: 12px;
}
.action-row {
width: 100%;
}
@@ -1285,6 +1341,10 @@ tbody tr:hover {
padding: 14px;
}
.table-wrap .account-table {
display: none;
}
.search-inline {
width: 100%;
min-width: 0;
@@ -1299,6 +1359,25 @@ tbody tr:hover {
flex: 1 1 calc(50% - 4px);
}
.mobile-account-list {
padding: 12px;
}
.account-select-card {
padding: 12px;
gap: 8px;
}
.account-select-card .kpi-inline {
justify-content: space-between;
}
.account-select-card .task-meta .tag {
flex: 1 1 calc(50% - 4px);
justify-content: center;
text-align: center;
}
.entity-cell {
align-items: flex-start;
}
@@ -1314,6 +1393,11 @@ tbody tr:hover {
gap: 6px;
}
.kpi-inline {
gap: 8px;
row-gap: 6px;
}
table {
min-width: 680px;
}
@@ -1427,6 +1511,38 @@ tbody tr:hover {
width: 100%;
}
.hero-card .chip-row {
flex-wrap: nowrap;
overflow-x: auto;
padding-bottom: 2px;
scrollbar-width: none;
}
.hero-card .chip-row::-webkit-scrollbar {
display: none;
}
.compact-summary-row .tag {
width: calc(50% - 4px);
text-align: center;
}
.task-item.compact,
.review-card.compact {
padding: 12px;
}
.task-item.compact h4,
.review-card.compact h4 {
font-size: 14px;
line-height: 1.4;
}
.task-item.compact p,
.review-card.compact p {
font-size: 11px;
}
.filter {
min-width: 100%;
flex-basis: 100%;