feat: add FFmpeg status check and shutdown button
- FFmpeg check no longer blocks server startup - Add /api/checkFFmpeg endpoint to query FFmpeg availability - Add /api/shutdown endpoint to gracefully stop the server - Add FFmpeg status indicator in web header - Add shutdown button in web interface - Move static files output to cmd/bilidown/static for embedding - Update .gitignore to exclude cmd/bilidown/static Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+29
-2
@@ -1,12 +1,29 @@
|
||||
import van from 'vanjs-core'
|
||||
import { now } from 'vanjs-router'
|
||||
import { GLOBAL_HAS_LOGIN } from './mixin'
|
||||
import { GLOBAL_HAS_LOGIN, getApi } from './mixin'
|
||||
|
||||
const { a, div } = van.tags
|
||||
const { a, div, button, span } = van.tags
|
||||
|
||||
export const FFmpegAvailable = van.state<boolean | null>(null)
|
||||
|
||||
export const checkFFmpeg = async () => {
|
||||
try {
|
||||
const res = await getApi('/checkFFmpeg')
|
||||
FFmpegAvailable.val = res.data?.available ?? false
|
||||
} catch {
|
||||
FFmpegAvailable.val = false
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const classStr = (name: string) => van.derive(() => `text-nowrap nav-link ${now.val.split('/')[0] == name ? 'active' : ''}`)
|
||||
|
||||
const shutdown = async () => {
|
||||
if (confirm('确定要关闭服务吗?')) {
|
||||
await getApi('/shutdown')
|
||||
}
|
||||
}
|
||||
|
||||
return div({ class: 'hstack gap-4' },
|
||||
div({ class: 'fs-4 fw-bold text-nowrap' }, 'Bilidown'),
|
||||
div({ class: 'nav nav-underline flex-nowrap overflow-auto' },
|
||||
@@ -22,6 +39,16 @@ export default () => {
|
||||
div({ class: 'nav-item', hidden: GLOBAL_HAS_LOGIN },
|
||||
a({ class: classStr('login'), href: '#/login' }, '扫码登录')
|
||||
),
|
||||
),
|
||||
div({ class: 'ms-auto hstack gap-2' },
|
||||
// FFmpeg 状态指示器
|
||||
div({ class: 'hstack gap-1' },
|
||||
span({ class: () => `badge ${FFmpegAvailable.val === true ? 'bg-success' : FFmpegAvailable.val === false ? 'bg-danger' : 'bg-secondary'}` },
|
||||
() => FFmpegAvailable.val === true ? 'FFmpeg ✓' : FFmpegAvailable.val === false ? 'FFmpeg ✗' : '检查中...'
|
||||
)
|
||||
),
|
||||
// 关闭按钮
|
||||
button({ class: 'btn btn-outline-danger btn-sm', onclick: shutdown }, '关闭服务')
|
||||
)
|
||||
)
|
||||
}
|
||||
+4
-1
@@ -1,6 +1,6 @@
|
||||
/// <reference types="vite/client" />
|
||||
import van from 'vanjs-core'
|
||||
import Header from './header'
|
||||
import Header, { checkFFmpeg } from './header'
|
||||
import Work from './work'
|
||||
import Task from './task'
|
||||
import Login from './login'
|
||||
@@ -16,6 +16,9 @@ const { div } = van.tags
|
||||
|
||||
redirect('home', 'work')
|
||||
|
||||
// 启动时检查 FFmpeg 状态
|
||||
checkFFmpeg()
|
||||
|
||||
van.add(document.body,
|
||||
div({ class: 'container py-4 vstack gap-4', hidden: GLOBAL_HIDE_PAGE },
|
||||
Header(),
|
||||
|
||||
@@ -66,4 +66,10 @@ export const formatSeconds = (seconds: number) => {
|
||||
if (secs > 0) str += `${secs}秒`
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
/** API 请求封装 */
|
||||
export const getApi = async <T = unknown>(path: string, options?: RequestInit): Promise<ResJSON<T>> => {
|
||||
const res = await fetch('/api' + path, options)
|
||||
return res.json() as Promise<ResJSON<T>>
|
||||
}
|
||||
Reference in New Issue
Block a user