优化,现有bug处理

This commit is contained in:
truewhile
2026-09-18 21:55:12 +08:00
parent 45f4763b0c
commit 61a7260eaf
42 changed files with 2429 additions and 92 deletions
+16 -14
View File
@@ -82,14 +82,6 @@ export const MediaCard = memo(function MediaCard({
</div>
)}
{/* Episode count badge:统一放右下角(桌面端与移动端一致),与左上角评分彻底错开 */}
{(count !== undefined && count > 1) || (count === undefined && versionCount > 1) ? (
<span className="absolute bottom-2 right-2 inline-flex items-center gap-1 rounded-lg border border-white/15 bg-[#111827]/90 px-1.5 py-0.5 text-[10px] font-bold text-white shadow-sm">
<Layers size={10} className="shrink-0 text-[#c9954a]" />
<span>{count !== undefined && count > 1 ? `${count} 集` : `${versionCount} 版本`}</span>
</span>
) : null}
{/* Rating Badge */}
{displayRating > 0 && (
<span className="absolute left-2 top-2 inline-flex items-center gap-0.5 rounded-lg border border-white/15 bg-[#111827]/90 px-1.5 py-0.5 text-[10px] font-bold text-[#c9954a] shadow-sm">
@@ -137,13 +129,23 @@ export const MediaCard = memo(function MediaCard({
}`}>
{media.title}
</p>
<div className="flex items-center justify-between text-[11px] font-bold uppercase tracking-wider text-[var(--app-muted)]">
<div className="flex items-center justify-between gap-2 text-[11px] font-bold uppercase tracking-wider text-[var(--app-muted)]">
<span>{media.year > 0 ? media.year : "未知年份"}</span>
{media.video_codec && (
<span className="rounded-xl border border-[var(--app-border)] bg-[var(--app-panel-soft)] px-1.5 py-0.5 text-[var(--app-subtle)]">
{media.video_codec}
</span>
)}
<span className="flex items-center gap-1.5">
{/* 集数/版本数徽标:放在海报下方的信息行而不是压在画面上。海报底部通常
自带片名,角标会盖住它(Game of Thrones / Breaking Bad 都很明显)。 */}
{(count !== undefined && count > 1) || (count === undefined && versionCount > 1) ? (
<span className="inline-flex items-center gap-1 rounded-xl border border-[var(--app-border)] bg-[var(--app-panel-soft)] px-1.5 py-0.5 text-[var(--app-subtle)]">
<Layers size={10} className="shrink-0 text-[#c9954a]" />
<span>{count !== undefined && count > 1 ? `${count} 集` : `${versionCount} 版本`}</span>
</span>
) : null}
{media.video_codec && (
<span className="rounded-xl border border-[var(--app-border)] bg-[var(--app-panel-soft)] px-1.5 py-0.5 text-[var(--app-subtle)]">
{media.video_codec}
</span>
)}
</span>
</div>
</div>
</div>
+11 -11
View File
@@ -46,13 +46,13 @@ export function AdminUsersTable({
<table className="min-w-[900px] 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>
<th className="py-2 whitespace-nowrap">用户名</th>
<th className="whitespace-nowrap">角色</th>
<th className="whitespace-nowrap">媒体库权限</th>
<th className="whitespace-nowrap">状态</th>
<th>权限说明</th>
<th>最近登录</th>
<th className="text-right">操作</th>
<th className="whitespace-nowrap">最近登录</th>
<th className="whitespace-nowrap text-right">操作</th>
</tr>
</thead>
<tbody>
@@ -72,8 +72,8 @@ export function AdminUsersTable({
</span>
)}
</td>
<td className="text-ink-100">{u.role === 'admin' ? '管理员' : '观看用户'}</td>
<td>
<td className="text-ink-100 whitespace-nowrap">{u.role === 'admin' ? '管理员' : '观看用户'}</td>
<td className="whitespace-nowrap">
{u.role === 'admin' ? (
<span className="inline-flex items-center rounded-full bg-sand-100 px-2.5 py-0.5 text-xs text-sand-600 font-medium">
全库 (管理员)
@@ -94,13 +94,13 @@ export function AdminUsersTable({
</button>
)}
</td>
<td className={u.is_active ? 'text-green-500' : 'text-red-400'}>
<td className={`whitespace-nowrap ${u.is_active ? 'text-green-500' : 'text-red-400'}`}>
{u.is_active ? '正常' : '已禁用'}
</td>
<td className="text-ink-50">
<td className="text-ink-50 max-w-[22rem]">
{u.role === 'admin' ? '全部管理权限' : '仅浏览/播放/外部播放器,无下载与文件操作'}
</td>
<td className="text-ink-50">
<td className="text-ink-50 whitespace-nowrap">
<span className="inline-flex flex-wrap items-center gap-2">
<span>{u.last_login_at ? new Date(u.last_login_at).toLocaleString() : '从未登录'}</span>
{u.realtime_online && <span className="rounded border border-green-400/40 px-1.5 py-0.5 text-[11px] text-green-500">在线</span>}
+2 -2
View File
@@ -20,7 +20,7 @@ export function DlnaPage() {
dlnaAPI
.list(force)
.then(setDevices)
.catch(() => toast.error('设备发现失败,容器网络可能不支持组播'))
.catch(() => toast.error('设备发现失败,容器网络可能不支持组播'))
.finally(() => setScanning(false))
}
@@ -94,7 +94,7 @@ export function DlnaPage() {
{devices.length === 0 && !scanning && (
<div className="glass-panel">
<p className="text-ink-100">
未发现任何 DLNA 设备。请确保:服务器与设备在同一局域网,容器使用 host 网络模式,
未发现任何 DLNA 设备。请确保:服务器与设备在同一局域网,容器使用 host 网络模式,
目标设备已开启 DLNA / 屏幕镜像。
</p>
</div>
+7
View File
@@ -1539,6 +1539,13 @@ export function PlayerPage() {
setHlsSource('local')
setCloudWaiting(false)
setCloudWaitMessage('')
// 本地档位不可用(宿主机没有可用的 ffmpeg)时不要进入必然失败的 HLS:
// 保持直连播放并说明怎么修,避免播放器先打一个 500 再回退。
if (!quality.available) {
setPlaybackMode('direct')
toast.error(quality.note || '当前无法进行 HLS 转码,请在「系统设置 → 常规」安装 ffmpeg 后重试')
return
}
if (position > 2) setHlsStartSec(position)
setPlaybackMode('hls')
},
+1 -1
View File
@@ -154,7 +154,7 @@ export function ProfileManagementPage() {
<div className="glass-panel py-12 text-center">
<div className="mb-2 text-4xl">👤</div>
<p className="font-medium text-ink-600">暂无 Profile</p>
<p className="text-sm text-ink-50">点击右上角"创建 Profile"开始</p>
<p className="text-sm text-ink-50">点击右上角「创建 Profile」开始</p>
</div>
)}