From 579e26ecc179d174e3e9bb874cde92faecb74996 Mon Sep 17 00:00:00 2001 From: matevip Date: Fri, 8 May 2026 15:05:04 +0800 Subject: [PATCH] feat(ui): add workflow editor + run viewer + trigger manager views --- mateclaw-ui/src/api/index.ts | 119 +++++ mateclaw-ui/src/router/index.ts | 12 + mateclaw-ui/src/views/Settings/Layout.vue | 12 + mateclaw-ui/src/views/Triggers.vue | 355 +++++++++++++ mateclaw-ui/src/views/Workflows.vue | 583 ++++++++++++++++++++++ 5 files changed, 1081 insertions(+) create mode 100644 mateclaw-ui/src/views/Triggers.vue create mode 100644 mateclaw-ui/src/views/Workflows.vue diff --git a/mateclaw-ui/src/api/index.ts b/mateclaw-ui/src/api/index.ts index a1ec953d..fae0e38d 100644 --- a/mateclaw-ui/src/api/index.ts +++ b/mateclaw-ui/src/api/index.ts @@ -768,3 +768,122 @@ export const hotCacheApi = { regenerate: (kbId: number) => http.post(`/wiki/hot-cache/${kbId}/regenerate`), reset: (kbId: number) => http.delete(`/wiki/hot-cache/${kbId}`), } + +// ==================== Workflow ==================== + +export interface WorkflowSummary { + id: number + workspaceId: number + name: string + description?: string + enabled: boolean + draftJson?: string + draftUpdatedAt?: string + latestRevisionId?: number + createTime: string + updateTime: string +} + +export interface WorkflowCompileError { + code: string + path: string + message: string +} + +export interface WorkflowCompileFailure { + errorCount: number + errors: WorkflowCompileError[] +} + +export interface WorkflowRun { + id: number + workflowId: number + revisionId: number + workspaceId: number + state: string + triggeredBy?: string + initialInputRef?: string + finalOutputRef?: string + errorMessage?: string + startedAt?: string + completedAt?: string +} + +export interface WorkflowRunStep { + id: number + runId: number + stepIndex: number + iterationIndex?: number + stepName?: string + state: string + outputRef?: string + outputSummary?: string + outputContentType?: string + errorMessage?: string + durationMs?: number + startedAt?: string + completedAt?: string +} + +export const workflowApi = { + list: (workspaceId: number) => + http.get('/workflows', { params: { workspaceId } }), + get: (id: number) => http.get(`/workflows/${id}`), + create: (data: Partial) => + http.post('/workflows', data), + update: (id: number, data: Partial) => + http.put(`/workflows/${id}`, data), + delete: (id: number) => http.delete(`/workflows/${id}`), + saveDraft: (id: number, draftJson: string, userId?: number) => + http.put(`/workflows/${id}/draft`, { draftJson }, { params: userId ? { userId } : {} }), + compile: (id: number) => http.post(`/workflows/${id}/compile`), + publish: (id: number, note?: string, userId?: number) => + http.post(`/workflows/${id}/publish`, + note ? { note } : {}, + { params: userId ? { userId } : {} }), + runs: (id: number, limit = 50) => + http.get(`/workflows/${id}/runs`, { params: { limit } }), + runDetail: (runId: number) => + http.get<{ run: WorkflowRun; steps: WorkflowRunStep[] }>(`/workflows/runs/${runId}`), +} + +// ==================== Trigger ==================== + +export interface TriggerSummary { + id: number + workspaceId: number + name?: string + patternType: string + patternJson: string + targetType: string + targetId: number + payloadTemplate?: string + rateLimitPerMin: number + dedupWindowSecs: number + botSelfFilter: boolean + enabled: boolean + fireCount: number + maxFires: number + lastFiredAt?: string + patternVersion: number + createTime: string + updateTime: string +} + +export const triggerApi = { + list: (workspaceId: number) => + http.get('/triggers', { params: { workspaceId } }), + get: (id: number) => http.get(`/triggers/${id}`), + create: (data: Partial) => + http.post('/triggers', data), + update: (id: number, data: Partial) => + http.put(`/triggers/${id}`, data), + delete: (id: number) => http.delete(`/triggers/${id}`), + ingestEvent: (envelope: { + workspaceId: number + patternType: string + eventId?: string + senderId?: string + data?: Record + }) => http.post('/triggers/events', envelope), +} diff --git a/mateclaw-ui/src/router/index.ts b/mateclaw-ui/src/router/index.ts index 9bba9cfc..d5bc1c83 100644 --- a/mateclaw-ui/src/router/index.ts +++ b/mateclaw-ui/src/router/index.ts @@ -164,6 +164,18 @@ const router = createRouter({ component: () => import('@/views/CronJobs.vue'), meta: { title: 'Settings - Cron Jobs' }, }, + { + path: 'workflows', + name: 'SettingsWorkflows', + component: () => import('@/views/Workflows.vue'), + meta: { title: 'Settings - Workflows' }, + }, + { + path: 'triggers', + name: 'SettingsTriggers', + component: () => import('@/views/Triggers.vue'), + meta: { title: 'Settings - Triggers' }, + }, { path: 'datasources', name: 'SettingsDatasources', diff --git a/mateclaw-ui/src/views/Settings/Layout.vue b/mateclaw-ui/src/views/Settings/Layout.vue index 77f0b03f..037346da 100644 --- a/mateclaw-ui/src/views/Settings/Layout.vue +++ b/mateclaw-ui/src/views/Settings/Layout.vue @@ -157,6 +157,18 @@ const sections = computed(() => [ label: t('nav.cronJobs'), icon: '', }, + { + id: 'workflows', + path: '/settings/workflows', + label: t('nav.workflows', 'Workflows'), + icon: '', + }, + { + id: 'triggers', + path: '/settings/triggers', + label: t('nav.triggers', 'Triggers'), + icon: '', + }, { id: 'datasources', path: '/settings/datasources', diff --git a/mateclaw-ui/src/views/Triggers.vue b/mateclaw-ui/src/views/Triggers.vue new file mode 100644 index 00000000..ce7e3fa3 --- /dev/null +++ b/mateclaw-ui/src/views/Triggers.vue @@ -0,0 +1,355 @@ +