feat: update desktop workflows and app center

This commit is contained in:
inman
2026-05-13 19:14:56 +08:00
parent 20b5aff4ad
commit 7c8781a6e3
160 changed files with 55492 additions and 1423 deletions

1479
src/pages/Tasks/index.tsx Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
import type { ComponentType } from 'react';
import {
BarChart3,
Bell,
FileText,
} from 'lucide-react';
import type { CronJob, ScheduleType } from '@/types/cron';
export const schedulePresets: { key: string; value: string; type: ScheduleType }[] = [
{ key: 'everyMinute', value: '* * * * *', type: 'interval' },
{ key: 'every5Min', value: '*/5 * * * *', type: 'interval' },
{ key: 'every15Min', value: '*/15 * * * *', type: 'interval' },
{ key: 'everyHour', value: '0 * * * *', type: 'interval' },
{ key: 'daily9am', value: '0 9 * * *', type: 'daily' },
{ key: 'daily6pm', value: '0 18 * * *', type: 'daily' },
{ key: 'weeklyMon', value: '0 9 * * 1', type: 'weekly' },
{ key: 'monthly1st', value: '0 9 1 * *', type: 'monthly' },
];
export type ScheduledTaskDraft = {
name: string;
message: string;
schedule: string;
enabled?: boolean;
};
export type TaskTemplate = {
id: string;
nameKey: string;
descriptionKey: string;
messageKey: string;
schedule: string;
icon: ComponentType<{ className?: string }>;
};
export const taskTemplates: TaskTemplate[] = [
{
id: 'daily-brief',
nameKey: 'templates.dailyBrief.name',
descriptionKey: 'templates.dailyBrief.description',
messageKey: 'templates.dailyBrief.message',
schedule: '0 9 * * *',
icon: FileText,
},
{
id: 'weekly-review',
nameKey: 'templates.weeklyReview.name',
descriptionKey: 'templates.weeklyReview.description',
messageKey: 'templates.weeklyReview.message',
schedule: '0 18 * * 5',
icon: BarChart3,
},
{
id: 'risk-check',
nameKey: 'templates.riskCheck.name',
descriptionKey: 'templates.riskCheck.description',
messageKey: 'templates.riskCheck.message',
schedule: '0 10 * * *',
icon: Bell,
},
];
export function parseScheduleExpr(schedule: CronJob['schedule']): string {
if (typeof schedule === 'string') return schedule;
if (schedule && typeof schedule === 'object' && 'expr' in schedule && typeof schedule.expr === 'string') {
return schedule.expr;
}
return '0 9 * * *';
}
export function formatSchedule(schedule: CronJob['schedule'], t: (key: string, options?: Record<string, unknown>) => string): string {
const expr = parseScheduleExpr(schedule);
const preset = schedulePresets.find((item) => item.value === expr);
if (preset) return t(`presets.${preset.key}`);
const parts = expr.split(' ');
if (parts.length !== 5) return expr;
const [minute, hour, dayOfMonth, , dayOfWeek] = parts;
if (minute === '*' && hour === '*') return t('presets.everyMinute');
if (minute.startsWith('*/')) return t('schedule.everyMinutes', { count: Number(minute.slice(2)) });
if (hour === '*' && minute === '0') return t('presets.everyHour');
if (dayOfWeek !== '*' && dayOfMonth === '*') return t('schedule.weeklyAt', { day: dayOfWeek, time: `${hour}:${minute.padStart(2, '0')}` });
if (dayOfMonth !== '*') return t('schedule.monthlyAtDay', { day: dayOfMonth, time: `${hour}:${minute.padStart(2, '0')}` });
if (hour !== '*') return t('schedule.dailyAt', { time: `${hour}:${minute.padStart(2, '0')}` });
return expr;
}