feat: add scheduler config
This commit is contained in:
@@ -21,7 +21,6 @@ const backupLoading = ref(false)
|
||||
const restoreLoading = ref(false)
|
||||
const fileInput = ref<HTMLInputElement>()
|
||||
const showConfirm = ref(false)
|
||||
const pendingFile = ref<File | null>(null)
|
||||
|
||||
async function checkBackupStatus() {
|
||||
try {
|
||||
@@ -49,11 +48,20 @@ function downloadBackup() {
|
||||
setTimeout(checkBackupStatus, 6000)
|
||||
}
|
||||
|
||||
function triggerFileSelect() {
|
||||
function showRestoreConfirm() {
|
||||
showConfirm.value = true
|
||||
}
|
||||
|
||||
function confirmRestore() {
|
||||
showConfirm.value = false
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
function handleFileSelect(e: Event) {
|
||||
function cancelRestore() {
|
||||
showConfirm.value = false
|
||||
}
|
||||
|
||||
async function handleFileSelect(e: Event) {
|
||||
const target = e.target as HTMLInputElement
|
||||
const file = target.files?.[0]
|
||||
if (!file) return
|
||||
@@ -64,33 +72,19 @@ function handleFileSelect(e: Event) {
|
||||
return
|
||||
}
|
||||
|
||||
pendingFile.value = file
|
||||
showConfirm.value = true
|
||||
target.value = ''
|
||||
}
|
||||
|
||||
async function confirmRestore() {
|
||||
if (!pendingFile.value) return
|
||||
|
||||
showConfirm.value = false
|
||||
restoreLoading.value = true
|
||||
try {
|
||||
await api.settings.restoreBackup(pendingFile.value)
|
||||
await api.settings.restoreBackup(file)
|
||||
toast.success('恢复成功,页面即将刷新')
|
||||
setTimeout(() => window.location.reload(), 1500)
|
||||
} catch (e: any) {
|
||||
toast.error(e.message || '恢复失败')
|
||||
} finally {
|
||||
restoreLoading.value = false
|
||||
pendingFile.value = null
|
||||
target.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
function cancelRestore() {
|
||||
showConfirm.value = false
|
||||
pendingFile.value = null
|
||||
}
|
||||
|
||||
onMounted(checkBackupStatus)
|
||||
</script>
|
||||
|
||||
@@ -112,7 +106,7 @@ onMounted(checkBackupStatus)
|
||||
</div>
|
||||
<div class="border-t pt-4 mt-4">
|
||||
<div class="flex items-center gap-4">
|
||||
<Button @click="triggerFileSelect" :disabled="restoreLoading" variant="outline">
|
||||
<Button @click="showRestoreConfirm" :disabled="restoreLoading" variant="outline">
|
||||
<Upload class="w-4 h-4 mr-2" />
|
||||
{{ restoreLoading ? '恢复中...' : '恢复备份' }}
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { api } from '@/api'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
interface SchedulerSettings {
|
||||
worker_count: string
|
||||
queue_size: string
|
||||
rate_interval: string
|
||||
}
|
||||
|
||||
const form = ref<SchedulerSettings>({
|
||||
worker_count: '4',
|
||||
queue_size: '100',
|
||||
rate_interval: '200'
|
||||
})
|
||||
const loading = ref(false)
|
||||
const showConfirm = ref(false)
|
||||
|
||||
async function loadSettings() {
|
||||
try {
|
||||
const res = await api.settings.getScheduler()
|
||||
form.value = res
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function confirmSave() {
|
||||
showConfirm.value = true
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
showConfirm.value = false
|
||||
loading.value = true
|
||||
try {
|
||||
await api.settings.updateScheduler({
|
||||
worker_count: String(form.value.worker_count),
|
||||
queue_size: String(form.value.queue_size),
|
||||
rate_interval: String(form.value.rate_interval)
|
||||
})
|
||||
toast.success('保存成功,调度配置已重新加载')
|
||||
} catch {
|
||||
toast.error('保存失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadSettings)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right">Worker 数量</Label>
|
||||
<div class="col-span-3 flex items-center gap-2">
|
||||
<Input v-model="form.worker_count" type="number" class="w-24" />
|
||||
<span class="text-xs text-muted-foreground">并发执行任务的 worker 数量</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right">队列大小</Label>
|
||||
<div class="col-span-3 flex items-center gap-2">
|
||||
<Input v-model="form.queue_size" type="number" class="w-24" />
|
||||
<span class="text-xs text-muted-foreground">任务队列缓冲区大小</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right">速率间隔</Label>
|
||||
<div class="col-span-3 flex items-center gap-2">
|
||||
<Input v-model="form.rate_interval" type="number" class="w-24" />
|
||||
<span class="text-xs text-muted-foreground">ms,任务启动间隔(200ms = 每秒最多5个)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end pt-2">
|
||||
<Button @click="confirmSave" :disabled="loading">
|
||||
{{ loading ? '保存中...' : '保存设置' }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<AlertDialog :open="showConfirm" @update:open="showConfirm = $event">
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认保存</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
保存后调度配置将立即生效,正在执行的任务不受影响。确定要保存吗?
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||
<AlertDialogAction @click="saveSettings">确认保存</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -4,6 +4,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import PasswordSettings from './PasswordSettings.vue'
|
||||
import SiteSettings from './SiteSettings.vue'
|
||||
import SchedulerSettings from './SchedulerSettings.vue'
|
||||
import BackupSettings from './BackupSettings.vue'
|
||||
import AboutSettings from './AboutSettings.vue'
|
||||
|
||||
@@ -21,6 +22,7 @@ const activeTab = ref('password')
|
||||
<TabsList>
|
||||
<TabsTrigger value="password">密码修改</TabsTrigger>
|
||||
<TabsTrigger value="site">站点设置</TabsTrigger>
|
||||
<TabsTrigger value="scheduler">调度设置</TabsTrigger>
|
||||
<TabsTrigger value="backup">备份恢复</TabsTrigger>
|
||||
<TabsTrigger value="about">关于</TabsTrigger>
|
||||
</TabsList>
|
||||
@@ -49,6 +51,18 @@ const activeTab = ref('password')
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="scheduler" class="mt-6">
|
||||
<Card class="max-w-xl">
|
||||
<CardHeader>
|
||||
<CardTitle>调度设置</CardTitle>
|
||||
<CardDescription>配置任务调度器参数</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<SchedulerSettings />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="backup" class="mt-6">
|
||||
<Card class="max-w-xl">
|
||||
<CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user