Skip to content

Commit ac8f448

Browse files
author
linyuan.yang
committed
scheduler
1 parent 2f3e039 commit ac8f448

5 files changed

Lines changed: 20 additions & 53 deletions

File tree

packages/admin/src/components/modals/SchedulerListModal.vue

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { ref, computed } from 'vue'
2+
import { ref } from 'vue'
33
import { useI18n } from 'vue-i18n'
44
import { apiFetch } from '@/shared/api'
55
import { useToast, useConfirm, SModal, SButton, SBadge } from 'sbot-ui'
@@ -9,47 +9,23 @@ const { t, locale } = useI18n()
99
const { show } = useToast()
1010
const { confirm } = useConfirm()
1111
12-
interface ChannelSessionRow {
13-
id: number
14-
profileId: number
15-
}
16-
1712
const visible = ref(false)
18-
const dbSessionId = ref<number | null>(null)
1913
const profileIdRef = ref<string | null>(null)
2014
const sessionLabel = ref('')
2115
const loading = ref(false)
22-
const all = ref<SchedulerRow[]>([])
23-
24-
const filtered = computed(() => {
25-
// scheduler 按 profileId 绑(同 profile 的所有 session 共享视图)
26-
const pid = profileIdRef.value ? Number(profileIdRef.value) : null
27-
if (!pid) return []
28-
return all.value.filter(r => r.profileId === pid)
29-
})
16+
const rows = ref<SchedulerRow[]>([])
3017
3118
function formatTime(ts: number | null): string {
3219
if (!ts) return '-'
3320
return new Date(ts).toLocaleString(locale.value === 'zh' ? 'zh-CN' : undefined)
3421
}
3522
3623
async function load() {
24+
if (!profileIdRef.value) return
3725
loading.value = true
3826
try {
39-
const [timersRes, sessionsRes] = await Promise.all([
40-
apiFetch('/api/schedulers'),
41-
apiFetch('/api/channel-sessions'),
42-
])
43-
all.value = timersRes.data || []
44-
const sessions: ChannelSessionRow[] = sessionsRes.data || []
45-
// 任一入口都最终归位到 profileId 上做过滤
46-
if (profileIdRef.value == null && dbSessionId.value != null) {
47-
const row = sessions.find(s => s.id === dbSessionId.value)
48-
profileIdRef.value = row ? String(row.profileId) : null
49-
} else if (dbSessionId.value == null && profileIdRef.value) {
50-
const row = sessions.find(s => String(s.profileId) === profileIdRef.value)
51-
dbSessionId.value = row?.id ?? null
52-
}
27+
const res = await apiFetch(`/api/schedulers?profileId=${encodeURIComponent(profileIdRef.value)}`)
28+
rows.value = res.data || []
5329
} catch (e: any) {
5430
show(e?.message || String(e), 'error')
5531
} finally {
@@ -68,25 +44,15 @@ async function remove(row: SchedulerRow) {
6844
}
6945
}
7046
71-
function open(id: number, label: string) {
72-
dbSessionId.value = id
73-
profileIdRef.value = null
74-
sessionLabel.value = label
75-
all.value = []
76-
visible.value = true
77-
load()
78-
}
79-
8047
function openByProfileId(profileId: string, label: string) {
81-
dbSessionId.value = null
8248
profileIdRef.value = profileId
8349
sessionLabel.value = label
84-
all.value = []
50+
rows.value = []
8551
visible.value = true
8652
load()
8753
}
8854
89-
defineExpose({ open, openByProfileId })
55+
defineExpose({ openByProfileId })
9056
</script>
9157

9258
<template>
@@ -105,9 +71,9 @@ defineExpose({ open, openByProfileId })
10571
</template>
10672

10773
<div v-if="loading" class="modal-loading">{{ t('common.loading') }}</div>
108-
<div v-else-if="filtered.length === 0" class="modal-empty">{{ t('scheduler.empty') }}</div>
74+
<div v-else-if="rows.length === 0" class="modal-empty">{{ t('scheduler.empty') }}</div>
10975
<ul v-else class="sched-list">
110-
<li v-for="row in filtered" :key="row.id" class="sched-row">
76+
<li v-for="row in rows" :key="row.id" class="sched-row">
11177
<div class="sched-row-main">
11278
<span class="sched-row-id">#{{ row.id }}</span>
11379
<SBadge :variant="TYPE_VARIANT[detectUIType(row.expr)]" size="sm" pill>

packages/admin/src/views/chat/ChannelsView.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ async function refresh() {
684684
<div class="ops-cell">
685685
<SButton v-if="s.saver || c.saver" type="outline" size="sm" @click="saverViewModal?.openByDbId(s.id, saverOptions.find(o => o.id === (s.saver || c.saver))?.label || (s.saver || c.saver))">{{ t('channels.history') }}</SButton>
686686
<SButton type="outline" size="sm" @click="todoListModal?.openByProfileId(String(s.profileId), s.sessionName || s.autoSessionName || s.sessionId)">{{ t('todo.title') }}</SButton>
687-
<SButton type="outline" size="sm" @click="schedulerListModal?.open(s.id, s.sessionName || s.autoSessionName || s.sessionId)">{{ t('scheduler.title') }}</SButton>
687+
<SButton type="outline" size="sm" @click="schedulerListModal?.openByProfileId(String(s.profileId), s.sessionName || s.autoSessionName || s.sessionId)">{{ t('scheduler.title') }}</SButton>
688688
<SButton type="outline" size="sm" @click="openEditSession(s)">{{ t('common.edit') }}</SButton>
689689
<SButton type="danger" size="sm" @click="removeSession(id as string, s)">{{ t('common.delete') }}</SButton>
690690
</div>
@@ -768,7 +768,7 @@ async function refresh() {
768768
</div>
769769
<div class="mobile-card-ops">
770770
<SButton type="outline" size="sm" @click="todoListModal?.openByProfileId(String(s.profileId), s.sessionName || s.autoSessionName || s.sessionId)">{{ t('todo.title') }}</SButton>
771-
<SButton type="outline" size="sm" @click="schedulerListModal?.open(s.id, s.sessionName || s.autoSessionName || s.sessionId)">{{ t('scheduler.title') }}</SButton>
771+
<SButton type="outline" size="sm" @click="schedulerListModal?.openByProfileId(String(s.profileId), s.sessionName || s.autoSessionName || s.sessionId)">{{ t('scheduler.title') }}</SButton>
772772
<SButton type="outline" size="sm" @click="openEditSession(s)">{{ t('common.edit') }}</SButton>
773773
<SButton type="danger" size="sm" @click="removeSession(id as string, s)">{{ t('common.delete') }}</SButton>
774774
</div>

packages/sbot/src/Scheduler/SchedulerService.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,10 @@ class SchedulerService {
146146
this.executor.stopAll();
147147
}
148148

149-
/** 列出 scheduler,附 nextRun。disabled 默认排除;可按 profileId 过滤 */
150-
async list(opts?: { profileId?: number; includeDisabled?: boolean }): Promise<(SchedulerRow & { nextRun: number | null })[]> {
151-
const where: Record<string, any> = {};
152-
if (opts?.profileId != null) where.profileId = opts.profileId;
153-
if (!opts?.includeDisabled) where.disabled = false;
149+
/** 列出未禁用 scheduler,附 nextRun。可按 profileId 过滤 */
150+
async list(profileId?: number): Promise<(SchedulerRow & { nextRun: number | null })[]> {
151+
const where: Record<string, any> = { disabled: false };
152+
if (profileId != null) where.profileId = profileId;
154153
const rows = await database.findAll<SchedulerRow>(database.scheduler, { where });
155154
return rows.map(r => ({ ...(r as any), nextRun: this.nextDate(r.id) }));
156155
}

packages/sbot/src/Server/routes/schedulers.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import type { RouteContext } from './types';
55

66
export class SchedulerRoutes {
77
register(app: express.Application, _ctx: RouteContext): void {
8-
app.get('/api/schedulers', api(async () => {
9-
const rows = await schedulerService.list();
8+
app.get('/api/schedulers', api(async req => {
9+
const profileId = req.query.profileId != null ? Number(req.query.profileId) : undefined;
10+
if (profileId != null && !Number.isInteger(profileId)) throwBad('Invalid profileId');
11+
const rows = await schedulerService.list(profileId);
1012
return rows.map(r => ({ ...toPlain(r), nextRun: r.nextRun }));
1113
}));
1214

packages/sbot/src/Tools/Scheduler/list.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function createSchedulerListTool(profileId: number): StructuredToolInterf
1515
schema: z.object({}) as any,
1616
func: async (_args: any): Promise<MCPToolResult> => {
1717
try {
18-
const timers = await schedulerService.list({ profileId });
18+
const timers = await schedulerService.list(profileId);
1919

2020
if (timers.length === 0) {
2121
return createSuccessResult(createTextContent('No scheduled tasks'));

0 commit comments

Comments
 (0)