33namespace App \Http \Controllers \V2 \Admin ;
44
55use App \Http \Controllers \Controller ;
6- use App \Models \Log as LogModel ;
6+ use App \Models \AdminAuditLog ;
77use App \Utils \CacheKey ;
88use Illuminate \Http \Request ;
99use Illuminate \Support \Facades \Cache ;
@@ -23,37 +23,10 @@ public function getSystemStatus()
2323 'schedule ' => $ this ->getScheduleStatus (),
2424 'horizon ' => $ this ->getHorizonStatus (),
2525 'schedule_last_runtime ' => Cache::get (CacheKey::get ('SCHEDULE_LAST_CHECK_AT ' , null )),
26- 'logs ' => $ this ->getLogStatistics ()
2726 ];
2827 return $ this ->success ($ data );
2928 }
3029
31- /**
32- * 获取日志统计信息
33- *
34- * @return array 各级别日志的数量统计
35- */
36- protected function getLogStatistics (): array
37- {
38- // 初始化日志统计数组
39- $ statistics = [
40- 'info ' => 0 ,
41- 'warning ' => 0 ,
42- 'error ' => 0 ,
43- 'total ' => 0
44- ];
45-
46- if (class_exists (LogModel::class) && LogModel::count () > 0 ) {
47- $ statistics ['info ' ] = LogModel::where ('level ' , 'INFO ' )->count ();
48- $ statistics ['warning ' ] = LogModel::where ('level ' , 'WARNING ' )->count ();
49- $ statistics ['error ' ] = LogModel::where ('level ' , 'ERROR ' )->count ();
50- $ statistics ['total ' ] = LogModel::count ();
51-
52- return $ statistics ;
53- }
54- return $ statistics ;
55- }
56-
5730 public function getQueueWorkload (WorkloadRepository $ workload )
5831 {
5932 return $ this ->success (collect ($ workload ->get ())->sortBy ('name ' )->values ()->toArray ());
@@ -125,34 +98,26 @@ protected function totalPausedMasters()
12598 })->count ();
12699 }
127100
128- public function getSystemLog (Request $ request )
101+ public function getAuditLog (Request $ request )
129102 {
130- $ current = $ request ->input ('current ' ) ? $ request ->input ('current ' ) : 1 ;
131- $ pageSize = $ request ->input ('page_size ' ) >= 10 ? $ request ->input ('page_size ' ) : 10 ;
132- $ level = $ request ->input ('level ' );
133- $ keyword = $ request ->input ('keyword ' );
134-
135- $ builder = LogModel::orderBy ('created_at ' , 'DESC ' )
136- ->when ($ level , function ($ query ) use ($ level ) {
137- return $ query ->where ('level ' , strtoupper ($ level ));
138- })
139- ->when ($ keyword , function ($ query ) use ($ keyword ) {
140- return $ query ->where (function ($ q ) use ($ keyword ) {
141- $ q ->where ('data ' , 'like ' , '% ' . $ keyword . '% ' )
142- ->orWhere ('context ' , 'like ' , '% ' . $ keyword . '% ' )
143- ->orWhere ('title ' , 'like ' , '% ' . $ keyword . '% ' )
144- ->orWhere ('uri ' , 'like ' , '% ' . $ keyword . '% ' );
103+ $ current = max (1 , (int ) $ request ->input ('current ' , 1 ));
104+ $ pageSize = max (10 , (int ) $ request ->input ('page_size ' , 10 ));
105+
106+ $ builder = AdminAuditLog::with ('admin:id,email ' )
107+ ->orderBy ('id ' , 'DESC ' )
108+ ->when ($ request ->input ('action ' ), fn ($ q , $ v ) => $ q ->where ('action ' , $ v ))
109+ ->when ($ request ->input ('admin_id ' ), fn ($ q , $ v ) => $ q ->where ('admin_id ' , $ v ))
110+ ->when ($ request ->input ('keyword ' ), function ($ q , $ keyword ) {
111+ $ q ->where (function ($ q ) use ($ keyword ) {
112+ $ q ->where ('uri ' , 'like ' , '% ' . $ keyword . '% ' )
113+ ->orWhere ('request_data ' , 'like ' , '% ' . $ keyword . '% ' );
145114 });
146115 });
147116
148117 $ total = $ builder ->count ();
149- $ res = $ builder ->forPage ($ current , $ pageSize )
150- ->get ();
118+ $ res = $ builder ->forPage ($ current , $ pageSize )->get ();
151119
152- return response ([
153- 'data ' => $ res ,
154- 'total ' => $ total
155- ]);
120+ return response (['data ' => $ res , 'total ' => $ total ]);
156121 }
157122
158123 public function getHorizonFailedJobs (Request $ request , JobRepository $ jobRepository )
@@ -176,125 +141,4 @@ public function getHorizonFailedJobs(Request $request, JobRepository $jobReposit
176141 ]);
177142 }
178143
179- /**
180- * 清除系统日志
181- *
182- * @param Request $request
183- * @return \Illuminate\Http\JsonResponse
184- */
185- public function clearSystemLog (Request $ request )
186- {
187- $ request ->validate ([
188- 'days ' => 'integer|min:0|max:365 ' ,
189- 'level ' => 'string|in:info,warning,error,all ' ,
190- 'limit ' => 'integer|min:100|max:10000 '
191- ], [
192- 'days.required ' => '请指定要清除多少天前的日志 ' ,
193- 'days.integer ' => '天数必须为整数 ' ,
194- 'days.min ' => '天数不能少于1天 ' ,
195- 'days.max ' => '天数不能超过365天 ' ,
196- 'level.in ' => '日志级别只能是:info、warning、error、all ' ,
197- 'limit.min ' => '单次清除数量不能少于100条 ' ,
198- 'limit.max ' => '单次清除数量不能超过10000条 '
199- ]);
200-
201- $ days = $ request ->input ('days ' , 30 ); // 默认清除30天前的日志
202- $ level = $ request ->input ('level ' , 'all ' ); // 默认清除所有级别
203- $ limit = $ request ->input ('limit ' , 1000 ); // 默认单次清除1000条
204-
205- try {
206- $ cutoffDate = now ()->subDays ($ days );
207-
208- // 构建查询条件
209- $ query = LogModel::where ('created_at ' , '< ' , $ cutoffDate ->timestamp );
210-
211- if ($ level !== 'all ' ) {
212- $ query ->where ('level ' , strtoupper ($ level ));
213- }
214-
215- // 获取要删除的记录数量
216- $ totalCount = $ query ->count ();
217-
218- if ($ totalCount === 0 ) {
219- return $ this ->success ([
220- 'message ' => '没有找到符合条件的日志记录 ' ,
221- 'deleted_count ' => 0 ,
222- 'total_count ' => $ totalCount
223- ]);
224- }
225-
226- // 分批删除,避免单次删除过多数据
227- $ deletedCount = 0 ;
228- $ batchSize = min ($ limit , 1000 ); // 每批最多1000条
229-
230- while ($ deletedCount < $ limit && $ deletedCount < $ totalCount ) {
231- $ remainingLimit = min ($ batchSize , $ limit - $ deletedCount );
232-
233- $ batchQuery = LogModel::where ('created_at ' , '< ' , $ cutoffDate ->timestamp );
234- if ($ level !== 'all ' ) {
235- $ batchQuery ->where ('level ' , strtoupper ($ level ));
236- }
237-
238- $ idsToDelete = $ batchQuery ->limit ($ remainingLimit )->pluck ('id ' );
239-
240- if ($ idsToDelete ->isEmpty ()) {
241- break ;
242- }
243-
244- $ batchDeleted = LogModel::whereIn ('id ' , $ idsToDelete )->delete ();
245- $ deletedCount += $ batchDeleted ;
246-
247- // 避免长时间占用数据库连接
248- if ($ deletedCount < $ limit && $ deletedCount < $ totalCount ) {
249- usleep (100000 ); // 暂停0.1秒
250- }
251- }
252-
253- return $ this ->success ([
254- 'message ' => '日志清除完成 ' ,
255- 'deleted_count ' => $ deletedCount ,
256- 'total_count ' => $ totalCount ,
257- 'remaining_count ' => max (0 , $ totalCount - $ deletedCount )
258- ]);
259-
260- } catch (\Exception $ e ) {
261- return $ this ->fail (ResponseEnum::HTTP_ERROR , null , '清除日志失败: ' . $ e ->getMessage ());
262- }
263- }
264-
265- /**
266- * 获取日志清除统计信息
267- *
268- * @param Request $request
269- * @return \Illuminate\Http\JsonResponse
270- */
271- public function getLogClearStats (Request $ request )
272- {
273- $ days = $ request ->input ('days ' , 30 );
274- $ level = $ request ->input ('level ' , 'all ' );
275-
276- try {
277- $ cutoffDate = now ()->subDays ($ days );
278-
279- $ query = LogModel::where ('created_at ' , '< ' , $ cutoffDate ->timestamp );
280- if ($ level !== 'all ' ) {
281- $ query ->where ('level ' , strtoupper ($ level ));
282- }
283-
284- $ stats = [
285- 'days ' => $ days ,
286- 'level ' => $ level ,
287- 'cutoff_date ' => $ cutoffDate ->format (format: 'Y-m-d H:i:s ' ),
288- 'total_logs ' => LogModel::count (),
289- 'logs_to_clear ' => $ query ->count (),
290- 'oldest_log ' => LogModel::orderBy ('created_at ' , 'asc ' )->first (),
291- 'newest_log ' => LogModel::orderBy ('created_at ' , 'desc ' )->first (),
292- ];
293-
294- return $ this ->success ($ stats );
295-
296- } catch (\Exception $ e ) {
297- return $ this ->fail (ResponseEnum::HTTP_ERROR , null , '获取统计信息失败: ' . $ e ->getMessage ());
298- }
299- }
300144}
0 commit comments