CleanupController.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <?php
  2. namespace App\Module\Cleanup\Controllers;
  3. use App\Module\Cleanup\Services\CleanupService;
  4. use App\Module\Cleanup\Models\CleanupPlan;
  5. use App\Module\Cleanup\Models\CleanupTask;
  6. use App\Module\Cleanup\Models\CleanupConfig;
  7. use App\Module\Cleanup\Models\CleanupBackup;
  8. use App\Module\Cleanup\Enums\PLAN_TYPE;
  9. use App\Module\Cleanup\Enums\DATA_CATEGORY;
  10. use App\Module\Cleanup\Enums\CLEANUP_TYPE;
  11. use Illuminate\Http\Request;
  12. use Illuminate\Http\JsonResponse;
  13. use UCore\ControllerCore;
  14. /**
  15. * 清理模块控制器
  16. *
  17. * 提供清理模块的后台管理接口
  18. */
  19. class CleanupController extends ControllerCore
  20. {
  21. /**
  22. * 显示清理模块首页
  23. */
  24. public function index(): JsonResponse
  25. {
  26. try {
  27. $stats = CleanupService::getCleanupStats();
  28. $health = CleanupService::getSystemHealth();
  29. $recommendations = CleanupService::getRecommendedPlans();
  30. return $this->success([
  31. 'stats' => $stats,
  32. 'health' => $health,
  33. 'recommendations' => $recommendations,
  34. ]);
  35. } catch (\Exception $e) {
  36. return $this->error('获取数据失败: ' . $e->getMessage());
  37. }
  38. }
  39. /**
  40. * 扫描数据表
  41. */
  42. public function scanTables(Request $request): JsonResponse
  43. {
  44. try {
  45. $forceRefresh = $request->boolean('force_refresh', false);
  46. $result = CleanupService::scanTables($forceRefresh);
  47. return $this->success($result, '表扫描完成');
  48. } catch (\Exception $e) {
  49. return $this->error('扫描失败: ' . $e->getMessage());
  50. }
  51. }
  52. /**
  53. * 获取清理配置列表
  54. */
  55. public function getConfigs(Request $request): JsonResponse
  56. {
  57. try {
  58. $query = CleanupConfig::query();
  59. // 筛选条件
  60. if ($request->has('module')) {
  61. $query->byModule($request->input('module'));
  62. }
  63. if ($request->has('category')) {
  64. $query->byCategory($request->input('category'));
  65. }
  66. if ($request->has('enabled')) {
  67. $query->where('is_enabled', $request->boolean('enabled'));
  68. }
  69. if ($request->has('search')) {
  70. $query->searchTable($request->input('search'));
  71. }
  72. // 排序
  73. $query->orderByPriority();
  74. // 分页
  75. $configs = $query->paginate($request->input('per_page', 20));
  76. return $this->success($configs);
  77. } catch (\Exception $e) {
  78. return $this->error('获取配置失败: ' . $e->getMessage());
  79. }
  80. }
  81. /**
  82. * 更新清理配置
  83. */
  84. public function updateConfig(Request $request, int $id): JsonResponse
  85. {
  86. try {
  87. $config = CleanupConfig::findOrFail($id);
  88. $validated = $request->validate([
  89. 'default_cleanup_type' => 'sometimes|integer|in:1,2,3,4,5',
  90. 'default_conditions' => 'sometimes|array',
  91. 'is_enabled' => 'sometimes|boolean',
  92. 'priority' => 'sometimes|integer|min:1|max:999',
  93. 'batch_size' => 'sometimes|integer|min:100|max:10000',
  94. 'description' => 'sometimes|string|max:500',
  95. ]);
  96. $config->update($validated);
  97. return $this->success($config, '配置更新成功');
  98. } catch (\Exception $e) {
  99. return $this->error('更新配置失败: ' . $e->getMessage());
  100. }
  101. }
  102. /**
  103. * 获取清理计划列表
  104. */
  105. public function getPlans(Request $request): JsonResponse
  106. {
  107. try {
  108. $query = CleanupPlan::with(['contents']);
  109. // 筛选条件
  110. if ($request->has('type')) {
  111. $query->byType($request->input('type'));
  112. }
  113. if ($request->has('enabled')) {
  114. $query->where('is_enabled', $request->boolean('enabled'));
  115. }
  116. if ($request->has('template')) {
  117. if ($request->boolean('template')) {
  118. $query->templates();
  119. } else {
  120. $query->nonTemplates();
  121. }
  122. }
  123. if ($request->has('search')) {
  124. $query->searchName($request->input('search'));
  125. }
  126. // 排序
  127. $query->orderBy('created_at', 'desc');
  128. // 分页
  129. $plans = $query->paginate($request->input('per_page', 20));
  130. return $this->success($plans);
  131. } catch (\Exception $e) {
  132. return $this->error('获取计划失败: ' . $e->getMessage());
  133. }
  134. }
  135. /**
  136. * 创建清理计划
  137. */
  138. public function createPlan(Request $request): JsonResponse
  139. {
  140. try {
  141. $validated = $request->validate([
  142. 'plan_name' => 'required|string|max:100|unique:cleanup_plans',
  143. 'plan_type' => 'required|integer|in:1,2,3,4,5',
  144. 'target_selection' => 'sometimes|array',
  145. 'global_conditions' => 'sometimes|array',
  146. 'backup_config' => 'sometimes|array',
  147. 'is_template' => 'sometimes|boolean',
  148. 'is_enabled' => 'sometimes|boolean',
  149. 'description' => 'sometimes|string|max:500',
  150. ]);
  151. $result = CleanupService::createCleanupPlan($validated);
  152. if ($result['success']) {
  153. return $this->success($result, '计划创建成功');
  154. } else {
  155. return $this->error($result['message']);
  156. }
  157. } catch (\Exception $e) {
  158. return $this->error('创建计划失败: ' . $e->getMessage());
  159. }
  160. }
  161. /**
  162. * 获取计划详情
  163. */
  164. public function getPlan(int $id): JsonResponse
  165. {
  166. try {
  167. $plan = CleanupPlan::with(['contents', 'tasks', 'backups'])->findOrFail($id);
  168. return $this->success($plan);
  169. } catch (\Exception $e) {
  170. return $this->error('获取计划详情失败: ' . $e->getMessage());
  171. }
  172. }
  173. /**
  174. * 更新清理计划
  175. */
  176. public function updatePlan(Request $request, int $id): JsonResponse
  177. {
  178. try {
  179. $plan = CleanupPlan::findOrFail($id);
  180. $validated = $request->validate([
  181. 'plan_name' => 'sometimes|string|max:100|unique:cleanup_plans,plan_name,' . $id,
  182. 'target_selection' => 'sometimes|array',
  183. 'global_conditions' => 'sometimes|array',
  184. 'backup_config' => 'sometimes|array',
  185. 'is_enabled' => 'sometimes|boolean',
  186. 'description' => 'sometimes|string|max:500',
  187. ]);
  188. $plan->update($validated);
  189. return $this->success($plan, '计划更新成功');
  190. } catch (\Exception $e) {
  191. return $this->error('更新计划失败: ' . $e->getMessage());
  192. }
  193. }
  194. /**
  195. * 删除清理计划
  196. */
  197. public function deletePlan(int $id): JsonResponse
  198. {
  199. try {
  200. $plan = CleanupPlan::findOrFail($id);
  201. // 检查是否有正在运行的任务
  202. $runningTasks = $plan->tasks()->running()->count();
  203. if ($runningTasks > 0) {
  204. return $this->error('该计划有正在运行的任务,无法删除');
  205. }
  206. $plan->delete();
  207. return $this->success(null, '计划删除成功');
  208. } catch (\Exception $e) {
  209. return $this->error('删除计划失败: ' . $e->getMessage());
  210. }
  211. }
  212. /**
  213. * 生成计划内容
  214. */
  215. public function generatePlanContents(int $id): JsonResponse
  216. {
  217. try {
  218. $result = CleanupService::generatePlanContents($id);
  219. if ($result['success']) {
  220. return $this->success($result, '计划内容生成成功');
  221. } else {
  222. return $this->error($result['message']);
  223. }
  224. } catch (\Exception $e) {
  225. return $this->error('生成计划内容失败: ' . $e->getMessage());
  226. }
  227. }
  228. /**
  229. * 预览计划清理结果
  230. */
  231. public function previewPlan(int $id): JsonResponse
  232. {
  233. try {
  234. $result = CleanupService::previewPlanCleanup($id);
  235. return $this->success($result);
  236. } catch (\Exception $e) {
  237. return $this->error('预览失败: ' . $e->getMessage());
  238. }
  239. }
  240. /**
  241. * 获取清理任务列表
  242. */
  243. public function getTasks(Request $request): JsonResponse
  244. {
  245. try {
  246. $query = CleanupTask::with(['plan']);
  247. // 筛选条件
  248. if ($request->has('plan_id')) {
  249. $query->byPlan($request->input('plan_id'));
  250. }
  251. if ($request->has('status')) {
  252. $query->byStatus($request->input('status'));
  253. }
  254. if ($request->has('search')) {
  255. $query->searchName($request->input('search'));
  256. }
  257. // 排序
  258. $query->orderBy('created_at', 'desc');
  259. // 分页
  260. $tasks = $query->paginate($request->input('per_page', 20));
  261. return $this->success($tasks);
  262. } catch (\Exception $e) {
  263. return $this->error('获取任务失败: ' . $e->getMessage());
  264. }
  265. }
  266. /**
  267. * 创建清理任务
  268. */
  269. public function createTask(Request $request): JsonResponse
  270. {
  271. try {
  272. $validated = $request->validate([
  273. 'plan_id' => 'required|integer|exists:cleanup_plans,id',
  274. 'task_name' => 'sometimes|string|max:100',
  275. 'execute_immediately' => 'sometimes|boolean',
  276. ]);
  277. $result = CleanupService::createCleanupTask(
  278. $validated['plan_id'],
  279. $validated
  280. );
  281. if ($result['success']) {
  282. return $this->success($result, '任务创建成功');
  283. } else {
  284. return $this->error($result['message']);
  285. }
  286. } catch (\Exception $e) {
  287. return $this->error('创建任务失败: ' . $e->getMessage());
  288. }
  289. }
  290. /**
  291. * 获取任务详情
  292. */
  293. public function getTask(int $id): JsonResponse
  294. {
  295. try {
  296. $task = CleanupTask::with(['plan', 'backup', 'logs'])->findOrFail($id);
  297. return $this->success($task);
  298. } catch (\Exception $e) {
  299. return $this->error('获取任务详情失败: ' . $e->getMessage());
  300. }
  301. }
  302. /**
  303. * 执行清理任务
  304. */
  305. public function executeTask(Request $request, int $id): JsonResponse
  306. {
  307. try {
  308. $dryRun = $request->boolean('dry_run', false);
  309. $result = CleanupService::executeCleanupTask($id, $dryRun);
  310. if ($result['success']) {
  311. return $this->success($result, '任务执行成功');
  312. } else {
  313. return $this->error($result['message']);
  314. }
  315. } catch (\Exception $e) {
  316. return $this->error('执行任务失败: ' . $e->getMessage());
  317. }
  318. }
  319. /**
  320. * 获取任务进度
  321. */
  322. public function getTaskProgress(int $id): JsonResponse
  323. {
  324. try {
  325. $result = CleanupService::getTaskProgress($id);
  326. return $this->success($result);
  327. } catch (\Exception $e) {
  328. return $this->error('获取进度失败: ' . $e->getMessage());
  329. }
  330. }
  331. /**
  332. * 停止任务
  333. */
  334. public function stopTask(int $id): JsonResponse
  335. {
  336. try {
  337. $result = CleanupService::stopTask($id);
  338. if ($result['success']) {
  339. return $this->success($result, '任务已停止');
  340. } else {
  341. return $this->error($result['message']);
  342. }
  343. } catch (\Exception $e) {
  344. return $this->error('停止任务失败: ' . $e->getMessage());
  345. }
  346. }
  347. /**
  348. * 获取备份列表
  349. */
  350. public function getBackups(Request $request): JsonResponse
  351. {
  352. try {
  353. $query = CleanupBackup::with(['plan', 'task']);
  354. // 筛选条件
  355. if ($request->has('plan_id')) {
  356. $query->byPlan($request->input('plan_id'));
  357. }
  358. if ($request->has('status')) {
  359. $query->byStatus($request->input('status'));
  360. }
  361. if ($request->has('search')) {
  362. $query->searchName($request->input('search'));
  363. }
  364. // 排序
  365. $query->orderBy('created_at', 'desc');
  366. // 分页
  367. $backups = $query->paginate($request->input('per_page', 20));
  368. return $this->success($backups);
  369. } catch (\Exception $e) {
  370. return $this->error('获取备份失败: ' . $e->getMessage());
  371. }
  372. }
  373. /**
  374. * 创建备份
  375. */
  376. public function createBackup(Request $request): JsonResponse
  377. {
  378. try {
  379. $validated = $request->validate([
  380. 'plan_id' => 'required|integer|exists:cleanup_plans,id',
  381. 'backup_type' => 'sometimes|integer|in:1,2,3',
  382. 'compression_type' => 'sometimes|integer|in:1,2,3',
  383. 'include_structure' => 'sometimes|boolean',
  384. ]);
  385. $result = CleanupService::createPlanBackup(
  386. $validated['plan_id'],
  387. $validated
  388. );
  389. if ($result['success']) {
  390. return $this->success($result, '备份创建成功');
  391. } else {
  392. return $this->error($result['message']);
  393. }
  394. } catch (\Exception $e) {
  395. return $this->error('创建备份失败: ' . $e->getMessage());
  396. }
  397. }
  398. /**
  399. * 获取枚举选项
  400. */
  401. public function getEnumOptions(): JsonResponse
  402. {
  403. try {
  404. return $this->success([
  405. 'plan_types' => PLAN_TYPE::getDetailOptions(),
  406. 'data_categories' => DATA_CATEGORY::getDetailOptions(),
  407. 'cleanup_types' => CLEANUP_TYPE::getDetailOptions(),
  408. ]);
  409. } catch (\Exception $e) {
  410. return $this->error('获取选项失败: ' . $e->getMessage());
  411. }
  412. }
  413. }