erp-backend/app/Http/Controllers/OperationLogController.php
2026-04-01 17:07:04 +08:00

368 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers;
use App\Models\OperationLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class OperationLogController extends Controller
{
/**
* 操作日志列表
*/
public function index(Request $request)
{
$query = OperationLog::with('user')->orderBy('created_at', 'desc');
// 筛选条件
if ($request->filled('user_id')) {
$query->where('user_id', $request->user_id);
}
if ($request->filled('user_name')) {
$query->where('user_name', 'like', "%{$request->user_name}%");
}
if ($request->filled('module')) {
$query->where('module', $request->module);
}
if ($request->filled('action')) {
$query->where('action', $request->action);
}
if ($request->filled('method')) {
$query->where('method', $request->method);
}
if ($request->filled('path')) {
$query->where('path', 'like', "%{$request->path}%");
}
if ($request->filled('ip')) {
$query->where('ip', 'like', "%{$request->ip}%");
}
if ($request->filled('response_code')) {
if ($request->response_code === 'success') {
$query->where('response_code', '<', 400);
} elseif ($request->response_code === 'error') {
$query->where('response_code', '>=', 400);
} else {
$query->where('response_code', $request->response_code);
}
}
if ($request->filled('keyword')) {
$keyword = $request->keyword;
$query->where(function ($q) use ($keyword) {
$q->where('user_name', 'like', "%{$keyword}%")
->orWhere('module', 'like', "%{$keyword}%")
->orWhere('action', 'like', "%{$keyword}%")
->orWhere('path', 'like', "%{$keyword}%")
->orWhere('ip', 'like', "%{$keyword}%")
->orWhere('remark', 'like', "%{$keyword}%");
});
}
if ($request->filled('date_range')) {
$dates = explode(',', $request->date_range);
if (count($dates) === 2) {
$query->whereBetween('created_at', [$dates[0], $dates[1]]);
}
}
$perPage = $request->input('limit', 20);
$logs = $query->paginate($perPage);
return response()->json([
'code' => 200,
'data' => [
'list' => $logs->items(),
'total' => $logs->total(),
'current_page' => $logs->currentPage(),
'last_page' => $logs->lastPage(),
],
'message' => 'success'
]);
}
/**
* 操作日志详情
*/
public function show(string $id)
{
$log = OperationLog::with('user')->find($id);
if (!$log) {
return response()->json([
'code' => 404,
'message' => '日志不存在'
], 404);
}
return response()->json([
'code' => 200,
'data' => $log,
'message' => 'success'
]);
}
/**
* 删除操作日志
*/
public function destroy(string $id)
{
$log = OperationLog::find($id);
if (!$log) {
return response()->json([
'code' => 404,
'message' => '日志不存在'
], 404);
}
try {
$log->delete();
return response()->json([
'code' => 200,
'message' => '操作日志删除成功'
]);
} catch (\Exception $e) {
return response()->json([
'code' => 500,
'message' => '删除失败: ' . $e->getMessage()
], 500);
}
}
/**
* 批量删除操作日志
*/
public function batchDelete(Request $request)
{
$request->validate([
'log_ids' => 'required|array|min:1',
'log_ids.*' => 'integer|exists:operation_logs,id',
]);
$successCount = 0;
$failedLogs = [];
try {
foreach ($request->log_ids as $logId) {
$log = OperationLog::find($logId);
if (!$log) {
$failedLogs[] = ['id' => $logId, 'reason' => '日志不存在'];
continue;
}
$log->delete();
$successCount++;
}
return response()->json([
'code' => 200,
'data' => [
'success_count' => $successCount,
'failed_logs' => $failedLogs,
],
'message' => "批量删除成功,成功 {$successCount}"
]);
} catch (\Exception $e) {
return response()->json([
'code' => 500,
'message' => '批量删除失败: ' . $e->getMessage()
], 500);
}
}
/**
* 清空操作日志
*/
public function clear(Request $request)
{
$request->validate([
'days' => 'nullable|integer|min:1|max:365',
]);
try {
$query = OperationLog::query();
if ($request->filled('days')) {
$date = now()->subDays($request->days);
$query->where('created_at', '<', $date);
}
$deletedCount = $query->delete();
return response()->json([
'code' => 200,
'data' => ['deleted_count' => $deletedCount],
'message' => "成功清空 {$deletedCount} 条操作日志"
]);
} catch (\Exception $e) {
return response()->json([
'code' => 500,
'message' => '清空失败: ' . $e->getMessage()
], 500);
}
}
/**
* 获取操作统计
*/
public function statistics(Request $request)
{
$request->validate([
'start_date' => 'nullable|date',
'end_date' => 'nullable|date',
'group_by' => 'nullable|string|in:day,week,month',
]);
$startDate = $request->start_date ?: now()->subDays(30)->toDateString();
$endDate = $request->end_date ?: now()->toDateString();
$groupBy = $request->group_by ?: 'day';
// 总体统计
$overallStats = OperationLog::getStatistics($startDate, $endDate);
// 时间趋势统计
$trendQuery = OperationLog::whereBetween('created_at', [$startDate, $endDate]);
switch ($groupBy) {
case 'day':
$trendQuery->selectRaw('DATE(created_at) as date, COUNT(*) as count')
->groupBy(DB::raw('DATE(created_at)'))
->orderBy('date', 'asc');
break;
case 'week':
$trendQuery->selectRaw('YEARWEEK(created_at, 1) as week, COUNT(*) as count')
->groupBy(DB::raw('YEARWEEK(created_at, 1)'))
->orderBy('week', 'asc');
break;
case 'month':
$trendQuery->selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, COUNT(*) as count')
->groupBy(DB::raw('DATE_FORMAT(created_at, "%Y-%m")'))
->orderBy('month', 'asc');
break;
}
$trendStats = $trendQuery->get();
// 模块统计详情
$moduleStats = OperationLog::whereBetween('created_at', [$startDate, $endDate])
->selectRaw('module, COUNT(*) as total,
SUM(CASE WHEN response_code < 400 THEN 1 ELSE 0 END) as success,
SUM(CASE WHEN response_code >= 400 THEN 1 ELSE 0 END) as error')
->groupBy('module')
->orderBy('total', 'desc')
->get();
// 用户操作统计
$userStats = OperationLog::whereBetween('created_at', [$startDate, $endDate])
->selectRaw('user_id, user_name, COUNT(*) as total')
->groupBy('user_id', 'user_name')
->orderBy('total', 'desc')
->limit(20)
->get();
// 响应时间统计
$responseTimeStats = OperationLog::whereBetween('created_at', [$startDate, $endDate])
->selectRaw('AVG(execution_time) as avg_time,
MIN(execution_time) as min_time,
MAX(execution_time) as max_time')
->first();
return response()->json([
'code' => 200,
'data' => [
'overall' => $overallStats,
'trend' => $trendStats,
'modules' => $moduleStats,
'users' => $userStats,
'response_time' => $responseTimeStats,
'date_range' => [
'start_date' => $startDate,
'end_date' => $endDate,
],
],
'message' => 'success'
]);
}
/**
* 获取模块列表
*/
public function getModules()
{
$modules = OperationLog::select('module')
->distinct()
->orderBy('module', 'asc')
->pluck('module');
return response()->json([
'code' => 200,
'data' => $modules,
'message' => 'success'
]);
}
/**
* 获取操作类型列表
*/
public function getActions()
{
$actions = OperationLog::select('action')
->distinct()
->orderBy('action', 'asc')
->pluck('action');
return response()->json([
'code' => 200,
'data' => $actions,
'message' => 'success'
]);
}
/**
* 导出操作日志
*/
public function export(Request $request)
{
$request->validate([
'format' => 'required|string|in:csv,excel',
'columns' => 'nullable|array',
'start_date' => 'nullable|date',
'end_date' => 'nullable|date',
]);
$query = OperationLog::with('user')->orderBy('created_at', 'desc');
if ($request->filled('start_date')) {
$query->where('created_at', '>=', $request->start_date);
}
if ($request->filled('end_date')) {
$query->where('created_at', '<=', $request->end_date);
}
$logs = $query->get();
// TODO: 实现导出功能
// 这里返回导出信息实际导出需要前端处理或使用Laravel Excel
return response()->json([
'code' => 200,
'data' => [
'total' => $logs->count(),
'format' => $request->format,
'download_url' => null, // 实际项目中这里应该是导出文件的URL
],
'message' => '导出请求已接收'
]);
}
}