import { FormEvent, useEffect, useState } from 'react'
import toast from 'react-hot-toast'
import { Trash2 } from 'lucide-react'
import { adminAPI } from '../api/admin'
import { libraryAPI } from '../api/library'
import { schedulerAPI, type JobStatus } from '../api/scheduler'
import type { Library, User } from '../types'
import { DownloadClientCard } from '../components/DownloadClientCard'
import { NotifyChannelCard } from '../components/NotifyChannelCard'
import { APIConfigsPanel } from '../components/APIConfigsPanel'
import { SitesPage } from './SitesPage'
export function AdminPage() {
const [tab, setTab] = useState<
'sites' | 'library' | 'users' | 'settings' | 'api' | 'downloads' | 'notify' | 'scheduler'
>('sites')
const tabs = [
{ key: 'sites' as const, label: '站点管理' },
{ key: 'library' as const, label: '媒体库' },
{ key: 'users' as const, label: '用户' },
{ key: 'api' as const, label: '外部API' },
{ key: 'settings' as const, label: '系统设置' },
{ key: 'downloads' as const, label: '下载客户端' },
{ key: 'notify' as const, label: '通知渠道' },
{ key: 'scheduler' as const, label: '定时任务' },
]
return (
管理后台
{tabs.map((k) => (
))}
{tab === 'sites' &&
}
{tab === 'library' &&
}
{tab === 'users' &&
}
{tab === 'api' &&
}
{tab === 'settings' &&
}
{tab === 'downloads' &&
}
{tab === 'notify' &&
}
{tab === 'scheduler' &&
}
)
}
function LibraryPanel() {
const [libs, setLibs] = useState([])
const [name, setName] = useState('')
const [path, setPath] = useState('')
const [type, setType] = useState('movie')
const refresh = () => libraryAPI.list().then(setLibs)
useEffect(() => {
refresh().catch(() => undefined)
}, [])
const handleCreate = async (e: FormEvent) => {
e.preventDefault()
try {
await libraryAPI.create(name, path, type)
toast.success('媒体库已创建')
setName('')
setPath('')
await refresh()
} catch (err: unknown) {
const msg =
(err as { response?: { data?: { error?: string } } })?.response?.data?.error ??
'创建失败'
toast.error(msg)
}
}
return (
| 名称 |
路径 |
类型 |
操作 |
{libs.map((l) => (
| {l.name} |
{l.path} |
{l.type} |
|
))}
)
}
function UsersPanel() {
const [users, setUsers] = useState([])
const refresh = () => adminAPI.listUsers().then(setUsers)
useEffect(() => {
refresh().catch(() => undefined)
}, [])
return (
| 用户名 |
角色 |
最近登录 |
操作 |
{users.map((u) => (
| {u.username} |
{u.role} |
{u.last_login_at ? new Date(u.last_login_at).toLocaleString() : '从未登录'}
|
|
))}
)
}
function SettingsPanel() {
const [items, setItems] = useState<{ key: string; value: string }[]>([])
const [k, setK] = useState('')
const [v, setV] = useState('')
const refresh = () => adminAPI.listSettings().then(setItems)
useEffect(() => {
refresh().catch(() => undefined)
}, [])
const onSave = async (e: FormEvent) => {
e.preventDefault()
await adminAPI.updateSetting(k, v)
toast.success('已保存')
setK('')
setV('')
await refresh()
}
return (
| 键 |
值 |
{items.map((it) => (
| {it.key} |
{it.value} |
))}
)
}
function SchedulerPanel() {
const [tasks, setTasks] = useState([])
const [loading, setLoading] = useState(false)
const refresh = () => {
setLoading(true)
schedulerAPI.status().then(setTasks).finally(() => setLoading(false))
}
useEffect(() => {
refresh()
}, [])
return (
{loading &&
加载中...
}
{!loading && tasks.length === 0 && (
暂无定时任务
)}
{!loading && tasks.length > 0 && (
| 名称 |
间隔 |
上次运行 |
操作 |
{tasks.map((t) => (
| {t.name} |
{t.interval} |
{t.last_run ? new Date(t.last_run).toLocaleString() : '-'}
|
|
))}
)}
)
}