diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..b84eaf2 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "nuxt-remote": { + "type": "http", + "url": "https://nuxt.com/mcp" + }, + "nuxt-ui-remote": { + "type": "http", + "url": "https://ui.nuxt.com/mcp" + } + } +} diff --git a/AGENTS.md b/AGENTS.md index eaf8550..92bc71e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -## 开发页面时必须加载 +## 开发页面时必须加载如下mcp -- nuxt-ui -- nuxt \ No newline at end of file +- nuxt-remote +- nuxt-ui-remote \ No newline at end of file diff --git a/app/components/SchedulerTaskModal.vue b/app/components/SchedulerTaskModal.vue index e74225c..40f355e 100644 --- a/app/components/SchedulerTaskModal.vue +++ b/app/components/SchedulerTaskModal.vue @@ -1,5 +1,6 @@ diff --git a/app/pages/admin/scheduler/[id]/index.vue b/app/pages/admin/scheduler/[id]/index.vue index a22f0f1..6279122 100644 --- a/app/pages/admin/scheduler/[id]/index.vue +++ b/app/pages/admin/scheduler/[id]/index.vue @@ -28,8 +28,10 @@ function statusColor(status: string): "success" | "error" | "warning" | "neutral } } -function timeAgo(ts: number): string { - const diff = Date.now() - ts +function timeAgo(ts: number | string): string { + const t = typeof ts === "string" ? new Date(ts).getTime() : ts + const diff = Date.now() - t + if (isNaN(diff)) return "" const mins = Math.floor(diff / 60000) if (mins < 1) return "just now" if (mins < 60) return `${mins}m ago` diff --git a/app/pages/admin/scheduler/index.vue b/app/pages/admin/scheduler/index.vue index cba3aa6..4e629c0 100644 --- a/app/pages/admin/scheduler/index.vue +++ b/app/pages/admin/scheduler/index.vue @@ -22,14 +22,6 @@ const statsData = computed(() => (stats.data.value ?? {}) as { const showCreateModal = ref(false) const editingTask = ref(null) -const columns: any[] = [ - { key: "name", label: "Name" }, - { key: "cronExpression", label: "Cron" }, - { key: "type", label: "Type" }, - { key: "enabled", label: "Status" }, - { key: "actions", label: "" }, -] - function statusBadge(enabled: number) { return enabled ? { label: "Active", color: "success" as const } @@ -98,42 +90,52 @@ function onModalClose() { -
- - - - +
+ + + + + + + + + + + + + + + + + + + + + + +
NameCronTypeStatusActions
No tasks yet
{{ t.name }}{{ t.cronExpression }} + + {{ t.type }} + + + + {{ statusBadge(t.enabled).label }} + + +
+ Trigger + + {{ t.enabled ? 'Pause' : 'Resume' }} + + Detail + Edit + Delete +
+
diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite index fff6c52..29b3dde 100644 Binary files a/packages/drizzle-pkg/db.sqlite and b/packages/drizzle-pkg/db.sqlite differ diff --git a/server/scheduler/engine.ts b/server/scheduler/engine.ts index 512719b..09e48bd 100644 --- a/server/scheduler/engine.ts +++ b/server/scheduler/engine.ts @@ -133,10 +133,13 @@ async function executeHttpTask(task: TaskRow): Promise { const timeoutSignal = AbortSignal.timeout(task.timeoutSeconds * 1000); + const method = (task.httpMethod ?? "GET").toUpperCase(); + const hasBody = ["POST", "PUT", "PATCH", "DELETE"].includes(method); + const response = await fetch(task.httpUrl, { - method: (task.httpMethod ?? "GET").toUpperCase(), - headers: { "Content-Type": "application/json", ...headers }, - body: task.httpBody ?? undefined, + method, + headers: hasBody ? { "Content-Type": "application/json", ...headers } : headers, + body: hasBody ? (task.httpBody ?? undefined) : undefined, signal: timeoutSignal, });