统一后台列表页样式并调整站长菜单

This commit is contained in:
2026-04-26 18:10:37 +08:00
parent 61cfc2091c
commit 00270b3904
36 changed files with 2590 additions and 2345 deletions
@@ -16,6 +16,7 @@
@section('title', 'AI 厂商配置')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div x-data="{
showForm: false,
editId: null,
@@ -68,12 +69,12 @@
}">
{{-- 全局开关 + 高级设置 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden mb-6">
<div class="{{ $adminListCardClass }} mb-6">
<div class="p-6">
<!-- 顶部栏:开关和添加按钮 -->
<div class="flex items-center justify-between border-b border-gray-100 pb-4 mb-4">
<div class="flex items-center gap-4">
<h2 class="text-lg font-bold text-gray-800">🤖 AI 聊天机器人配置</h2>
<h2 class="{{ $adminListHeaderTitleClass }}">🤖 AI 聊天机器人配置</h2>
<div class="flex items-center gap-2">
<span class="text-sm text-gray-500">大厅状态:</span>
<button id="chatbot-toggle-btn" data-ai-chatbot-toggle-url="{{ route('admin.ai-providers.toggle-chatbot') }}"
@@ -87,8 +88,7 @@
</span>
</div>
</div>
<button x-on:click="openNew()"
class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition font-bold text-sm">
<button x-on:click="openNew()" class="{{ $adminListPrimaryButtonClass }}">
+ 添加 AI 厂商
</button>
</div>
@@ -145,26 +145,26 @@
</div>
{{-- 厂商列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600">
<div class="{{ $adminListCardClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-6 py-3 text-left font-bold">厂商</th>
<th class="px-6 py-3 text-left font-bold">模型</th>
<th class="px-6 py-3 text-left font-bold">API 端点</th>
<th class="px-6 py-3 text-center font-bold">参数</th>
<th class="px-6 py-3 text-center font-bold">排序</th>
<th class="px-6 py-3 text-center font-bold">状态</th>
<th class="px-6 py-3 text-center font-bold">默认</th>
<th class="px-6 py-3 text-center font-bold">操作</th>
<th class="{{ $adminListTableHeadCellClass }}">厂商</th>
<th class="{{ $adminListTableHeadCellClass }}">模型</th>
<th class="{{ $adminListTableHeadCellClass }}">API 端点</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">参数</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">排序</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">默认</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($providers as $provider)
<tr class="hover:bg-gray-50 transition {{ !$provider->is_enabled ? 'opacity-50' : '' }}">
<tr class="{{ $adminListTableRowClass }} {{ !$provider->is_enabled ? 'opacity-50' : '' }}">
<td class="px-6 py-4">
<div class="font-bold text-gray-800">{{ $provider->name }}</div>
<div class="text-xs text-gray-400">{{ $provider->provider }}</div>
<div class="{{ $adminListPrimaryTextClass }}">{{ $provider->name }}</div>
<div class="{{ $adminListSecondaryTextClass }}">{{ $provider->provider }}</div>
</td>
<td class="px-6 py-4">
<code class="bg-gray-100 px-2 py-1 rounded text-xs">{{ $provider->model }}</code>
@@ -202,22 +202,22 @@
<div class="flex items-center justify-center gap-2">
<button data-ai-provider-test-url="{{ route('admin.ai-providers.test', $provider->id) }}"
data-ai-provider-name="{{ $provider->name }}"
class="text-teal-600 hover:text-teal-800 text-xs font-bold"> 测试</button>
class="{{ $adminListActionButtonClass }} text-teal-600 hover:text-teal-800 hover:bg-teal-50"> 测试</button>
<button x-on:click="openEdit({{ $provider->toJson() }})"
class="text-indigo-600 hover:text-indigo-800 text-xs font-bold">编辑</button>
class="{{ $adminListActionButtonClass }} text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50">编辑</button>
<form action="{{ route('admin.ai-providers.destroy', $provider->id) }}" method="POST"
data-admin-confirm="确定要删除 {{ $provider->name }} 吗?">
@csrf
@method('DELETE')
<button type="submit"
class="text-red-500 hover:text-red-700 text-xs font-bold">删除</button>
class="{{ $adminListActionButtonClass }} text-red-500 hover:text-red-700 hover:bg-red-50">删除</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="px-6 py-12 text-center text-gray-400">
<td colspan="8" class="{{ $adminListEmptyClass }}">
暂无 AI 厂商配置,请点击上方"添加 AI 厂商"按钮。
</td>
</tr>
@@ -11,13 +11,18 @@
@section('title', '权限操作日志 · ' . $userPosition->user->username)
@section('content')
<div class="mb-6">
<a href="{{ route('admin.appointments.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回任命管理</a>
<h2 class="text-lg font-bold text-gray-800 mt-2">
{{ $userPosition->position->icon }} {{ $userPosition->user->username }} · {{ $userPosition->position->name }}
</h2>
<p class="text-sm text-gray-500 mt-1">权限操作记录(共 {{ $logs->total() }} 条)</p>
</div>
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div>
<a href="{{ route('admin.appointments.index') }}" class="text-sm font-semibold text-indigo-600 hover:text-indigo-700"> 返回任命管理</a>
<h2 class="mt-2 {{ $adminListHeaderTitleClass }}">
{{ $userPosition->position->icon }} {{ $userPosition->user->username }} · {{ $userPosition->position->name }}
</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">权限操作记录(共 {{ $logs->total() }} 条)</p>
</div>
</div>
@php
$actionColors = [
@@ -32,42 +37,51 @@
];
@endphp
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<tr>
<th class="px-4 py-3 text-left">操作时间</th>
<th class="px-4 py-3 text-center">操作类型</th>
<th class="px-4 py-3 text-left">操作对象</th>
<th class="px-4 py-3 text-left">目标职务</th>
<th class="px-4 py-3 text-center">奖励金额</th>
<th class="px-4 py-3 text-left">备注</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($logs as $log)
@php $colorClass = $actionColors[$log->action_type] ?? 'bg-gray-100 text-gray-600'; @endphp
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-gray-500 text-xs">{{ $log->created_at->format('m-d H:i:s') }}</td>
<td class="px-4 py-3 text-center">
<span class="text-xs px-2 py-0.5 rounded font-bold {{ $colorClass }}">
{{ $log->action_label }}
</span>
</td>
<td class="px-4 py-3 font-bold text-gray-700">{{ $log->targetUser->username ?? '—' }}</td>
<td class="px-4 py-3 text-gray-500">{{ $log->targetPosition?->name ?? '—' }}</td>
<td class="px-4 py-3 text-center text-yellow-600 font-bold">
{{ $log->amount ? number_format($log->amount) . ' 金币' : '—' }}
</td>
<td class="px-4 py-3 text-gray-400 text-xs">{{ $log->remark ?? '—' }}</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-12 text-center text-gray-400">暂无权限操作记录</td>
</tr>
@endforelse
</tbody>
</table>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">权限操作日志</h3>
<p class="{{ $adminListSectionDescClass }}">覆盖任命周期内的任命、撤销、奖励、警告、踢出、禁言等权限动作。</p>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">操作时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作类型</th>
<th class="{{ $adminListTableHeadCellClass }}">操作对象</th>
<th class="{{ $adminListTableHeadCellClass }}">目标职务</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">奖励金额</th>
<th class="{{ $adminListTableHeadCellClass }}">备注</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
@php $colorClass = $actionColors[$log->action_type] ?? 'bg-gray-100 text-gray-600'; @endphp
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $log->created_at->format('m-d H:i:s') }}</td>
<td class="px-4 py-3 text-center">
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-semibold {{ $colorClass }}">
{{ $log->action_label }}
</span>
</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $log->targetUser->username ?? '—' }}</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $log->targetPosition?->name ?? '—' }}</td>
<td class="px-4 py-3 text-center text-sm font-semibold text-yellow-600">
{{ $log->amount ? number_format($log->amount) . ' 金币' : '—' }}
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $log->remark ?? '—' }}</td>
</tr>
@empty
<tr>
<td colspan="6" class="{{ $adminListEmptyClass }}">暂无权限操作记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $logs->links() }}</div>
@endif
</div>
</div>
<div class="mt-4">{{ $logs->links() }}</div>
@endsection
@@ -11,70 +11,81 @@
@section('title', '在职登录日志 · ' . $userPosition->user->username)
@section('content')
<div class="mb-6">
<a href="{{ route('admin.appointments.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回任命管理</a>
<h2 class="text-lg font-bold text-gray-800 mt-2">
{{ $userPosition->position->icon }} {{ $userPosition->user->username }} · {{ $userPosition->position->name }}
</h2>
<p class="text-sm text-gray-500 mt-1">
任命于 {{ $userPosition->appointed_at->format('Y-m-d') }}
任命人:{{ $userPosition->appointedBy?->username ?? '系统' }}
</p>
</div>
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div>
<a href="{{ route('admin.appointments.index') }}" class="text-sm font-semibold text-indigo-600 hover:text-indigo-700"> 返回任命管理</a>
<h2 class="mt-2 {{ $adminListHeaderTitleClass }}">
{{ $userPosition->position->icon }} {{ $userPosition->user->username }} · {{ $userPosition->position->name }}
</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
任命于 {{ $userPosition->appointed_at->format('Y-m-d') }},任命人:{{ $userPosition->appointedBy?->username ?? '系统' }}
</p>
</div>
</div>
{{-- 统计摘要 --}}
<div class="grid grid-cols-3 gap-4 mb-6">
<div class="bg-white rounded-xl p-5 border shadow-sm text-center">
<div class="grid gap-4 md:grid-cols-3">
<div class="{{ $adminListCardClass }} p-5 text-center">
<div class="text-2xl font-bold text-indigo-600">{{ $logs->total() }}</div>
<div class="text-xs text-gray-500 mt-1">总登录次数</div>
</div>
<div class="bg-white rounded-xl p-5 border shadow-sm text-center">
<div class="{{ $adminListCardClass }} p-5 text-center">
<div class="text-2xl font-bold text-green-600">
{{ intdiv($totalSeconds, 3600) }}h {{ intdiv($totalSeconds % 3600, 60) }}m
</div>
<div class="text-xs text-gray-500 mt-1">累计在线时长(所有)</div>
</div>
<div class="bg-white rounded-xl p-5 border shadow-sm text-center">
<div class="{{ $adminListCardClass }} p-5 text-center">
<div class="text-2xl font-bold text-orange-600">{{ $userPosition->total_rewarded_coins }}</div>
<div class="text-xs text-gray-500 mt-1">在职期间发放金币</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<tr>
<th class="px-4 py-3 text-left">登录时间</th>
<th class="px-4 py-3 text-left">退出时间</th>
<th class="px-4 py-3 text-center">在线时长</th>
<th class="px-4 py-3 text-center">房间</th>
<th class="px-4 py-3 text-left">IP 地址</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($logs as $log)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-gray-700">{{ $log->login_at->format('m-d H:i:s') }}</td>
<td class="px-4 py-3 text-gray-500">{{ $log->logout_at?->format('m-d H:i:s') ?? '在线中...' }}</td>
<td class="px-4 py-3 text-center">
@if ($log->duration_seconds)
<span
class="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">{{ $log->formatted_duration }}</span>
@else
<span class="text-xs text-gray-400"></span>
@endif
</td>
<td class="px-4 py-3 text-center text-gray-500">{{ $log->room_id ? "房间#{$log->room_id}" : '—' }}
</td>
<td class="px-4 py-3 text-gray-400 font-mono text-xs">{{ $log->ip_address }}</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-4 py-12 text-center text-gray-400">暂无登录记录</td>
</tr>
@endforelse
</tbody>
</table>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">在职登录记录</h3>
<p class="{{ $adminListSectionDescClass }}">记录该任职周期内的登录、退出、在线时长与所在房间信息。</p>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">登录时间</th>
<th class="{{ $adminListTableHeadCellClass }}">退出时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">在线时长</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">房间</th>
<th class="{{ $adminListTableHeadCellClass }}">IP 地址</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $log->login_at->format('m-d H:i:s') }}</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $log->logout_at?->format('m-d H:i:s') ?? '在线中...' }}</td>
<td class="px-4 py-3 text-center">
@if ($log->duration_seconds)
<span class="inline-flex items-center rounded-full bg-blue-100 px-2 py-0.5 text-xs font-semibold text-blue-700">{{ $log->formatted_duration }}</span>
@else
<span class="{{ $adminListSecondaryTextClass }}"></span>
@endif
</td>
<td class="px-4 py-3 text-center {{ $adminListBodyTextClass }}">{{ $log->room_id ? "房间#{$log->room_id}" : '—' }}</td>
<td class="px-4 py-3 {{ $adminListNumericTextClass }} text-gray-400">{{ $log->ip_address }}</td>
</tr>
@empty
<tr>
<td colspan="5" class="{{ $adminListEmptyClass }}">暂无登录记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $logs->links() }}</div>
@endif
</div>
</div>
<div class="mt-4">{{ $logs->links() }}</div>
@endsection
@@ -11,52 +11,67 @@
@section('title', '历史任职记录')
@section('content')
<div class="mb-6">
<a href="{{ route('admin.appointments.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回任命管理</a>
<h2 class="text-lg font-bold text-gray-800 mt-2">历史任职记录</h2>
<p class="text-sm text-gray-500 mt-1">已撤销的职务记录(共 {{ $history->total() }} 条)</p>
</div>
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<tr>
<th class="px-4 py-3 text-left">用户</th>
<th class="px-4 py-3 text-left">职务</th>
<th class="px-4 py-3 text-left">任命人</th>
<th class="px-4 py-3 text-center">任命时间</th>
<th class="px-4 py-3 text-left">撤销人</th>
<th class="px-4 py-3 text-center">撤销时间</th>
<th class="px-4 py-3 text-center">在职天数</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($history as $up)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 font-bold text-gray-800">{{ $up->user->username }}</td>
<td class="px-4 py-3">
<span class="mr-1">{{ $up->position->icon }}</span>
<span style="color: {{ $up->position->department->color }}">{{ $up->position->name }}</span>
<span class="text-xs text-gray-400 ml-1">{{ $up->position->department->name }}</span>
</td>
<td class="px-4 py-3 text-gray-500">{{ $up->appointedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center text-gray-500 text-xs">{{ $up->appointed_at->format('Y-m-d') }}
</td>
<td class="px-4 py-3 text-gray-500">{{ $up->revokedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center text-gray-500 text-xs">
{{ $up->revoked_at?->format('Y-m-d') ?? '—' }}</td>
<td class="px-4 py-3 text-center">
<span class="text-xs bg-gray-100 text-gray-600 px-2 py-0.5 rounded">{{ $up->duration_days }}
</span>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-12 text-center text-gray-400">暂无历史记录</td>
</tr>
@endforelse
</tbody>
</table>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div>
<a href="{{ route('admin.appointments.index') }}" class="text-sm font-semibold text-indigo-600 hover:text-indigo-700"> 返回任命管理</a>
<h2 class="mt-2 {{ $adminListHeaderTitleClass }}">历史任职记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">已撤销的职务记录(共 {{ $history->total() }} 条)</p>
</div>
</div>
</div>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">任职历史列表</h3>
<p class="{{ $adminListSectionDescClass }}">按撤销后的记录保留完整的任命与撤销链路,便于审计追踪。</p>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">用户</th>
<th class="{{ $adminListTableHeadCellClass }}">职务</th>
<th class="{{ $adminListTableHeadCellClass }}">任命人</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">任命时间</th>
<th class="{{ $adminListTableHeadCellClass }}">撤销人</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">撤销时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">在职天数</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($history as $up)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $up->user->username }}</td>
<td class="px-4 py-3">
<div class="flex items-center gap-1">
<span>{{ $up->position->icon }}</span>
<span class="text-sm font-semibold" style="color: {{ $up->position->department->color }}">{{ $up->position->name }}</span>
<span class="{{ $adminListSecondaryTextClass }}">{{ $up->position->department->name }}</span>
</div>
</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $up->appointedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center {{ $adminListSecondaryTextClass }}">{{ $up->appointed_at->format('Y-m-d') }}</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $up->revokedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center {{ $adminListSecondaryTextClass }}">{{ $up->revoked_at?->format('Y-m-d') ?? '—' }}</td>
<td class="px-4 py-3 text-center">
<span class="inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-semibold text-gray-600">{{ $up->duration_days }} </span>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无历史记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($history->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $history->links() }}</div>
@endif
</div>
</div>
<div class="mt-4">{{ $history->links() }}</div>
@endsection
@@ -12,6 +12,8 @@
@section('title', '任命管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div x-data="{
showForm: false,
username: '',
@@ -52,79 +54,86 @@
}
}">
<div class="{{ $adminListPageClass }}">
{{-- 头部 --}}
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-lg font-bold text-gray-800">任命管理</h2>
<p class="text-sm text-gray-500">管理当前所有在职职位人员,执行任命或撤销操作</p>
</div>
<div class="flex space-x-2">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">任命管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">管理当前所有在职职位人员,执行任命或撤销操作</p>
</div>
<div class="flex flex-wrap items-center gap-2">
<a href="{{ route('admin.appointments.history') }}"
style="background-color:#e5e7eb;color:#374151;padding:0.5rem 1rem;border-radius:0.5rem;font-weight:700;font-size:0.875rem;display:inline-flex;align-items:center;text-decoration:none;"
onmouseover="this.style.backgroundColor='#d1d5db'" onmouseout="this.style.backgroundColor='#e5e7eb'">
class="{{ $adminListSecondaryButtonClass }} inline-flex items-center justify-center">
历史记录
</a>
<button @click="openAppoint()"
style="background-color:#f97316;color:#fff;padding:0.5rem 1.25rem;border-radius:0.5rem;font-weight:700;border:none;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.1);"
onmouseover="this.style.backgroundColor='#ea580c'" onmouseout="this.style.backgroundColor='#f97316'">
class="inline-flex items-center justify-center rounded-lg bg-orange-500 px-4 py-2 text-sm font-semibold text-white shadow-sm transition hover:bg-orange-600">
+ 新增任命
</button>
</div>
</div>
</div>
{{-- 在职人员列表 --}}
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<tr>
<th class="px-4 py-3 text-left">用户</th>
<th class="px-4 py-3 text-left">部门·职务</th>
<th class="px-4 py-3 text-center">等级</th>
<th class="px-4 py-3 text-left">任命人</th>
<th class="px-4 py-3 text-center">任命时间</th>
<th class="px-4 py-3 text-center">在职天数</th>
<th class="px-4 py-3 text-right">操作</th>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">在职人员列表</h3>
<p class="{{ $adminListSectionDescClass }}">展示当前所有已任命且仍在职的人员,可直接查看履职日志或执行撤销。</p>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">用户</th>
<th class="{{ $adminListTableHeadCellClass }}">部门·职务</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">等级</th>
<th class="{{ $adminListTableHeadCellClass }}">任命人</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">任命时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">在职天数</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($activePositions as $up)
<tr class="hover:bg-gray-50 transition">
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3">
<div class="font-bold text-gray-800">{{ $up->user->username }}</div>
<div class="text-xs text-gray-400">Lv.{{ $up->user->user_level }}</div>
<div class="{{ $adminListPrimaryTextClass }}">{{ $up->user->username }}</div>
<div class="{{ $adminListSecondaryTextClass }}">Lv.{{ $up->user->user_level }}</div>
</td>
<td class="px-4 py-3">
<div class="flex items-center space-x-1">
<span class="text-lg">{{ $up->position->icon }}</span>
<div>
<div class="text-xs text-gray-400">{{ $up->position->department->name }}</div>
<div class="font-bold" style="color: {{ $up->position->department->color }}">
<div class="{{ $adminListSecondaryTextClass }}">{{ $up->position->department->name }}</div>
<div class="text-sm font-semibold" style="color: {{ $up->position->department->color }}">
{{ $up->position->name }}
</div>
</div>
</div>
</td>
<td class="px-4 py-3 text-center">
<span class="text-xs bg-orange-100 text-orange-700 px-2 py-0.5 rounded font-mono">
<span class="inline-flex items-center rounded-full bg-orange-100 px-2 py-0.5 text-xs font-mono font-semibold text-orange-700">
Lv.{{ $up->position->level }}
</span>
</td>
<td class="px-4 py-3 text-gray-600">{{ $up->appointedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center text-gray-500">
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $up->appointedBy?->username ?? '系统' }}</td>
<td class="px-4 py-3 text-center {{ $adminListSecondaryTextClass }}">
{{ $up->appointed_at->format('Y-m-d') }}
</td>
<td class="px-4 py-3 text-center">
<span class="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">
<span class="inline-flex items-center rounded-full bg-blue-100 px-2 py-0.5 text-xs font-semibold text-blue-700">
{{ $up->duration_days }}
</span>
</td>
<td class="px-4 py-3 text-right space-x-1">
<td class="px-4 py-3 text-right">
<div class="flex flex-wrap items-center justify-end gap-2">
<a href="{{ route('admin.appointments.duty-logs', $up->id) }}"
class="text-xs bg-blue-50 text-blue-600 font-bold px-2 py-1 rounded hover:bg-blue-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-blue-50 text-blue-600 hover:bg-blue-600 hover:text-white">
登录日志
</a>
<a href="{{ route('admin.appointments.authority-logs', $up->id) }}"
class="text-xs bg-purple-50 text-purple-600 font-bold px-2 py-1 rounded hover:bg-purple-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-purple-50 text-purple-600 hover:bg-purple-600 hover:text-white">
操作日志
</a>
<form action="{{ route('admin.appointments.revoke', $up->id) }}" method="POST"
@@ -132,53 +141,53 @@
data-admin-confirm="确定撤销【{{ $up->user->username }}】的【{{ $up->position->name }}】职务?撤销后其等级将归 1。">
@csrf @method('DELETE')
<button type="submit"
class="text-xs bg-red-50 text-red-600 font-bold px-2 py-1 rounded hover:bg-red-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-600 hover:text-white">
撤销职务
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-12 text-center text-gray-400">暂无在职人员</td>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无在职人员</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
{{-- 新增任命弹窗 --}}
<div x-show="showForm" style="display: none;"
class="fixed inset-0 z-50 bg-black/60 flex items-center justify-center p-4">
<div @click.away="showForm = false" class="bg-white rounded-xl shadow-2xl w-full max-w-md" x-transition>
<div
style="background-color:#c2410c;padding:1rem 1.5rem;display:flex;justify-content:space-between;align-items:center;border-radius:0.75rem 0.75rem 0 0;">
<h3 style="font-weight:700;font-size:1.125rem;color:#fff;margin:0;">新增任命</h3>
<div class="flex items-center justify-between rounded-t-xl border-b border-orange-800 bg-orange-700 px-6 py-4">
<h3 class="text-lg font-bold text-white">新增任命</h3>
<button @click="showForm = false"
style="color:#fed7aa;background:none;border:none;font-size:1.5rem;cursor:pointer;line-height:1;"
onmouseover="this.style.color='#fff'" onmouseout="this.style.color='#fed7aa'">&times;</button>
class="text-2xl leading-none text-orange-200 transition hover:text-white">&times;</button>
</div>
<div class="p-6">
<form action="{{ route('admin.appointments.store') }}" method="POST">
@csrf
<div class="space-y-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">用户名</label>
<label class="{{ $adminListFilterLabelClass }}">用户名</label>
<div class="relative">
<input type="text" name="username" x-model="username" required
placeholder="输入关键字搜索用户..." @input="doSearch($event.target.value)"
@blur="setTimeout(() => showDropdown = false, 200)"
@focus="if(username.length > 0) doSearch(username)"
class="w-full border rounded-md p-2 text-sm" autocomplete="off">
class="w-full {{ $adminListFilterInputClass }}" autocomplete="off">
{{-- 搜索中指示 --}}
<span x-show="searching"
class="absolute right-2 top-2.5 text-gray-400 text-xs">搜索中…</span>
{{-- 下拉结果 --}}
<div x-show="showDropdown" style="display:none;"
class="absolute z-50 w-full bg-white border rounded-md shadow-lg mt-1 max-h-48 overflow-y-auto">
class="absolute z-50 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-orange-100 bg-white shadow-lg">
<template x-for="u in searchResults" :key="u.id">
<div @mousedown="selectUser(u)"
class="px-3 py-2 hover:bg-orange-50 cursor-pointer flex justify-between items-center">
class="flex cursor-pointer items-center justify-between px-3 py-2 hover:bg-orange-50">
<span class="font-bold text-sm" x-text="u.username"></span>
<span class="text-xs text-gray-400" x-text="'Lv.' + u.user_level"></span>
</div>
@@ -189,9 +198,9 @@
</div>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">目标职务</label>
<label class="{{ $adminListFilterLabelClass }}">目标职务</label>
<select name="position_id" x-model="position_id" required
class="w-full border rounded-md p-2 text-sm">
class="w-full {{ $adminListFilterInputClass }}">
<option value="">-- 请选择职务 --</option>
@foreach ($departments as $dept)
<optgroup label="{{ $dept->name }}">
@@ -215,21 +224,16 @@
</select>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">任命备注(可选)</label>
<label class="{{ $adminListFilterLabelClass }}">任命备注(可选)</label>
<input type="text" name="remark" x-model="remark" maxlength="255"
placeholder="例:表现优秀,特此提拔" class="w-full border rounded-md p-2 text-sm">
placeholder="例:表现优秀,特此提拔" class="w-full {{ $adminListFilterInputClass }}">
</div>
</div>
<div
style="display:flex;justify-content:flex-end;gap:0.75rem;padding-top:1rem;margin-top:1rem;border-top:1px solid #e5e7eb;">
<div class="mt-4 flex justify-end gap-3 border-t border-gray-100 pt-4">
<button type="button" @click="showForm = false"
style="padding:0.5rem 1rem;border:1px solid #d1d5db;border-radius:0.375rem;font-weight:500;color:#4b5563;background:#fff;cursor:pointer;"
onmouseover="this.style.background='#f9fafb'"
onmouseout="this.style.background='#fff'">取消</button>
class="{{ $adminListSecondaryButtonClass }}">取消</button>
<button type="submit"
style="padding:0.5rem 1rem;background-color:#f97316;color:#fff;border-radius:0.375rem;font-weight:700;border:none;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.1);"
onmouseover="this.style.backgroundColor='#ea580c'"
onmouseout="this.style.backgroundColor='#f97316'">
class="rounded-lg bg-orange-500 px-4 py-2 text-sm font-semibold text-white shadow-sm transition hover:bg-orange-600">
确认任命
</button>
</div>
@@ -237,5 +241,6 @@
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -12,13 +12,16 @@
@section('title', '我的履职记录')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
{{-- ── 页面标题 ── --}}
<div class="mb-6">
<h2 class="text-xl font-bold text-gray-800">📝 我的履职记录</h2>
<p class="text-sm text-gray-500 mt-1">
<div class="{{ $adminListHeaderCardClass }}">
<h2 class="{{ $adminListHeaderTitleClass }}">📝 我的履职记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
{{ $user->username }} 的全部职务操作历史,共
<span class="font-bold text-gray-700">{{ $logs->total() }}</span> 条记录
<span class="font-semibold text-gray-700">{{ $logs->total() }}</span> 条记录
</p>
</div>
@@ -72,14 +75,14 @@
];
@endphp
<div style="display:grid; grid-template-columns:repeat(6,1fr); gap:12px; margin-bottom:24px;">
<div class="grid gap-3 md:grid-cols-3 xl:grid-cols-6">
@foreach ($statCards as $type => $card)
@php
$stat = $summary->get($type);
$c = $colorMap[$card['color']];
@endphp
<a href="{{ request()->fullUrlWithQuery(['type' => $type, 'page' => 1]) }}"
class="rounded-xl border {{ $c['bg'] }} {{ $c['border'] }} px-3 py-3 text-center hover:shadow-md transition
class="rounded-xl border shadow-sm {{ $c['bg'] }} {{ $c['border'] }} px-3 py-3 text-center hover:shadow-md transition
{{ request('type') === $type ? 'ring-2 ring-offset-1 ring-indigo-400 shadow-md' : '' }}">
<div class="text-xl mb-0.5">{{ $card['icon'] }}</div>
<div class="text-xs text-gray-500 mb-0.5 whitespace-nowrap">{{ $card['label'] }}</div>
@@ -92,11 +95,13 @@
</div>
{{-- ── 筛选栏 ── --}}
<form method="GET" class="bg-white rounded-xl shadow-sm border p-4 mb-4 flex flex-wrap gap-3 items-end">
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="block text-xs text-gray-500 mb-1">操作类型</label>
<label class="{{ $adminListFilterLabelClass }}">操作类型</label>
<select name="type"
class="border rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-300 outline-none">
class="{{ $adminListFilterInputClass }}">
<option value="">全部类型</option>
@foreach ($statCards as $type => $card)
<option value="{{ $type }}" {{ request('type') === $type ? 'selected' : '' }}>
@@ -106,26 +111,28 @@
</select>
</div>
<div>
<label class="block text-xs text-gray-500 mb-1">开始日期</label>
<label class="{{ $adminListFilterLabelClass }}">开始日期</label>
<input type="date" name="date_from" value="{{ request('date_from') }}"
class="border rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-300 outline-none">
class="{{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs text-gray-500 mb-1">结束日期</label>
<label class="{{ $adminListFilterLabelClass }}">结束日期</label>
<input type="date" name="date_to" value="{{ request('date_to') }}"
class="border rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-300 outline-none">
class="{{ $adminListFilterInputClass }}">
</div>
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white text-sm font-bold rounded-lg hover:bg-indigo-700 transition">
class="{{ $adminListPrimaryButtonClass }}">
🔍 查询
</button>
@if (request()->hasAny(['type', 'date_from', 'date_to']))
<a href="{{ route('admin.appointments.my-duty-logs') }}"
class="px-5 py-2 bg-gray-100 text-gray-600 text-sm rounded-lg hover:bg-gray-200 transition">
class="{{ $adminListSecondaryButtonClass }}">
清除筛选
</a>
@endif
</form>
</div>
</div>
{{-- ── 记录表格 ── --}}
@php
@@ -141,66 +148,74 @@
];
@endphp
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<tr>
<th class="px-4 py-3 text-left">操作时间</th>
<th class="px-4 py-3 text-center">操作类型</th>
<th class="px-4 py-3 text-left">操作对象</th>
<th class="px-4 py-3 text-left">所属职务</th>
<th class="px-4 py-3 text-center">金币金额</th>
<th class="px-4 py-3 text-left">备注说明</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($logs as $log)
@php $colorClass = $actionColors[$log->action_type] ?? 'bg-gray-100 text-gray-600'; @endphp
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-400 text-xs whitespace-nowrap">
{{ $log->created_at->format('Y-m-d H:i') }}
</td>
<td class="px-4 py-3 text-center">
<span class="text-xs px-2 py-0.5 rounded-full font-bold {{ $colorClass }}">
{{ $log->action_label }}
</span>
</td>
<td class="px-4 py-3 font-bold text-gray-700">
{{ $log->targetUser?->username ?? '—' }}
</td>
<td class="px-4 py-3 text-gray-500 text-xs">
@if ($log->userPosition?->position)
<span class="text-gray-400">{{ $log->userPosition->position->department?->name }}</span>
@if ($log->userPosition->position->department)
<span class="text-gray-300 mx-1">·</span>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">履职操作记录</h3>
<p class="{{ $adminListSectionDescClass }}">可按操作类型和日期范围筛选当前登录者的历史履职行为。</p>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">操作时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作类型</th>
<th class="{{ $adminListTableHeadCellClass }}">操作对象</th>
<th class="{{ $adminListTableHeadCellClass }}">所属职务</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">金币金额</th>
<th class="{{ $adminListTableHeadCellClass }}">备注说明</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
@php $colorClass = $actionColors[$log->action_type] ?? 'bg-gray-100 text-gray-600'; @endphp
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 whitespace-nowrap {{ $adminListSecondaryTextClass }}">
{{ $log->created_at->format('Y-m-d H:i') }}
</td>
<td class="px-4 py-3 text-center">
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-semibold {{ $colorClass }}">
{{ $log->action_label }}
</span>
</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">
{{ $log->targetUser?->username ?? '—' }}
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">
@if ($log->userPosition?->position)
<span>{{ $log->userPosition->position->department?->name }}</span>
@if ($log->userPosition->position->department)
<span class="mx-1 text-gray-300">·</span>
@endif
<span class="text-gray-600">{{ $log->userPosition->position->name }}</span>
@else
<span class="text-gray-300">超级管理员</span>
@endif
{{ $log->userPosition->position->name }}
@else
<span class="text-gray-300">超级管理员</span>
@endif
</td>
<td class="px-4 py-3 text-center">
@if ($log->amount)
<span class="text-yellow-600 font-bold">+{{ number_format($log->amount) }}</span>
<span class="text-gray-400 text-xs">金币</span>
@else
<span class="text-gray-300"></span>
@endif
</td>
<td class="px-4 py-3 text-gray-400 text-xs">{{ $log->remark ?: '—' }}</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-16 text-center text-gray-400">
<div class="text-4xl mb-3">📋</div>
<div>暂无履职操作记录</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</td>
<td class="px-4 py-3 text-center">
@if ($log->amount)
<span class="text-sm font-semibold text-yellow-600">+{{ number_format($log->amount) }}</span>
<span class="{{ $adminListSecondaryTextClass }}">金币</span>
@else
<span class="text-gray-300"></span>
@endif
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $log->remark ?: '—' }}</td>
</tr>
@empty
<tr>
<td colspan="6" class="{{ $adminListEmptyClass }}">
<div class="mb-3 text-4xl">📋</div>
<div>暂无履职操作记录</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $logs->links() }}</div>
@endif
</div>
<div class="mt-4">{{ $logs->links() }}</div>
</div>
@endsection
+49 -50
View File
@@ -3,30 +3,33 @@
@section('title', '随机事件管理')
@section('content')
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-6 border-b border-gray-100 flex justify-between items-center bg-gray-50">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }} flex justify-between items-center">
<div>
<h2 class="text-lg font-bold text-gray-800">随机事件管理 (autoact)</h2>
<p class="text-xs text-gray-500 mt-1">管理聊天室中随机触发的好运/坏运事件,可增减经验和金币</p>
<h2 class="{{ $adminListSectionTitleClass }}">随机事件管理 (autoact)</h2>
<p class="{{ $adminListSectionDescClass }}">管理聊天室中随机触发的好运、坏运和中性事件,保留原有奖励与惩罚语义</p>
</div>
</div>
</div>
{{-- 新增事件表单 --}}
<div class="p-6 border-b border-gray-100 bg-indigo-50/50">
<h3 class="text-sm font-bold text-gray-700 mb-3"> 添加新事件</h3>
<div class="p-6 border-b border-gray-100 bg-indigo-50/50">
<h3 class="{{ $adminListSectionTitleClass }} mb-3"> 添加新事件</h3>
<form action="{{ route('admin.autoact.store') }}" method="POST">
@csrf
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-4xl">
<div class="md:col-span-2">
<label class="block text-xs font-bold text-gray-600 mb-1">事件文本
<label class="{{ $adminListFilterLabelClass }}">事件文本
<span class="text-gray-400 font-normal">{username} 将被替换为触发者用户名)</span></label>
<input type="text" name="text_body" required placeholder="例:🎉 恭喜【{username}】获得 100 经验値!"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border">
class="w-full {{ $adminListFilterInputClass }} bg-white">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">事件类型</label>
<label class="{{ $adminListFilterLabelClass }}">事件类型</label>
<select name="event_type"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border">
class="w-full {{ $adminListFilterInputClass }} bg-white">
<option value="good">🟢 好运(奖励)</option>
<option value="bad">🔴 坏运(惩罚)</option>
<option value="neutral">🟣 中性(纯文字)</option>
@@ -34,20 +37,19 @@
</div>
<div class="flex gap-3">
<div class="flex-1">
<label class="block text-xs font-bold text-gray-600 mb-1">经验变化</label>
<label class="{{ $adminListFilterLabelClass }}">经验变化</label>
<input type="number" name="exp_change" value="0"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border">
class="w-full {{ $adminListFilterInputClass }} bg-white">
</div>
<div class="flex-1">
<label class="block text-xs font-bold text-gray-600 mb-1">金币变化</label>
<label class="{{ $adminListFilterLabelClass }}">金币变化</label>
<input type="number" name="jjb_change" value="0"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border">
class="w-full {{ $adminListFilterInputClass }} bg-white">
</div>
</div>
</div>
<div class="mt-4">
<button type="submit"
class="px-6 py-2 bg-indigo-600 text-white rounded-md font-bold hover:bg-indigo-700 shadow-sm transition text-sm">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
添加事件
</button>
</div>
@@ -55,52 +57,49 @@
</div>
{{-- 事件列表 --}}
<div class="p-6">
<h3 class="text-sm font-bold text-gray-700 mb-3">📋 现有事件列表(共 {{ $events->count() }} 条)</h3>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-50 text-gray-600 text-left border-b">
<th class="p-3 w-10">ID</th>
<th class="p-3">事件文本</th>
<th class="p-3 w-20">类型</th>
<th class="p-3 w-16">经验</th>
<th class="p-3 w-16">金币</th>
<th class="p-3 w-16">状态</th>
<th class="p-3 w-32">操作</th>
</tr>
</thead>
<tbody>
<div class="p-6">
<h3 class="{{ $adminListSectionTitleClass }} mb-3">📋 现有事件列表(共 {{ $events->count() }} 条)</h3>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="{{ $adminListTableHeadCellClass }} w-10">ID</th>
<th class="{{ $adminListTableHeadCellClass }}">事件文本</th>
<th class="{{ $adminListTableHeadCellClass }} w-20">类型</th>
<th class="{{ $adminListTableHeadCellClass }} w-16">经验</th>
<th class="{{ $adminListTableHeadCellClass }} w-16">金币</th>
<th class="{{ $adminListTableHeadCellClass }} w-16">状态</th>
<th class="{{ $adminListTableHeadCellClass }} w-32">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($events as $event)
<tr class="border-b hover:bg-gray-50 {{ !$event->enabled ? 'opacity-40' : '' }}">
<td class="p-3 text-gray-400">{{ $event->id }}</td>
<tr class="{{ $adminListTableRowClass }} {{ !$event->enabled ? 'opacity-40' : '' }}">
<td class="p-3 {{ $adminListSecondaryTextClass }}">{{ $event->id }}</td>
<td class="p-3">
<span class="text-xs">{{ Str::limit($event->text_body, 60) }}</span>
<span class="{{ $adminListBodyTextClass }}">{{ Str::limit($event->text_body, 60) }}</span>
</td>
<td class="p-3">
@if ($event->event_type === 'good')
<span
class="px-2 py-0.5 rounded-full bg-green-100 text-green-700 text-xs font-bold">好运</span>
<span class="{{ $adminListBadgeBaseClass }} border-green-200 bg-green-100 text-green-700">好运</span>
@elseif($event->event_type === 'bad')
<span
class="px-2 py-0.5 rounded-full bg-red-100 text-red-700 text-xs font-bold">坏运</span>
<span class="{{ $adminListBadgeBaseClass }} border-red-200 bg-red-100 text-red-700">坏运</span>
@else
<span
class="px-2 py-0.5 rounded-full bg-purple-100 text-purple-700 text-xs font-bold">中性</span>
<span class="{{ $adminListBadgeBaseClass }} border-purple-200 bg-purple-100 text-purple-700">中性</span>
@endif
</td>
<td
class="p-3 {{ $event->exp_change > 0 ? 'text-green-600' : ($event->exp_change < 0 ? 'text-red-600' : 'text-gray-400') }} font-bold">
class="p-3 {{ $adminListNumericTextClass }} {{ $event->exp_change > 0 ? 'text-green-600' : ($event->exp_change < 0 ? 'text-red-600' : 'text-gray-400') }} font-bold">
{{ $event->exp_change > 0 ? '+' : '' }}{{ $event->exp_change }}
</td>
<td
class="p-3 {{ $event->jjb_change > 0 ? 'text-green-600' : ($event->jjb_change < 0 ? 'text-red-600' : 'text-gray-400') }} font-bold">
class="p-3 {{ $adminListNumericTextClass }} {{ $event->jjb_change > 0 ? 'text-green-600' : ($event->jjb_change < 0 ? 'text-red-600' : 'text-gray-400') }} font-bold">
{{ $event->jjb_change > 0 ? '+' : '' }}{{ $event->jjb_change }}
</td>
<td class="p-3">
<button type="button"
data-autoact-toggle-url="{{ route('admin.autoact.toggle', $event->id) }}"
class="text-xs px-2 py-1 rounded {{ $event->enabled ? 'bg-green-100 text-green-700' : 'bg-gray-200 text-gray-500' }} cursor-pointer">
class="{{ $adminListBadgeBaseClass }} px-2 py-1 {{ $event->enabled ? 'border-green-200 bg-green-100 text-green-700' : 'border-gray-200 bg-gray-200 text-gray-500' }} cursor-pointer">
{{ $event->enabled ? '启用' : '禁用' }}
</button>
</td>
@@ -110,19 +109,19 @@
@csrf
@method('DELETE')
<button type="submit"
class="text-red-500 hover:text-red-700 text-xs font-bold">删除</button>
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-100">删除</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="p-6 text-center text-gray-400">暂无事件,请添加。</td>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无事件,请添加。</td>
</tr>
@endforelse
</tbody>
</table>
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
+95 -85
View File
@@ -9,94 +9,104 @@
@section('title', '开发日志管理')
@section('content')
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-xl font-bold text-gray-800">📋 开发日志管理</h2>
<p class="text-sm text-gray-500 mt-1">管理版本更新记录,发布后可在大厅消息区通知用户</p>
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">📋 开发日志管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">管理版本更新记录,发布后可在大厅消息区通知用户</p>
</div>
<a href="{{ route('admin.changelogs.create') }}"
class="{{ $adminListPrimaryButtonClass }} inline-flex items-center justify-center">
+ 新增日志
</a>
</div>
</div>
<a href="{{ route('admin.changelogs.create') }}"
class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg font-bold text-sm shadow transition">
+ 新增日志
</a>
</div>
{{-- 日志列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr class="text-left text-gray-500 text-xs font-bold uppercase tracking-wider">
<th class="px-5 py-3">版本号</th>
<th class="px-5 py-3">标题</th>
<th class="px-5 py-3">类型</th>
<th class="px-5 py-3">状态</th>
<th class="px-5 py-3">发布时间</th>
<th class="px-5 py-3 text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse($logs as $log)
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-5 py-3 font-mono text-indigo-700 font-bold">v{{ $log->version }}</td>
<td class="px-5 py-3 text-gray-800 font-medium">{{ $log->title }}</td>
<td class="px-5 py-3">
@php
$typeConfig = \App\Models\DevChangelog::TYPE_CONFIG[$log->type] ?? null;
$colorMap = [
'emerald' => 'bg-emerald-100 text-emerald-700',
'rose' => 'bg-rose-100 text-rose-700',
'blue' => 'bg-blue-100 text-blue-700',
'slate' => 'bg-slate-100 text-slate-700',
];
@endphp
<span
class="px-2 py-0.5 rounded-full text-xs font-bold {{ $colorMap[$typeConfig['color'] ?? 'slate'] ?? 'bg-slate-100 text-slate-700' }}">
{{ $typeConfig['label'] ?? '其他' }}
</span>
</td>
<td class="px-5 py-3">
@if ($log->is_published)
<span class="px-2 py-0.5 bg-green-100 text-green-700 rounded-full text-xs font-bold">
已发布</span>
@else
<span class="px-2 py-0.5 bg-gray-100 text-gray-500 rounded-full text-xs font-bold">🔒
草稿</span>
@endif
</td>
<td class="px-5 py-3 text-gray-400 text-xs">
{{ $log->published_at?->format('Y-m-d H:i') ?? '—' }}
</td>
<td class="px-5 py-3 text-right">
<div class="flex items-center justify-end gap-2">
<a href="{{ route('admin.changelogs.edit', $log->id) }}"
class="text-blue-600 hover:text-blue-800 font-semibold text-xs px-2 py-1 rounded hover:bg-blue-50 transition">
编辑
</a>
<form action="{{ route('admin.changelogs.destroy', $log->id) }}" method="POST"
data-admin-confirm="确定要删除这条日志吗?">
@csrf @method('DELETE')
<button type="submit"
class="text-red-600 hover:text-red-800 font-semibold text-xs px-2 py-1 rounded hover:bg-red-50 transition">
删除
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-5 py-12 text-center text-gray-400">
<p class="text-3xl mb-2">📭</p>
<p>还没有任何日志,点击右上角「新增日志」开始吧</p>
</td>
</tr>
@endforelse
</tbody>
</table>
@if ($logs->hasPages())
<div class="px-5 py-4 border-t border-gray-100">
{{ $logs->links() }}
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}">开发日志列表</h3>
<p class="{{ $adminListSectionDescClass }}">统一查看版本、类型、发布状态与管理操作。</p>
</div>
@endif
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} whitespace-nowrap">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">版本号</th>
<th class="{{ $adminListTableHeadCellClass }}">标题</th>
<th class="{{ $adminListTableHeadCellClass }}">类型</th>
<th class="{{ $adminListTableHeadCellClass }}">状态</th>
<th class="{{ $adminListTableHeadCellClass }}">发布时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse($logs as $log)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-5 py-3 font-mono text-sm font-semibold text-indigo-700">v{{ $log->version }}</td>
<td class="px-5 py-3 {{ $adminListPrimaryTextClass }}">{{ $log->title }}</td>
<td class="px-5 py-3">
@php
$typeConfig = \App\Models\DevChangelog::TYPE_CONFIG[$log->type] ?? null;
$colorMap = [
'emerald' => 'bg-emerald-100 text-emerald-700',
'rose' => 'bg-rose-100 text-rose-700',
'blue' => 'bg-blue-100 text-blue-700',
'slate' => 'bg-slate-100 text-slate-700',
];
@endphp
<span
class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-semibold {{ $colorMap[$typeConfig['color'] ?? 'slate'] ?? 'bg-slate-100 text-slate-700' }}">
{{ $typeConfig['label'] ?? '其他' }}
</span>
</td>
<td class="px-5 py-3">
@if ($log->is_published)
<span class="inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-700"> 已发布</span>
@else
<span class="inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-semibold text-gray-500">🔒 草稿</span>
@endif
</td>
<td class="px-5 py-3 {{ $adminListSecondaryTextClass }}">
{{ $log->published_at?->format('Y-m-d H:i') ?? '—' }}
</td>
<td class="px-5 py-3 text-right">
<div class="flex items-center justify-end gap-2">
<a href="{{ route('admin.changelogs.edit', $log->id) }}"
class="{{ $adminListActionButtonClass }} bg-blue-50 text-blue-600 hover:bg-blue-600 hover:text-white">
编辑
</a>
<form action="{{ route('admin.changelogs.destroy', $log->id) }}" method="POST"
data-admin-confirm="确定要删除这条日志吗?">
@csrf @method('DELETE')
<button type="submit"
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-600 hover:text-white">
删除
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="{{ $adminListEmptyClass }}">
<p class="mb-2 text-3xl">📭</p>
<p>还没有任何日志,点击右上角「新增日志」开始吧</p>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">
{{ $logs->links() }}
</div>
@endif
</div>
</div>
@endsection
@@ -9,28 +9,32 @@
@section('title', '积分流水统计')
@section('content')
<div class="p-6 max-w-6xl mx-auto">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold text-gray-800">📊 积分流水活动统计</h1>
{{-- 日期选择器 --}}
<form method="GET" action="{{ route('admin.currency-stats.index') }}" class="flex items-center gap-3">
<label class="text-sm text-gray-600">查询日期:</label>
<input type="date" name="date" value="{{ $date }}"
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400">
<button type="submit"
class="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm hover:bg-indigo-700 transition">
查询
</button>
</form>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 xl:flex-row xl:items-center xl:justify-between">
<div>
<h1 class="{{ $adminListHeaderTitleClass }}">📊 积分流水活动统计</h1>
<p class="{{ $adminListHeaderSubtitleClass }}">查看指定日期下各活动来源的经验、金币、魅力产出,以及当日净流通量。</p>
</div>
<form method="GET" action="{{ route('admin.currency-stats.index') }}"
class="flex flex-wrap items-end gap-3">
<div>
<label class="{{ $adminListFilterLabelClass }}">查询日期</label>
<input type="date" name="date" value="{{ $date }}"
class="{{ $adminListFilterInputClass }}">
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">查询</button>
</form>
</div>
</div>
{{-- 净流通量摘要卡片 --}}
<div class="grid grid-cols-3 gap-4 mb-8">
<div class="grid gap-4 md:grid-cols-3">
@foreach (['exp' => ['label' => '经验', 'icon' => '⚡', 'color' => 'amber'], 'gold' => ['label' => '金币', 'icon' => '💰', 'color' => 'yellow'], 'charm' => ['label' => '魅力', 'icon' => '🌸', 'color' => 'pink']] as $cur => $info)
@php $flow = $netFlow[$cur] ?? ['in'=>0,'out'=>0,'net'=>0]; @endphp
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-5">
<div class="{{ $adminListCardClass }} p-5">
<div class="flex items-center gap-2 mb-3">
<span class="text-2xl">{{ $info['icon'] }}</span>
<span class="font-semibold text-gray-700">{{ $info['label'] }} 流通</span>
@@ -43,26 +47,27 @@
净增:{{ $flow['net'] >= 0 ? '+' : '' }}{{ number_format($flow['net']) }}
</div>
</div>
@endforeach
@endforeach
</div>
{{-- 来源活动详细统计表 --}}
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
<div class="px-6 py-4 border-b border-gray-200 bg-gray-50">
<h2 class="text-lg font-semibold text-gray-700">各活动来源产出明细</h2>
<p class="text-xs text-gray-400 mt-1">日期:{{ $date }}(仅统计正向增加,不含消耗)</p>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h2 class="{{ $adminListSectionTitleClass }}">各活动来源产出明细</h2>
<p class="{{ $adminListSectionDescClass }}">日期:{{ $date }}(仅统计正向增加,不含消耗)</p>
</div>
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b text-gray-600">
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-6 py-3 text-left">来源活动</th>
<th class="px-6 py-3 text-right"> 经验产出</th>
<th class="px-6 py-3 text-right">💰 金币产出</th>
<th class="px-6 py-3 text-right">🌸 魅力产出</th>
<th class="px-6 py-3 text-right">参与人次</th>
<th class="{{ $adminListTableHeadCellClass }}">来源活动</th>
<th class="{{ $adminListTableHeadCellClass }} text-right"> 经验产出</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">💰 金币产出</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">🌸 魅力产出</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">参与人次</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@foreach ($allSources as $source)
@php
$expRow = $statsByType['exp'][$source->value] ?? null;
@@ -75,28 +80,30 @@
$charmRow?->participant_count ?? 0,
);
@endphp
<tr class="{{ $hasData ? '' : 'opacity-40' }} hover:bg-gray-50 transition">
<td class="px-6 py-3 font-medium text-gray-700">{{ $source->label() }}</td>
<tr class="{{ $adminListTableRowClass }} {{ $hasData ? '' : 'opacity-40' }}">
<td class="px-4 py-3">
<span class="{{ $adminListPrimaryTextClass }}">{{ $source->label() }}</span>
</td>
<td
class="px-6 py-3 text-right {{ $expRow?->total_amount > 0 ? 'text-amber-600 font-semibold' : 'text-gray-300' }}">
class="px-4 py-3 text-right {{ $adminListNumericTextClass }} {{ $expRow?->total_amount > 0 ? 'text-amber-600 font-semibold' : 'text-gray-300' }}">
{{ $expRow ? number_format($expRow->total_amount) : '—' }}
</td>
<td
class="px-6 py-3 text-right {{ $goldRow?->total_amount > 0 ? 'text-yellow-600 font-semibold' : 'text-gray-300' }}">
class="px-4 py-3 text-right {{ $adminListNumericTextClass }} {{ $goldRow?->total_amount > 0 ? 'text-yellow-600 font-semibold' : 'text-gray-300' }}">
{{ $goldRow ? number_format($goldRow->total_amount) : '—' }}
</td>
<td
class="px-6 py-3 text-right {{ $charmRow?->total_amount > 0 ? 'text-pink-600 font-semibold' : 'text-gray-300' }}">
class="px-4 py-3 text-right {{ $adminListNumericTextClass }} {{ $charmRow?->total_amount > 0 ? 'text-pink-600 font-semibold' : 'text-gray-300' }}">
{{ $charmRow ? number_format($charmRow->total_amount) : '—' }}
</td>
<td class="px-6 py-3 text-right text-gray-500">
<td class="px-4 py-3 text-right {{ $adminListBodyTextClass }}">
{{ $maxParticipants > 0 ? $maxParticipants . ' 人' : '—' }}
</td>
</tr>
@endforeach
</tbody>
</table>
</tbody>
</table>
</div>
</div>
</div>
@endsection
+32 -23
View File
@@ -10,7 +10,9 @@
@section('title', '用户反馈管理')
@section('content')
<div class="flex justify-between items-center mb-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListHeaderCardClass }} mb-6">
<div>
<h2 class="text-xl font-bold text-gray-800">
💬 用户反馈管理
@@ -20,12 +22,12 @@
</span>
@endif
</h2>
<p class="text-sm text-gray-500 mt-1">管理用户提交的 Bug 报告和功能建议,修改状态后前台实时更新</p>
<p class="{{ $adminListHeaderSubtitleClass }}">管理用户提交的 Bug 报告和功能建议,修改状态后前台实时更新</p>
</div>
</div>
{{-- 筛选栏 --}}
<div class="flex flex-wrap gap-3 mb-5" x-data="{
<div class="{{ $adminListFilterCardClass }} mb-5" x-data="{
type: '{{ $currentType ?? '' }}',
status: '{{ $currentStatus ?? '' }}',
go() {
@@ -35,25 +37,32 @@
window.location.href = '/admin/feedback?' + params.toString();
}
}">
<select x-model="type" @change="go()"
class="border border-gray-200 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none bg-white">
<option value="">所有类型</option>
<option value="bug">🐛 Bug报告</option>
<option value="suggestion">💡 功能建议</option>
</select>
<select x-model="status" @change="go()"
class="border border-gray-200 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none bg-white">
<option value="">所有状态</option>
@foreach ($statusConfig as $key => $config)
<option value="{{ $key }}">{{ $config['icon'] }} {{ $config['label'] }}</option>
@endforeach
</select>
@if ($currentType || $currentStatus)
<a href="{{ route('admin.feedback.index') }}"
class="px-3 py-2 text-sm text-gray-500 hover:text-gray-700 border border-gray-200 rounded-lg bg-white hover:bg-gray-50 transition">
清除筛选
</a>
@endif
<div class="{{ $adminListFilterInnerClass }}">
<div class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">反馈类型</label>
<select x-model="type" @change="go()" class="{{ $adminListFilterInputClass }}">
<option value="">所有类型</option>
<option value="bug">🐛 Bug报告</option>
<option value="suggestion">💡 功能建议</option>
</select>
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">处理状态</label>
<select x-model="status" @change="go()" class="{{ $adminListFilterInputClass }}">
<option value="">所有状态</option>
@foreach ($statusConfig as $key => $config)
<option value="{{ $key }}">{{ $config['icon'] }} {{ $config['label'] }}</option>
@endforeach
</select>
</div>
@if ($currentType || $currentStatus)
<a href="{{ route('admin.feedback.index') }}" class="{{ $adminListSecondaryButtonClass }}">
清除筛选
</a>
@endif
</div>
</div>
</div>
{{-- 反馈列表 --}}
@@ -180,7 +189,7 @@
{{-- 分页 --}}
@if ($feedbacks->hasPages())
<div class="mt-6">
<div class="{{ $adminListPaginationClass }} mt-6">
{{ $feedbacks->links() }}
</div>
@endif
+66 -62
View File
@@ -3,6 +3,8 @@
@section('title', '钓鱼事件管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
@php
$fishingEventPayload = $events->mapWithKeys(
fn($event) => [
@@ -25,59 +27,62 @@
<script type="application/json" id="admin-fishing-events-data">@json($fishingEventPayload)</script>
<div class="space-y-6">
<div class="{{ $adminListPageClass }}">
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
<div>
<h2 class="text-lg font-bold text-gray-800">🎣 钓鱼事件管理</h2>
<p class="text-xs text-gray-500 mt-1">
管理钓鱼随机事件。权重越大被触发概率越高。
当前激活事件权重<strong class="text-indigo-600">{{ $totalWeight }}</strong>
</p>
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">🎣 钓鱼事件管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
管理钓鱼随机事件权重越大被触发概率越高。
当前激活事件总权重:<strong class="text-indigo-600">{{ $totalWeight }}</strong>
</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="{{ $adminListSecondaryButtonClass }} inline-flex items-center justify-center">
⚙️ 钓鱼参数设置
</a>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
⚙️ 钓鱼参数设置
</a>
</div>
{{-- 钓鱼事件列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">排序</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">符号</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">名称</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase w-1/3">播报内容</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">经验</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">金币</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">权重</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">概率</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
<th class="{{ $adminListTableHeadCellClass }}">排序</th>
<th class="{{ $adminListTableHeadCellClass }}">符号</th>
<th class="{{ $adminListTableHeadCellClass }}">名称</th>
<th class="{{ $adminListTableHeadCellClass }} w-1/3">播报内容</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">经验</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">金币</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">权重</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">概率</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
<tbody class="{{ $adminListTableBodyClass }}">
@foreach ($events as $event)
<tr id="row-{{ $event->id }}" class="{{ $event->is_active ? '' : 'opacity-50' }}">
<td class="px-4 py-3 text-gray-500 text-xs">{{ $event->sort }}</td>
<tr id="row-{{ $event->id }}" class="{{ $adminListTableRowClass }} {{ $event->is_active ? '' : 'opacity-50' }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $event->sort }}</td>
<td class="px-4 py-3 text-xl">{{ $event->emoji }}</td>
<td class="px-4 py-3 font-medium text-gray-800">{{ $event->name }}</td>
<td class="px-4 py-3 text-gray-500 text-xs">{{ $event->message }}</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $event->name }}</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $event->message }}</td>
<td
class="px-4 py-3 text-center font-mono text-xs
class="px-4 py-3 text-center {{ $adminListNumericTextClass }}
{{ $event->exp > 0 ? 'text-green-600' : ($event->exp < 0 ? 'text-red-500' : 'text-gray-400') }}">
{{ $event->exp > 0 ? '+' : '' }}{{ $event->exp }}
</td>
<td
class="px-4 py-3 text-center font-mono text-xs
class="px-4 py-3 text-center {{ $adminListNumericTextClass }}
{{ $event->jjb > 0 ? 'text-amber-600' : ($event->jjb < 0 ? 'text-red-500' : 'text-gray-400') }}">
{{ $event->jjb > 0 ? '+' : '' }}{{ $event->jjb }}
</td>
<td class="px-4 py-3 text-center text-xs text-indigo-600 font-bold">{{ $event->weight }}</td>
<td class="px-4 py-3 text-center text-xs text-gray-500">
<td class="px-4 py-3 text-center text-indigo-600 {{ $adminListNumericTextClass }} font-bold">{{ $event->weight }}</td>
<td class="px-4 py-3 text-center {{ $adminListBodyTextClass }}">
@if ($totalWeight > 0 && $event->is_active)
{{ number_format(($event->weight / $totalWeight) * 100, 1) }}%
@else
@@ -87,78 +92,78 @@
<td class="px-4 py-3 text-center">
<button type="button" data-fishing-toggle-id="{{ $event->id }}"
id="toggle-{{ $event->id }}"
class="px-2 py-1 rounded-full text-xs font-bold transition
{{ $event->is_active ? 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200' : 'bg-gray-100 text-gray-500 hover:bg-gray-200' }}">
class="{{ $adminListBadgeBaseClass }} px-2 py-1 transition
{{ $event->is_active ? 'border-emerald-200 bg-emerald-100 text-emerald-700 hover:bg-emerald-200' : 'border-gray-200 bg-gray-100 text-gray-500 hover:bg-gray-200' }}">
{{ $event->is_active ? '启用' : '禁用' }}
</button>
</td>
<td class="px-4 py-3 text-right">
<button type="button" data-fishing-edit-id="{{ $event->id }}"
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition mr-1">
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-700 hover:bg-indigo-100 mr-1">
编辑
</button>
<form action="{{ route('admin.fishing.destroy', $event->id) }}" method="POST"
class="inline" data-fishing-delete-confirm="确定删除事件「{{ $event->name }}」?">
@csrf @method('DELETE')
<button type="submit"
class="px-3 py-1 bg-red-50 text-red-600 rounded text-xs font-bold hover:bg-red-100 transition">
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-100">
删除
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</tbody>
</table>
</div>
</div>
{{-- 新增事件卡片 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-5 border-b border-gray-100 bg-gray-50">
<h3 class="font-bold text-gray-700 text-sm"> 新增钓鱼事件</h3>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}"> 新增钓鱼事件</h3>
</div>
<form action="{{ route('admin.fishing.store') }}" method="POST" class="p-5">
@csrf
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">Emoji 符号</label>
<label class="{{ $adminListFilterLabelClass }}">Emoji 符号</label>
<input type="text" name="emoji" value="{{ old('emoji') }}" placeholder="🐟" required
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">名称</label>
<label class="{{ $adminListFilterLabelClass }}">名称</label>
<input type="text" name="name" value="{{ old('name') }}" placeholder="小鲤鱼" required
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">经验变化</label>
<label class="{{ $adminListFilterLabelClass }}">经验变化</label>
<input type="number" name="exp" value="{{ old('exp', 0) }}"
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">金币变化</label>
<label class="{{ $adminListFilterLabelClass }}">金币变化</label>
<input type="number" name="jjb" value="{{ old('jjb', 0) }}"
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div class="md:col-span-2">
<label class="block text-xs font-bold text-gray-600 mb-1">播报内容</label>
<label class="{{ $adminListFilterLabelClass }}">播报内容</label>
<input type="text" name="message" value="{{ old('message') }}" placeholder="钓到一条小鲤鱼..." required
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">权重(概率)</label>
<label class="{{ $adminListFilterLabelClass }}">权重(概率)</label>
<input type="number" name="weight" value="{{ old('weight', 10) }}" min="1"
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">排序</label>
<label class="{{ $adminListFilterLabelClass }}">排序</label>
<input type="number" name="sort" value="{{ old('sort', 0) }}" min="0"
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
class="w-full {{ $adminListFilterInputClass }}">
</div>
</div>
<div class="mt-4 flex items-center gap-4">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm shadow-sm">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
💾 添加事件
</button>
<label class="flex items-center gap-2 text-sm text-gray-600 cursor-pointer">
@@ -224,12 +229,11 @@
</div>
</div>
<div class="mt-5 flex gap-3">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
💾 保存修改
</button>
<button type="button" data-fishing-edit-close
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
class="{{ $adminListSecondaryButtonClass }}">
取消
</button>
</div>
@@ -11,20 +11,19 @@
@section('title', '禁用用户名管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 标题 --}}
<div class="flex items-start justify-between mb-6">
<div>
<h2 class="text-xl font-bold text-gray-800">🚫 禁用用户名管理</h2>
<p class="text-sm text-gray-500 mt-1">
以下词语永久禁止注册或改名使用(领导人名称、攻击性词汇、违禁词等)
临时保留的旧昵称(改名后30天)不在此列表中显示。
</p>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">🚫 禁用用户名管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
以下词语永久禁止注册或改名使用。临时保留的旧昵称(改名后 30 天)不在此列表中显示
</p>
</div>
</div>
</div>
{{-- 新增表单 + 搜索栏 --}}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6" x-data="{
<div class="grid grid-cols-1 gap-4 md:grid-cols-2" x-data="{
tab: 'single',
username: '',
words: '',
@@ -76,107 +75,112 @@
}
}">
{{-- 新增卡片(单个 + 批量 Tab --}}
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-5">
{{-- Tab 切换 --}}
<div class="flex border-b border-gray-200 mb-4 -mx-5 px-5 gap-1">
<button @click="tab='single'; msg=''"
:class="tab === 'single' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
'text-gray-500 hover:text-gray-700'"
class="pb-2 text-sm px-1 transition"> 单个添加</button>
<button @click="tab='batch'; msg=''"
:class="tab === 'batch' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
'text-gray-500 hover:text-gray-700'"
class="pb-2 text-sm px-1 transition">📋 批量添加</button>
</div>
<div class="space-y-3">
{{-- 单个模式 --}}
<div x-show="tab==='single'">
<label class="text-xs text-gray-500 mb-1 block">禁用词 <span class="text-red-500">*</span></label>
<input x-model="username" type="text" maxlength="50" placeholder="如:admin、习近平、fuck…"
@keydown.enter="addSingle()"
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none">
<div class="{{ $adminListCardClass }} p-5">
{{-- Tab 切换 --}}
<div class="mb-4 -mx-5 flex gap-1 border-b border-gray-200 px-5">
<button @click="tab='single'; msg=''"
:class="tab === 'single' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
'text-gray-500 hover:text-gray-700'"
class="px-1 pb-2 text-sm transition"> 单个添加</button>
<button @click="tab='batch'; msg=''"
:class="tab === 'batch' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
'text-gray-500 hover:text-gray-700'"
class="px-1 pb-2 text-sm transition">📋 批量添加</button>
</div>
{{-- 批量模式 --}}
<div x-show="tab==='batch'">
<label class="text-xs text-gray-500 mb-1 block">
批量词语 <span class="text-red-500">*</span>
<span class="text-gray-400 font-normal">(每行一个,或用逗号/空格分隔)</span>
</label>
<textarea x-model="words" rows="6" maxlength="5000"
placeholder="admin&#10;root&#10;fuck&#10;操,草,傻&#10;…(每行一个或逗号分隔)"
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none resize-y font-mono"></textarea>
<p class="text-xs text-gray-400 mt-1">
自动去重,跳过已存在的词语,超过50字符的词语忽略
</p>
</div>
<div class="space-y-3">
{{-- 单个模式 --}}
<div x-show="tab==='single'">
<label class="{{ $adminListFilterLabelClass }}">禁用词 <span class="text-red-500">*</span></label>
<input x-model="username" type="text" maxlength="50" placeholder="如:admin、习近平、fuck…"
@keydown.enter="addSingle()"
class="w-full {{ $adminListFilterInputClass }}">
</div>
{{-- 共用原因 --}}
<div>
<label class="text-xs text-gray-500 mb-1 block">禁用原因(选填)</label>
<input x-model="reason" type="text" maxlength="100" placeholder="如:国家领导人姓名 / 攻击性词汇"
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none">
</div>
{{-- 批量模式 --}}
<div x-show="tab==='batch'">
<label class="{{ $adminListFilterLabelClass }}">
批量词语 <span class="text-red-500">*</span>
<span class="text-gray-400 font-normal">(每行一个,或用逗号/空格分隔)</span>
</label>
<textarea x-model="words" rows="6" maxlength="5000"
placeholder="admin&#10;root&#10;fuck&#10;操,草,傻&#10;…(每行一个或逗号分隔)"
class="w-full resize-y font-mono {{ $adminListFilterInputClass }}"></textarea>
<p class="mt-1 text-xs text-gray-400">
自动去重,跳过已存在的词语,超过50字符的词语忽略
</p>
</div>
{{-- 提交按钮 --}}
<button x-show="tab==='single'" @click="addSingle()" :disabled="saving || !username.trim()"
class="w-full bg-indigo-600 hover:bg-indigo-700 disabled:opacity-40 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
<span x-text="saving ? '添加中…' : ' 添加到禁用列表'"></span>
</button>
<button x-show="tab==='batch'" @click="addBatch()" :disabled="saving || !words.trim()"
class="w-full bg-indigo-600 hover:bg-indigo-700 disabled:opacity-40 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
<span x-text="saving ? '处理中…' : '📋 批量添加到禁用列表'"></span>
</button>
{{-- 共用原因 --}}
<div>
<label class="{{ $adminListFilterLabelClass }}">禁用原因(选填)</label>
<input x-model="reason" type="text" maxlength="100" placeholder="如:国家领导人姓名 / 攻击性词汇"
class="w-full {{ $adminListFilterInputClass }}">
</div>
<p x-show="msg" x-text="msg" :class="msgOk ? 'text-green-600' : 'text-red-500'"
class="text-xs font-bold"></p>
</div>
</div>
{{-- 搜索卡片 --}}
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-5">
<h3 class="font-bold text-gray-700 text-sm mb-3">🔍 搜索禁用词</h3>
<form method="GET" action="{{ route('admin.forbidden-usernames.index') }}" class="space-y-3">
<input type="text" name="q" value="{{ $q }}" placeholder="输入关键词搜索…"
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none">
<div class="flex gap-2">
<button type="submit"
class="flex-1 bg-gray-600 hover:bg-gray-700 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
搜索
{{-- 提交按钮 --}}
<button x-show="tab==='single'" @click="addSingle()" :disabled="saving || !username.trim()"
class="w-full rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-indigo-700 disabled:opacity-40">
<span x-text="saving ? '添加中…' : ' 添加到禁用列表'"></span>
</button>
<button x-show="tab==='batch'" @click="addBatch()" :disabled="saving || !words.trim()"
class="w-full rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-indigo-700 disabled:opacity-40">
<span x-text="saving ? '处理中…' : '📋 批量添加到禁用列表'"></span>
</button>
@if ($q)
<a href="{{ route('admin.forbidden-usernames.index') }}"
class="px-4 py-2 text-sm text-gray-500 border border-gray-300 rounded-lg hover:bg-gray-50 transition">
清除
</a>
@endif
</div>
</form>
<p class="text-xs text-gray-400 mt-3">
<strong>{{ $items->total() }}</strong> 条永久禁用词
@if ($q)
(当前筛选"{{ $q }}"
@endif
</p>
</div>
</div>
{{-- 禁用词列表 --}}
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">词语</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">禁用原因</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">添加时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($items as $item)
<tr x-data="{
<p x-show="msg" x-text="msg" :class="msgOk ? 'text-green-600' : 'text-red-500'"
class="text-xs font-bold"></p>
</div>
</div>
<div class="{{ $adminListCardClass }} p-5">
<h3 class="{{ $adminListSectionTitleClass }} mb-3">🔍 搜索禁用词</h3>
<form method="GET" action="{{ route('admin.forbidden-usernames.index') }}" class="space-y-3">
<input type="text" name="q" value="{{ $q }}" placeholder="输入关键词搜索…"
class="w-full {{ $adminListFilterInputClass }}">
<div class="flex gap-2">
<button type="submit"
class="flex-1 rounded-lg bg-gray-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-gray-700">
搜索
</button>
@if ($q)
<a href="{{ route('admin.forbidden-usernames.index') }}"
class="{{ $adminListSecondaryButtonClass }}">
清除
</a>
@endif
</div>
</form>
<p class="mt-3 text-xs text-gray-400">
<strong>{{ $items->total() }}</strong> 条永久禁用词
@if ($q)
(当前筛选"{{ $q }}"
@endif
</p>
</div>
</div>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">禁用词列表</h3>
<p class="{{ $adminListSectionDescClass }}">表格、按钮与分页统一到用户管理页风格,保留高风险词的红色提示。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">词语</th>
<th class="{{ $adminListTableHeadCellClass }}">禁用原因</th>
<th class="{{ $adminListTableHeadCellClass }}">添加时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($items as $item)
<tr x-data="{
editing: false,
reason: @js($item->reason ?? ''),
saving: false,
@@ -209,11 +213,11 @@
});
location.reload();
}
}" class="hover:bg-gray-50 transition">
}" class="{{ $adminListTableRowClass }}">
{{-- 词语 --}}
<td class="px-4 py-3">
<span
class="font-mono font-bold text-gray-800 bg-red-50 border border-red-200 px-2 py-0.5 rounded text-xs">
class="inline-flex items-center rounded-full border border-red-200 bg-red-50 px-2 py-0.5 text-xs font-semibold text-gray-800">
{{ $item->username }}
</span>
</td>
@@ -224,9 +228,9 @@
<div x-show="editing" class="flex items-center gap-2">
<input x-model="reason" type="text" maxlength="100" @keydown.enter="saveReason()"
@keydown.escape="editing = false"
class="border border-indigo-300 rounded px-2 py-1 text-xs focus:ring-1 focus:ring-indigo-400 outline-none w-48">
class="w-48 rounded border border-indigo-300 px-2 py-1 text-xs outline-none focus:ring-1 focus:ring-indigo-400">
<button @click="saveReason()" :disabled="saving"
class="text-xs bg-indigo-600 text-white rounded px-2 py-1 hover:bg-indigo-700 disabled:opacity-50">
class="{{ $adminListActionButtonClass }} bg-indigo-600 text-white hover:bg-indigo-700 disabled:opacity-50">
<span x-text="saving ? '…' : '保存'"></span>
</button>
<button @click="editing = false"
@@ -240,29 +244,30 @@
{{-- 操作 --}}
<td class="px-4 py-3 text-center">
<button @click="destroy()"
class="text-xs text-red-600 hover:text-red-800 border border-red-200 hover:border-red-400 rounded px-3 py-1 transition">
class="{{ $adminListActionButtonClass }} border border-red-200 text-red-600 hover:border-red-400 hover:bg-red-50">
🗑 删除
</button>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="py-16 text-center text-gray-400">
<td colspan="4" class="{{ $adminListEmptyClass }}">
<p class="text-3xl mb-2">🚫</p>
<p class="font-bold">暂无禁用词</p>
<p class="text-xs mt-1">使用左侧表单添加第一条禁用词</p>
</td>
</tr>
@endforelse
</tbody>
</table>
</tbody>
</table>
</div>
@if ($items->hasPages())
<div class="{{ $adminListPaginationClass }}">
{{ $items->links() }}
</div>
@endif
</div>
</div>
{{-- 分页 --}}
@if ($items->hasPages())
<div class="mt-6">
{{ $items->links() }}
</div>
@endif
@endsection
@@ -3,110 +3,113 @@
@section('title', "百家乐第 #{$round->id} 局下注明细")
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🎲 百家乐 #{{ $round->id }} 局下注明细</h2>
<p class="text-xs text-gray-500 mt-1">
<h2 class="{{ $adminListHeaderTitleClass }}">🎲 百家乐 #{{ $round->id }} 局下注明细</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
结算时间:{{ $round->settled_at?->format('Y-m-d H:i:s') ?? '未结算' }}
&nbsp;·&nbsp;结果:
<span class="font-bold text-indigo-600">{{ $round->resultLabel() }}</span>
&nbsp;·&nbsp;总点数:<span class="font-bold">{{ $round->total_points }}</span>
&nbsp;·&nbsp;结果:<span class="font-semibold text-indigo-600">{{ $round->resultLabel() }}</span>
&nbsp;·&nbsp;总点数:<span class="font-semibold text-gray-700">{{ $round->total_points }}</span>
</p>
</div>
<a href="{{ route('admin.game-history.baccarat') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-history.baccarat') }}" class="{{ $adminListSecondaryButtonClass }}">
返回历史列表
</a>
</div>
{{-- 本局摘要 --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($round->bet_count ?? 0) }}</div>
<div class="text-xs text-gray-500 mt-1">参与下注人数</div>
<div class="mt-1 text-xs text-gray-500">参与下注人数</div>
</div>
<div class="bg-red-50 rounded-xl shadow-sm border border-red-100 p-5">
<div class="rounded-xl border border-red-100 bg-red-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-red-600">{{ number_format($round->total_bet_big ?? 0) }}</div>
<div class="text-xs text-red-400 mt-1">押大总金额</div>
<div class="mt-1 text-xs text-red-400">押大总金额</div>
</div>
<div class="bg-blue-50 rounded-xl shadow-sm border border-blue-100 p-5">
<div class="rounded-xl border border-blue-100 bg-blue-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-blue-600">{{ number_format($round->total_bet_small ?? 0) }}</div>
<div class="text-xs text-blue-400 mt-1">押小总金额</div>
<div class="mt-1 text-xs text-blue-400">押小总金额</div>
</div>
<div class="bg-amber-50 rounded-xl shadow-sm border border-amber-100 p-5">
<div class="rounded-xl border border-amber-100 bg-amber-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($round->total_payout ?? 0) }}</div>
<div class="text-xs text-amber-400 mt-1">本局派奖总额</div>
<div class="mt-1 text-xs text-amber-400">本局派奖总额</div>
</div>
</div>
{{-- 下注明细表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">玩家</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">押注方向</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">押注金额</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">实际获得</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">是否中奖</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">下注时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($bets as $bet)
@php
$betLabels = ['big' => '大', 'small' => '小', 'triple' => '豹子'];
$betColors = [
'big' => 'bg-red-100 text-red-700',
'small' => 'bg-blue-100 text-blue-700',
'triple' => 'bg-purple-100 text-purple-700',
];
$won = $bet->payout > 0;
@endphp
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 font-medium text-gray-800">
{{ $bet->user?->username ?? '已注销' }}
</td>
<td class="px-4 py-3 text-center">
<span
class="px-2 py-0.5 rounded-full text-xs font-bold {{ $betColors[$bet->bet_type] ?? 'bg-gray-100 text-gray-600' }}">
{{ $betLabels[$bet->bet_type] ?? $bet->bet_type }}
</span>
</td>
<td class="px-4 py-3 text-right font-mono text-sm text-gray-700">
{{ number_format($bet->amount) }}
</td>
<td
class="px-4 py-3 text-right font-mono text-sm {{ $won ? 'text-emerald-600 font-bold' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($bet->payout) : '0' }}
</td>
<td class="px-4 py-3 text-center">
@if ($won)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-emerald-100 text-emerald-700">🎉
中奖</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-gray-100 text-gray-500">未中</span>
@endif
</td>
<td class="px-4 py-3 text-right text-xs text-gray-400">
{{ $bet->created_at->format('H:i:s') }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">下注明细</div>
<div class="{{ $adminListSectionDescClass }}">保留原有大小单双与中奖状态颜色,统一列表结构与空态层级。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">玩家</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">押注方向</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">押注金额</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">实际获得</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">是否中奖</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">下注时间</th>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-10 text-center text-gray-400 text-sm">本局无人下注</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($bets as $bet)
@php
$betLabels = ['big' => '大', 'small' => '小', 'triple' => '豹子'];
$betColors = [
'big' => 'bg-red-100 text-red-700 border-red-200',
'small' => 'bg-blue-100 text-blue-700 border-blue-200',
'triple' => 'bg-purple-100 text-purple-700 border-purple-200',
];
$won = $bet->payout > 0;
@endphp
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $bet->user?->username ?? '已注销' }}
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $betColors[$bet->bet_type] ?? 'bg-gray-100 text-gray-600 border-gray-200' }}">
{{ $betLabels[$bet->bet_type] ?? $bet->bet_type }}
</span>
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} text-gray-700">
{{ number_format($bet->amount) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} {{ $won ? 'font-semibold text-emerald-600' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($bet->payout) : '0' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($won)
<span class="{{ $badgeClass }} bg-emerald-100 text-emerald-700 border-emerald-200">🎉 中奖</span>
@else
<span class="{{ $badgeClass }} bg-gray-100 text-gray-500 border-gray-200">未中</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListSecondaryTextClass }}">
{{ $bet->created_at->format('H:i:s') }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="{{ $adminListEmptyClass }}">本局无人下注</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($bets->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $bets->links() }}
</div>
@endif
@@ -3,43 +3,46 @@
@section('title', '百家乐历史记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🎲 百家乐历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询所有已结算的百家乐局次及下注明细。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">🎲 百家乐历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询所有已结算的百家乐局次及下注明细。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-5 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_rounds']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总局数</div>
<div class="mt-1 text-xs text-gray-500">历史总局数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($summary['total_bets']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总下注次</div>
<div class="mt-1 text-xs text-gray-500">历史总下注次</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['total_payout']) }}</div>
<div class="text-xs text-gray-500 mt-1">累计派奖金币</div>
<div class="mt-1 text-xs text-gray-500">累计派奖金币</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-red-100 p-5">
<div class="rounded-xl border border-red-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-red-600">{{ number_format($summary['total_lost']) }}</div>
<div class="text-xs text-gray-500 mt-1">会员输掉金币</div>
<div class="mt-1 text-xs text-gray-500">会员输掉金币</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-sm font-bold text-gray-700 mb-2">结果分布</div>
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="mb-2 text-sm font-bold text-gray-700">结果分布</div>
<div class="space-y-1">
@foreach (['big' => '大', 'small' => '小', 'triple' => '豹子', 'kill' => '收割'] as $key => $label)
<div class="flex justify-between text-xs">
<div class="flex items-center justify-between text-xs">
<span class="text-gray-500">{{ $label }}</span>
<span class="font-bold text-gray-700">{{ $summary['result_dist'][$key] ?? 0 }} </span>
</div>
@@ -48,93 +51,96 @@
</div>
</div>
{{-- 局次列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">局次ID</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">结算时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">骰子</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">点数</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">结果</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">押注笔数</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">押大//</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">派奖金币</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($rounds as $round)
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-400 text-xs font-mono">#{{ $round->id }}</td>
<td class="px-4 py-3 text-xs text-gray-600">
{{ $round->settled_at ? $round->settled_at->format('m-d H:i') : '—' }}
</td>
<td class="px-4 py-3 text-center text-lg">
@if ($round->dice1)
{{ $round->dice1 }} {{ $round->dice2 }} {{ $round->dice3 }}
@else
@endif
</td>
<td class="px-4 py-3 text-center font-bold text-gray-700">
{{ $round->total_points ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
@php
$resultColors = [
'big' => 'bg-red-100 text-red-700',
'small' => 'bg-blue-100 text-blue-700',
'triple' => 'bg-purple-100 text-purple-700',
'kill' => 'bg-gray-100 text-gray-600',
];
$label = match ($round->result) {
'big' => '大',
'small' => '小',
'triple' => '豹子',
'kill' => '收割',
default => $round->result ?? '—',
};
$colorClass = $resultColors[$round->result] ?? 'bg-gray-100 text-gray-600';
@endphp
@if ($round->result)
<span class="px-2 py-0.5 rounded-full text-xs font-bold {{ $colorClass }}">
{{ $label }}
</span>
@else
<span class="text-gray-400 text-xs">未结算</span>
@endif
</td>
<td class="px-4 py-3 text-center text-xs font-bold text-indigo-600">
{{ number_format($round->bet_count ?? 0) }}
</td>
<td class="px-4 py-3 text-right text-xs text-gray-500 font-mono">
<span class="text-red-500">{{ number_format($round->total_bet_big ?? 0) }}</span> /
<span class="text-blue-500">{{ number_format($round->total_bet_small ?? 0) }}</span> /
<span class="text-purple-500">{{ number_format($round->total_bet_triple ?? 0) }}</span>
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-amber-600 font-bold">
{{ number_format($round->total_payout ?? 0) }}
</td>
<td class="px-4 py-3 text-right">
<a href="{{ route('admin.game-history.baccarat.round', $round->id) }}"
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition">
下注明细
</a>
</td>
</tr>
@empty
<tr>
<td colspan="9" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">局次列表</div>
<div class="{{ $adminListSectionDescClass }}">统一展示结算结果、投注分布与派奖数据。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">局次ID</th>
<th class="{{ $adminListTableHeadCellClass }}">结算时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">骰子</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">点数</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">结果</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">押注笔数</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">押大//</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">派奖金币</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($rounds as $round)
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }} font-mono">#{{ $round->id }}</td>
<td class="{{ $tableCellClass }} {{ $adminListBodyTextClass }}">
{{ $round->settled_at ? $round->settled_at->format('m-d H:i') : '—' }}
</td>
<td class="{{ $tableCellClass }} text-center text-lg">
@if ($round->dice1)
{{ $round->dice1 }} {{ $round->dice2 }} {{ $round->dice3 }}
@else
@endif
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListPrimaryTextClass }}">
{{ $round->total_points ?? '—' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@php
$resultColors = [
'big' => 'bg-red-100 text-red-700 border-red-200',
'small' => 'bg-blue-100 text-blue-700 border-blue-200',
'triple' => 'bg-purple-100 text-purple-700 border-purple-200',
'kill' => 'bg-gray-100 text-gray-600 border-gray-200',
];
$label = match ($round->result) {
'big' => '大',
'small' => '小',
'triple' => '豹子',
'kill' => '收割',
default => $round->result ?? '—',
};
$colorClass = $resultColors[$round->result] ?? 'bg-gray-100 text-gray-600 border-gray-200';
@endphp
@if ($round->result)
<span class="{{ $badgeClass }} {{ $colorClass }}">{{ $label }}</span>
@else
<span class="{{ $adminListSecondaryTextClass }}">未结算</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-center text-sm font-semibold text-indigo-600">
{{ number_format($round->bet_count ?? 0) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} text-gray-500">
<span class="text-red-500">{{ number_format($round->total_bet_big ?? 0) }}</span> /
<span class="text-blue-500">{{ number_format($round->total_bet_small ?? 0) }}</span> /
<span class="text-purple-500">{{ number_format($round->total_bet_triple ?? 0) }}</span>
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold text-amber-600">
{{ number_format($round->total_payout ?? 0) }}
</td>
<td class="{{ $tableCellClass }} text-right">
<a href="{{ route('admin.game-history.baccarat.round', $round->id) }}"
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-700 hover:bg-indigo-100">
下注明细
</a>
</td>
</tr>
@empty
<tr>
<td colspan="9" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- 分页 --}}
@if ($rounds->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $rounds->links() }}
</div>
@endif
@@ -3,49 +3,49 @@
@section('title', '神秘占卜历史记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
$gradeAll = [
'jackpot' => ['label' => '上上签', 'color' => 'text-amber-600'],
'good' => ['label' => '上签', 'color' => 'text-emerald-600'],
'normal' => ['label' => '中签', 'color' => 'text-gray-500'],
'bad' => ['label' => '下签', 'color' => 'text-orange-500'],
'curse' => ['label' => '大凶签', 'color' => 'text-red-600'],
];
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🔮 神秘占卜历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询所有玩家的占卜记录,支持按等级和玩家名筛选。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">🔮 神秘占卜历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询所有玩家的占卜记录,支持按等级和玩家名筛选。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_times']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总占卜次</div>
<div class="mt-1 text-xs text-gray-500">历史总占卜次</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-2xl font-bold text-amber-500">{{ number_format($summary['grade_dist']['jackpot'] ?? 0) }}
</div>
<div class="text-xs text-gray-500 mt-1"> 上上签次数</div>
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-500">{{ number_format($summary['grade_dist']['jackpot'] ?? 0) }}</div>
<div class="mt-1 text-xs text-gray-500"> 上上签次数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-red-500">{{ number_format($summary['grade_dist']['curse'] ?? 0) }}</div>
<div class="text-xs text-gray-500 mt-1">💀 大凶签次数</div>
<div class="mt-1 text-xs text-gray-500">💀 大凶签次数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-sm font-bold text-gray-700 mb-2">签文分布</div>
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="mb-2 text-sm font-bold text-gray-700">签文分布</div>
<div class="space-y-1">
@php
$gradeAll = [
'jackpot' => ['label' => '上上签', 'color' => 'text-amber-600'],
'good' => ['label' => '上签', 'color' => 'text-emerald-600'],
'normal' => ['label' => '中签', 'color' => 'text-gray-500'],
'bad' => ['label' => '下签', 'color' => 'text-orange-500'],
'curse' => ['label' => '大凶签', 'color' => 'text-red-600'],
];
@endphp
@foreach ($gradeAll as $key => $meta)
<div class="flex justify-between text-xs">
<div class="flex items-center justify-between text-xs">
<span class="{{ $meta['color'] }}">{{ $meta['label'] }}</span>
<span class="font-bold text-gray-700">{{ $summary['grade_dist'][$key] ?? 0 }}</span>
</div>
@@ -54,107 +54,100 @@
</div>
</div>
{{-- 筛选 --}}
<form method="GET"
class="bg-white rounded-xl shadow-sm border border-gray-100 p-4 flex flex-wrap items-end gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">签文等级</label>
<select name="grade"
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 min-w-[130px]">
<option value="">全部等级</option>
@foreach ($gradeAll as $key => $meta)
<option value="{{ $key }}" {{ request('grade') === $key ? 'selected' : '' }}>
{{ $meta['label'] }}
</option>
@endforeach
</select>
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">签文等级</label>
<select name="grade" class="min-w-[130px] {{ $adminListFilterInputClass }}">
<option value="">全部等级</option>
@foreach ($gradeAll as $key => $meta)
<option value="{{ $key }}" {{ request('grade') === $key ? 'selected' : '' }}>
{{ $meta['label'] }}
</option>
@endforeach
</select>
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">玩家名称</label>
<input type="text" name="username" value="{{ request('username') }}" placeholder="模糊搜索..."
class="w-40 {{ $adminListFilterInputClass }}">
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">筛选</button>
<a href="{{ route('admin.game-history.fortune') }}" class="{{ $adminListSecondaryButtonClass }}">重置</a>
</form>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">玩家名称</label>
<input type="text" name="username" value="{{ request('username') }}" placeholder="模糊搜索..."
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 w-40">
</div>
<div class="flex gap-2">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
🔍 筛选
</button>
<a href="{{ route('admin.game-history.fortune') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
重置
</a>
</div>
</form>
</div>
{{-- 记录列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">时间</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">玩家</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">签文等级</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase w-1/3">签文内容</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">加成/减益</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">是否免费</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">消耗金币</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($logs as $log)
@php
$gradeInfo = match ($log->grade) {
'jackpot' => ['label' => '✨ 上上签', 'color' => 'bg-amber-100 text-amber-700'],
'good' => ['label' => '🌸 上签', 'color' => 'bg-emerald-100 text-emerald-700'],
'normal' => ['label' => '📜 中签', 'color' => 'bg-gray-100 text-gray-600'],
'bad' => ['label' => '😞 下签', 'color' => 'bg-orange-100 text-orange-700'],
'curse' => ['label' => '💀 大凶签', 'color' => 'bg-red-100 text-red-700'],
default => ['label' => $log->grade, 'color' => 'bg-gray-100 text-gray-500'],
};
@endphp
<tr
class="hover:bg-gray-50 transition {{ in_array($log->grade, ['jackpot']) ? 'bg-amber-50/50' : (in_array($log->grade, ['curse']) ? 'bg-red-50/30' : '') }}">
<td class="px-4 py-3 text-xs text-gray-400">
{{ $log->created_at->format('m-d H:i') }}
</td>
<td class="px-4 py-3 font-medium text-gray-800">
{{ $log->user?->username ?? '已注销' }}
</td>
<td class="px-4 py-3 text-center">
<span class="px-2 py-0.5 rounded-full text-xs font-bold {{ $gradeInfo['color'] }}">
{{ $gradeInfo['label'] }}
</span>
</td>
<td class="px-4 py-3 text-xs text-gray-600 leading-relaxed">
{{ \Illuminate\Support\Str::limit($log->text, 50) }}
</td>
<td class="px-4 py-3 text-xs text-gray-500">
{{ $log->buff_desc ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
@if ($log->is_free)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-emerald-100 text-emerald-700">免费</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-amber-100 text-amber-700">付费</span>
@endif
</td>
<td
class="px-4 py-3 text-right font-mono text-xs {{ $log->cost > 0 ? 'text-red-500' : 'text-gray-400' }}">
{{ $log->cost > 0 ? '-' . number_format($log->cost) : '0' }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">占卜记录</div>
<div class="{{ $adminListSectionDescClass }}">统一表格与筛选层级,保留签文等级、免费状态和消耗配色。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">时间</th>
<th class="{{ $adminListTableHeadCellClass }}">玩家</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">签文等级</th>
<th class="{{ $adminListTableHeadCellClass }} w-1/3">签文内容</th>
<th class="{{ $adminListTableHeadCellClass }}">加成/减益</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">是否免费</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">消耗金币</th>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
@php
$gradeInfo = match ($log->grade) {
'jackpot' => ['label' => '✨ 上上签', 'color' => 'bg-amber-100 text-amber-700 border-amber-200'],
'good' => ['label' => '🌸 上签', 'color' => 'bg-emerald-100 text-emerald-700 border-emerald-200'],
'normal' => ['label' => '📜 中签', 'color' => 'bg-gray-100 text-gray-600 border-gray-200'],
'bad' => ['label' => '😞 下签', 'color' => 'bg-orange-100 text-orange-700 border-orange-200'],
'curse' => ['label' => '💀 大凶签', 'color' => 'bg-red-100 text-red-700 border-red-200'],
default => ['label' => $log->grade, 'color' => 'bg-gray-100 text-gray-500 border-gray-200'],
};
@endphp
<tr class="{{ $adminListTableRowClass }} {{ in_array($log->grade, ['jackpot']) ? 'bg-amber-50/50' : (in_array($log->grade, ['curse']) ? 'bg-red-50/30' : '') }}">
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }}">
{{ $log->created_at->format('m-d H:i') }}
</td>
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $log->user?->username ?? '已注销' }}
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $gradeInfo['color'] }}">{{ $gradeInfo['label'] }}</span>
</td>
<td class="{{ $tableCellClass }} text-xs leading-relaxed text-gray-600">
{{ \Illuminate\Support\Str::limit($log->text, 50) }}
</td>
<td class="{{ $tableCellClass }} text-xs text-gray-500">
{{ $log->buff_desc ?? '—' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($log->is_free)
<span class="{{ $badgeClass }} border-emerald-200 bg-emerald-100 text-emerald-700">免费</span>
@else
<span class="{{ $badgeClass }} border-amber-200 bg-amber-100 text-amber-700">付费</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} {{ $log->cost > 0 ? 'text-red-500' : 'text-gray-400' }}">
{{ $log->cost > 0 ? '-' . number_format($log->cost) : '0' }}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $logs->links() }}
</div>
@endif
@@ -3,120 +3,122 @@
@section('title', '五子棋对局记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">♟️ 五子棋历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询全站所有的五子棋人机及 PvP 对局。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">♟️ 五子棋历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询全站所有的五子棋人机及 PvP 对局。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_games']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史对局数</div>
<div class="mt-1 text-xs text-gray-500">历史对局数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['completed']) }}</div>
<div class="text-xs text-gray-500 mt-1">正常完赛</div>
<div class="mt-1 text-xs text-gray-500">正常完赛</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($summary['pvp_count']) }}</div>
<div class="text-xs text-gray-500 mt-1">PvP 人人对战数</div>
<div class="mt-1 text-xs text-gray-500">PvP 人人对战数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-rose-600">{{ number_format($summary['today_games']) }}</div>
<div class="text-xs text-gray-500 mt-1">今日新建对局</div>
<div class="mt-1 text-xs text-gray-500">今日新建对局</div>
</div>
</div>
{{-- 期数列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">赛事ID</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">创建时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">模式</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">黑方 (发起)</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">白方 (迎战)</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">胜负</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($games as $game)
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-600 text-xs font-mono font-bold">#{{ $game->id }}</td>
<td class="px-4 py-3 text-xs text-gray-600">
{{ $game->created_at ? $game->created_at->format('m-d H:i') : '—' }}
</td>
<td class="px-4 py-3 text-center">
@if ($game->mode === 'pve')
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-purple-100 text-purple-700">单机
PvEL{{ $game->ai_level }}</span>
@else
<span class="px-2 py-0.5 rounded-full text-xs font-bold bg-blue-100 text-blue-700">在线
PvP</span>
@endif
</td>
<td class="px-4 py-3 text-center font-bold">
{{ $game->playerBlack?->username ?? '已注销/未知' }}
</td>
<td class="px-4 py-3 text-center font-bold">
@if ($game->mode === 'pve')
<span class="text-xs text-gray-400">AI 机器人</span>
@else
{{ $game->playerWhite?->username ?? '已注销/未加入' }}
@endif
</td>
<td class="px-4 py-3 text-center">
@php
$s = match ($game->status) {
'waiting' => ['label' => '等待中', 'bg' => 'bg-amber-100 text-amber-600'],
'playing' => ['label' => '对弈中', 'bg' => 'bg-blue-100 text-blue-600'],
'finished' => ['label' => '已结束', 'bg' => 'bg-emerald-100 text-emerald-700'],
default => ['label' => $game->status, 'bg' => 'bg-gray-100 text-gray-600'],
};
@endphp
<span
class="px-2 py-0.5 rounded-full text-xs font-bold {{ $s['bg'] }}">{{ $s['label'] }}</span>
</td>
<td class="px-4 py-3 text-center">
@if ($game->status !== 'finished')
<span class="text-xs text-gray-400">-</span>
@else
@if ($game->winner === 1)
<span class="text-xs font-bold text-gray-800 bg-gray-200 px-2 py-1 rounded">
黑胜</span>
@elseif($game->winner === 2)
<span class="text-xs font-bold bg-white border border-gray-300 px-2 py-1 rounded">
白胜</span>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">对局列表</div>
<div class="{{ $adminListSectionDescClass }}">统一表格层次,保留 PvE/PvP、对局状态与胜负视觉语义。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">赛事ID</th>
<th class="{{ $adminListTableHeadCellClass }}">创建时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">模式</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">黑方 (发起)</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">白方 (迎战)</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">胜负</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($games as $game)
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }} font-mono">#{{ $game->id }}</td>
<td class="{{ $tableCellClass }} {{ $adminListBodyTextClass }}">
{{ $game->created_at ? $game->created_at->format('m-d H:i') : '—' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($game->mode === 'pve')
<span class="{{ $badgeClass }} border-purple-200 bg-purple-100 text-purple-700">单机 PvEL{{ $game->ai_level }}</span>
@else
<span
class="text-xs font-bold text-gray-500 bg-gray-100 px-2 py-1 rounded">平局撤销</span>
<span class="{{ $badgeClass }} border-blue-200 bg-blue-100 text-blue-700">在线 PvP</span>
@endif
@endif
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListPrimaryTextClass }}">
{{ $game->playerBlack?->username ?? '已注销/未知' }}
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListPrimaryTextClass }}">
@if ($game->mode === 'pve')
<span class="{{ $adminListSecondaryTextClass }}">AI 机器人</span>
@else
{{ $game->playerWhite?->username ?? '已注销/未加入' }}
@endif
</td>
<td class="{{ $tableCellClass }} text-center">
@php
$s = match ($game->status) {
'waiting' => ['label' => '等待中', 'bg' => 'bg-amber-100 text-amber-600 border-amber-200'],
'playing' => ['label' => '对弈中', 'bg' => 'bg-blue-100 text-blue-600 border-blue-200'],
'finished' => ['label' => '已结束', 'bg' => 'bg-emerald-100 text-emerald-700 border-emerald-200'],
default => ['label' => $game->status, 'bg' => 'bg-gray-100 text-gray-600 border-gray-200'],
};
@endphp
<span class="{{ $badgeClass }} {{ $s['bg'] }}">{{ $s['label'] }}</span>
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($game->status !== 'finished')
<span class="{{ $adminListSecondaryTextClass }}">-</span>
@else
@if ($game->winner === 1)
<span class="{{ $badgeClass }} border-gray-300 bg-gray-200 text-gray-800"> 黑胜</span>
@elseif ($game->winner === 2)
<span class="{{ $badgeClass }} border-gray-300 bg-white text-gray-700"> 白胜</span>
@else
<span class="{{ $badgeClass }} border-gray-200 bg-gray-100 text-gray-500">平局撤销</span>
@endif
@endif
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($games->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $games->links() }}
</div>
@endif
@@ -3,43 +3,44 @@
@section('title', "赛马第 #{$race->id} 场下注明细")
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
@php
$horses = $race->horses ?? [];
$winner = collect($horses)->firstWhere('id', $race->winner_horse_id);
@endphp
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$horses = $race->horses ?? [];
$winner = collect($horses)->firstWhere('id', $race->winner_horse_id);
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🐎 赛马 #{{ $race->id }} 场下注明细</h2>
<p class="text-xs text-gray-500 mt-1">
<h2 class="{{ $adminListHeaderTitleClass }}">🐎 赛马 #{{ $race->id }} 场下注明细</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
结算时间:{{ $race->settled_at?->format('Y-m-d H:i:s') ?? '未结算' }}
@if ($winner)
&nbsp;·&nbsp;胜者:<span class="font-bold text-indigo-600">{{ $winner['emoji'] ?? '' }}
{{ $winner['name'] ?? '' }}</span>
&nbsp;·&nbsp;胜者:<span class="font-semibold text-indigo-600">{{ $winner['emoji'] ?? '' }} {{ $winner['name'] ?? '' }}</span>
@endif
&nbsp;·&nbsp;注池:<span class="font-bold text-amber-600">{{ number_format($race->total_pool ?? 0) }}
金币</span>
&nbsp;·&nbsp;注池:<span class="font-semibold text-amber-600">{{ number_format($race->total_pool ?? 0) }} 金币</span>
</p>
</div>
<a href="{{ route('admin.game-history.horse') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-history.horse') }}" class="{{ $adminListSecondaryButtonClass }}">
返回场次列表
</a>
</div>
{{-- 马匹信息 --}}
@if (count($horses) > 0)
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-sm font-bold text-gray-700 mb-3">参赛马匹</div>
<div class="flex flex-wrap gap-3">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">参赛马匹</div>
<div class="{{ $adminListSectionDescClass }}">保留冠军高亮,仅统一容器与间距风格。</div>
</div>
<div class="flex flex-wrap gap-3 p-6">
@foreach ($horses as $horse)
<div
class="px-4 py-2 rounded-lg {{ $horse['id'] === $race->winner_horse_id ? 'bg-amber-100 border-2 border-amber-400' : 'bg-gray-100' }}">
class="rounded-lg border px-4 py-3 {{ $horse['id'] === $race->winner_horse_id ? 'border-amber-400 bg-amber-100' : 'border-gray-200 bg-gray-50' }}">
<div class="text-lg">{{ $horse['emoji'] ?? '🐎' }}</div>
<div
class="text-xs font-bold {{ $horse['id'] === $race->winner_horse_id ? 'text-amber-700' : 'text-gray-600' }}">
<div class="mt-1 text-xs font-bold {{ $horse['id'] === $race->winner_horse_id ? 'text-amber-700' : 'text-gray-600' }}">
{{ $horse['name'] }}
@if ($horse['id'] === $race->winner_horse_id)
🏆
@@ -51,71 +52,72 @@
</div>
@endif
{{-- 下注明细表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">玩家</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">押注马匹</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">押注金额</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">实际获得</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">是否中奖</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">下注时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($bets as $bet)
@php
$betHorse = collect($horses)->firstWhere('id', $bet->horse_id);
$isWinner = $bet->horse_id === $race->winner_horse_id;
$won = ($bet->payout ?? 0) > 0;
@endphp
<tr class="hover:bg-gray-50 transition {{ $won ? 'bg-amber-50/50' : '' }}">
<td class="px-4 py-3 font-medium text-gray-800">
{{ $bet->user?->username ?? '已注销' }}
</td>
<td class="px-4 py-3 text-center">
@if ($betHorse)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold {{ $isWinner ? 'bg-amber-100 text-amber-700' : 'bg-gray-100 text-gray-600' }}">
{{ $betHorse['emoji'] ?? '' }} {{ $betHorse['name'] ?? '' }}
</span>
@else
<span class="text-gray-400 text-xs">#{{ $bet->horse_id }}</span>
@endif
</td>
<td class="px-4 py-3 text-right font-mono text-sm text-gray-700">
{{ number_format($bet->amount) }}
</td>
<td
class="px-4 py-3 text-right font-mono text-sm {{ $won ? 'text-emerald-600 font-bold' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($bet->payout) : '0' }}
</td>
<td class="px-4 py-3 text-center">
@if ($won)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-emerald-100 text-emerald-700">🎉
中奖</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-gray-100 text-gray-500">未中</span>
@endif
</td>
<td class="px-4 py-3 text-right text-xs text-gray-400">
{{ $bet->created_at->format('H:i:s') }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">下注明细</div>
<div class="{{ $adminListSectionDescClass }}">统一下注列表样式,保留命中胜马与中奖状态颜色。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">玩家</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">押注马匹</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">押注金额</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">实际获得</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">是否中奖</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">下注时间</th>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-10 text-center text-gray-400 text-sm">本场无人下注</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($bets as $bet)
@php
$betHorse = collect($horses)->firstWhere('id', $bet->horse_id);
$isWinner = $bet->horse_id === $race->winner_horse_id;
$won = ($bet->payout ?? 0) > 0;
@endphp
<tr class="{{ $adminListTableRowClass }} {{ $won ? 'bg-amber-50/50' : '' }}">
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $bet->user?->username ?? '已注销' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($betHorse)
<span class="{{ $badgeClass }} {{ $isWinner ? 'border-amber-200 bg-amber-100 text-amber-700' : 'border-gray-200 bg-gray-100 text-gray-600' }}">
{{ $betHorse['emoji'] ?? '' }} {{ $betHorse['name'] ?? '' }}
</span>
@else
<span class="{{ $adminListSecondaryTextClass }}">#{{ $bet->horse_id }}</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} text-gray-700">
{{ number_format($bet->amount) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} {{ $won ? 'font-semibold text-emerald-600' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($bet->payout) : '0' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($won)
<span class="{{ $badgeClass }} border-emerald-200 bg-emerald-100 text-emerald-700">🎉 中奖</span>
@else
<span class="{{ $badgeClass }} border-gray-200 bg-gray-100 text-gray-500">未中</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListSecondaryTextClass }}">
{{ $bet->created_at->format('H:i:s') }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="{{ $adminListEmptyClass }}">本场无人下注</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($bets->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $bets->links() }}
</div>
@endif
@@ -3,108 +3,115 @@
@section('title', '赛马竞猜历史记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🐎 赛马竞猜历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询所有已完成的赛马场次及下注明细。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">🐎 赛马竞猜历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询所有已完成的赛马场次及下注明细。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_races']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总场次</div>
<div class="mt-1 text-xs text-gray-500">历史总场次</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($summary['total_bets']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总下注笔</div>
<div class="mt-1 text-xs text-gray-500">历史总下注笔</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['total_pool']) }}</div>
<div class="text-xs text-gray-500 mt-1">累计注池金币</div>
<div class="mt-1 text-xs text-gray-500">累计注池金币</div>
</div>
</div>
{{-- 场次列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">场次ID</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">结算时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">参赛马匹</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">胜者</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">下注总笔</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">注池总额</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($races as $race)
@php
$horses = $race->horses ?? [];
$winner = collect($horses)->firstWhere('id', $race->winner_horse_id);
$statusLabel = match ($race->status) {
'betting' => ['label' => '押注中', 'color' => 'bg-blue-100 text-blue-700'],
'running' => ['label' => '比赛中', 'color' => 'bg-amber-100 text-amber-700'],
'settled' => ['label' => '已结算', 'color' => 'bg-emerald-100 text-emerald-700'],
'canceled' => ['label' => '已取消', 'color' => 'bg-red-100 text-red-600'],
default => ['label' => $race->status, 'color' => 'bg-gray-100 text-gray-500'],
};
@endphp
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-400 text-xs font-mono">#{{ $race->id }}</td>
<td class="px-4 py-3 text-xs text-gray-600">
{{ $race->settled_at ? $race->settled_at->format('m-d H:i') : '—' }}
</td>
<td class="px-4 py-3 text-center text-sm">
{{ collect($horses)->pluck('emoji')->implode('') ?: '—' }}
<span class="text-xs text-gray-400">{{ count($horses) }} 匹)</span>
</td>
<td class="px-4 py-3 text-center font-bold text-indigo-700">
@if ($winner)
{{ $winner['emoji'] ?? '' }} {{ $winner['name'] ?? '' }}
@else
<span class="text-gray-400"></span>
@endif
</td>
<td class="px-4 py-3 text-center">
<span class="px-2 py-0.5 rounded-full text-xs font-bold {{ $statusLabel['color'] }}">
{{ $statusLabel['label'] }}
</span>
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-indigo-600 font-bold">
{{ number_format($race->total_bets ?? 0) }}
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-amber-600 font-bold">
{{ number_format($race->total_pool ?? 0) }}
</td>
<td class="px-4 py-3 text-right">
<a href="{{ route('admin.game-history.horse.race', $race->id) }}"
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition">
下注明细
</a>
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">场次列表</div>
<div class="{{ $adminListSectionDescClass }}">统一表格层级,保留场次状态与胜者展示语义。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">场次ID</th>
<th class="{{ $adminListTableHeadCellClass }}">结算时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">参赛马匹</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">胜者</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">下注总笔</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">注池总额</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($races as $race)
@php
$horses = $race->horses ?? [];
$winner = collect($horses)->firstWhere('id', $race->winner_horse_id);
$statusLabel = match ($race->status) {
'betting' => ['label' => '押注中', 'color' => 'bg-blue-100 text-blue-700 border-blue-200'],
'running' => ['label' => '比赛中', 'color' => 'bg-amber-100 text-amber-700 border-amber-200'],
'settled' => ['label' => '已结算', 'color' => 'bg-emerald-100 text-emerald-700 border-emerald-200'],
'canceled' => ['label' => '已取消', 'color' => 'bg-red-100 text-red-600 border-red-200'],
default => ['label' => $race->status, 'color' => 'bg-gray-100 text-gray-500 border-gray-200'],
};
@endphp
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }} font-mono">#{{ $race->id }}</td>
<td class="{{ $tableCellClass }} {{ $adminListBodyTextClass }}">
{{ $race->settled_at ? $race->settled_at->format('m-d H:i') : '—' }}
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListBodyTextClass }}">
{{ collect($horses)->pluck('emoji')->implode('') ?: '—' }}
<span class="{{ $adminListSecondaryTextClass }}">{{ count($horses) }} 匹)</span>
</td>
<td class="{{ $tableCellClass }} text-center font-semibold text-indigo-700">
@if ($winner)
{{ $winner['emoji'] ?? '' }} {{ $winner['name'] ?? '' }}
@else
<span class="{{ $adminListSecondaryTextClass }}"></span>
@endif
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $statusLabel['color'] }}">{{ $statusLabel['label'] }}</span>
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold text-indigo-600">
{{ number_format($race->total_bets ?? 0) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold text-amber-600">
{{ number_format($race->total_pool ?? 0) }}
</td>
<td class="{{ $tableCellClass }} text-right">
<a href="{{ route('admin.game-history.horse.race', $race->id) }}"
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-700 hover:bg-indigo-100">
下注明细
</a>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($races->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $races->links() }}
</div>
@endif
@@ -3,117 +3,111 @@
@section('title', "双色球第 {$issue->issue_no} 期购买明细")
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🎟️ 双色球 {{ $issue->issue_no }} 期购买明细</h2>
<p class="text-xs text-gray-500 mt-1">
<h2 class="{{ $adminListHeaderTitleClass }}">🎟️ 双色球第 {{ $issue->issue_no }} 期购买明细</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
开奖时间:{{ $issue->draw_at?->format('Y-m-d H:i:s') ?? '未开奖' }}
@if ($issue->status === 'settled')
&nbsp;·&nbsp;开奖号码:
<span class="font-bold text-indigo-600">
<span
class="bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="bg-blue-100 text-blue-600 px-1 rounded">{{ str_pad($issue->blue, 2, '0', STR_PAD_LEFT) }}</span>
<span class="inline-flex items-center gap-1 font-semibold text-indigo-600">
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-red-600">{{ str_pad($issue->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-red-600">{{ str_pad($issue->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-red-600">{{ str_pad($issue->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-blue-200 bg-blue-100 px-1.5 py-0.5 text-blue-600">{{ str_pad($issue->blue, 2, '0', STR_PAD_LEFT) }}</span>
</span>
@endif
&nbsp;·&nbsp;奖池:<span class="font-bold text-amber-600">{{ number_format($issue->pool_amount ?? 0) }}
金币</span>
&nbsp;·&nbsp;奖池:<span class="font-semibold text-amber-600">{{ number_format($issue->pool_amount ?? 0) }} 金币</span>
</p>
</div>
<a href="{{ route('admin.game-history.lottery') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-history.lottery') }}" class="{{ $adminListSecondaryButtonClass }}">
返回期号列表
</a>
</div>
{{-- 购买明细表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">玩家</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">投注号码</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">彩票类型</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">花费</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">奖金获得</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">中奖等级</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">下注时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($tickets as $ticket)
@php
$won = ($ticket->payout ?? 0) > 0;
@endphp
<tr class="hover:bg-gray-50 transition {{ $won ? 'bg-amber-50/50' : '' }}">
<td class="px-4 py-3 font-medium text-gray-800">
{{ $ticket->user?->username ?? '已注销' }}
</td>
<td class="px-4 py-3 text-center font-mono">
<div class="flex items-center justify-center gap-1 flex-wrap">
<span
class="text-xs bg-red-50 text-red-500 px-1 rounded shadow-sm border border-red-100">{{ str_pad($ticket->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-red-50 text-red-500 px-1 rounded shadow-sm border border-red-100">{{ str_pad($ticket->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-red-50 text-red-500 px-1 rounded shadow-sm border border-red-100">{{ str_pad($ticket->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-blue-50 text-blue-500 px-1 rounded shadow-sm border border-blue-100">{{ str_pad($ticket->blue, 2, '0', STR_PAD_LEFT) }}</span>
</div>
</td>
<td class="px-4 py-3 text-center">
@if ($ticket->is_quick_pick)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-purple-100 text-purple-700">随机机选</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-blue-100 text-blue-700">自选号码</span>
@endif
</td>
<td class="px-4 py-3 text-right font-mono text-sm text-gray-700">
{{ number_format($ticket->amount) }}
</td>
<td
class="px-4 py-3 text-right font-mono text-sm {{ $won ? 'text-emerald-600 font-bold' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($ticket->payout) : '0' }}
</td>
<td class="px-4 py-3 text-center">
@if ($issue->status === 'settled')
@if ($won)
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-amber-100 text-amber-700">
🎉 {{ $ticket->prize_level }}等奖
</span>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">购买明细</div>
<div class="{{ $adminListSectionDescClass }}">统一明细表格样式,保留号码球颜色、票种和中奖等级语义。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">玩家</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">投注号码</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">彩票类型</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">花费</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">奖金获得</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">中奖等级</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">下注时间</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($tickets as $ticket)
@php
$won = ($ticket->payout ?? 0) > 0;
@endphp
<tr class="{{ $adminListTableRowClass }} {{ $won ? 'bg-amber-50/50' : '' }}">
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $ticket->user?->username ?? '已注销' }}
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListNumericTextClass }}">
<div class="flex flex-wrap items-center justify-center gap-1">
<span class="rounded border border-red-100 bg-red-50 px-1.5 py-0.5 text-xs text-red-500">{{ str_pad($ticket->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-100 bg-red-50 px-1.5 py-0.5 text-xs text-red-500">{{ str_pad($ticket->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-100 bg-red-50 px-1.5 py-0.5 text-xs text-red-500">{{ str_pad($ticket->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-blue-100 bg-blue-50 px-1.5 py-0.5 text-xs text-blue-500">{{ str_pad($ticket->blue, 2, '0', STR_PAD_LEFT) }}</span>
</div>
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($ticket->is_quick_pick)
<span class="{{ $badgeClass }} border-purple-200 bg-purple-100 text-purple-700">随机机选</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-gray-100 text-gray-500">未中奖</span>
<span class="{{ $badgeClass }} border-blue-200 bg-blue-100 text-blue-700">自选号码</span>
@endif
@else
<span class="text-xs text-gray-400">等待开奖</span>
@endif
</td>
<td class="px-4 py-3 text-right text-xs text-gray-400">
{{ $ticket->created_at->format('H:i:s') }}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-10 text-center text-gray-400 text-sm">本期暂无人购买</td>
</tr>
@endforelse
</tbody>
</table>
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} text-gray-700">
{{ number_format($ticket->amount) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} {{ $won ? 'font-semibold text-emerald-600' : 'text-gray-400' }}">
{{ $won ? '+' . number_format($ticket->payout) : '0' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($issue->status === 'settled')
@if ($won)
<span class="{{ $badgeClass }} border-amber-200 bg-amber-100 text-amber-700">🎉 {{ $ticket->prize_level }}等奖</span>
@else
<span class="{{ $badgeClass }} border-gray-200 bg-gray-100 text-gray-500">未中奖</span>
@endif
@else
<span class="{{ $adminListSecondaryTextClass }}">等待开奖</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListSecondaryTextClass }}">
{{ $ticket->created_at->format('H:i:s') }}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">本期暂无人购买</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($tickets->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $tickets->links() }}
</div>
@endif
@@ -3,109 +3,112 @@
@section('title', '双色球彩票开奖记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🎟️ 双色球彩票历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询各期双色球的开奖结果及购买明细。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">🎟️ 双色球彩票历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询各期双色球的开奖结果及购买明细。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_issues']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总期数</div>
<div class="mt-1 text-xs text-gray-500">历史总期数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['drawn_count']) }}</div>
<div class="text-xs text-gray-500 mt-1">已开奖期数</div>
<div class="mt-1 text-xs text-gray-500">已开奖期数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($summary['total_tickets']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史售出彩票</div>
<div class="mt-1 text-xs text-gray-500">历史售出彩票</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-rose-600">{{ number_format($summary['total_pool']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史开奖总奖池</div>
<div class="mt-1 text-xs text-gray-500">历史开奖总奖池</div>
</div>
</div>
{{-- 期数列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">期号</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">开奖时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">开奖号码</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">售出票数</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">奖池</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($issues as $issue)
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-600 text-xs font-mono font-bold"> {{ $issue->issue_no }} </td>
<td class="px-4 py-3 text-xs text-gray-600">
{{ $issue->draw_at ? $issue->draw_at->format('m-d H:i') : '—' }}
</td>
<td class="px-4 py-3 text-center">
@if ($issue->status === 'settled')
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-emerald-100 text-emerald-700">已开奖</span>
@else
<span
class="px-2 py-0.5 rounded-full text-xs font-bold bg-amber-100 text-amber-700">销售中</span>
@endif
</td>
<td class="px-4 py-3 text-center font-mono">
@if ($issue->status === 'settled')
<div class="flex items-center justify-center gap-1">
<span
class="text-xs bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-red-100 text-red-600 px-1 rounded">{{ str_pad($issue->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span
class="text-xs bg-blue-100 text-blue-600 px-1 rounded">{{ str_pad($issue->blue, 2, '0', STR_PAD_LEFT) }}</span>
</div>
@else
<span class="text-xs text-gray-400">等待开奖</span>
@endif
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-indigo-600 font-bold">
{{ number_format($issue->total_tickets) }}
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-amber-600 font-bold">
{{ number_format($issue->pool_amount) }}
</td>
<td class="px-4 py-3 text-right">
<a href="{{ route('admin.game-history.lottery.issue', $issue->id) }}"
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition">
购买明细
</a>
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">期数列表</div>
<div class="{{ $adminListSectionDescClass }}">统一开奖记录列表结构,保留双色球号码配色和开奖状态语义。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}"></th>
<th class="{{ $adminListTableHeadCellClass }}">开奖时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">开奖号码</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">售出票数</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">期奖池</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($issues as $issue)
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }} font-mono"> {{ $issue->issue_no }} </td>
<td class="{{ $tableCellClass }} {{ $adminListBodyTextClass }}">
{{ $issue->draw_at ? $issue->draw_at->format('m-d H:i') : '—' }}
</td>
<td class="{{ $tableCellClass }} text-center">
@if ($issue->status === 'settled')
<span class="{{ $badgeClass }} border-emerald-200 bg-emerald-100 text-emerald-700">已开奖</span>
@else
<span class="{{ $badgeClass }} border-amber-200 bg-amber-100 text-amber-700">销售中</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListNumericTextClass }}">
@if ($issue->status === 'settled')
<div class="flex flex-wrap items-center justify-center gap-1">
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-xs text-red-600">{{ str_pad($issue->red1, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-xs text-red-600">{{ str_pad($issue->red2, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-red-200 bg-red-100 px-1.5 py-0.5 text-xs text-red-600">{{ str_pad($issue->red3, 2, '0', STR_PAD_LEFT) }}</span>
<span class="rounded border border-blue-200 bg-blue-100 px-1.5 py-0.5 text-xs text-blue-600">{{ str_pad($issue->blue, 2, '0', STR_PAD_LEFT) }}</span>
</div>
@else
<span class="{{ $adminListSecondaryTextClass }}">等待开奖</span>
@endif
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold text-indigo-600">
{{ number_format($issue->total_tickets) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold text-amber-600">
{{ number_format($issue->pool_amount) }}
</td>
<td class="{{ $tableCellClass }} text-right">
<a href="{{ route('admin.game-history.lottery.issue', $issue->id) }}"
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-700 hover:bg-indigo-100">
购买明细
</a>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($issues->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $issues->links() }}
</div>
@endif
@@ -3,46 +3,49 @@
@section('title', '神秘箱子历史记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">📦 神秘箱子历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询所有投放过的神秘箱子记录,含领取情况。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">📦 神秘箱子历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询所有投放过的神秘箱子记录,含领取情况。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_dropped']) }}</div>
<div class="text-xs text-gray-500 mt-1">历史总投放数</div>
<div class="mt-1 text-xs text-gray-500">历史总投放数</div>
</div>
<div class="bg-emerald-50 rounded-xl shadow-sm border border-emerald-100 p-5">
<div class="rounded-xl border border-emerald-100 bg-emerald-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['total_claimed']) }}</div>
<div class="text-xs text-emerald-500 mt-1">已被领取</div>
<div class="mt-1 text-xs text-emerald-500">已被领取</div>
</div>
<div class="bg-gray-50 rounded-xl shadow-sm border border-gray-200 p-5">
<div class="rounded-xl border border-gray-200 bg-gray-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-gray-500">{{ number_format($summary['total_expired']) }}</div>
<div class="text-xs text-gray-400 mt-1">已过期/未领取</div>
<div class="mt-1 text-xs text-gray-400">已过期/未领取</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-sm font-bold text-gray-700 mb-2">类型分布</div>
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="mb-2 text-sm font-bold text-gray-700">类型分布</div>
<div class="space-y-1">
<div class="flex justify-between text-xs">
<div class="flex items-center justify-between text-xs">
<span class="text-gray-500">📦 普通箱</span>
<span class="font-bold">{{ $summary['type_dist']['normal'] ?? 0 }}</span>
</div>
<div class="flex justify-between text-xs">
<div class="flex items-center justify-between text-xs">
<span class="text-gray-500">💎 稀有箱</span>
<span class="font-bold text-purple-600">{{ $summary['type_dist']['rare'] ?? 0 }}</span>
</div>
<div class="flex justify-between text-xs">
<div class="flex items-center justify-between text-xs">
<span class="text-gray-500">☠️ 黑化箱</span>
<span class="font-bold text-red-600">{{ $summary['type_dist']['trap'] ?? 0 }}</span>
</div>
@@ -50,122 +53,115 @@
</div>
</div>
{{-- 筛选条件 --}}
<form method="GET"
class="bg-white rounded-xl shadow-sm border border-gray-100 p-4 flex flex-wrap items-end gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">箱子类型</label>
<select name="box_type"
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 min-w-[130px]">
<option value="">全部类型</option>
<option value="normal" {{ request('box_type') === 'normal' ? 'selected' : '' }}>📦 普通</option>
<option value="rare" {{ request('box_type') === 'rare' ? 'selected' : '' }}>💎 稀有</option>
<option value="trap" {{ request('box_type') === 'trap' ? 'selected' : '' }}>☠️ 黑化箱</option>
</select>
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">箱子类型</label>
<select name="box_type" class="min-w-[130px] {{ $adminListFilterInputClass }}">
<option value="">全部类型</option>
<option value="normal" {{ request('box_type') === 'normal' ? 'selected' : '' }}>📦 普通箱</option>
<option value="rare" {{ request('box_type') === 'rare' ? 'selected' : '' }}>💎 稀有</option>
<option value="trap" {{ request('box_type') === 'trap' ? 'selected' : '' }}>☠️ 黑化</option>
</select>
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">状态</label>
<select name="status" class="min-w-[120px] {{ $adminListFilterInputClass }}">
<option value="">全部状态</option>
<option value="open" {{ request('status') === 'open' ? 'selected' : '' }}>等待领取</option>
<option value="claimed" {{ request('status') === 'claimed' ? 'selected' : '' }}>已领取</option>
<option value="expired" {{ request('status') === 'expired' ? 'selected' : '' }}>已过期</option>
</select>
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">筛选</button>
<a href="{{ route('admin.game-history.mystery-box') }}" class="{{ $adminListSecondaryButtonClass }}">重置</a>
</form>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">状态</label>
<select name="status"
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 min-w-[120px]">
<option value="">全部状态</option>
<option value="open" {{ request('status') === 'open' ? 'selected' : '' }}>等待领取</option>
<option value="claimed" {{ request('status') === 'claimed' ? 'selected' : '' }}>已领取</option>
<option value="expired" {{ request('status') === 'expired' ? 'selected' : '' }}>已过期</option>
</select>
</div>
<div class="flex gap-2">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
🔍 筛选
</button>
<a href="{{ route('admin.game-history.mystery-box') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
重置
</a>
</div>
</form>
</div>
{{-- 箱子列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">投放时间</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">类型</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">奖励范围</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">暗号</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">领取者</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">实际奖励</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">领取时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($boxes as $box)
@php
$typeInfo = match ($box->box_type) {
'normal' => ['label' => '📦 普通箱', 'color' => 'bg-emerald-100 text-emerald-700'],
'rare' => ['label' => '💎 稀有箱', 'color' => 'bg-purple-100 text-purple-700'],
'trap' => ['label' => '☠️ 黑化箱', 'color' => 'bg-red-100 text-red-700'],
default => ['label' => '📦 未知', 'color' => 'bg-gray-100 text-gray-600'],
};
$statusInfo = match ($box->status) {
'open' => ['label' => '等待领取', 'color' => 'bg-blue-100 text-blue-700'],
'claimed' => ['label' => '✅ 已领取', 'color' => 'bg-emerald-100 text-emerald-700'],
'expired' => ['label' => '⏰ 已过期', 'color' => 'bg-gray-100 text-gray-500'],
default => ['label' => $box->status, 'color' => 'bg-gray-100 text-gray-500'],
};
$claim = $box->claim;
@endphp
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-xs text-gray-400">
{{ $box->created_at->format('m-d H:i:s') }}
</td>
<td class="px-4 py-3 text-center">
<span class="px-2 py-0.5 rounded-full text-xs font-bold {{ $typeInfo['color'] }}">
{{ $typeInfo['label'] }}
</span>
</td>
<td class="px-4 py-3 text-center text-xs text-gray-600 font-mono">
{{ number_format($box->reward_min) }} ~ {{ number_format($box->reward_max) }}
</td>
<td class="px-4 py-3 text-center">
<code class="bg-gray-100 px-2 py-0.5 rounded text-xs text-indigo-700 font-bold">
{{ $box->passcode ?? '—' }}
</code>
</td>
<td class="px-4 py-3 text-center">
<span class="px-2 py-0.5 rounded-full text-xs font-bold {{ $statusInfo['color'] }}">
{{ $statusInfo['label'] }}
</span>
</td>
<td class="px-4 py-3 font-medium text-gray-700 text-sm">
{{ $claim?->user?->username ?? '—' }}
</td>
<td class="px-4 py-3 text-right font-mono text-xs">
@if ($claim)
<span
class="{{ $claim->reward_amount > 0 ? 'text-emerald-600 font-bold' : 'text-red-500 font-bold' }}">
{{ $claim->reward_amount > 0 ? '+' : '' }}{{ number_format($claim->reward_amount) }}
</span>
@else
<span class="text-gray-400"></span>
@endif
</td>
<td class="px-4 py-3 text-xs text-gray-400">
{{ $claim?->created_at?->format('m-d H:i:s') ?? '—' }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">箱子列表</div>
<div class="{{ $adminListSectionDescClass }}">统一列表容器与分页层级,保留箱子类型、状态和奖励色彩语义。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">投放时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">类型</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">奖励范围</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">暗号</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }}">领取者</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">实际奖励</th>
<th class="{{ $adminListTableHeadCellClass }}">领取时间</th>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($boxes as $box)
@php
$typeInfo = match ($box->box_type) {
'normal' => ['label' => '📦 普通箱', 'color' => 'bg-emerald-100 text-emerald-700 border-emerald-200'],
'rare' => ['label' => '💎 稀有箱', 'color' => 'bg-purple-100 text-purple-700 border-purple-200'],
'trap' => ['label' => '☠️ 黑化箱', 'color' => 'bg-red-100 text-red-700 border-red-200'],
default => ['label' => '📦 未知', 'color' => 'bg-gray-100 text-gray-600 border-gray-200'],
};
$statusInfo = match ($box->status) {
'open' => ['label' => '等待领取', 'color' => 'bg-blue-100 text-blue-700 border-blue-200'],
'claimed' => ['label' => '✅ 已领取', 'color' => 'bg-emerald-100 text-emerald-700 border-emerald-200'],
'expired' => ['label' => '⏰ 已过期', 'color' => 'bg-gray-100 text-gray-500 border-gray-200'],
default => ['label' => $box->status, 'color' => 'bg-gray-100 text-gray-500 border-gray-200'],
};
$claim = $box->claim;
@endphp
<tr class="{{ $adminListTableRowClass }}">
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }}">
{{ $box->created_at->format('m-d H:i:s') }}
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $typeInfo['color'] }}">{{ $typeInfo['label'] }}</span>
</td>
<td class="{{ $tableCellClass }} text-center {{ $adminListNumericTextClass }} text-gray-600">
{{ number_format($box->reward_min) }} ~ {{ number_format($box->reward_max) }}
</td>
<td class="{{ $tableCellClass }} text-center">
<code class="rounded bg-gray-100 px-2 py-0.5 text-xs font-bold text-indigo-700">
{{ $box->passcode ?? '—' }}
</code>
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $statusInfo['color'] }}">{{ $statusInfo['label'] }}</span>
</td>
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $claim?->user?->username ?? '—' }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }}">
@if ($claim)
<span class="{{ $claim->reward_amount > 0 ? 'font-semibold text-emerald-600' : 'font-semibold text-red-500' }}">
{{ $claim->reward_amount > 0 ? '+' : '' }}{{ number_format($claim->reward_amount) }}
</span>
@else
<span class="{{ $adminListSecondaryTextClass }}"></span>
@endif
</td>
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }}">
{{ $claim?->created_at?->format('m-d H:i:s') ?? '—' }}
</td>
</tr>
@empty
<tr>
<td colspan="8" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($boxes->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $boxes->links() }}
</div>
@endif
+139 -131
View File
@@ -3,167 +3,175 @@
@section('title', '老虎机历史记录')
@section('content')
<div class="space-y-6">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
{{-- 页头 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
@php
$tableCellClass = 'px-4 py-3';
$badgeClass = $adminListBadgeBaseClass;
$resultLabels = [
'jackpot' => ['label' => '🎉 三个7', 'color' => 'bg-yellow-100 text-yellow-700 border-yellow-200'],
'triple_gem' => ['label' => '💎 三钻', 'color' => 'bg-blue-100 text-blue-700 border-blue-200'],
'triple' => ['label' => '✨ 三同', 'color' => 'bg-green-100 text-green-700 border-green-200'],
'pair' => ['label' => '🎁 两同', 'color' => 'bg-indigo-100 text-indigo-700 border-indigo-200'],
'curse' => ['label' => '☠️ 三骷髅', 'color' => 'bg-red-100 text-red-700 border-red-200'],
'miss' => ['label' => '😔 未中奖', 'color' => 'bg-gray-100 text-gray-600 border-gray-200'],
];
@endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }} flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-lg font-bold text-gray-800">🎰 老虎机历史记录</h2>
<p class="text-xs text-gray-500 mt-1">查询所有玩家的老虎机转动记录,支持按结果类型和玩家名筛选。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">🎰 老虎机历史记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查询所有玩家的老虎机转动记录,支持按结果类型和玩家名筛选。</p>
</div>
<a href="{{ route('admin.game-configs.index') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-bold hover:bg-gray-200 transition">
<a href="{{ route('admin.game-configs.index') }}" class="{{ $adminListSecondaryButtonClass }}">
⚙️ 游戏配置
</a>
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 md:grid-cols-5 gap-4">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-indigo-600">{{ number_format($summary['total_spins']) }}</div>
<div class="text-xs text-gray-500 mt-1">总转动次数</div>
<div class="mt-1 text-xs text-gray-500">总转动次数</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-red-500">{{ number_format($summary['total_cost']) }}</div>
<div class="text-xs text-gray-500 mt-1">总消耗金币</div>
<div class="mt-1 text-xs text-gray-500">总消耗金币</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-emerald-600">{{ number_format($summary['total_payout']) }}</div>
<div class="text-xs text-gray-500 mt-1">总派奖金币</div>
<div class="mt-1 text-xs text-gray-500">总派奖金币</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="text-2xl font-bold text-amber-600">{{ number_format($summary['net_income']) }}</div>
<div class="text-xs text-gray-500 mt-1">庄家净收(消耗-派奖)</div>
<div class="mt-1 text-xs text-gray-500">庄家净收(消耗-派奖)</div>
</div>
<div class="bg-yellow-50 rounded-xl shadow-sm border border-yellow-100 p-5">
<div class="text-2xl font-bold text-yellow-600">{{ number_format($summary['result_dist']['jackpot'] ?? 0) }}
</div>
<div class="text-xs text-yellow-500 mt-1">🎉 三7大奖次数</div>
<div class="rounded-xl border border-yellow-100 bg-yellow-50 p-5 shadow-sm">
<div class="text-2xl font-bold text-yellow-600">{{ number_format($summary['result_dist']['jackpot'] ?? 0) }}</div>
<div class="mt-1 text-xs text-yellow-500">🎉 三7大奖次数</div>
</div>
</div>
{{-- 结果分布 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-5">
<div class="text-sm font-bold text-gray-700 mb-3">结果类型分布</div>
<div class="flex flex-wrap gap-3">
@php
$resultLabels = [
'jackpot' => ['label' => '🎉 三个7', 'color' => 'bg-yellow-100 text-yellow-700'],
'triple_gem' => ['label' => '💎 三钻', 'color' => 'bg-blue-100 text-blue-700'],
'triple' => ['label' => '✨ 三同', 'color' => 'bg-green-100 text-green-700'],
'pair' => ['label' => '🎁 两同', 'color' => 'bg-indigo-100 text-indigo-700'],
'curse' => ['label' => '☠️ 三骷髅', 'color' => 'bg-red-100 text-red-700'],
'miss' => ['label' => '😔 未中奖', 'color' => 'bg-gray-100 text-gray-600'],
];
@endphp
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">结果类型分布</div>
<div class="{{ $adminListSectionDescClass }}">保留中奖结果配色,仅统一卡片容器与排版节奏。</div>
</div>
<div class="flex flex-wrap gap-3 p-6">
@foreach ($resultLabels as $key => $meta)
<div class="px-4 py-2 rounded-lg {{ $meta['color'] }}">
@php
$distributionBorderClass = match ($key) {
'jackpot' => 'border-yellow-200',
'triple_gem' => 'border-blue-200',
'triple' => 'border-green-200',
'pair' => 'border-indigo-200',
'curse' => 'border-red-200',
default => 'border-gray-200',
};
@endphp
<div class="rounded-lg border px-4 py-2 {{ $distributionBorderClass }} {{ $meta['color'] }}">
<div class="text-sm font-bold">{{ $meta['label'] }}</div>
<div class="text-xs mt-0.5">{{ number_format($summary['result_dist'][$key] ?? 0) }} </div>
<div class="mt-0.5 text-xs">{{ number_format($summary['result_dist'][$key] ?? 0) }} </div>
</div>
@endforeach
</div>
</div>
{{-- 筛选条件 --}}
<form method="GET"
class="bg-white rounded-xl shadow-sm border border-gray-100 p-4 flex flex-wrap items-end gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">结果类型</label>
<select name="result_type"
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 min-w-[140px]">
<option value="">全部结果</option>
@foreach ($resultLabels as $key => $meta)
<option value="{{ $key }}" {{ request('result_type') === $key ? 'selected' : '' }}>
{{ $meta['label'] }}
</option>
@endforeach
</select>
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">结果类型</label>
<select name="result_type" class="min-w-[140px] {{ $adminListFilterInputClass }}">
<option value="">全部结果</option>
@foreach ($resultLabels as $key => $meta)
<option value="{{ $key }}" {{ request('result_type') === $key ? 'selected' : '' }}>
{{ $meta['label'] }}
</option>
@endforeach
</select>
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">玩家名称</label>
<input type="text" name="username" value="{{ request('username') }}" placeholder="模糊搜索..."
class="w-40 {{ $adminListFilterInputClass }}">
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">筛选</button>
<a href="{{ route('admin.game-history.slot') }}" class="{{ $adminListSecondaryButtonClass }}">重置</a>
</form>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">玩家名称</label>
<input type="text" name="username" value="{{ request('username') }}" placeholder="模糊搜索..."
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:border-indigo-400 w-40">
</div>
<div class="flex gap-2">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
🔍 筛选
</button>
<a href="{{ route('admin.game-history.slot') }}"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
重置
</a>
</div>
</form>
</div>
{{-- 记录列表 --}}
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">时间</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">玩家</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">三列图案</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">结果</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">消耗</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">获得</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">净值</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
@forelse ($logs as $log)
@php
$symbols = \App\Models\SlotMachineLog::symbols();
$r1Emoji = $symbols[$log->reel1]['emoji'] ?? $log->reel1;
$r2Emoji = $symbols[$log->reel2]['emoji'] ?? $log->reel2;
$r3Emoji = $symbols[$log->reel3]['emoji'] ?? $log->reel3;
$net = $log->payout - $log->cost;
$rowBg = match ($log->result_type) {
'jackpot' => 'bg-yellow-50',
'triple_gem' => 'bg-blue-50',
'curse' => 'bg-red-50',
default => '',
};
@endphp
<tr class="hover:bg-gray-50 transition {{ $rowBg }}">
<td class="px-4 py-3 text-xs text-gray-400">
{{ $log->created_at->format('m-d H:i:s') }}
</td>
<td class="px-4 py-3 font-medium text-gray-800">
{{ $log->user?->username ?? '已注销' }}
</td>
<td class="px-4 py-3 text-center text-lg tracking-widest">
{{ $r1Emoji }} {{ $r2Emoji }} {{ $r3Emoji }}
</td>
<td class="px-4 py-3 text-center">
<span
class="px-2 py-0.5 rounded-full text-xs font-bold {{ $resultLabels[$log->result_type]['color'] ?? 'bg-gray-100 text-gray-600' }}">
{{ $resultLabels[$log->result_type]['label'] ?? $log->result_type }}
</span>
</td>
<td class="px-4 py-3 text-right font-mono text-xs text-red-500">
-{{ number_format($log->cost) }}
</td>
<td
class="px-4 py-3 text-right font-mono text-xs {{ $log->payout > 0 ? 'text-emerald-600 font-bold' : 'text-gray-400' }}">
{{ $log->payout > 0 ? '+' . number_format($log->payout) : '0' }}
</td>
<td
class="px-4 py-3 text-right font-mono text-xs {{ $net >= 0 ? 'text-emerald-600' : 'text-red-500' }} font-bold">
{{ $net >= 0 ? '+' : '' }}{{ number_format($net) }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="{{ $adminListSectionTitleClass }}">转动记录</div>
<div class="{{ $adminListSectionDescClass }}">统一表格、空态和分页样式,保留高价值结果的行底色提示。</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">时间</th>
<th class="{{ $adminListTableHeadCellClass }}">玩家</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">三列图案</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">结果</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">消耗</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">获得</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">净值</th>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-10 text-center text-gray-400 text-sm">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
@php
$symbols = \App\Models\SlotMachineLog::symbols();
$r1Emoji = $symbols[$log->reel1]['emoji'] ?? $log->reel1;
$r2Emoji = $symbols[$log->reel2]['emoji'] ?? $log->reel2;
$r3Emoji = $symbols[$log->reel3]['emoji'] ?? $log->reel3;
$net = $log->payout - $log->cost;
$rowBg = match ($log->result_type) {
'jackpot' => 'bg-yellow-50',
'triple_gem' => 'bg-blue-50',
'curse' => 'bg-red-50',
default => '',
};
@endphp
<tr class="{{ $adminListTableRowClass }} {{ $rowBg }}">
<td class="{{ $tableCellClass }} {{ $adminListSecondaryTextClass }}">
{{ $log->created_at->format('m-d H:i:s') }}
</td>
<td class="{{ $tableCellClass }} {{ $adminListPrimaryTextClass }}">
{{ $log->user?->username ?? '已注销' }}
</td>
<td class="{{ $tableCellClass }} text-center text-lg tracking-widest">
{{ $r1Emoji }} {{ $r2Emoji }} {{ $r3Emoji }}
</td>
<td class="{{ $tableCellClass }} text-center">
<span class="{{ $badgeClass }} {{ $resultLabels[$log->result_type]['color'] ?? 'bg-gray-100 text-gray-600 border-gray-200' }}">
{{ $resultLabels[$log->result_type]['label'] ?? $log->result_type }}
</span>
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} text-red-500">
-{{ number_format($log->cost) }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} {{ $log->payout > 0 ? 'font-semibold text-emerald-600' : 'text-gray-400' }}">
{{ $log->payout > 0 ? '+' . number_format($log->payout) : '0' }}
</td>
<td class="{{ $tableCellClass }} text-right {{ $adminListNumericTextClass }} font-semibold {{ $net >= 0 ? 'text-emerald-600' : 'text-red-500' }}">
{{ $net >= 0 ? '+' : '' }}{{ number_format($net) }}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="px-4 py-3 border-t border-gray-100">
<div class="{{ $adminListPaginationClass }}">
{{ $logs->links() }}
</div>
@endif
@@ -4,6 +4,8 @@
@section('title', '节日福利管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
@php
$visibleEvents = $events->getCollection();
$enabledCount = $visibleEvents->where('enabled', true)->count();
@@ -24,14 +26,13 @@
];
@endphp
<div class="space-y-6">
{{-- 页头 --}}
<div class="rounded-xl border border-gray-100 bg-white p-5 shadow-sm">
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div class="space-y-2">
<div>
<h2 class="text-xl font-black tracking-tight text-slate-800">节日福利管理</h2>
<p class="mt-1 text-sm text-slate-500">统一维护节日福利模板与触发计划。</p>
<h2 class="{{ $adminListHeaderTitleClass }}">节日福利管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">统一维护节日福利模板与触发计划。</p>
</div>
<div class="flex flex-wrap gap-2 text-xs font-semibold">
<span class="rounded-full bg-slate-100 px-3 py-1 text-slate-600">当前页 {{ $visibleEvents->count() }} 个活动</span>
@@ -41,40 +42,39 @@
</div>
<a href="{{ route('admin.holiday-events.create') }}"
class="inline-flex items-center justify-center gap-2 rounded-lg bg-amber-500 px-4 py-2.5 text-sm font-bold text-white shadow-sm transition hover:bg-amber-600">
class="inline-flex items-center justify-center gap-2 rounded-lg bg-amber-500 px-4 py-2.5 text-sm font-semibold text-white shadow-sm transition hover:bg-amber-600">
<span class="text-base leading-none"></span>
<span>创建活动</span>
</a>
</div>
</div>
{{-- 列表 --}}
<div class="overflow-hidden rounded-xl border border-gray-100 bg-white shadow-sm">
<div class="border-b border-gray-100 px-6 py-3">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div class="flex flex-col gap-1 lg:flex-row lg:items-center lg:justify-between">
<div>
<h3 class="text-base font-bold text-slate-800">福利模板列表</h3>
<p class="mt-1 text-xs text-slate-500">列表按关键信息压缩展示,适合批量查看。</p>
<h3 class="{{ $adminListSectionTitleClass }}">福利模板列表</h3>
<p class="{{ $adminListSectionDescClass }}">列表按关键信息压缩展示,适合批量查看。</p>
</div>
<div class="text-xs text-slate-400">年度模板额外显示月日、持续天数、轮次与轮次间隔</div>
</div>
</div>
<div class="overflow-x-auto">
<div class="{{ $adminListTableWrapClass }}">
<table class="min-w-[1120px] w-full table-fixed text-sm">
<thead class="bg-slate-50 text-left text-xs font-bold uppercase tracking-[0.16em] text-slate-500">
<tr>
<th class="px-4 py-3 w-14">编号</th>
<th class="px-4 py-3 w-[25%]">活动信息</th>
<th class="px-4 py-3 w-[10%]">奖池</th>
<th class="px-4 py-3 w-[10%]">分配</th>
<th class="px-4 py-3 w-[11%]">限额 / 重复</th>
<th class="px-4 py-3 w-[15%]">触发计划</th>
<th class="px-4 py-3 w-[13%]">运行状态</th>
<th class="px-4 py-3 w-[16%] text-right">操作</th>
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }} w-14">编号</th>
<th class="{{ $adminListTableHeadCellClass }} w-[25%]">活动信息</th>
<th class="{{ $adminListTableHeadCellClass }} w-[10%]">奖池</th>
<th class="{{ $adminListTableHeadCellClass }} w-[10%]">分配</th>
<th class="{{ $adminListTableHeadCellClass }} w-[11%]">限额 / 重复</th>
<th class="{{ $adminListTableHeadCellClass }} w-[15%]">触发计划</th>
<th class="{{ $adminListTableHeadCellClass }} w-[13%]">运行状态</th>
<th class="{{ $adminListTableHeadCellClass }} w-[16%] text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($events as $event)
@php
[$statusLabel, $statusClass] = $statusMap[$event->status] ?? ['未知', 'bg-slate-100 text-slate-600'];
@@ -203,14 +203,14 @@
method="POST" data-holiday-event-confirm="确定立即触发此活动吗?">
@csrf
<button type="submit"
class="inline-flex items-center justify-center rounded-lg bg-amber-500 px-3 py-2 text-xs font-bold text-white transition hover:bg-amber-600">
class="{{ $adminListActionButtonClass }} inline-flex items-center justify-center bg-amber-500 text-white hover:bg-amber-600">
立即触发
</button>
</form>
@endif
<a href="{{ route('admin.holiday-events.edit', $event) }}"
class="inline-flex items-center justify-center rounded-lg bg-indigo-50 px-3 py-2 text-xs font-bold text-indigo-700 transition hover:bg-indigo-100">
class="{{ $adminListActionButtonClass }} inline-flex items-center justify-center bg-indigo-50 text-indigo-700 hover:bg-indigo-100">
编辑
</a>
@@ -219,7 +219,7 @@
@csrf
@method('DELETE')
<button type="submit"
class="inline-flex items-center justify-center rounded-lg bg-rose-50 px-3 py-2 text-xs font-bold text-rose-600 transition hover:bg-rose-100">
class="{{ $adminListActionButtonClass }} inline-flex items-center justify-center bg-rose-50 text-rose-600 hover:bg-rose-100">
删除
</button>
</form>
@@ -228,7 +228,7 @@
</tr>
@empty
<tr>
<td colspan="8" class="px-6 py-16 text-center text-slate-400">
<td colspan="8" class="{{ $adminListEmptyClass }}">
暂无节日福利活动,<a href="{{ route('admin.holiday-events.create') }}"
class="font-bold text-amber-500 hover:text-amber-600">立即创建一个</a>
</td>
@@ -239,7 +239,7 @@
</div>
@if ($events->hasPages())
<div class="border-t border-gray-100 px-6 py-4">
<div class="{{ $adminListPaginationClass }}">
{{ $events->links() }}
</div>
@endif
+12 -12
View File
@@ -64,10 +64,6 @@
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.wechat_bot.edit') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.wechat_bot.*') ? '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' }}">
{!! '💴 用户流水' !!}
@@ -84,14 +80,6 @@
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.sign-in-rules.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
{!! '✅ 签到奖励' !!}
</a>
<a href="{{ route('admin.vip.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
{!! '👑 VIP 会员等级' !!}
</a>
<a href="{{ route('admin.vip-payment-logs.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip-payment-logs.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
{!! '🧾 会员购买日志' !!}
</a>
<a href="{{ route('admin.shop.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.shop.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
{!! '🛒 商店管理' !!}
@@ -133,6 +121,18 @@
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip-payment.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
💳 VIP 支付配置
</a>
<a href="{{ route('admin.vip.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
👑 VIP 会员等级
</a>
<a href="{{ route('admin.vip-payment-logs.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip-payment-logs.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
🧾 会员购买日志
</a>
<a href="{{ route('admin.wechat_bot.edit') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.wechat_bot.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
🤖 微信机器人
</a>
<a href="{{ route('admin.ai-providers.index') }}"
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.ai-providers.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
🤖 AI 厂商配置
@@ -10,95 +10,108 @@
@section('title', '婚礼红包记录')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="flex items-center justify-between mb-5">
<h2 class="text-xl font-bold text-gray-800">🎊 婚礼红包记录</h2>
<a href="{{ route('admin.marriages.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回总览</a>
</div>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">🎊 婚礼红包记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">统一查看婚礼红包发放进度与领取详情。</p>
</div>
<a href="{{ route('admin.marriages.index') }}" class="{{ $adminListSecondaryButtonClass }}">返回总览</a>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs uppercase">
<tr>
<th class="px-4 py-3 text-left">ID</th>
<th class="px-4 py-3 text-left">新人</th>
<th class="px-4 py-3 text-left">档位</th>
<th class="px-4 py-3 text-center">总金额</th>
<th class="px-4 py-3 text-center">在线人数</th>
<th class="px-4 py-3 text-center">领取进度</th>
<th class="px-4 py-3 text-center">状态</th>
<th class="px-4 py-3 text-left">时间</th>
<th class="px-4 py-3 text-center">详情</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse ($ceremonies as $c)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-gray-400 font-mono text-xs">{{ $c->id }}</td>
<td class="px-4 py-3">
<span class="font-bold">{{ $c->marriage?->user?->username }}</span>
<span class="text-gray-400 mx-1">×</span>
<span class="font-bold">{{ $c->marriage?->partner?->username }}</span>
</td>
<td class="px-4 py-3">
{{ $c->tier?->icon }} {{ $c->tier?->name ?? '—' }}
</td>
<td class="px-4 py-3 text-center font-bold text-amber-600">
{{ number_format($c->total_amount) }}
</td>
<td class="px-4 py-3 text-center text-gray-600">
{{ $c->online_count ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
@if ($c->total_amount > 0)
<div class="text-xs text-gray-600">
{{ $c->claimed_count }} / {{ $c->online_count ?? '?' }}
</div>
<div class="text-xs text-emerald-600 font-bold">
{{ number_format($c->claimed_amount) }} / {{ number_format($c->total_amount) }}
</div>
@else
<span class="text-gray-300 text-xs">无红包</span>
@endif
</td>
<td class="px-4 py-3 text-center">
<span
class="px-2 py-0.5 rounded-full text-xs font-bold
{{ match ($c->status) {
'completed' => 'bg-green-100 text-green-700',
'active' => 'bg-blue-100 text-blue-700',
'pending' => 'bg-amber-100 text-amber-700',
'expired' => 'bg-gray-100 text-gray-500',
'cancelled' => 'bg-red-100 text-red-600',
default => 'bg-gray-100 text-gray-600',
} }}">
{{ ['completed' => '已完成', 'active' => '进行中', 'pending' => '待触发', 'expired' => '已过期', 'cancelled' => '已取消'][$c->status] ?? $c->status }}
</span>
</td>
<td class="px-4 py-3 text-xs text-gray-500">
{{ $c->ceremony_at?->format('Y-m-d H:i') }}
</td>
<td class="px-4 py-3 text-center">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">婚礼红包列表</h3>
<p class="{{ $adminListSectionDescClass }}">保留婚礼状态色彩与金额语义,其他布局统一到后台列表样式。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">ID</th>
<th class="{{ $adminListTableHeadCellClass }}">新人</th>
<th class="{{ $adminListTableHeadCellClass }}">档位</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">总金额</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">在线人数</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">领取进度</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }}">时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">详情</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($ceremonies as $c)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }} {{ $adminListNumericTextClass }}">{{ $c->id }}</td>
<td class="px-4 py-3">
<span class="{{ $adminListPrimaryTextClass }}">{{ $c->marriage?->user?->username }}</span>
<span class="mx-1 text-gray-400">×</span>
<span class="{{ $adminListPrimaryTextClass }}">{{ $c->marriage?->partner?->username }}</span>
</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">
{{ $c->tier?->icon }} {{ $c->tier?->name ?? '—' }}
</td>
<td class="px-4 py-3 text-center font-semibold text-amber-600">
{{ number_format($c->total_amount) }}
</td>
<td class="px-4 py-3 text-center {{ $adminListBodyTextClass }}">
{{ $c->online_count ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
@if ($c->total_amount > 0)
<div class="text-xs text-gray-600">
{{ $c->claimed_count }} / {{ $c->online_count ?? '?' }}
</div>
<div class="text-xs font-semibold text-emerald-600">
{{ number_format($c->claimed_amount) }} / {{ number_format($c->total_amount) }}
</div>
@else
<span class="text-gray-300 text-xs">无红包</span>
@endif
</td>
<td class="px-4 py-3 text-center">
<span
class="{{ $adminListBadgeBaseClass }} {{ match ($c->status) {
'completed' => 'border-green-200 bg-green-100 text-green-700',
'active' => 'border-blue-200 bg-blue-100 text-blue-700',
'pending' => 'border-amber-200 bg-amber-100 text-amber-700',
'expired' => 'border-gray-200 bg-gray-100 text-gray-500',
'cancelled' => 'border-red-200 bg-red-100 text-red-600',
default => 'border-gray-200 bg-gray-100 text-gray-600',
} }}">
{{ ['completed' => '已完成', 'active' => '进行中', 'pending' => '待触发', 'expired' => '已过期', 'cancelled' => '已取消'][$c->status] ?? $c->status }}
</span>
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">
{{ $c->ceremony_at?->format('Y-m-d H:i') }}
</td>
<td class="px-4 py-3 text-center">
@if ($c->total_amount > 0)
<a href="{{ route('admin.marriages.claim-detail', $c->id) }}"
class="text-xs text-indigo-600 hover:underline font-bold">明细</a>
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-600 hover:bg-indigo-600 hover:text-white">明细</a>
@else
<span class="text-gray-300 text-xs"></span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="9" class="px-4 py-12 text-center text-gray-400">暂无婚礼记录</td>
</tr>
@endforelse
</tbody>
</table>
</td>
</tr>
@empty
<tr>
<td colspan="9" class="{{ $adminListEmptyClass }}">暂无婚礼记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($ceremonies->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $ceremonies->links() }}</div>
@endif
</div>
@if ($ceremonies->hasPages())
<div class="px-4 py-4 border-t">{{ $ceremonies->links() }}</div>
@endif
</div>
@endsection
@@ -10,76 +10,85 @@
@section('title', '婚礼红包明细')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="flex items-center justify-between mb-5">
<div>
<h2 class="text-xl font-bold text-gray-800">🎁 红包领取明细</h2>
<p class="text-sm text-gray-500 mt-1">
{{ $ceremony->marriage?->user?->username }} × {{ $ceremony->marriage?->partner?->username }}
{{ $ceremony->tier?->icon }} {{ $ceremony->tier?->name ?? '婚礼' }}
· 总额 <strong class="text-amber-600">{{ number_format($ceremony->total_amount) }} </strong>
</p>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">🎁 红包领取明细</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">
{{ $ceremony->marriage?->user?->username }} × {{ $ceremony->marriage?->partner?->username }}
{{ $ceremony->tier?->icon }} {{ $ceremony->tier?->name ?? '婚礼' }}
· 总额 <strong class="text-amber-600">{{ number_format($ceremony->total_amount) }} </strong>
</p>
</div>
<a href="{{ route('admin.marriages.ceremonies') }}" class="{{ $adminListSecondaryButtonClass }}">返回婚礼列表</a>
</div>
</div>
<a href="{{ route('admin.marriages.ceremonies') }}" class="text-sm text-indigo-600 hover:underline"> 返回婚礼列表</a>
</div>
{{-- 汇总 --}}
<div class="grid grid-cols-3 gap-4 mb-5">
<div class="bg-white rounded-xl border shadow-sm p-4 text-center">
<div class="text-2xl font-bold text-indigo-600">{{ $ceremony->online_count ?? 0 }}</div>
<div class="text-xs text-gray-500 mt-1">在线人数</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<div class="{{ $adminListCardClass }} p-4 text-center">
<div class="text-2xl font-bold text-indigo-600">{{ $ceremony->online_count ?? 0 }}</div>
<div class="mt-1 text-xs text-gray-500">在线人数</div>
</div>
<div class="{{ $adminListCardClass }} p-4 text-center">
<div class="text-2xl font-bold text-green-600">{{ $ceremony->claimed_count }}</div>
<div class="mt-1 text-xs text-gray-500">已领取人数</div>
</div>
<div class="{{ $adminListCardClass }} p-4 text-center">
<div class="text-2xl font-bold text-amber-600">{{ number_format($ceremony->claimed_amount) }}</div>
<div class="mt-1 text-xs text-gray-500">已领取金额</div>
</div>
</div>
<div class="bg-white rounded-xl border shadow-sm p-4 text-center">
<div class="text-2xl font-bold text-green-600">{{ $ceremony->claimed_count }}</div>
<div class="text-xs text-gray-500 mt-1">已领取人数</div>
</div>
<div class="bg-white rounded-xl border shadow-sm p-4 text-center">
<div class="text-2xl font-bold text-amber-600">{{ number_format($ceremony->claimed_amount) }}</div>
<div class="text-xs text-gray-500 mt-1">已领取金额</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-xs uppercase text-gray-600">
<tr>
<th class="px-4 py-3 text-left">用户</th>
<th class="px-4 py-3 text-center">分配金额</th>
<th class="px-4 py-3 text-center">状态</th>
<th class="px-4 py-3 text-left">领取时间</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse ($claims as $claim)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 font-bold">{{ $claim->user?->username }}</td>
<td class="px-4 py-3 text-center font-bold text-amber-600">
{{ number_format($claim->amount) }}
</td>
<td class="px-4 py-3 text-center">
@if ($claim->claimed)
<span class="px-2 py-0.5 rounded-full text-xs bg-green-100 text-green-700 font-bold">
已领取</span>
@else
<span class="px-2 py-0.5 rounded-full text-xs bg-gray-100 text-gray-500">未领取</span>
@endif
</td>
<td class="px-4 py-3 text-xs text-gray-500">
{{ $claim->claimed_at?->format('H:i:s') ?? '—' }}
</td>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">领取明细</h3>
<p class="{{ $adminListSectionDescClass }}">明细表头、正文、状态徽章与分页统一到后台列表页样式。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">用户</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">分配金额</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }}">领取时间</th>
</tr>
@empty
<tr>
<td colspan="4" class="px-4 py-12 text-center text-gray-400">暂无领取记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($claims as $claim)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $claim->user?->username }}</td>
<td class="px-4 py-3 text-center font-semibold text-amber-600">
{{ number_format($claim->amount) }}
</td>
<td class="px-4 py-3 text-center">
@if ($claim->claimed)
<span class="{{ $adminListBadgeBaseClass }} border-green-200 bg-green-100 text-green-700"> 已领取</span>
@else
<span class="{{ $adminListBadgeBaseClass }} border-gray-200 bg-gray-100 text-gray-500">未领取</span>
@endif
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">
{{ $claim->claimed_at?->format('H:i:s') ?? '—' }}
</td>
</tr>
@empty
<tr>
<td colspan="4" class="{{ $adminListEmptyClass }}">暂无领取记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($claims->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $claims->links() }}</div>
@endif
</div>
@if ($claims->hasPages())
<div class="px-4 py-4 border-t">{{ $claims->links() }}</div>
@endif
</div>
@endsection
@@ -10,88 +10,101 @@
@section('title', '亲密度日志')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="flex items-center justify-between mb-5">
<h2 class="text-xl font-bold text-gray-800">💞 亲密度变更日志</h2>
<a href="{{ route('admin.marriages.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回总览</a>
</div>
{{-- 筛选 --}}
<form method="GET" class="bg-white rounded-xl border shadow-sm p-4 mb-5 flex flex-wrap gap-3 items-end">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">搜索用户名</label>
<input type="text" name="search" value="{{ request('search') }}" placeholder="双方任一用户名..."
class="border rounded-lg px-3 py-2 text-sm w-44 focus:outline-none">
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">💞 亲密度变更日志</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">按统一后台列表样式审计婚姻亲密度的增减来源与余额变化。</p>
</div>
<a href="{{ route('admin.marriages.index') }}" class="{{ $adminListSecondaryButtonClass }}">返回总览</a>
</div>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">来源(Source</label>
<select name="source" class="border rounded-lg px-3 py-2 text-sm focus:outline-none">
<option value="">全部</option>
@foreach (\App\Enums\IntimacySource::cases() as $src)
<option value="{{ $src->value }}" @selected(request('source') === $src->value)>
{{ $src->label() }}
</option>
@endforeach
</select>
</div>
<button type="submit"
class="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-indigo-700 transition">
筛选
</button>
<a href="{{ route('admin.marriages.intimacy-logs') }}" class="text-sm text-gray-500 hover:underline py-2">重置</a>
</form>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-xs uppercase text-gray-600">
<tr>
<th class="px-4 py-3 text-left">ID</th>
<th class="px-4 py-3 text-left">婚姻双方</th>
<th class="px-4 py-3 text-center">变动量</th>
<th class="px-4 py-3 text-center">变后余额</th>
<th class="px-4 py-3 text-left">来源</th>
<th class="px-4 py-3 text-left">备注</th>
<th class="px-4 py-3 text-left">时间</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse ($logs as $log)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-gray-400 font-mono text-xs">{{ $log->id }}</td>
<td class="px-4 py-3">
<span class="font-bold">{{ $log->marriage?->user?->username }}</span>
<span class="text-gray-400 mx-1">×</span>
<span class="font-bold">{{ $log->marriage?->partner?->username }}</span>
</td>
<td
class="px-4 py-3 text-center font-bold {{ $log->amount >= 0 ? 'text-green-600' : 'text-red-500' }}">
{{ $log->amount >= 0 ? '+' : '' }}{{ $log->amount }}
</td>
<td class="px-4 py-3 text-center text-indigo-600 font-bold">
{{ number_format($log->balance_after) }}
</td>
<td class="px-4 py-3">
<span class="text-xs bg-purple-50 text-purple-700 px-2 py-0.5 rounded-full font-mono">
{{ \App\Enums\IntimacySource::tryFrom($log->source)?->label() ?? $log->source }}
</span>
</td>
<td class="px-4 py-3 text-xs text-gray-500">{{ $log->remark ?? '—' }}</td>
<td class="px-4 py-3 text-xs text-gray-400">
{{ $log->created_at?->format('m-d H:i') }}
</td>
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">搜索用户名</label>
<input type="text" name="search" value="{{ request('search') }}" placeholder="双方任一用户名..."
class="w-44 {{ $adminListFilterInputClass }}">
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">来源Source</label>
<select name="source" class="{{ $adminListFilterInputClass }}">
<option value="">全部</option>
@foreach (\App\Enums\IntimacySource::cases() as $src)
<option value="{{ $src->value }}" @selected(request('source') === $src->value)>
{{ $src->label() }}
</option>
@endforeach
</select>
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">筛选</button>
<a href="{{ route('admin.marriages.intimacy-logs') }}" class="{{ $adminListSecondaryButtonClass }}">重置</a>
</form>
</div>
</div>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">亲密度日志</h3>
<p class="{{ $adminListSectionDescClass }}">保留增减与来源的颜色语义,其他样式对齐统一列表页。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">ID</th>
<th class="{{ $adminListTableHeadCellClass }}">婚姻双方</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">变动量</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">变后余额</th>
<th class="{{ $adminListTableHeadCellClass }}">来源</th>
<th class="{{ $adminListTableHeadCellClass }}">备注</th>
<th class="{{ $adminListTableHeadCellClass }}">时间</th>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-12 text-center text-gray-400">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }} {{ $adminListNumericTextClass }}">{{ $log->id }}</td>
<td class="px-4 py-3">
<span class="{{ $adminListPrimaryTextClass }}">{{ $log->marriage?->user?->username }}</span>
<span class="mx-1 text-gray-400">×</span>
<span class="{{ $adminListPrimaryTextClass }}">{{ $log->marriage?->partner?->username }}</span>
</td>
<td class="px-4 py-3 text-center font-semibold {{ $log->amount >= 0 ? 'text-green-600' : 'text-red-500' }}">
{{ $log->amount >= 0 ? '+' : '' }}{{ $log->amount }}
</td>
<td class="px-4 py-3 text-center font-semibold text-indigo-600">
{{ number_format($log->balance_after) }}
</td>
<td class="px-4 py-3">
<span class="{{ $adminListBadgeBaseClass }} border-purple-200 bg-purple-50 text-purple-700">
{{ \App\Enums\IntimacySource::tryFrom($log->source)?->label() ?? $log->source }}
</span>
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $log->remark ?? '—' }}</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">
{{ $log->created_at?->format('m-d H:i') }}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $logs->links() }}</div>
@endif
</div>
@if ($logs->hasPages())
<div class="px-4 py-4 border-t">{{ $logs->links() }}</div>
@endif
</div>
@endsection
+116 -105
View File
@@ -10,99 +10,110 @@
@section('title', '婚姻列表')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="flex items-center justify-between mb-5">
<h2 class="text-xl font-bold text-gray-800">📋 婚姻列表</h2>
<a href="{{ route('admin.marriages.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回总览</a>
</div>
{{-- 筛选栏 --}}
<form method="GET" class="bg-white rounded-xl border shadow-sm p-4 mb-5 flex flex-wrap gap-3 items-end">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">状态</label>
<select name="status" class="border rounded-lg px-3 py-2 text-sm focus:outline-none">
<option value="">全部</option>
@foreach (['married' => '已婚', 'pending' => '求婚中', 'divorced' => '已离婚', 'rejected' => '被拒', 'expired' => '已过期'] as $val => $label)
<option value="{{ $val }}" @selected(request('status') === $val)>{{ $label }}</option>
@endforeach
</select>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">📋 婚姻列表</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">统一查看婚姻状态、亲密度与后台管理操作。</p>
</div>
<a href="{{ route('admin.marriages.index') }}" class="{{ $adminListSecondaryButtonClass }}">返回总览</a>
</div>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">搜索用户名</label>
<input type="text" name="search" value="{{ request('search') }}" placeholder="双方任一用户名..."
class="border rounded-lg px-3 py-2 text-sm w-48 focus:outline-none">
</div>
<button type="submit"
class="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-bold hover:bg-indigo-700 transition">
筛选
</button>
<a href="{{ route('admin.marriages.list') }}" class="text-sm text-gray-500 hover:underline py-2">重置</a>
</form>
{{-- 婚姻列表 --}}
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs uppercase">
<tr>
<th class="px-4 py-3 text-left">ID</th>
<th class="px-4 py-3 text-left">双方</th>
<th class="px-4 py-3 text-left">戒指</th>
<th class="px-4 py-3 text-center">状态</th>
<th class="px-4 py-3 text-center">亲密度/等级</th>
<th class="px-4 py-3 text-center">结婚天数</th>
<th class="px-4 py-3 text-left">时间</th>
<th class="px-4 py-3 text-center">操作</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse ($marriages as $m)
<tr class="hover:bg-gray-50 transition">
<td class="px-4 py-3 text-gray-400 font-mono text-xs">{{ $m->id }}</td>
<td class="px-4 py-3">
<div class="font-bold">{{ $m->user?->username }}</div>
<div class="text-gray-400 text-xs">× {{ $m->partner?->username }}</div>
</td>
<td class="px-4 py-3">
{{ $m->ringItem?->icon }} {{ $m->ringItem?->name ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
<span
class="px-2 py-0.5 rounded-full text-xs font-bold
{{ match ($m->status) {
'married' => 'bg-green-100 text-green-700',
'pending' => 'bg-amber-100 text-amber-700',
'divorced' => 'bg-red-100 text-red-700',
'rejected' => 'bg-gray-100 text-gray-600',
'expired' => 'bg-slate-100 text-slate-500',
default => 'bg-gray-100 text-gray-600',
} }}">
{{ ['married' => '💑 已婚', 'pending' => '💍 求婚中', 'divorced' => '💔 已离婚', 'rejected' => '❌ 被拒', 'expired' => '⏰ 已过期'][$m->status] ?? $m->status }}
</span>
</td>
<td class="px-4 py-3 text-center">
<div class="font-bold text-indigo-600">{{ number_format($m->intimacy) }}</div>
<div class="text-xs text-gray-400">
{{ \App\Services\MarriageIntimacyService::levelIcon($m->level) }}
Lv{{ $m->level }}</div>
</td>
<td class="px-4 py-3 text-center text-gray-600">
{{ $m->married_at ? $m->married_at->diffInDays(now()) . ' 天' : '—' }}
</td>
<td class="px-4 py-3 text-xs text-gray-500">
@if ($m->married_at)
结婚:{{ $m->married_at->format('Y-m-d') }}
@elseif ($m->proposed_at)
求婚:{{ $m->proposed_at->format('Y-m-d') }}
@endif
@if ($m->divorced_at)
<div>离婚:{{ $m->divorced_at->format('Y-m-d') }}</div>
@endif
</td>
<td class="px-4 py-3 text-center" x-data="{ showDissolve: false }">
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form method="GET" class="{{ $adminListFilterFormClass }}">
<div>
<label class="{{ $adminListFilterLabelClass }}">状态</label>
<select name="status" class="{{ $adminListFilterInputClass }}">
<option value="">全部</option>
@foreach (['married' => '已婚', 'pending' => '求婚中', 'divorced' => '已离婚', 'rejected' => '被拒', 'expired' => '已过期'] as $val => $label)
<option value="{{ $val }}" @selected(request('status') === $val)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="{{ $adminListFilterLabelClass }}">搜索用户名</label>
<input type="text" name="search" value="{{ request('search') }}" placeholder="双方任一用户名..."
class="w-48 {{ $adminListFilterInputClass }}">
</div>
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">筛选</button>
<a href="{{ route('admin.marriages.list') }}" class="{{ $adminListSecondaryButtonClass }}">重置</a>
</form>
</div>
</div>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">婚姻记录</h3>
<p class="{{ $adminListSectionDescClass }}">保留婚姻状态语义色,其他列表结构按统一后台样式展示。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">ID</th>
<th class="{{ $adminListTableHeadCellClass }}">双方</th>
<th class="{{ $adminListTableHeadCellClass }}">戒指</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">亲密度/等级</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">结婚天数</th>
<th class="{{ $adminListTableHeadCellClass }}">时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($marriages as $m)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }} {{ $adminListNumericTextClass }}">{{ $m->id }}</td>
<td class="px-4 py-3">
<div class="{{ $adminListPrimaryTextClass }}">{{ $m->user?->username }}</div>
<div class="{{ $adminListSecondaryTextClass }}">× {{ $m->partner?->username }}</div>
</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">
{{ $m->ringItem?->icon }} {{ $m->ringItem?->name ?? '—' }}
</td>
<td class="px-4 py-3 text-center">
<span
class="{{ $adminListBadgeBaseClass }} {{ match ($m->status) {
'married' => 'border-green-200 bg-green-100 text-green-700',
'pending' => 'border-amber-200 bg-amber-100 text-amber-700',
'divorced' => 'border-red-200 bg-red-100 text-red-700',
'rejected' => 'border-gray-200 bg-gray-100 text-gray-600',
'expired' => 'border-slate-200 bg-slate-100 text-slate-500',
default => 'border-gray-200 bg-gray-100 text-gray-600',
} }}">
{{ ['married' => '💑 已婚', 'pending' => '💍 求婚中', 'divorced' => '💔 已离婚', 'rejected' => '❌ 被拒', 'expired' => '⏰ 已过期'][$m->status] ?? $m->status }}
</span>
</td>
<td class="px-4 py-3 text-center">
<div class="text-sm font-semibold text-indigo-600">{{ number_format($m->intimacy) }}</div>
<div class="{{ $adminListSecondaryTextClass }}">
{{ \App\Services\MarriageIntimacyService::levelIcon($m->level) }}
Lv{{ $m->level }}</div>
</td>
<td class="px-4 py-3 text-center {{ $adminListBodyTextClass }}">
{{ $m->married_at ? $m->married_at->diffInDays(now()) . ' 天' : '—' }}
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">
@if ($m->married_at)
结婚:{{ $m->married_at->format('Y-m-d') }}
@elseif ($m->proposed_at)
求婚:{{ $m->proposed_at->format('Y-m-d') }}
@endif
@if ($m->divorced_at)
<div>离婚:{{ $m->divorced_at->format('Y-m-d') }}</div>
@endif
</td>
<td class="px-4 py-3 text-center" x-data="{ showDissolve: false }">
@if ($m->status === 'married')
<button @click="showDissolve = true"
class="text-xs bg-red-50 text-red-600 font-bold px-3 py-1.5 rounded hover:bg-red-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-600 hover:text-white">
强制离婚
</button>
{{-- 强制离婚确认弹窗 --}}
@@ -123,9 +134,9 @@
class="w-full border rounded px-3 py-2 text-sm mb-3">
<div class="flex gap-2 justify-end">
<button type="button" @click="showDissolve = false"
class="px-3 py-1.5 border rounded text-sm text-gray-600">取消</button>
class="{{ $adminListSecondaryButtonClass }}">取消</button>
<button type="submit"
class="px-3 py-1.5 bg-red-600 text-white rounded text-sm font-bold">确认解除</button>
class="{{ $adminListActionButtonClass }} bg-red-600 text-white hover:bg-red-700">确认解除</button>
</div>
</form>
</div>
@@ -135,28 +146,28 @@
data-admin-confirm="确定取消该求婚吗?">
@csrf
<button type="submit"
class="text-xs bg-amber-50 text-amber-600 font-bold px-3 py-1.5 rounded hover:bg-amber-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-amber-50 text-amber-600 hover:bg-amber-600 hover:text-white">
取消求婚
</button>
</form>
@else
<span class="text-xs text-gray-300"></span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-12 text-center text-gray-400">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="{{ $adminListEmptyClass }}">暂无记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- 分页 --}}
@if ($marriages->hasPages())
<div class="px-4 py-4 border-t">{{ $marriages->links() }}</div>
@endif
@if ($marriages->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $marriages->links() }}</div>
@endif
</div>
</div>
@endsection
@@ -10,82 +10,94 @@
@section('title', '求婚记录')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="flex items-center justify-between mb-5">
<h2 class="text-xl font-bold text-gray-800">💌 求婚记录</h2>
<a href="{{ route('admin.marriages.index') }}" class="text-sm text-indigo-600 hover:underline"> 返回总览</a>
</div>
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">💌 求婚记录</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">统一查看求婚进度,并保留婚姻状态语义色彩。</p>
</div>
<a href="{{ route('admin.marriages.index') }}" class="{{ $adminListSecondaryButtonClass }}">返回总览</a>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-xs uppercase text-gray-600">
<tr>
<th class="px-4 py-3 text-left">ID</th>
<th class="px-4 py-3 text-left">发起方</th>
<th class="px-4 py-3 text-left">目标</th>
<th class="px-4 py-3 text-left">戒指</th>
<th class="px-4 py-3 text-center">状态</th>
<th class="px-4 py-3 text-left">求婚时间</th>
<th class="px-4 py-3 text-left">过期时间</th>
<th class="px-4 py-3 text-center">操作</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse ($proposals as $p)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-gray-400 font-mono text-xs">{{ $p->id }}</td>
<td class="px-4 py-3 font-bold">{{ $p->user?->username }}</td>
<td class="px-4 py-3 font-bold">{{ $p->partner?->username }}</td>
<td class="px-4 py-3">{{ $p->ringItem?->icon }} {{ $p->ringItem?->name ?? '—' }}</td>
<td class="px-4 py-3 text-center">
<span
class="px-2 py-0.5 rounded-full text-xs font-bold
{{ match ($p->status) {
'pending' => 'bg-amber-100 text-amber-700',
'rejected' => 'bg-red-100 text-red-600',
'expired' => 'bg-gray-100 text-gray-500',
'married' => 'bg-emerald-100 text-emerald-700',
'divorced' => 'bg-purple-100 text-purple-700',
default => 'bg-gray-100 text-gray-600',
} }}">
{{ ['pending' => '⏳ 等待中', 'rejected' => '❌ 已拒绝', 'expired' => '⏰ 已过期', 'married' => '✅ 已结婚', 'divorced' => '💔 已离婚'][$p->status] ?? $p->status }}
</span>
</td>
<td class="px-4 py-3 text-xs text-gray-500">{{ $p->proposed_at?->format('Y-m-d H:i') }}</td>
<td
class="px-4 py-3 text-xs {{ $p->expires_at?->isPast() ? 'text-red-400' : 'text-gray-500' }}">
{{ $p->expires_at?->format('Y-m-d H:i') }}
@if ($p->status === 'pending' && $p->expires_at?->isPast())
<span class="text-red-500">(已超时)</span>
@endif
</td>
<td class="px-4 py-3 text-center">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<div>
<h3 class="{{ $adminListSectionTitleClass }}">求婚列表</h3>
<p class="{{ $adminListSectionDescClass }}">列表布局、表头、按钮与分页对齐后台统一风格。</p>
</div>
</div>
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead>
<tr class="{{ $adminListTableHeadRowClass }}">
<th class="{{ $adminListTableHeadCellClass }}">ID</th>
<th class="{{ $adminListTableHeadCellClass }}">发起方</th>
<th class="{{ $adminListTableHeadCellClass }}">目标</th>
<th class="{{ $adminListTableHeadCellClass }}">戒指</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }}">求婚时间</th>
<th class="{{ $adminListTableHeadCellClass }}">过期时间</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($proposals as $p)
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }} {{ $adminListNumericTextClass }}">{{ $p->id }}</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $p->user?->username }}</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $p->partner?->username }}</td>
<td class="px-4 py-3 {{ $adminListBodyTextClass }}">{{ $p->ringItem?->icon }} {{ $p->ringItem?->name ?? '—' }}</td>
<td class="px-4 py-3 text-center">
<span
class="{{ $adminListBadgeBaseClass }} {{ match ($p->status) {
'pending' => 'border-amber-200 bg-amber-100 text-amber-700',
'rejected' => 'border-red-200 bg-red-100 text-red-600',
'expired' => 'border-gray-200 bg-gray-100 text-gray-500',
'married' => 'border-emerald-200 bg-emerald-100 text-emerald-700',
'divorced' => 'border-purple-200 bg-purple-100 text-purple-700',
default => 'border-gray-200 bg-gray-100 text-gray-600',
} }}">
{{ ['pending' => '⏳ 等待中', 'rejected' => '❌ 已拒绝', 'expired' => '⏰ 已过期', 'married' => '✅ 已结婚', 'divorced' => '💔 已离婚'][$p->status] ?? $p->status }}
</span>
</td>
<td class="px-4 py-3 {{ $adminListSecondaryTextClass }}">{{ $p->proposed_at?->format('Y-m-d H:i') }}</td>
<td class="px-4 py-3 text-xs {{ $p->expires_at?->isPast() ? 'text-red-400' : 'text-gray-500' }}">
{{ $p->expires_at?->format('Y-m-d H:i') }}
@if ($p->status === 'pending' && $p->expires_at?->isPast())
<span class="text-red-500">(已超时)</span>
@endif
</td>
<td class="px-4 py-3 text-center">
@if ($p->status === 'pending')
<form action="{{ route('admin.marriages.cancel-proposal', $p->id) }}" method="POST"
data-admin-confirm="确定取消该求婚吗?">
@csrf
<button type="submit"
class="text-xs bg-amber-50 text-amber-600 font-bold px-3 py-1.5 rounded hover:bg-amber-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-amber-50 text-amber-600 hover:bg-amber-600 hover:text-white">
取消求婚
</button>
</form>
@else
<span class="text-gray-300 text-xs"></span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-12 text-center text-gray-400">暂无求婚记录</td>
</tr>
@endforelse
</tbody>
</table>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="{{ $adminListEmptyClass }}">暂无求婚记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($proposals->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $proposals->links() }}</div>
@endif
</div>
@if ($proposals->hasPages())
<div class="px-4 py-4 border-t">{{ $proposals->links() }}</div>
@endif
</div>
@endsection
@@ -0,0 +1,31 @@
<?php
$adminListPageClass = 'space-y-6';
$adminListHeaderCardClass = 'rounded-xl border border-gray-100 bg-white p-5 shadow-sm';
$adminListHeaderTitleClass = 'text-lg font-bold text-gray-800';
$adminListHeaderSubtitleClass = 'mt-1 text-sm text-gray-500';
$adminListFilterCardClass = 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden mb-6';
$adminListFilterInnerClass = 'p-6 border-b border-gray-100 bg-gray-50';
$adminListFilterFormClass = 'flex flex-wrap items-end gap-3';
$adminListFilterLabelClass = 'block mb-1 text-xs font-semibold uppercase tracking-wider text-gray-500';
$adminListFilterInputClass = 'px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm';
$adminListPrimaryButtonClass = 'bg-indigo-600 text-white px-4 py-2 rounded-lg font-semibold shadow-sm transition hover:bg-indigo-700';
$adminListSecondaryButtonClass = 'px-4 py-2 bg-white border border-gray-300 rounded-lg text-sm font-semibold text-gray-700 hover:bg-gray-50 transition';
$adminListCardClass = 'bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden';
$adminListSectionHeadClass = 'px-6 py-4 border-b border-gray-100 bg-gray-50';
$adminListSectionTitleClass = 'text-base font-semibold text-gray-700';
$adminListSectionDescClass = 'text-xs text-gray-400 mt-1';
$adminListTableWrapClass = 'overflow-x-auto';
$adminListTableClass = 'w-full text-sm';
$adminListTableHeadRowClass = 'bg-gray-50 border-b border-gray-100';
$adminListTableHeadCellClass = 'px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500';
$adminListTableBodyClass = 'divide-y divide-gray-100';
$adminListTableRowClass = 'hover:bg-gray-50 transition';
$adminListPrimaryTextClass = 'text-sm font-semibold text-gray-800';
$adminListSecondaryTextClass = 'text-xs text-gray-400';
$adminListBodyTextClass = 'text-sm text-gray-600';
$adminListNumericTextClass = 'text-sm font-mono';
$adminListPaginationClass = 'p-4 border-t border-gray-100 text-sm text-gray-600';
$adminListEmptyClass = 'px-4 py-12 text-center text-gray-400';
$adminListBadgeBaseClass = 'inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-semibold';
$adminListActionButtonClass = 'text-xs font-semibold px-3 py-1.5 rounded transition cursor-pointer';
+36 -38
View File
@@ -12,6 +12,7 @@
@section('title', '职务管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div x-data="{
showForm: false,
editing: null,
@@ -82,30 +83,27 @@
}">
{{-- 头部 --}}
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-lg font-bold text-gray-800">职务管理</h2>
<p class="text-sm text-gray-500">管理各部门职务,配置等级、图标、人数上限和任命权限</p>
</div>
<div class="flex space-x-2">
<div class="{{ $adminListHeaderCardClass }} mb-6">
<div class="flex justify-between items-center">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">职务管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">管理各部门职务,配置等级、图标、人数上限和任命权限</p>
</div>
<div class="flex space-x-2">
<a href="{{ route('admin.departments.index') }}"
style="background-color:#e5e7eb;color:#374151;padding:0.5rem 1rem;border-radius:0.5rem;font-weight:700;font-size:0.875rem;display:inline-flex;align-items:center;text-decoration:none;"
onmouseover="this.style.backgroundColor='#d1d5db'" onmouseout="this.style.backgroundColor='#e5e7eb'">
class="{{ $adminListSecondaryButtonClass }}">
部门管理
</a>
<a href="{{ route('admin.appointments.index') }}"
style="background-color:#f97316;color:#fff;padding:0.5rem 1rem;border-radius:0.5rem;font-weight:700;font-size:0.875rem;display:inline-flex;align-items:center;text-decoration:none;box-shadow:0 1px 2px rgba(0,0,0,.1);"
onmouseover="this.style.backgroundColor='#ea580c'" onmouseout="this.style.backgroundColor='#f97316'">
class="px-4 py-2 rounded-lg text-sm font-semibold text-white bg-orange-500 hover:bg-orange-600 transition shadow-sm">
🎖️ 任命管理
</a>
@if (Auth::id() === 1)
<button @click="openCreate()"
style="background-color:#4f46e5;color:#fff;padding:0.5rem 1.25rem;border-radius:0.5rem;font-weight:700;border:none;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.1);"
onmouseover="this.style.backgroundColor='#4338ca'"
onmouseout="this.style.backgroundColor='#4f46e5'">
<button @click="openCreate()" class="{{ $adminListPrimaryButtonClass }}">
+ 新增职务
</button>
@endif
</div>
</div>
</div>
@@ -176,33 +174,33 @@
<span class="text-xs text-gray-400">位阶 {{ $dept->rank }}</span>
</div>
<div class="bg-white rounded-xl shadow-sm border overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs">
<div class="{{ $adminListCardClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-4 py-3 text-left">图标</th>
<th class="px-4 py-3 text-left">职务名</th>
<th class="px-4 py-3 text-center">位阶</th>
<th class="px-4 py-3 text-center">等级</th>
<th class="px-4 py-3 text-center">人数上限</th>
<th class="px-4 py-3 text-center">当前在职</th>
<th class="px-4 py-3 text-center">单次上限</th>
<th class="px-4 py-3 text-center">单日上限</th>
<th class="px-4 py-3 text-center">任命权</th>
<th class="px-4 py-3 text-center">礼包默认</th>
<th class="px-4 py-3 text-center">聊天室权限</th>
<th class="{{ $adminListTableHeadCellClass }}">图标</th>
<th class="{{ $adminListTableHeadCellClass }}">职务名</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">位阶</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">等级</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">人数上限</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">当前在职</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">单次上限</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">单日上限</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">任命权</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">礼包默认</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">聊天室权限</th>
@php $superLvl = (int) \App\Models\Sysparam::getValue('superlevel', '100'); @endphp
@if (Auth::user()->user_level >= $superLvl)
<th class="px-4 py-3 text-right">操作</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
@endif
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($dept->positions as $pos)
@php $appointableIds = $pos->appointablePositions->pluck('id')->toArray(); @endphp
<tr class="hover:bg-gray-50 transition">
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-3 text-xl">{{ $pos->icon }}</td>
<td class="px-4 py-3 font-bold">{{ $pos->name }}</td>
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}">{{ $pos->name }}</td>
<td class="px-4 py-3 text-center">
<span
class="text-xs bg-indigo-100 text-indigo-700 px-2 py-0.5 rounded font-mono">{{ $pos->rank }}</span>
@@ -313,7 +311,7 @@
sort_order: {{ $pos->sort_order }},
requestUrl: '{{ route('admin.positions.update', $pos->id) }}'
}, {{ json_encode($appointableIds) }}, {{ json_encode($pos->permissions ?? []) }})"
class="text-xs bg-indigo-50 text-indigo-600 font-bold px-2 py-1 rounded hover:bg-indigo-600 hover:text-white transition">
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-600 hover:bg-indigo-600 hover:text-white">
编辑
</button>
@endif
@@ -323,17 +321,17 @@
data-admin-confirm="确定删除职务【{{ $pos->name }}】?">
@csrf @method('DELETE')
<button type="submit"
class="text-xs bg-red-50 text-red-600 font-bold px-2 py-1 rounded hover:bg-red-600 hover:text-white transition">
删除
</button>
</form>
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-600 hover:text-white">
删除
</button>
</form>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="{{ Auth::user()->user_level >= $superLvl ? 11 : 10 }}"
class="px-4 py-6 text-center text-gray-400">该部门暂无职务</td>
class="{{ $adminListEmptyClass }}">该部门暂无职务</td>
</tr>
@endforelse
</tbody>
+32 -30
View File
@@ -12,6 +12,7 @@
@section('title', '🛒 商店商品管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
@php
$typeLabels = [
@@ -90,48 +91,49 @@
}">
{{-- 头部操作栏 --}}
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-lg font-bold text-gray-800">商店商品列表</h2>
<p class="text-sm text-gray-500">管理聊天室商店内所有可出售商品,支持上下架控制。</p>
<div class="{{ $adminListHeaderCardClass }} mb-6">
<div class="flex justify-between items-center">
<div>
<h2 class="{{ $adminListHeaderTitleClass }}">商店商品列表</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">管理聊天室商店内所有可出售商品,支持上下架控制。</p>
</div>
@if ($isSuperAdmin)
<button @click="openCreate()" class="{{ $adminListPrimaryButtonClass }}">
+ 新增商品
</button>
@endif
</div>
@if ($isSuperAdmin)
<button @click="openCreate()"
class="bg-indigo-600 text-white px-5 py-2.5 rounded-lg font-bold hover:bg-indigo-700 transition shadow-sm">
+ 新增商品
</button>
@endif
</div>
{{-- 商品列表表格 --}}
<div class="bg-white rounded-xl shadow overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-500 uppercase text-xs tracking-wider">
<div class="{{ $adminListCardClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-4 py-3 text-left">商品</th>
<th class="px-4 py-3 text-left">类型</th>
<th class="px-4 py-3 text-right">价格</th>
<th class="px-4 py-3 text-center">有效期</th>
<th class="px-4 py-3 text-center">排序</th>
<th class="px-4 py-3 text-center">状态</th>
<th class="px-4 py-3 text-center">操作</th>
<th class="{{ $adminListTableHeadCellClass }}">商品</th>
<th class="{{ $adminListTableHeadCellClass }}">类型</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">价格</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">有效期</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">排序</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($items as $item)
@php $tl = $typeLabels[$item->type] ?? ['label' => $item->type, 'color' => 'bg-gray-100 text-gray-600']; @endphp
<tr class="hover:bg-gray-50 transition {{ $item->is_active ? '' : 'opacity-50' }}">
<tr class="{{ $adminListTableRowClass }} {{ $item->is_active ? '' : 'opacity-50' }}">
{{-- 商品信息 --}}
<td class="px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-2xl leading-none">{{ $item->icon }}</span>
<div>
<p class="font-semibold text-gray-800">{{ $item->name }}</p>
<p class="text-xs text-gray-400 font-mono">{{ $item->slug }}</p>
@if ($item->description)
<p class="text-xs text-gray-500 mt-0.5 max-w-xs truncate">
<p class="{{ $adminListPrimaryTextClass }}">{{ $item->name }}</p>
<p class="{{ $adminListSecondaryTextClass }} font-mono">{{ $item->slug }}</p>
@if ($item->description)
<p class="text-xs text-gray-500 mt-0.5 max-w-xs truncate" title="{{ $item->description }}">
{{ $item->description }}</p>
@endif
@endif
</div>
</div>
</td>
@@ -189,7 +191,7 @@
'sort_order' => $item->sort_order,
'is_active' => (bool) $item->is_active,
]) }})"
class="text-indigo-600 hover:text-indigo-800 text-xs font-semibold px-2 py-1 rounded hover:bg-indigo-50 transition">
class="{{ $adminListActionButtonClass }} text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50">
编辑
</button>
@if ($isSuperAdmin)
@@ -197,7 +199,7 @@
data-admin-confirm="确定要删除「{{ $item->name }}」吗?此操作不可撤销!">
@csrf @method('DELETE')
<button type="submit"
class="text-red-500 hover:text-red-700 text-xs font-semibold px-2 py-1 rounded hover:bg-red-50 transition">
class="{{ $adminListActionButtonClass }} text-red-500 hover:text-red-700 hover:bg-red-50">
删除
</button>
</form>
@@ -207,7 +209,7 @@
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-12 text-center text-gray-400">暂无商品数据</td>
<td colspan="7" class="{{ $adminListEmptyClass }}">暂无商品数据</td>
</tr>
@endforelse
</tbody>
@@ -3,6 +3,8 @@
@section('title', '签到奖励管理')
@section('content')
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
@php
$signInRulePayload = $rules->mapWithKeys(
fn($rule) => [
@@ -27,60 +29,63 @@
<script type="application/json" id="admin-sign-in-rules-data">@json($signInRulePayload)</script>
<div class="space-y-6">
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex items-center justify-between gap-4">
<div>
<h2 class="text-lg font-bold text-gray-800"> 签到奖励管理</h2>
<p class="text-xs text-gray-500 mt-1">按连续签到天数配置金币、经验、魅力和专属身份。</p>
<h2 class="{{ $adminListHeaderTitleClass }}"> 签到奖励管理</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">按连续签到天数配置金币、经验、魅力和专属身份。</p>
</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-100">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }}">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">连续天数</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">金币</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">经验</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">魅力</th>
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">身份</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">有效期</th>
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
<th class="{{ $adminListTableHeadCellClass }}">连续天数</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">金币</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">经验</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">魅力</th>
<th class="{{ $adminListTableHeadCellClass }}">身份</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">有效期</th>
<th class="{{ $adminListTableHeadCellClass }} text-center">状态</th>
<th class="{{ $adminListTableHeadCellClass }} text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-50">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($rules as $rule)
<tr id="rule-row-{{ $rule->id }}" class="{{ $rule->is_enabled ? '' : 'opacity-50' }}">
<td class="px-4 py-3 font-bold text-gray-800"> {{ $rule->streak_days }} </td>
<td class="px-4 py-3 text-center text-amber-600 font-mono">+{{ $rule->gold_reward }}</td>
<td class="px-4 py-3 text-center text-emerald-600 font-mono">+{{ $rule->exp_reward }}</td>
<td class="px-4 py-3 text-center text-pink-600 font-mono">+{{ $rule->charm_reward }}</td>
<tr id="rule-row-{{ $rule->id }}" class="{{ $adminListTableRowClass }} {{ $rule->is_enabled ? '' : 'opacity-50' }}">
<td class="px-4 py-3 {{ $adminListPrimaryTextClass }}"> {{ $rule->streak_days }} </td>
<td class="px-4 py-3 text-center text-amber-600 {{ $adminListNumericTextClass }}">+{{ $rule->gold_reward }}</td>
<td class="px-4 py-3 text-center text-emerald-600 {{ $adminListNumericTextClass }}">+{{ $rule->exp_reward }}</td>
<td class="px-4 py-3 text-center text-pink-600 {{ $adminListNumericTextClass }}">+{{ $rule->charm_reward }}</td>
<td class="px-4 py-3">
@if ($rule->identity_badge_name)
<span class="inline-flex items-center gap-1 rounded-full border px-2 py-1 text-xs font-bold"
<span class="{{ $adminListBadgeBaseClass }} px-2 py-1"
style="color: {{ $rule->identity_badge_color ?: '#0f766e' }}; border-color: #99f6e4; background: #f0fdfa;">
<span>{{ $rule->identity_badge_icon ?: '✅' }}</span>
<span>{{ $rule->identity_badge_name }}</span>
</span>
<div class="mt-1 text-[11px] text-gray-400">{{ $rule->identity_badge_code }}</div>
<div class="mt-1 {{ $adminListSecondaryTextClass }}">{{ $rule->identity_badge_code }}</div>
@else
<span class="text-xs text-gray-400">未配置身份</span>
<span class="{{ $adminListSecondaryTextClass }}">未配置身份</span>
@endif
</td>
<td class="px-4 py-3 text-center text-xs text-gray-600">
<td class="px-4 py-3 text-center {{ $adminListBodyTextClass }}">
{{ $rule->identity_duration_days > 0 ? $rule->identity_duration_days . ' 天' : '永久' }}
</td>
<td class="px-4 py-3 text-center">
<button type="button" data-sign-in-rule-toggle-url="{{ route('admin.sign-in-rules.toggle', $rule) }}"
id="toggle-rule-{{ $rule->id }}"
class="px-2 py-1 rounded-full text-xs font-bold transition {{ $rule->is_enabled ? 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200' : 'bg-gray-100 text-gray-500 hover:bg-gray-200' }}">
class="{{ $adminListBadgeBaseClass }} px-2 py-1 transition {{ $rule->is_enabled ? 'border-emerald-200 bg-emerald-100 text-emerald-700 hover:bg-emerald-200' : 'border-gray-200 bg-gray-100 text-gray-500 hover:bg-gray-200' }}">
{{ $rule->is_enabled ? '启用' : '停用' }}
</button>
</td>
<td class="px-4 py-3 text-right">
<button type="button" data-sign-in-rule-edit-id="{{ $rule->id }}"
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition mr-1">
class="{{ $adminListActionButtonClass }} bg-indigo-50 text-indigo-700 hover:bg-indigo-100 mr-1">
编辑
</button>
<form action="{{ route('admin.sign-in-rules.destroy', $rule) }}" method="POST"
@@ -88,7 +93,7 @@
@csrf
@method('DELETE')
<button type="submit"
class="px-3 py-1 bg-red-50 text-red-600 rounded text-xs font-bold hover:bg-red-100 transition">
class="{{ $adminListActionButtonClass }} bg-red-50 text-red-600 hover:bg-red-100">
删除
</button>
</form>
@@ -96,23 +101,23 @@
</tr>
@empty
<tr>
<td colspan="8" class="px-4 py-8 text-center text-sm text-gray-400">暂无签到奖励规则。</td>
<td colspan="8" class="{{ $adminListEmptyClass }}">暂无签到奖励规则。</td>
</tr>
@endforelse
</tbody>
</table>
</tbody>
</table>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-5 border-b border-gray-100 bg-gray-50">
<h3 class="font-bold text-gray-700 text-sm"> 新增签到档位</h3>
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListSectionHeadClass }}">
<h3 class="{{ $adminListSectionTitleClass }}"> 新增签到档位</h3>
</div>
<form action="{{ route('admin.sign-in-rules.store') }}" method="POST" class="p-5">
@csrf
@include('admin.sign-in-rules.partials.form-fields', ['rule' => null])
<div class="mt-4 flex items-center gap-4">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm shadow-sm">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
💾 添加规则
</button>
<label class="flex items-center gap-2 text-sm text-gray-600 cursor-pointer">
@@ -124,9 +129,9 @@
</div>
</div>
<div id="edit-rule-modal" class="hidden fixed inset-0 bg-black/40 z-50 flex items-center justify-center p-4">
<div class="bg-white rounded-xl w-full max-w-3xl shadow-2xl">
<div class="p-5 border-b border-gray-100 flex justify-between items-center">
<div id="edit-rule-modal" class="hidden fixed inset-0 bg-black/40 z-50 flex items-center justify-center p-4">
<div class="bg-white rounded-xl w-full max-w-3xl shadow-2xl">
<div class="p-5 border-b border-gray-100 flex justify-between items-center">
<h3 class="font-bold text-gray-800">✏️ 编辑签到规则</h3>
<button type="button" data-sign-in-rule-close class="text-gray-400 hover:text-gray-600 text-xl"></button>
</div>
@@ -135,8 +140,7 @@
@method('PUT')
@include('admin.sign-in-rules.partials.form-fields', ['rule' => null, 'prefix' => 'edit-'])
<div class="mt-5 flex items-center gap-4">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
💾 保存修改
</button>
<label class="flex items-center gap-2 text-sm text-gray-600 cursor-pointer">
@@ -144,7 +148,7 @@
启用此规则
</label>
<button type="button" data-sign-in-rule-close
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
class="{{ $adminListSecondaryButtonClass }}">
取消
</button>
</div>
@@ -7,110 +7,117 @@
@section('title', '会员购买日志')
@section('content')
<div class="bg-white p-5 rounded-xl border border-gray-100 shadow-sm mb-6">
<form action="{{ route('admin.vip-payment-logs.index') }}" method="GET" class="flex flex-wrap items-end gap-4">
<div class="flex-1 min-w-[140px]">
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">用户名</label>
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form action="{{ route('admin.vip-payment-logs.index') }}" method="GET"
class="{{ $adminListFilterFormClass }}">
<div class="flex-1 min-w-[140px]">
<label class="{{ $adminListFilterLabelClass }}">用户名</label>
<input type="text" name="username" value="{{ request('username') }}"
class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2"
class="w-full {{ $adminListFilterInputClass }}"
placeholder="支持模糊搜索">
</div>
</div>
<div class="flex-1 min-w-[140px]">
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">订单号/流水号</label>
<div class="flex-1 min-w-[140px]">
<label class="{{ $adminListFilterLabelClass }}">订单号/流水号</label>
<input type="text" name="order_no" value="{{ request('order_no') }}"
class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2"
class="w-full {{ $adminListFilterInputClass }}"
placeholder="本地单号 / 平台单号 / 第三方单号">
</div>
</div>
<div class="flex-1 min-w-[130px]">
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">订单状态</label>
<select name="status"
class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2">
<option value="">全部状态</option>
@foreach ($statusOptions as $value => $label)
<option value="{{ $value }}" {{ request('status') === $value ? 'selected' : '' }}>{{ $label }}</option>
@endforeach
</select>
</div>
<div class="flex-1 min-w-[130px]">
<label class="{{ $adminListFilterLabelClass }}">订单状态</label>
<select name="status" class="w-full {{ $adminListFilterInputClass }}">
<option value="">全部状态</option>
@foreach ($statusOptions as $value => $label)
<option value="{{ $value }}" {{ request('status') === $value ? 'selected' : '' }}>{{ $label }}</option>
@endforeach
</select>
</div>
<div class="flex-none w-36">
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">开始日期</label>
<div class="flex-none w-36">
<label class="{{ $adminListFilterLabelClass }}">开始日期</label>
<input type="date" name="date_start" value="{{ request('date_start') }}"
class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2">
</div>
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div class="flex-none w-36">
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">结束日期</label>
<div class="flex-none w-36">
<label class="{{ $adminListFilterLabelClass }}">结束日期</label>
<input type="date" name="date_end" value="{{ request('date_end') }}"
class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2">
</div>
class="w-full {{ $adminListFilterInputClass }}">
</div>
<div class="flex-none flex items-center space-x-2">
<button type="submit"
class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-5 rounded-lg shadow-sm transition text-sm">查询</button>
<a href="{{ route('admin.vip-payment-logs.index') }}"
class="bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 font-medium py-2 px-4 rounded-lg shadow-sm transition text-sm">重置</a>
<div class="flex-none flex items-center gap-2">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">查询</button>
<a href="{{ route('admin.vip-payment-logs.index') }}"
class="{{ $adminListSecondaryButtonClass }}">重置</a>
</div>
</form>
</div>
</form>
</div>
</div>
<div class="bg-white rounded shadow overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse min-w-[1200px]">
<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 whitespace-nowrap">订单ID</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">用户</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">会员等级</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">本地订单号</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">平台支付单号</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">支付金额</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">状态</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">支付时间</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap">开通时间</th>
<th class="px-6 py-4 font-semibold whitespace-nowrap text-right">创建时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} min-w-[1200px] text-left">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">订单ID</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">用户</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">会员等级</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">本地订单号</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">平台支付单号</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">支付金额</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">状态</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">支付时间</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap">开通时间</th>
<th class="{{ $adminListTableHeadCellClass }} whitespace-nowrap text-right">创建时间</th>
</tr>
</thead>
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($logs as $log)
@php
$statusClass = match ($log->status) {
'paid' => 'bg-emerald-100 text-emerald-700',
'pending' => 'bg-amber-100 text-amber-700',
'closed' => 'bg-gray-100 text-gray-500',
'failed' => 'bg-rose-100 text-rose-700',
default => 'bg-slate-100 text-slate-700',
'paid' => 'border-emerald-200 bg-emerald-100 text-emerald-700',
'pending' => 'border-amber-200 bg-amber-100 text-amber-700',
'closed' => 'border-gray-200 bg-gray-100 text-gray-500',
'failed' => 'border-rose-200 bg-rose-100 text-rose-700',
default => 'border-slate-200 bg-slate-100 text-slate-700',
};
@endphp
<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 whitespace-nowrap">
<div class="font-bold text-gray-800 whitespace-nowrap">{{ $log->user?->username ?? '未知用户' }}</div>
<tr class="{{ $adminListTableRowClass }} cursor-default">
<td class="px-4 py-4 {{ $adminListSecondaryTextClass }}">#{{ $log->id }}</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="{{ $adminListPrimaryTextClass }} whitespace-nowrap">{{ $log->user?->username ?? '未知用户' }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<td class="px-4 py-4 whitespace-nowrap">
<span style="color: {{ $log->vipLevel?->color ?: '#111827' }}">{{ $log->vipLevel?->icon ?: '👑' }}</span>
<span class="font-bold text-gray-800 ml-1">{{ $log->vip_name }}</span>
<span class="{{ $adminListPrimaryTextClass }} ml-1">{{ $log->vip_name }}</span>
</td>
<td class="px-6 py-4 font-mono text-xs text-gray-600 whitespace-nowrap">{{ $log->order_no }}</td>
<td class="px-6 py-4 font-mono text-xs text-gray-600 whitespace-nowrap">{{ $log->payment_order_no ?: '-' }}</td>
<td class="px-6 py-4 font-bold text-rose-600 whitespace-nowrap">¥{{ number_format((float) $log->amount, 2) }}</td>
<td class="px-6 py-4 whitespace-nowrap"><span class="inline-flex px-2.5 py-1 rounded-full text-xs font-bold {{ $statusClass }}">{{ $statusOptions[$log->status] ?? $log->status }}</span></td>
<td class="px-6 py-4 text-sm text-gray-500 whitespace-nowrap">{{ $log->paid_at?->format('Y-m-d H:i:s') ?? '未支付' }}</td>
<td class="px-6 py-4 text-sm text-gray-500 whitespace-nowrap">{{ $log->opened_vip_at?->format('Y-m-d H:i:s') ?? '未开通' }}</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>
<td class="px-4 py-4 {{ $adminListNumericTextClass }} text-xs text-gray-600 whitespace-nowrap">{{ $log->order_no }}</td>
<td class="px-4 py-4 {{ $adminListNumericTextClass }} text-xs text-gray-600 whitespace-nowrap">{{ $log->payment_order_no ?: '-' }}</td>
<td class="px-4 py-4 whitespace-nowrap font-bold text-rose-600">¥{{ number_format((float) $log->amount, 2) }}</td>
<td class="px-4 py-4 whitespace-nowrap">
<span class="{{ $adminListBadgeBaseClass }} {{ $statusClass }}">{{ $statusOptions[$log->status] ?? $log->status }}</span>
</td>
<td class="px-4 py-4 {{ $adminListBodyTextClass }} whitespace-nowrap">{{ $log->paid_at?->format('Y-m-d H:i:s') ?? '未支付' }}</td>
<td class="px-4 py-4 {{ $adminListBodyTextClass }} whitespace-nowrap">{{ $log->opened_vip_at?->format('Y-m-d H:i:s') ?? '未开通' }}</td>
<td class="px-4 py-4 {{ $adminListBodyTextClass }} text-right whitespace-nowrap">{{ $log->created_at->format('Y-m-d H:i:s') }}</td>
</tr>
@empty
<tr>
<td colspan="10" class="px-6 py-8 text-center text-gray-500">📭 暂无会员购买记录</td>
<td colspan="10" class="{{ $adminListEmptyClass }}">📭 暂无会员购买记录</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</tbody>
</table>
</div>
@if ($logs->hasPages())
<div class="px-6 py-4 border-t border-gray-200">{{ $logs->links() }}</div>
@endif
@if ($logs->hasPages())
<div class="{{ $adminListPaginationClass }}">{{ $logs->links() }}</div>
@endif
</div>
</div>
@endsection
+50 -45
View File
@@ -8,81 +8,86 @@
@section('title', $vip->name . ' 会员列表')
@section('content')
<div class="space-y-6">
<div class="flex flex-col gap-4 rounded-2xl border border-gray-200 bg-white p-6 shadow-sm lg:flex-row lg:items-center lg:justify-between">
@php require resource_path('views/admin/partials/list-theme.php'); @endphp
<div class="{{ $adminListPageClass }}">
<div class="{{ $adminListHeaderCardClass }}">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<div class="flex items-center gap-3">
<span class="text-3xl">{{ $vip->icon }}</span>
<div>
<h2 class="text-xl font-bold" style="color: {{ $vip->color }}">{{ $vip->name }} 会员列表</h2>
<p class="mt-1 text-sm text-gray-500">查看该等级下的会员用户名、当前状态与会员到期日期</p>
<h2 class="{{ $adminListHeaderTitleClass }}" style="color: {{ $vip->color }}">{{ $vip->name }} 会员列表</h2>
<p class="{{ $adminListHeaderSubtitleClass }}">查看该等级下的会员用户名、当前状态与会员到期日期</p>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-3 text-sm">
<span class="inline-flex items-center rounded-full bg-indigo-50 px-3 py-1 font-semibold text-indigo-600">
<span class="{{ $adminListBadgeBaseClass }} border-indigo-200 bg-indigo-50 px-3 py-1 text-indigo-600">
总分配人数:{{ $totalAssignedCount }}
</span>
<span class="inline-flex items-center rounded-full bg-emerald-50 px-3 py-1 font-semibold text-emerald-600">
<span class="{{ $adminListBadgeBaseClass }} border-emerald-200 bg-emerald-50 px-3 py-1 text-emerald-600">
当前有效会员:{{ $activeCount }}
</span>
<span class="inline-flex items-center rounded-full bg-amber-50 px-3 py-1 font-semibold text-amber-600">
<span class="{{ $adminListBadgeBaseClass }} border-amber-200 bg-amber-50 px-3 py-1 text-amber-600">
等级时长:{{ $vip->duration_days ?: '永久' }}
</span>
</div>
</div>
<div class="flex gap-3">
<div class="flex gap-3">
<a href="{{ route('admin.vip.index') }}"
class="inline-flex items-center justify-center rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-600 transition hover:bg-gray-50">
class="{{ $adminListSecondaryButtonClass }} inline-flex items-center justify-center">
返回等级列表
</a>
</div>
</div>
</div>
<div class="rounded-2xl border border-gray-200 bg-white p-5 shadow-sm">
<form action="{{ route('admin.vip.members', $vip->id) }}" method="GET" class="flex flex-wrap items-end gap-4">
<div class="{{ $adminListFilterCardClass }}">
<div class="{{ $adminListFilterInnerClass }}">
<form action="{{ route('admin.vip.members', $vip->id) }}" method="GET" class="{{ $adminListFilterFormClass }}">
<div class="min-w-[180px] flex-1">
<label class="mb-1.5 block text-xs font-semibold uppercase tracking-wider text-gray-500">用户名</label>
<label class="{{ $adminListFilterLabelClass }}">用户名</label>
<input type="text" name="keyword" value="{{ request('keyword') }}"
class="w-full rounded-lg border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
class="w-full {{ $adminListFilterInputClass }}"
placeholder="支持模糊搜索用户名">
</div>
<div class="w-44">
<label class="mb-1.5 block text-xs font-semibold uppercase tracking-wider text-gray-500">会员状态</label>
<select name="status"
class="w-full rounded-lg border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
<label class="{{ $adminListFilterLabelClass }}">会员状态</label>
<select name="status" class="w-full {{ $adminListFilterInputClass }}">
<option value="">全部状态</option>
<option value="active" @selected(request('status') === 'active')>当前有效</option>
<option value="expired" @selected(request('status') === 'expired')>已过期</option>
</select>
</div>
<div class="flex gap-2">
<button type="submit"
class="rounded-lg bg-indigo-600 px-5 py-2 text-sm font-semibold text-white transition hover:bg-indigo-700">
<div class="flex gap-2">
<button type="submit" class="{{ $adminListPrimaryButtonClass }}">
查询
</button>
<a href="{{ route('admin.vip.members', $vip->id) }}"
class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-600 transition hover:bg-gray-50">
class="{{ $adminListSecondaryButtonClass }}">
重置
</a>
</div>
</div>
</form>
</div>
</div>
<div class="overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm">
<div class="overflow-x-auto">
<table class="min-w-full text-left">
<thead class="bg-gray-50 text-xs font-semibold uppercase tracking-wider text-gray-500">
<div class="{{ $adminListCardClass }}">
<div class="{{ $adminListTableWrapClass }}">
<table class="{{ $adminListTableClass }} min-w-full text-left">
<thead class="{{ $adminListTableHeadRowClass }}">
<tr>
<th class="px-6 py-4">用户ID</th>
<th class="px-6 py-4">用户名</th>
<th class="px-6 py-4">性别</th>
<th class="px-6 py-4">会员状态</th>
<th class="px-6 py-4">到期日期</th>
<th class="px-6 py-4">注册时间</th>
<th class="{{ $adminListTableHeadCellClass }}">用户ID</th>
<th class="{{ $adminListTableHeadCellClass }}">用户名</th>
<th class="{{ $adminListTableHeadCellClass }}">性别</th>
<th class="{{ $adminListTableHeadCellClass }}">会员状态</th>
<th class="{{ $adminListTableHeadCellClass }}">到期日期</th>
<th class="{{ $adminListTableHeadCellClass }}">注册时间</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100 text-sm text-gray-700">
<tbody class="{{ $adminListTableBodyClass }}">
@forelse ($members as $member)
@php
$status = $member->hy_time === null ? 'permanent' : ($member->hy_time->isFuture() ? 'active' : 'expired');
@@ -92,9 +97,9 @@
default => '已过期',
};
$statusClass = match ($status) {
'permanent' => 'bg-purple-50 text-purple-600',
'active' => 'bg-emerald-50 text-emerald-600',
default => 'bg-rose-50 text-rose-600',
'permanent' => 'border-purple-200 bg-purple-50 text-purple-600',
'active' => 'border-emerald-200 bg-emerald-50 text-emerald-600',
default => 'border-rose-200 bg-rose-50 text-rose-600',
};
$sexLabel = match ((int) $member->sex) {
1 => '男',
@@ -102,29 +107,29 @@
default => '未知',
};
@endphp
<tr class="transition hover:bg-gray-50">
<td class="px-6 py-4 font-mono text-xs text-gray-500">#{{ $member->id }}</td>
<td class="px-6 py-4">
<div class="font-semibold text-gray-800">{{ $member->username }}</div>
<tr class="{{ $adminListTableRowClass }}">
<td class="px-4 py-4 {{ $adminListNumericTextClass }} text-xs text-gray-500">#{{ $member->id }}</td>
<td class="px-4 py-4">
<div class="{{ $adminListPrimaryTextClass }}">{{ $member->username }}</div>
</td>
<td class="px-6 py-4 text-gray-500">{{ $sexLabel }}</td>
<td class="px-6 py-4">
<span class="inline-flex rounded-full px-2.5 py-1 text-xs font-semibold {{ $statusClass }}">
<td class="px-4 py-4 {{ $adminListBodyTextClass }}">{{ $sexLabel }}</td>
<td class="px-4 py-4">
<span class="{{ $adminListBadgeBaseClass }} {{ $statusClass }}">
{{ $statusLabel }}
</span>
</td>
<td class="px-6 py-4 text-gray-600">
<td class="px-4 py-4 {{ $adminListBodyTextClass }}">
@if ($member->hy_time)
{{ $member->hy_time->format('Y-m-d H:i') }}
@else
永久
@endif
</td>
<td class="px-6 py-4 text-gray-500">{{ $member->created_at?->format('Y-m-d H:i') }}</td>
<td class="px-4 py-4 {{ $adminListBodyTextClass }}">{{ $member->created_at?->format('Y-m-d H:i') }}</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-6 py-12 text-center text-sm text-gray-400">
<td colspan="6" class="{{ $adminListEmptyClass }}">
当前条件下暂无该等级会员记录
</td>
</tr>
@@ -134,7 +139,7 @@
</div>
@if ($members->hasPages())
<div class="border-t border-gray-200 px-6 py-4">
<div class="{{ $adminListPaginationClass }}">
{{ $members->links() }}
</div>
@endif