初始提交:OCI 面板前端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NSpin, useDialog, useMessage } from 'naive-ui'
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { deleteTask, listTasks, runTask, updateTask } from '@/api/tasks'
|
||||
import EmptyCard from '@/components/EmptyCard.vue'
|
||||
import TaskCard from '@/components/task/TaskCard.vue'
|
||||
import TaskFormModal from '@/components/task/TaskFormModal.vue'
|
||||
import { parseSnatch } from '@/components/task/taskDisplay'
|
||||
import { useAsync } from '@/composables/useAsync'
|
||||
import { useScopeStore } from '@/stores/scope'
|
||||
import type { Task } from '@/types/api'
|
||||
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
const scope = useScopeStore()
|
||||
|
||||
const tasks = useAsync(listTasks)
|
||||
const showCreate = ref(false)
|
||||
const editingTask = ref<Task | null>(null)
|
||||
|
||||
// 每 5 秒静默刷新(不闪 loading)
|
||||
const refreshTimer = setInterval(() => void tasks.run({ silent: true }), 5000)
|
||||
onUnmounted(() => clearInterval(refreshTimer))
|
||||
|
||||
const cfgAliasById = computed(
|
||||
() => new Map((scope.configs.data ?? []).map((c) => [c.id, c.alias])),
|
||||
)
|
||||
|
||||
function aliasFor(task: Task): string | undefined {
|
||||
const s = parseSnatch(task)
|
||||
return s ? cfgAliasById.value.get(s.cfgId) : undefined
|
||||
}
|
||||
|
||||
function openEdit(task: Task) {
|
||||
editingTask.value = task
|
||||
showCreate.value = true
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
editingTask.value = null
|
||||
showCreate.value = true
|
||||
}
|
||||
|
||||
async function act(fn: () => Promise<unknown>, ok: string) {
|
||||
try {
|
||||
await fn()
|
||||
message.success(ok)
|
||||
void tasks.run({ silent: true })
|
||||
} catch (e) {
|
||||
message.error(e instanceof Error ? e.message : '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** active ↔ paused 切换;failed(熔断停止)同走恢复交互重新启用 */
|
||||
function toggle(task: Task) {
|
||||
const resume = task.status !== 'active'
|
||||
void act(
|
||||
() => updateTask(task.id, { status: resume ? 'active' : 'paused' }),
|
||||
resume ? (task.status === 'failed' ? '已重新启用' : '已恢复调度') : '已暂停',
|
||||
)
|
||||
}
|
||||
|
||||
function confirmRemove(task: Task) {
|
||||
dialog.warning({
|
||||
title: '删除任务',
|
||||
content: `删除任务「${task.name}」及其全部日志?`,
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => act(() => deleteTask(task.id), '已删除任务及其日志'),
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-4 p-6 pb-8 max-md:p-3">
|
||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||
<div class="flex flex-wrap items-baseline gap-2.5">
|
||||
<h1 class="page-title">任务</h1>
|
||||
<span class="text-[13px] text-ink-3">
|
||||
{{ tasks.data.value?.length ?? '…' }} 个任务 · cron 为服务器本地时区
|
||||
</span>
|
||||
</div>
|
||||
<NButton size="small" type="primary" @click="openCreate">新建任务</NButton>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="tasks.loading.value && !tasks.data.value"
|
||||
class="panel flex items-center justify-center py-20"
|
||||
>
|
||||
<NSpin size="small" />
|
||||
</div>
|
||||
<div v-else class="flex flex-col gap-3">
|
||||
<TaskCard
|
||||
v-for="task in tasks.data.value ?? []"
|
||||
:key="task.id"
|
||||
:task="task"
|
||||
:cfg-alias="aliasFor(task)"
|
||||
@run="act(() => runTask(task.id), `已触发执行:${task.name}`)"
|
||||
@toggle="toggle(task)"
|
||||
@edit="openEdit(task)"
|
||||
@remove="confirmRemove(task)"
|
||||
/>
|
||||
<EmptyCard
|
||||
v-if="tasks.data.value && !tasks.data.value.length"
|
||||
title="暂无任务"
|
||||
note="点击右上角「新建任务」创建测活 / 抢机 / 成本任务"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TaskFormModal v-model:show="showCreate" :task="editingTask" @created="tasks.run()" />
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user