mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-12 08:16:37 +08:00
refactor: split task runtime tables
This commit is contained in:
@@ -0,0 +1,85 @@
|
|||||||
|
import type { ActiveTranscode } from '../api/tasks'
|
||||||
|
import type { QBitTorrent } from '../types'
|
||||||
|
|
||||||
|
function fmtBytes(n: number): string {
|
||||||
|
if (!n || n <= 0) return '0 B'
|
||||||
|
const u = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
let v = n
|
||||||
|
let i = 0
|
||||||
|
while (v >= 1024 && i < u.length - 1) {
|
||||||
|
v /= 1024
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return `${v.toFixed(2)} ${u[i]}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TranscodeTaskTable({ transcodes }: { transcodes: ActiveTranscode[] }) {
|
||||||
|
if (transcodes.length === 0) return <p className="text-sand-500">暂无运行中转码。</p>
|
||||||
|
return (
|
||||||
|
<table className="w-full text-left text-sm">
|
||||||
|
<thead className="text-xs uppercase tracking-wider text-sand-500">
|
||||||
|
<tr>
|
||||||
|
<th className="py-2">媒体 ID</th>
|
||||||
|
<th>编码器</th>
|
||||||
|
<th>开始时间</th>
|
||||||
|
<th>就绪</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{transcodes.map((t) => (
|
||||||
|
<tr key={t.media_id} className="border-t border-gray-200">
|
||||||
|
<td className="py-2 font-mono text-xs text-ink-600">{t.media_id}</td>
|
||||||
|
<td className="text-ink-100">{t.encoder || 'libx264'}</td>
|
||||||
|
<td className="text-ink-100">{new Date(t.started_at).toLocaleTimeString()}</td>
|
||||||
|
<td>
|
||||||
|
{t.playlist_ok ? (
|
||||||
|
<span className="rounded-lg border border-emerald-400/40 px-1.5 py-0.5 text-xs text-emerald-400">
|
||||||
|
ready
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="rounded-lg border border-yellow-400/40 px-1.5 py-0.5 text-xs text-yellow-400">
|
||||||
|
starting
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TorrentTaskTable({ torrents }: { torrents: QBitTorrent[] }) {
|
||||||
|
if (torrents.length === 0) return <p className="text-sand-500">暂无运行中下载。</p>
|
||||||
|
return (
|
||||||
|
<table className="w-full text-left text-sm">
|
||||||
|
<thead className="text-xs uppercase tracking-wider text-sand-500">
|
||||||
|
<tr>
|
||||||
|
<th className="py-2">名称</th>
|
||||||
|
<th>状态</th>
|
||||||
|
<th>进度</th>
|
||||||
|
<th>体积</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{torrents.map((t) => (
|
||||||
|
<tr key={t.hash} className="border-t border-gray-200 align-top">
|
||||||
|
<td className="max-w-md truncate py-2 text-ink-600" title={t.name}>
|
||||||
|
{t.name}
|
||||||
|
</td>
|
||||||
|
<td className="text-ink-100">{t.state}</td>
|
||||||
|
<td className="text-ink-100">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="h-1 w-24 overflow-hidden rounded-lg bg-gray-200">
|
||||||
|
<div className="h-full bg-primary-400" style={{ width: `${Math.round(t.progress * 100)}%` }} />
|
||||||
|
</div>
|
||||||
|
{(t.progress * 100).toFixed(1)}%
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-ink-100">{fmtBytes(t.size)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -3,18 +3,7 @@ import toast from 'react-hot-toast'
|
|||||||
import { Activity, Copy } from 'lucide-react'
|
import { Activity, Copy } from 'lucide-react'
|
||||||
|
|
||||||
import { tasksAPI, type BackgroundTask, type TasksSnapshot } from '../api/tasks'
|
import { tasksAPI, type BackgroundTask, type TasksSnapshot } from '../api/tasks'
|
||||||
|
import { TorrentTaskTable, TranscodeTaskTable } from './TaskRuntimeTables'
|
||||||
function fmtBytes(n: number): string {
|
|
||||||
if (!n || n <= 0) return '0 B'
|
|
||||||
const u = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
||||||
let v = n
|
|
||||||
let i = 0
|
|
||||||
while (v >= 1024 && i < u.length - 1) {
|
|
||||||
v /= 1024
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return `${v.toFixed(2)} ${u[i]}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const metricLabels: Record<string, string> = {
|
const metricLabels: Record<string, string> = {
|
||||||
organized: '新增',
|
organized: '新增',
|
||||||
@@ -208,78 +197,12 @@ export function TasksPage() {
|
|||||||
|
|
||||||
<section className="glass-panel">
|
<section className="glass-panel">
|
||||||
<h2 className="mb-3 font-display text-lg font-semibold text-ink-600">转码任务</h2>
|
<h2 className="mb-3 font-display text-lg font-semibold text-ink-600">转码任务</h2>
|
||||||
{snap.transcodes.length === 0 && <p className="text-sand-500">暂无运行中转码。</p>}
|
<TranscodeTaskTable transcodes={snap.transcodes} />
|
||||||
{snap.transcodes.length > 0 && (
|
|
||||||
<table className="w-full text-left text-sm">
|
|
||||||
<thead className="text-xs uppercase tracking-wider text-sand-500">
|
|
||||||
<tr>
|
|
||||||
<th className="py-2">媒体 ID</th>
|
|
||||||
<th>编码器</th>
|
|
||||||
<th>开始时间</th>
|
|
||||||
<th>就绪</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{snap.transcodes.map((t) => (
|
|
||||||
<tr key={t.media_id} className="border-t border-gray-200">
|
|
||||||
<td className="py-2 font-mono text-xs text-ink-600">{t.media_id}</td>
|
|
||||||
<td className="text-ink-100">{t.encoder || 'libx264'}</td>
|
|
||||||
<td className="text-ink-100">{new Date(t.started_at).toLocaleTimeString()}</td>
|
|
||||||
<td>
|
|
||||||
{t.playlist_ok ? (
|
|
||||||
<span className="rounded-lg border border-emerald-400/40 px-1.5 py-0.5 text-xs text-emerald-400">
|
|
||||||
ready
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="rounded-lg border border-yellow-400/40 px-1.5 py-0.5 text-xs text-yellow-400">
|
|
||||||
starting
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)}
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="glass-panel">
|
<section className="glass-panel">
|
||||||
<h2 className="mb-3 font-display text-lg font-semibold text-ink-600">下载任务</h2>
|
<h2 className="mb-3 font-display text-lg font-semibold text-ink-600">下载任务</h2>
|
||||||
{torrents.length === 0 && <p className="text-sand-500">暂无运行中下载。</p>}
|
<TorrentTaskTable torrents={torrents} />
|
||||||
{torrents.length > 0 && (
|
|
||||||
<table className="w-full text-left text-sm">
|
|
||||||
<thead className="text-xs uppercase tracking-wider text-sand-500">
|
|
||||||
<tr>
|
|
||||||
<th className="py-2">名称</th>
|
|
||||||
<th>状态</th>
|
|
||||||
<th>进度</th>
|
|
||||||
<th>体积</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{torrents.map((t) => (
|
|
||||||
<tr key={t.hash} className="border-t border-gray-200 align-top">
|
|
||||||
<td className="max-w-md truncate py-2 text-ink-600" title={t.name}>
|
|
||||||
{t.name}
|
|
||||||
</td>
|
|
||||||
<td className="text-ink-100">{t.state}</td>
|
|
||||||
<td className="text-ink-100">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<div className="h-1 w-24 overflow-hidden rounded-lg bg-gray-200">
|
|
||||||
<div
|
|
||||||
className="h-full bg-primary-400"
|
|
||||||
style={{ width: `${Math.round(t.progress * 100)}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{(t.progress * 100).toFixed(1)}%
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-ink-100">{fmtBytes(t.size)}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)}
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user