#feature: add project&cronjob management

This commit is contained in:
2026-01-16 12:14:43 +08:00
parent bbe68839e3
commit 381d5e6e49
19 changed files with 2157 additions and 84 deletions

View File

@@ -0,0 +1,133 @@
<?php
namespace App\Services;
use Illuminate\Console\Scheduling\Schedule;
class ScheduledTaskService
{
private const CONFIG_KEY = 'scheduled_tasks';
private static ?ConfigService $configServiceInstance = null;
public function __construct(
private ConfigService $configService,
private Schedule $schedule
) {}
/**
* 静态方法:检查任务是否启用(供 console.php 中的 when() 回调使用)
*/
public static function isEnabled(string $name): bool
{
try {
self::$configServiceInstance ??= app(ConfigService::class);
$enabled = self::$configServiceInstance->get(self::CONFIG_KEY, []);
return $enabled[$name] ?? false;
} catch (\Exception $e) {
return false;
}
}
/**
* 获取所有任务(从 Schedule 实例动态获取)
*/
public function getAllTasks(): array
{
$this->ensureTasksLoaded();
$enabledTasks = $this->configService->get(self::CONFIG_KEY, []);
$tasks = [];
foreach ($this->schedule->events() as $event) {
$name = $this->getEventName($event);
$tasks[] = [
'name' => $name,
'command' => $this->getEventCommand($event),
'description' => $event->description ?: $name,
'frequency' => $this->getFrequencyLabel($event->expression),
'cron' => $event->expression,
'enabled' => $enabledTasks[$name] ?? false,
];
}
return $tasks;
}
/**
* 设置任务启用状态
*/
public function setTaskEnabled(string $name, bool $enabled): void
{
$this->ensureTasksLoaded();
// 验证任务是否存在
$exists = false;
foreach ($this->schedule->events() as $event) {
if ($this->getEventName($event) === $name) {
$exists = true;
break;
}
}
if (!$exists) {
throw new \InvalidArgumentException("未知任务: {$name}");
}
$tasks = $this->configService->get(self::CONFIG_KEY, []);
$tasks[$name] = $enabled;
$this->configService->set(self::CONFIG_KEY, $tasks, '定时任务启用状态');
}
/**
* 确保 console.php 中的任务已加载
*/
private function ensureTasksLoaded(): void
{
if (count($this->schedule->events()) === 0) {
require_once base_path('routes/console.php');
}
}
private function getEventName($event): string
{
if (property_exists($event, 'mutexName') && $event->mutexName) {
return $event->mutexName;
}
return $this->getEventCommand($event);
}
private function getEventCommand($event): string
{
if (property_exists($event, 'command') && $event->command) {
$command = $event->command;
if (str_contains($command, 'artisan')) {
$command = preg_replace('/^.*artisan\s+/', '', $command);
}
return trim(str_replace("'", '', $command));
}
return 'closure';
}
private function getFrequencyLabel(string $expression): string
{
$map = [
'* * * * *' => '每分钟',
'*/5 * * * *' => '每 5 分钟',
'*/10 * * * *' => '每 10 分钟',
'*/15 * * * *' => '每 15 分钟',
'*/30 * * * *' => '每 30 分钟',
'0 * * * *' => '每小时',
'0 */2 * * *' => '每 2 小时',
'0 */4 * * *' => '每 4 小时',
'0 */6 * * *' => '每 6 小时',
'0 */12 * * *' => '每 12 小时',
'0 0 * * *' => '每天凌晨 0:00',
'0 2 * * *' => '每天凌晨 2:00',
'0 0 * * 0' => '每周日凌晨',
'0 0 1 * *' => '每月 1 日凌晨',
];
return $map[$expression] ?? $expression;
}
}