notificationService = $notificationService; } public function getList(array $params): array { $query = Task::query(); if (!empty($params['keyword'])) { $query->where(function ($q) use ($params) { $q->where('name', 'like', '%' . $params['keyword'] . '%') ->orWhere('command', 'like', '%' . $params['keyword'] . '%'); }); } if (isset($params['is_active']) && $params['is_active'] !== '') { $query->where('is_active', $params['is_active']); } if (!empty($params['type'])) { $query->where('type', $params['type']); } $query->orderBy('id'); $pageSize = $params['page_size'] ?? 20; $list = $query->paginate($pageSize); return [ 'list' => $list->items(), 'total' => $list->total(), 'page' => $list->currentPage(), 'page_size' => $list->perPage(), ]; } public function getAll(): array { return Task::all()->toArray(); } public function getById(int $id): ?Task { return Task::find($id); } public function create(array $data): Task { Validator::make($data, [ 'name' => 'required|string|max:100', 'command' => 'required|string|max:255', 'type' => 'required|string|in:command,job,closure', 'expression' => 'required|string', ])->validate(); return Task::create($data); } public function update(int $id, array $data): Task { $task = Task::findOrFail($id); Validator::make($data, [ 'name' => 'sometimes|required|string|max:100', 'command' => 'sometimes|required|string|max:255', 'type' => 'sometimes|required|string|in:command,job,closure', 'expression' => 'sometimes|required|string', ])->validate(); $task->update($data); return $task; } public function delete(int $id): bool { $task = Task::findOrFail($id); return $task->delete(); } public function batchDelete(array $ids): bool { Task::whereIn('id', $ids)->delete(); return true; } public function batchUpdateStatus(array $ids, bool $status): bool { Task::whereIn('id', $ids)->update(['is_active' => $status]); return true; } public function run(int $id): array { $task = Task::findOrFail($id); $startTime = microtime(true); $output = ''; $status = 'success'; $errorMessage = ''; try { switch ($task->type) { case 'command': $command = $task->command; if ($task->run_in_background) { $command .= ' > /dev/null 2>&1 &'; } exec($command, $output, $statusCode); $output = implode("\n", $output); if ($statusCode !== 0) { throw new \Exception('Command failed with status code: ' . $statusCode); } break; case 'job': $jobClass = $task->command; if (class_exists($jobClass)) { dispatch(new $jobClass()); } else { throw new \Exception('Job class not found: ' . $jobClass); } break; case 'closure': throw new \Exception('Closure type tasks cannot be run directly'); } $task->increment('run_count'); } catch (\Exception $e) { $status = 'error'; $errorMessage = $e->getMessage(); $task->increment('failed_count'); } $executionTime = round((microtime(true) - $startTime) * 1000); $task->update([ 'last_run_at' => now(), 'last_output' => substr($output, 0, 10000), ]); // 发送任务执行结果通知 $this->sendTaskNotification($task, $status, $errorMessage, $executionTime); return [ 'status' => $status, 'output' => $output, 'error_message' => $errorMessage, 'execution_time' => $executionTime, ]; } public function getStatistics(): array { $total = Task::count(); $active = Task::where('is_active', true)->count(); $inactive = Task::where('is_active', false)->count(); return [ 'total' => $total, 'active' => $active, 'inactive' => $inactive, ]; } /** * 发送任务执行结果通知 * * @param Task $task * @param string $status * @param string|null $errorMessage * @param int $executionTime * @return void */ protected function sendTaskNotification(Task $task, string $status, ?string $errorMessage, int $executionTime): void { try { // 只对失败的任务或重要的成功任务发送通知 // 这里可以根据实际需求调整通知策略 if ($status === 'error') { // 任务失败通知 $title = '任务执行失败: ' . $task->name; $content = sprintf( "任务 %s 执行失败,错误信息:%s\n执行时间:%d 毫秒", $task->name, $errorMessage ?: '未知错误', $executionTime ); // 获取管理员用户ID列表 $adminUserIds = $this->getAdminUserIds(); if (!empty($adminUserIds)) { $this->notificationService->sendToUsers( $adminUserIds, $title, $content, \App\Models\System\Notification::TYPE_ERROR, \App\Models\System\Notification::CATEGORY_TASK, [ 'task_id' => $task->id, 'task_name' => $task->name, 'command' => $task->command, 'error_message' => $errorMessage, 'execution_time' => $executionTime, 'last_run_at' => $task->last_run_at?->toDateTimeString() ] ); } } elseif ($executionTime > 60000) { // 执行时间超过1分钟的成功任务,发送通知 $title = '任务执行完成: ' . $task->name; $content = sprintf( "任务 %s 执行成功,耗时:%.2f 秒", $task->name, $executionTime / 1000 ); $adminUserIds = $this->getAdminUserIds(); if (!empty($adminUserIds)) { $this->notificationService->sendToUsers( $adminUserIds, $title, $content, \App\Models\System\Notification::TYPE_SUCCESS, \App\Models\System\Notification::CATEGORY_TASK, [ 'task_id' => $task->id, 'task_name' => $task->name, 'execution_time' => $executionTime, 'last_run_at' => $task->last_run_at?->toDateTimeString() ] ); } } } catch (\Exception $e) { Log::error('发送任务通知失败', [ 'task_id' => $task->id, 'error' => $e->getMessage() ]); } } /** * 获取管理员用户ID列表 * * @return array */ protected function getAdminUserIds(): array { try { // 获取拥有管理员权限的用户 // 这里可以根据实际业务逻辑调整,例如获取特定角色的用户 $adminUserIds = \App\Models\Auth\User::where('status', 1) ->whereHas('roles', function ($query) { $query->where('name', 'admin'); }) ->pluck('id') ->toArray(); return $adminUserIds; } catch (\Exception $e) { Log::error('获取管理员用户列表失败', [ 'error' => $e->getMessage() ]); return []; } } }