diff --git a/app/Http/Controllers/V1/User/StatController.php b/app/Http/Controllers/V1/User/StatController.php index 41c2a77..11bb9c0 100644 --- a/app/Http/Controllers/V1/User/StatController.php +++ b/app/Http/Controllers/V1/User/StatController.php @@ -14,29 +14,13 @@ class StatController extends Controller public function getTrafficLog(Request $request) { $startDate = now()->startOfMonth()->timestamp; - - // Aggregate per-node data into per-day entries for backward compatibility $records = StatUser::query() - ->select([ - 'user_id', - 'server_rate', - 'record_at', - 'record_type', - DB::raw('SUM(u) as u'), - DB::raw('SUM(d) as d'), - ]) ->where('user_id', $request->user()->id) ->where('record_at', '>=', $startDate) - ->groupBy(['user_id', 'server_rate', 'record_at', 'record_type']) ->orderBy('record_at', 'DESC') - ->get() - ->map(function ($item) { - $item->u = (int) $item->u; - $item->d = (int) $item->d; - return $item; - }); + ->get(); - $data = TrafficLogResource::collection($records); + $data = TrafficLogResource::collection(collect($records)); return $this->success($data); } } diff --git a/app/Http/Controllers/V2/Admin/StatController.php b/app/Http/Controllers/V2/Admin/StatController.php index 71d4b9c..805fa94 100644 --- a/app/Http/Controllers/V2/Admin/StatController.php +++ b/app/Http/Controllers/V2/Admin/StatController.php @@ -13,7 +13,6 @@ use App\Models\Ticket; use App\Models\User; use App\Services\StatisticalService; use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; class StatController extends Controller { @@ -235,38 +234,14 @@ class StatController extends Controller ]); $pageSize = $request->input('pageSize', 10); - $page = $request->input('page', 1); - - // Aggregate per-node data into per-day entries for backward compatibility - $query = StatUser::query() - ->select([ - 'user_id', - 'server_rate', - 'record_at', - 'record_type', - DB::raw('SUM(u) as u'), - DB::raw('SUM(d) as d'), - DB::raw('MAX(created_at) as created_at'), - DB::raw('MAX(updated_at) as updated_at'), - ]) + $records = StatUser::orderBy('record_at', 'DESC') ->where('user_id', $request->input('user_id')) - ->groupBy(['user_id', 'server_rate', 'record_at', 'record_type']) - ->orderBy('record_at', 'DESC'); - - // Manual pagination for grouped query - $total = (clone $query)->get()->count(); - $data = $query->skip(($page - 1) * $pageSize)->take($pageSize)->get() - ->map(function ($item) { - $item->u = (int) $item->u; - $item->d = (int) $item->d; - $item->created_at = (int) $item->created_at; - $item->updated_at = (int) $item->updated_at; - return $item; - }); + ->paginate($pageSize); + $data = $records->items(); return [ 'data' => $data, - 'total' => $total, + 'total' => $records->total(), ]; } diff --git a/app/Jobs/StatUserJob.php b/app/Jobs/StatUserJob.php index 3bfb979..620443c 100644 --- a/app/Jobs/StatUserJob.php +++ b/app/Jobs/StatUserJob.php @@ -78,7 +78,6 @@ class StatUserJob implements ShouldQueue DB::transaction(function () use ($uid, $v, $recordAt) { $existingRecord = StatUser::where([ 'user_id' => $uid, - 'server_id' => $this->server['id'], 'server_rate' => $this->server['rate'], 'record_at' => $recordAt, 'record_type' => $this->recordType, @@ -93,7 +92,6 @@ class StatUserJob implements ShouldQueue } else { StatUser::create([ 'user_id' => $uid, - 'server_id' => $this->server['id'], 'server_rate' => $this->server['rate'], 'record_at' => $recordAt, 'record_type' => $this->recordType, @@ -111,7 +109,6 @@ class StatUserJob implements ShouldQueue StatUser::upsert( [ 'user_id' => $uid, - 'server_id' => $this->server['id'], 'server_rate' => $this->server['rate'], 'record_at' => $recordAt, 'record_type' => $this->recordType, @@ -120,7 +117,7 @@ class StatUserJob implements ShouldQueue 'created_at' => time(), 'updated_at' => time(), ], - ['user_id', 'server_id', 'server_rate', 'record_at', 'record_type'], + ['user_id', 'server_rate', 'record_at', 'record_type'], [ 'u' => DB::raw("u + VALUES(u)"), 'd' => DB::raw("d + VALUES(d)"), @@ -139,9 +136,9 @@ class StatUserJob implements ShouldQueue $u = intval($v[0] * $this->server['rate']); $d = intval($v[1] * $this->server['rate']); - $sql = "INSERT INTO {$table} (user_id, server_id, server_rate, record_at, record_type, u, d, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - ON CONFLICT (user_id, server_id, server_rate, record_at) + $sql = "INSERT INTO {$table} (user_id, server_rate, record_at, record_type, u, d, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (user_id, server_rate, record_at) DO UPDATE SET u = {$table}.u + EXCLUDED.u, d = {$table}.d + EXCLUDED.d, @@ -149,7 +146,6 @@ class StatUserJob implements ShouldQueue DB::statement($sql, [ $uid, - $this->server['id'], $this->server['rate'], $recordAt, $this->recordType, diff --git a/app/Models/StatUser.php b/app/Models/StatUser.php index 18f085d..a956bd7 100644 --- a/app/Models/StatUser.php +++ b/app/Models/StatUser.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Model; * * @property int $id * @property int $user_id 用户ID - * @property int|null $server_id 节点ID (nullable for legacy data) * @property int $u 上行流量 * @property int $d 下行流量 * @property int $record_at 记录时间 @@ -26,12 +25,4 @@ class StatUser extends Model 'created_at' => 'timestamp', 'updated_at' => 'timestamp' ]; - - /** - * Get the server that this traffic stat belongs to - */ - public function server() - { - return $this->belongsTo(Server::class, 'server_id'); - } } diff --git a/database/migrations/2025_11_29_000000_add_server_id_to_stat_user.php b/database/migrations/2025_11_29_000000_add_server_id_to_stat_user.php deleted file mode 100644 index 543c555..0000000 --- a/database/migrations/2025_11_29_000000_add_server_id_to_stat_user.php +++ /dev/null @@ -1,37 +0,0 @@ -integer('server_id')->nullable()->after('user_id')->comment('节点ID (nullable for legacy data)'); - - // Add index for per-node queries - if (config('database.default') !== 'sqlite') { - $table->index(['user_id', 'server_id', 'record_at'], 'user_server_record_idx'); - } - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::table('v2_stat_user', function (Blueprint $table) { - if (config('database.default') !== 'sqlite') { - $table->dropIndex('user_server_record_idx'); - } - $table->dropColumn('server_id'); - }); - } -}; diff --git a/database/migrations/2025_11_29_120000_update_stat_user_unique_constraint.php b/database/migrations/2025_11_29_120000_update_stat_user_unique_constraint.php deleted file mode 100644 index 6ae1b83..0000000 --- a/database/migrations/2025_11_29_120000_update_stat_user_unique_constraint.php +++ /dev/null @@ -1,55 +0,0 @@ -dropUnique('server_rate_user_id_record_at'); - - // Add new unique constraint including server_id - // Note: NULL server_id values (legacy) are treated as distinct in MySQL - $table->unique( - ['user_id', 'server_id', 'server_rate', 'record_at', 'record_type'], - 'stat_user_unique_idx' - ); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - if (config('database.default') === 'sqlite') { - return; - } - - Schema::table('v2_stat_user', function (Blueprint $table) { - // Drop new constraint - $table->dropUnique('stat_user_unique_idx'); - - // Restore original constraint - $table->unique( - ['server_rate', 'user_id', 'record_at'], - 'server_rate_user_id_record_at' - ); - }); - } -};