#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,260 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Project;
use App\Services\ProjectService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
class ProjectController extends Controller
{
public function __construct(private readonly ProjectService $projectService)
{
}
/**
* 获取所有项目
*/
public function index(): JsonResponse
{
$projects = $this->projectService->getAllProjects();
$projectsPath = $this->projectService->getProjectsPath();
// 为每个项目添加状态信息
$projectsWithStatus = $projects->map(function (Project $project) use ($projectsPath) {
$data = $project->toArray();
$data['path_valid'] = $project->isPathValid($projectsPath);
$data['full_path'] = $project->getFullPath($projectsPath);
return $data;
});
return response()->json([
'success' => true,
'data' => [
'projects' => $projectsWithStatus,
'projects_path' => $projectsPath,
],
]);
}
/**
* 获取单个项目
*/
public function show(string $slug): JsonResponse
{
$project = $this->projectService->getBySlug($slug);
if (!$project) {
return response()->json([
'success' => false,
'message' => '项目不存在',
], 404);
}
$status = $this->projectService->getProjectStatus($project);
return response()->json([
'success' => true,
'data' => [
'project' => $project,
'status' => $status,
],
]);
}
/**
* 创建项目
*/
public function store(Request $request): JsonResponse
{
$data = $request->validate([
'slug' => ['required', 'string', 'max:100', 'unique:projects,slug', 'regex:/^[a-z0-9\-_]+$/'],
'name' => ['required', 'string', 'max:255'],
'directory' => ['nullable', 'string', 'max:255'],
'absolute_path' => ['nullable', 'string', 'max:500'],
'jira_project_code' => ['nullable', 'string', 'max:50'],
'git_monitor_enabled' => ['nullable', 'boolean'],
'auto_create_release_branch' => ['nullable', 'boolean'],
'is_important' => ['nullable', 'boolean'],
'log_app_names' => ['nullable', 'array'],
'log_app_names.*' => ['string', 'max:100'],
'log_env' => ['nullable', 'string', 'max:50'],
]);
$project = $this->projectService->create($data);
return response()->json([
'success' => true,
'data' => [
'project' => $project,
],
]);
}
/**
* 更新项目
*/
public function update(Request $request, string $slug): JsonResponse
{
$project = $this->projectService->getBySlug($slug);
if (!$project) {
return response()->json([
'success' => false,
'message' => '项目不存在',
], 404);
}
$data = $request->validate([
'slug' => [
'sometimes',
'string',
'max:100',
'regex:/^[a-z0-9\-_]+$/',
Rule::unique('projects', 'slug')->ignore($project->id),
],
'name' => ['sometimes', 'string', 'max:255'],
'directory' => ['nullable', 'string', 'max:255'],
'absolute_path' => ['nullable', 'string', 'max:500'],
'jira_project_code' => ['nullable', 'string', 'max:50'],
'git_monitor_enabled' => ['nullable', 'boolean'],
'auto_create_release_branch' => ['nullable', 'boolean'],
'is_important' => ['nullable', 'boolean'],
'log_app_names' => ['nullable', 'array'],
'log_app_names.*' => ['string', 'max:100'],
'log_env' => ['nullable', 'string', 'max:50'],
]);
$project = $this->projectService->update($project, $data);
return response()->json([
'success' => true,
'data' => [
'project' => $project,
],
]);
}
/**
* 删除项目
*/
public function destroy(string $slug): JsonResponse
{
$project = $this->projectService->getBySlug($slug);
if (!$project) {
return response()->json([
'success' => false,
'message' => '项目不存在',
], 404);
}
$this->projectService->delete($project);
return response()->json([
'success' => true,
]);
}
/**
* 获取项目状态
*/
public function status(string $slug): JsonResponse
{
$project = $this->projectService->getBySlug($slug);
if (!$project) {
return response()->json([
'success' => false,
'message' => '项目不存在',
], 404);
}
$status = $this->projectService->getProjectStatus($project);
return response()->json([
'success' => true,
'data' => [
'status' => $status,
],
]);
}
/**
* 同步 Git 信息
*/
public function sync(string $slug): JsonResponse
{
$project = $this->projectService->getBySlug($slug);
if (!$project) {
return response()->json([
'success' => false,
'message' => '项目不存在',
], 404);
}
$project = $this->projectService->syncGitInfo($project);
return response()->json([
'success' => true,
'data' => [
'project' => $project,
],
]);
}
/**
* 发现新项目
*/
public function discover(): JsonResponse
{
$discovered = $this->projectService->discoverProjects();
return response()->json([
'success' => true,
'data' => [
'discovered' => $discovered,
],
]);
}
/**
* 批量添加发现的项目
*/
public function addDiscovered(Request $request): JsonResponse
{
$data = $request->validate([
'slugs' => ['required', 'array', 'min:1'],
'slugs.*' => ['string', 'max:100'],
]);
$added = $this->projectService->addDiscoveredProjects($data['slugs']);
return response()->json([
'success' => true,
'data' => [
'added' => $added,
],
]);
}
/**
* 一键同步所有项目的 Git 信息
*/
public function syncAll(): JsonResponse
{
$results = $this->projectService->syncAllGitInfo();
return response()->json([
'success' => true,
'data' => [
'synced' => $results['synced'],
'failed' => $results['failed'],
],
]);
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\ScheduledTaskService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ScheduledTaskController extends Controller
{
public function __construct(
private ScheduledTaskService $taskService
) {}
/**
* 获取所有定时任务列表
*/
public function index(): JsonResponse
{
return response()->json([
'success' => true,
'data' => [
'tasks' => $this->taskService->getAllTasks(),
],
]);
}
/**
* 切换定时任务启用状态
*/
public function toggle(Request $request, string $name): JsonResponse
{
$validated = $request->validate([
'enabled' => 'required|boolean',
]);
try {
$this->taskService->setTaskEnabled($name, $validated['enabled']);
return response()->json([
'success' => true,
'data' => [
'enabled' => $validated['enabled'],
],
'message' => $validated['enabled'] ? '任务已启用' : '任务已禁用',
]);
} catch (\InvalidArgumentException $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 400);
}
}
}