You've already forked agentic-coding-workflow
启动项目逻辑
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-500">在 main 工作区托管启动的运行档</span>
|
||||
<NButton
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="openCreate"
|
||||
>
|
||||
新建运行档
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
<NDataTable
|
||||
:columns="columns"
|
||||
:data="store.profiles"
|
||||
:loading="store.loading"
|
||||
:row-key="(row: RunProfile) => row.id"
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<div v-if="selectedId">
|
||||
<RunLogViewer
|
||||
:key="selectedId"
|
||||
:profile-id="selectedId"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<RunProfileDialog
|
||||
v-if="dialogOpen"
|
||||
:ws-id="ws.id"
|
||||
:profile="editing"
|
||||
@close="dialogOpen = false"
|
||||
@saved="onSaved"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, onMounted, ref } from 'vue'
|
||||
import {
|
||||
NButton,
|
||||
NDataTable,
|
||||
NSpace,
|
||||
NTag,
|
||||
useMessage,
|
||||
useDialog,
|
||||
type DataTableColumns,
|
||||
} from 'naive-ui'
|
||||
import { ApiException } from '@/api/types'
|
||||
import type { Workspace } from '@/api/types'
|
||||
import { useRunsStore } from '@/stores/runs'
|
||||
import type { RunProfile, RunState } from '@/api/runs'
|
||||
import RunProfileDialog from './RunProfileDialog.vue'
|
||||
import RunLogViewer from './RunLogViewer.vue'
|
||||
|
||||
const props = defineProps<{ ws: Workspace }>()
|
||||
const store = useRunsStore()
|
||||
const msg = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
const selectedId = ref<string | null>(null)
|
||||
const dialogOpen = ref(false)
|
||||
const editing = ref<RunProfile | null>(null)
|
||||
|
||||
onMounted(() => {
|
||||
store.fetch(props.ws.id).catch((e: unknown) => msg.error('加载运行档失败:' + errText(e)))
|
||||
})
|
||||
|
||||
function errText(e: unknown): string {
|
||||
return e instanceof ApiException ? e.body.message : e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
|
||||
const tagType: Record<RunState, 'success' | 'default' | 'error'> = {
|
||||
running: 'success',
|
||||
stopped: 'default',
|
||||
crashed: 'error',
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
editing.value = null
|
||||
dialogOpen.value = true
|
||||
}
|
||||
function openEdit(p: RunProfile) {
|
||||
editing.value = p
|
||||
dialogOpen.value = true
|
||||
}
|
||||
function onSaved() {
|
||||
dialogOpen.value = false
|
||||
}
|
||||
|
||||
async function act(fn: () => Promise<unknown>, ok: string) {
|
||||
try {
|
||||
await fn()
|
||||
msg.success(ok)
|
||||
} catch (e: unknown) {
|
||||
msg.error(errText(e))
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDelete(p: RunProfile) {
|
||||
dialog.warning({
|
||||
title: '删除运行档',
|
||||
content: `确定删除「${p.name}」?运行中的进程会被先停止。`,
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
await act(() => store.remove(p.id), '已删除')
|
||||
if (selectedId.value === p.id) selectedId.value = null
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const columns: DataTableColumns<RunProfile> = [
|
||||
{ title: '名称', key: 'name' },
|
||||
{ title: 'Slug', key: 'slug' },
|
||||
{ title: '命令', key: 'command', ellipsis: { tooltip: true } },
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
render: (row) =>
|
||||
h(NTag, { type: tagType[row.status], size: 'small' }, { default: () => row.status }),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
render: (row) =>
|
||||
h(NSpace, { size: 'small' }, () => [
|
||||
row.status === 'running'
|
||||
? h(
|
||||
NButton,
|
||||
{ size: 'tiny', onClick: () => act(() => store.stop(row.id), '已停止') },
|
||||
() => '停止',
|
||||
)
|
||||
: h(
|
||||
NButton,
|
||||
{
|
||||
size: 'tiny',
|
||||
type: 'primary',
|
||||
disabled: !row.enabled,
|
||||
onClick: () => act(() => store.start(row.id), '已启动'),
|
||||
},
|
||||
() => '启动',
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{ size: 'tiny', onClick: () => act(() => store.restart(row.id), '已重启') },
|
||||
() => '重启',
|
||||
),
|
||||
h(NButton, { size: 'tiny', onClick: () => (selectedId.value = row.id) }, () => '日志'),
|
||||
h(NButton, { size: 'tiny', onClick: () => openEdit(row) }, () => '编辑'),
|
||||
h(
|
||||
NButton,
|
||||
{ size: 'tiny', type: 'error', onClick: () => confirmDelete(row) },
|
||||
() => '删除',
|
||||
),
|
||||
]),
|
||||
},
|
||||
]
|
||||
</script>
|
||||
Reference in New Issue
Block a user