feat: 在管理后台针对superlevel级别用户新增全局金币流水查询页面
This commit is contained in:
70
app/Http/Controllers/Admin/CurrencyLogController.php
Normal file
70
app/Http/Controllers/Admin/CurrencyLogController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:用户金币/积分流水日志查询
|
||||
* 对应超级管理员级别的查询页面。可以按用户、增减、货币类型等筛选所有的账目流动。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Enums\CurrencySource;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\UserCurrencyLog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class CurrencyLogController extends Controller
|
||||
{
|
||||
/**
|
||||
* 显示流水日志列表
|
||||
* 支持多条件检索,仅 superlevel 以及上可以访问此页面
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$query = UserCurrencyLog::query()->with('user');
|
||||
|
||||
// 查询条件过滤
|
||||
if ($request->filled('username')) {
|
||||
$query->where('username', 'like', '%'.$request->input('username').'%');
|
||||
}
|
||||
|
||||
if ($request->filled('currency')) {
|
||||
$query->where('currency', $request->input('currency'));
|
||||
}
|
||||
|
||||
if ($request->filled('source')) {
|
||||
$query->where('source', $request->input('source'));
|
||||
}
|
||||
|
||||
if ($request->filled('remark')) {
|
||||
$query->where('remark', 'like', '%'.$request->input('remark').'%');
|
||||
}
|
||||
|
||||
if ($request->filled('direction')) {
|
||||
if ($request->input('direction') === 'in') {
|
||||
$query->where('amount', '>', 0);
|
||||
} elseif ($request->input('direction') === 'out') {
|
||||
$query->where('amount', '<', 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('date_start')) {
|
||||
$query->whereDate('created_at', '>=', $request->input('date_start'));
|
||||
}
|
||||
|
||||
if ($request->filled('date_end')) {
|
||||
$query->whereDate('created_at', '<=', $request->input('date_end'));
|
||||
}
|
||||
|
||||
// 默认按时间倒序
|
||||
$logs = $query->latest('id')->paginate(50)->withQueryString();
|
||||
|
||||
$allSources = CurrencySource::cases();
|
||||
|
||||
return view('admin.currency-logs.index', compact('logs', 'allSources'));
|
||||
}
|
||||
}
|
||||
181
resources/views/admin/currency-logs/index.blade.php
Normal file
181
resources/views/admin/currency-logs/index.blade.php
Normal file
@@ -0,0 +1,181 @@
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('title', '金币/积分流水查询')
|
||||
|
||||
@section('content')
|
||||
<!-- 筛选面板 -->
|
||||
<div class="bg-white p-6 rounded shadow mb-6">
|
||||
<form action="{{ route('admin.currency-logs.index') }}" method="GET" class="grid grid-cols-1 md:grid-cols-4 lg:grid-cols-5 gap-4 items-end">
|
||||
<!-- 用户名 -->
|
||||
<div>
|
||||
<label for="username" class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
|
||||
<input type="text" name="username" id="username" value="{{ request('username') }}"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||
placeholder="选填">
|
||||
</div>
|
||||
|
||||
<!-- 货币类型 -->
|
||||
<div>
|
||||
<label for="currency" class="block text-sm font-medium text-gray-700 mb-1">货币类型</label>
|
||||
<select name="currency" id="currency"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
|
||||
<option value="">全部类型</option>
|
||||
<option value="gold" {{ request('currency') == 'gold' ? 'selected' : '' }}>💰 金币</option>
|
||||
<option value="exp" {{ request('currency') == 'exp' ? 'selected' : '' }}>⭐ 经验</option>
|
||||
<option value="charm" {{ request('currency') == 'charm' ? 'selected' : '' }}>💖 魅力</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 变动方向 -->
|
||||
<div>
|
||||
<label for="direction" class="block text-sm font-medium text-gray-700 mb-1">变动方向</label>
|
||||
<select name="direction" id="direction"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
|
||||
<option value="">全部</option>
|
||||
<option value="in" {{ request('direction') == 'in' ? 'selected' : '' }}>➕ 增加</option>
|
||||
<option value="out" {{ request('direction') == 'out' ? 'selected' : '' }}>➖ 扣除</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 来源途径 -->
|
||||
<div>
|
||||
<label for="source" class="block text-sm font-medium text-gray-700 mb-1">来源途径</label>
|
||||
<select name="source" id="source"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
|
||||
<option value="">全部来源</option>
|
||||
@foreach ($allSources as $src)
|
||||
<option value="{{ $src->value }}" {{ request('source') == $src->value ? 'selected' : '' }}>
|
||||
{{ $src->label() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 备注关键词 -->
|
||||
<div>
|
||||
<label for="remark" class="block text-sm font-medium text-gray-700 mb-1">备注/房间流水</label>
|
||||
<input type="text" name="remark" id="remark" value="{{ request('remark') }}"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
||||
placeholder="包含(可搜房间名等)">
|
||||
</div>
|
||||
|
||||
<!-- 开始日期 -->
|
||||
<div>
|
||||
<label for="date_start" class="block text-sm font-medium text-gray-700 mb-1">开始日期</label>
|
||||
<input type="date" name="date_start" id="date_start" value="{{ request('date_start') }}"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
|
||||
</div>
|
||||
|
||||
<!-- 结束日期 -->
|
||||
<div>
|
||||
<label for="date_end" class="block text-sm font-medium text-gray-700 mb-1">结束日期</label>
|
||||
<input type="date" name="date_end" id="date_end" value="{{ request('date_end') }}"
|
||||
class="w-full border-gray-300 rounded shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm">
|
||||
</div>
|
||||
|
||||
<!-- 按钮组 -->
|
||||
<div class="md:col-span-2 lg:col-span-3 flex items-center space-x-3">
|
||||
<button type="submit"
|
||||
class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-6 rounded shadow transition">
|
||||
🔍 查询
|
||||
</button>
|
||||
<a href="{{ route('admin.currency-logs.index') }}"
|
||||
class="bg-gray-100 hover:bg-gray-200 text-gray-700 font-bold py-2 px-4 rounded shadow transition text-sm">
|
||||
重置
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="bg-white rounded shadow overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 text-gray-600 text-sm uppercase tracking-wider border-b border-gray-200">
|
||||
<th class="px-6 py-4 font-semibold">记录ID</th>
|
||||
<th class="px-6 py-4 font-semibold">用户</th>
|
||||
<th class="px-6 py-4 font-semibold">类型</th>
|
||||
<th class="px-6 py-4 font-semibold">变动数额</th>
|
||||
<th class="px-6 py-4 font-semibold">变后余额</th>
|
||||
<th class="px-6 py-4 font-semibold">来源</th>
|
||||
<th class="px-6 py-4 font-semibold w-1/4">备注信息</th>
|
||||
<th class="px-6 py-4 font-semibold text-right">发生时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@forelse ($logs as $log)
|
||||
<tr class="hover:bg-gray-50 transition cursor-default">
|
||||
<td class="px-6 py-4 text-sm text-gray-500">
|
||||
#{{ $log->id }}
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex flex-col">
|
||||
<span class="font-bold text-gray-800">{{ $log->username }}</span>
|
||||
<span class="text-xs text-gray-400">ID: {{ $log->user_id }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
@if($log->currency === 'gold')
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800">
|
||||
💰 金币
|
||||
</span>
|
||||
@elseif($log->currency === 'exp')
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800">
|
||||
⭐ 经验
|
||||
</span>
|
||||
@elseif($log->currency === 'charm')
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-pink-100 text-pink-800">
|
||||
💖 魅力
|
||||
</span>
|
||||
@else
|
||||
<span class="text-gray-500">{{ $log->currency }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 font-bold text-lg">
|
||||
@if ($log->amount > 0)
|
||||
<span class="text-emerald-500">+{{ $log->amount }}</span>
|
||||
@elseif ($log->amount === 0)
|
||||
<span class="text-gray-500">0</span>
|
||||
@else
|
||||
<span class="text-red-500">{{ $log->amount }}</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm font-medium text-gray-700">
|
||||
{{ $log->balance_after }}
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
@php
|
||||
$sourceLabel = \App\Enums\CurrencySource::tryFrom($log->source)?->label() ?? $log->source;
|
||||
@endphp
|
||||
<span class="bg-slate-100 text-slate-700 py-1 px-2 rounded font-medium text-xs whitespace-nowrap">
|
||||
{{ $sourceLabel }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-600">
|
||||
{{ $log->remark }}
|
||||
@if($log->room_id)
|
||||
<div class="mt-1 text-xs text-gray-400">房间ID: {{ $log->room_id }}</div>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500 text-right whitespace-nowrap">
|
||||
{{ $log->created_at->format('Y-m-d H:i:s') }}
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="px-6 py-8 text-center text-gray-500">
|
||||
📭 暂无相关流水记录
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@if ($logs->hasPages())
|
||||
<div class="px-6 py-4 border-t border-gray-200">
|
||||
{{ $logs->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
@@ -54,6 +54,10 @@
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.system.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '⚙️ 聊天室参数' !!}
|
||||
</a>
|
||||
<a href="{{ route('admin.currency-logs.index') }}"
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.currency-logs.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '💴 全局金币流水' !!}
|
||||
</a>
|
||||
<a href="{{ route('admin.rooms.index') }}"
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.rooms.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '🏠 房间管理' !!}
|
||||
|
||||
@@ -407,6 +407,9 @@ Route::middleware(['chat.auth', 'chat.has_position'])->prefix('admin')->name('ad
|
||||
Route::put('/vip/{vip}', [\App\Http\Controllers\Admin\VipController::class, 'update'])->name('vip.update');
|
||||
Route::delete('/vip/{vip}', [\App\Http\Controllers\Admin\VipController::class, 'destroy'])->name('vip.destroy');
|
||||
|
||||
// 全局用户金币/积分流水
|
||||
Route::get('/currency-logs', [\App\Http\Controllers\Admin\CurrencyLogController::class, 'index'])->name('currency-logs.index');
|
||||
|
||||
// 🛒 商店商品管理(查看/编辑所有 superlevel 可用,新增/删除仅 id=1)
|
||||
Route::get('/shop', [\App\Http\Controllers\Admin\ShopItemController::class, 'index'])->name('shop.index');
|
||||
Route::post('/shop', [\App\Http\Controllers\Admin\ShopItemController::class, 'store'])->name('shop.store');
|
||||
|
||||
Reference in New Issue
Block a user