314 lines
22 KiB
PHP
314 lines
22 KiB
PHP
{{--
|
||
文件功能:前台会员中心页面
|
||
展示当前用户会员状态、会员等级权益、购买入口以及用户自己的会员购买记录
|
||
--}}
|
||
@extends('layouts.app')
|
||
|
||
@section('title', '会员中心 - 飘落流星')
|
||
@section('nav-icon', '👑')
|
||
@section('nav-title', '会员中心')
|
||
|
||
@section('content')
|
||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 space-y-6">
|
||
<section class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||
<div class="lg:col-span-2 bg-white rounded-3xl border border-amber-100 shadow-sm p-6">
|
||
<div class="flex items-start justify-between gap-4">
|
||
<div>
|
||
<p class="text-sm font-bold text-amber-600">我的会员状态</p>
|
||
<h2 class="mt-2 text-2xl font-extrabold text-gray-900">
|
||
@if ($user->isVip())
|
||
{{ $user->vipName() ?: '尊贵会员' }}
|
||
@else
|
||
普通用户
|
||
@endif
|
||
</h2>
|
||
<p class="mt-3 text-sm text-gray-500">
|
||
@if ($user->isVip())
|
||
当前已开通会员权益,
|
||
@if ($user->hy_time)
|
||
到期时间:{{ $user->hy_time->format('Y-m-d H:i') }}
|
||
@else
|
||
当前为永久会员
|
||
@endif
|
||
@else
|
||
你当前还未开通会员,开通后可享受经验加成、金币加成和专属身份展示。
|
||
@endif
|
||
</p>
|
||
</div>
|
||
<div class="shrink-0 rounded-2xl bg-gradient-to-br from-amber-400 to-orange-500 text-white px-5 py-4 text-center min-w-[120px]">
|
||
<div class="text-sm opacity-90">当前徽章</div>
|
||
<div class="mt-2 text-3xl">{{ $user->vipIcon() ?: '⭐' }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-6 grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
<div class="rounded-2xl bg-indigo-50 border border-indigo-100 p-4">
|
||
<div class="text-xs font-bold text-indigo-500 uppercase tracking-wider">经验倍率</div>
|
||
<div class="mt-2 text-2xl font-extrabold text-indigo-900">×{{ $user->vipLevel?->exp_multiplier ?? 1 }}</div>
|
||
</div>
|
||
<div class="rounded-2xl bg-amber-50 border border-amber-100 p-4">
|
||
<div class="text-xs font-bold text-amber-500 uppercase tracking-wider">金币倍率</div>
|
||
<div class="mt-2 text-2xl font-extrabold text-amber-900">×{{ $user->vipLevel?->jjb_multiplier ?? 1 }}</div>
|
||
</div>
|
||
<div class="rounded-2xl bg-emerald-50 border border-emerald-100 p-4">
|
||
<div class="text-xs font-bold text-emerald-500 uppercase tracking-wider">累计已支付</div>
|
||
<div class="mt-2 text-2xl font-extrabold text-emerald-900">¥{{ number_format($totalAmount, 2) }}</div>
|
||
<div class="mt-1 text-xs text-emerald-700">成功订单 {{ $paidOrders }} 笔</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-slate-900 text-white rounded-3xl shadow-sm p-6">
|
||
<p class="text-sm font-bold text-amber-300">会员权益总览</p>
|
||
<ul class="mt-4 space-y-3 text-sm text-slate-200">
|
||
<li class="flex items-start gap-2"><span>⭐</span><span>挂机经验按会员倍率加成,升级更快。</span></li>
|
||
<li class="flex items-start gap-2"><span>💰</span><span>金币收益按会员倍率加成,参与玩法更轻松。</span></li>
|
||
<li class="flex items-start gap-2"><span>👑</span><span>昵称旁展示专属会员图标与会员名称。</span></li>
|
||
<li class="flex items-start gap-2"><span>✨</span><span>可使用会员专属进场欢迎语与离场提示语。</span></li>
|
||
</ul>
|
||
<div class="mt-6 rounded-2xl bg-white/10 border border-white/10 px-4 py-3 text-xs text-slate-200">
|
||
会员支付由平台支付中心统一处理,最终是否开通以异步回调结果为准。
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="bg-white rounded-3xl border border-gray-100 shadow-sm p-6">
|
||
<div class="flex items-center justify-between gap-4 mb-5">
|
||
<div>
|
||
<h3 class="text-xl font-extrabold text-gray-900">会员等级列表</h3>
|
||
<p class="mt-1 text-sm text-gray-500">不同档位提供不同倍率与时长,你可以按需要购买或续费。</p>
|
||
</div>
|
||
@if (! $vipPaymentEnabled)
|
||
<span class="inline-flex px-3 py-2 rounded-xl bg-gray-100 text-gray-500 text-sm font-bold">支付暂未开启</span>
|
||
@endif
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5">
|
||
@foreach ($vipLevels as $vip)
|
||
@php
|
||
$isCurrentVipLevel = $user->isVip() && (int) $user->vip_level_id === (int) $vip->id;
|
||
@endphp
|
||
<div class="rounded-3xl border {{ $isCurrentVipLevel ? 'border-amber-300 bg-amber-50/60' : 'border-gray-100 bg-white' }} shadow-sm p-5 flex flex-col">
|
||
<div class="flex items-center justify-between gap-3">
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-12 h-12 rounded-2xl bg-white border border-gray-100 flex items-center justify-center text-2xl shadow-sm">{{ $vip->icon }}</div>
|
||
<div>
|
||
<h4 class="text-lg font-extrabold" style="color: {{ $vip->color ?: '#111827' }}">{{ $vip->name }}</h4>
|
||
<p class="text-xs text-gray-500">当前已有 {{ $vip->users_count }} 位用户使用</p>
|
||
</div>
|
||
</div>
|
||
@if ($isCurrentVipLevel)
|
||
<span class="inline-flex px-2.5 py-1 rounded-full bg-amber-500 text-white text-xs font-bold">当前等级</span>
|
||
@endif
|
||
</div>
|
||
|
||
<div class="mt-5 grid grid-cols-2 gap-3 text-sm">
|
||
<div class="rounded-2xl bg-indigo-50 border border-indigo-100 p-3">
|
||
<div class="text-xs text-indigo-500 font-bold">经验倍率</div>
|
||
<div class="mt-1 text-xl font-extrabold text-indigo-900">×{{ $vip->exp_multiplier }}</div>
|
||
</div>
|
||
<div class="rounded-2xl bg-amber-50 border border-amber-100 p-3">
|
||
<div class="text-xs text-amber-500 font-bold">金币倍率</div>
|
||
<div class="mt-1 text-xl font-extrabold text-amber-900">×{{ $vip->jjb_multiplier }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-4 space-y-2 text-sm text-gray-600 flex-1">
|
||
<div class="flex items-center justify-between"><span>有效时长</span><span class="font-bold text-gray-900">{{ $vip->duration_days > 0 ? $vip->duration_days . ' 天' : '永久' }}</span></div>
|
||
<div class="flex items-center justify-between"><span>支付金额</span><span class="font-bold text-rose-600">{{ $vip->price > 0 ? '¥' . $vip->price : '联系管理员' }}</span></div>
|
||
</div>
|
||
|
||
<div class="mt-5">
|
||
@if ($vip->price > 0 && $vipPaymentEnabled)
|
||
<form action="{{ route('vip.payment.store') }}" method="POST"
|
||
onsubmit="return confirm('确认支付 {{ $vip->price }} 元购买【{{ $vip->name }}】吗?');">
|
||
@csrf
|
||
<input type="hidden" name="vip_level_id" value="{{ $vip->id }}">
|
||
<button type="submit" class="w-full py-3 rounded-2xl bg-indigo-600 hover:bg-indigo-700 text-white font-bold transition shadow-sm">
|
||
{{ $isCurrentVipLevel ? '立即续费' : '立即购买' }}
|
||
</button>
|
||
</form>
|
||
@elseif ($vip->price > 0)
|
||
<div class="w-full py-3 rounded-2xl bg-gray-100 text-gray-500 text-center font-bold">支付暂未开启</div>
|
||
@else
|
||
<div class="w-full py-3 rounded-2xl bg-emerald-100 text-emerald-700 text-center font-bold">请联系管理员开通</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
</section>
|
||
|
||
<section class="bg-white rounded-[2rem] border border-slate-200 shadow-sm overflow-hidden">
|
||
<div class="bg-[radial-gradient(circle_at_top_left,_rgba(251,191,36,0.24),_transparent_42%),linear-gradient(135deg,#0f172a,#1e293b,#334155)] px-6 py-6 text-white">
|
||
<div class="flex flex-col gap-2 md:flex-row md:items-end md:justify-between">
|
||
<div>
|
||
<p class="text-xs font-bold uppercase tracking-[0.28em] text-amber-300/90">会员进退场主题</p>
|
||
<h3 class="mt-2 text-2xl font-black">欢迎语、离开语与专属入场仪式</h3>
|
||
<p class="mt-2 max-w-2xl text-sm text-slate-200">
|
||
这里可以查看当前会员档位的专属特效和横幅风格;若当前档位允许自定义,你还可以设置自己的欢迎语和离开语。
|
||
</p>
|
||
</div>
|
||
@if ($user->isVip())
|
||
<div class="rounded-2xl border border-white/10 bg-white/10 px-4 py-3 text-sm text-slate-100">
|
||
当前档位:<span class="font-extrabold" style="color: {{ $user->vipLevel?->color ?: '#fef3c7' }}">{{ $user->vipName() }}</span>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 gap-6 p-6 lg:grid-cols-[1.2fr,0.8fr]">
|
||
<div class="space-y-5">
|
||
<div class="rounded-3xl border border-slate-200 bg-slate-50 p-5">
|
||
<div class="flex items-center gap-3">
|
||
<div class="flex h-12 w-12 items-center justify-center rounded-2xl bg-slate-900 text-2xl text-white shadow-lg">
|
||
{{ $user->vipLevel?->icon ?: '✨' }}
|
||
</div>
|
||
<div>
|
||
<p class="text-sm font-bold text-slate-500">当前主题预览</p>
|
||
<h4 class="text-xl font-black text-slate-900">{{ $user->vipLevel?->name ?? '普通用户' }}</h4>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-5 grid grid-cols-1 gap-3 md:grid-cols-2">
|
||
<div class="rounded-2xl border border-slate-200 bg-white p-4">
|
||
<p class="text-xs font-bold uppercase tracking-[0.18em] text-slate-400">入场特效</p>
|
||
<p class="mt-2 text-lg font-extrabold text-slate-900">{{ $effectOptions[$user->vipLevel?->joinEffectKey() ?? 'none'] ?? '无特效' }}</p>
|
||
<p class="mt-2 text-sm text-slate-500">横幅风格:{{ $bannerStyleOptions[$user->vipLevel?->joinBannerStyleKey() ?? 'aurora'] ?? '鎏光星幕' }}</p>
|
||
</div>
|
||
<div class="rounded-2xl border border-slate-200 bg-white p-4">
|
||
<p class="text-xs font-bold uppercase tracking-[0.18em] text-slate-400">离场特效</p>
|
||
<p class="mt-2 text-lg font-extrabold text-slate-900">{{ $effectOptions[$user->vipLevel?->leaveEffectKey() ?? 'none'] ?? '无特效' }}</p>
|
||
<p class="mt-2 text-sm text-slate-500">横幅风格:{{ $bannerStyleOptions[$user->vipLevel?->leaveBannerStyleKey() ?? 'farewell'] ?? '告别暮光' }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-3xl border border-amber-100 bg-amber-50/70 p-5">
|
||
<p class="text-sm font-bold text-amber-700">等级默认语句</p>
|
||
<div class="mt-4 grid gap-4 md:grid-cols-2">
|
||
<div class="rounded-2xl bg-white p-4 shadow-sm">
|
||
<p class="text-xs font-bold uppercase tracking-[0.18em] text-amber-500">默认欢迎语</p>
|
||
<p class="mt-3 text-sm leading-7 text-slate-700">
|
||
{{ $user->vipLevel?->join_templates_array[0] ?? '当前档位尚未配置默认欢迎语。' }}
|
||
</p>
|
||
</div>
|
||
<div class="rounded-2xl bg-white p-4 shadow-sm">
|
||
<p class="text-xs font-bold uppercase tracking-[0.18em] text-amber-500">默认离开语</p>
|
||
<p class="mt-3 text-sm leading-7 text-slate-700">
|
||
{{ $user->vipLevel?->leave_templates_array[0] ?? '当前档位尚未配置默认离开语。' }}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
|
||
<div class="flex items-start justify-between gap-3">
|
||
<div>
|
||
<p class="text-sm font-bold text-slate-500">我的个性化设置</p>
|
||
<h4 class="mt-1 text-xl font-black text-slate-900">自定义欢迎语与离开语</h4>
|
||
</div>
|
||
@if ($user->canCustomizeVipPresence())
|
||
<span class="inline-flex rounded-full bg-emerald-100 px-3 py-1 text-xs font-bold text-emerald-700">已开启</span>
|
||
@else
|
||
<span class="inline-flex rounded-full bg-gray-100 px-3 py-1 text-xs font-bold text-gray-500">未开放</span>
|
||
@endif
|
||
</div>
|
||
|
||
@if ($user->canCustomizeVipPresence())
|
||
<form action="{{ route('vip.center.presence.update') }}" method="POST" class="mt-5 space-y-4">
|
||
@csrf
|
||
@method('PUT')
|
||
<div>
|
||
<label class="mb-2 block text-sm font-bold text-slate-700">我的欢迎语</label>
|
||
<textarea name="custom_join_message" rows="4" maxlength="255"
|
||
class="w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-900 outline-none transition focus:border-amber-400 focus:bg-white"
|
||
placeholder="例:{username} 乘着星舰闪耀登场,今晚全场高光属于 TA!">{{ old('custom_join_message', $user->custom_join_message) }}</textarea>
|
||
<p class="mt-2 text-xs text-slate-500">支持使用 <span class="font-mono text-slate-700">{username}</span> 占位符自动替换成你的昵称。</p>
|
||
</div>
|
||
<div>
|
||
<label class="mb-2 block text-sm font-bold text-slate-700">我的离开语</label>
|
||
<textarea name="custom_leave_message" rows="4" maxlength="255"
|
||
class="w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-900 outline-none transition focus:border-amber-400 focus:bg-white"
|
||
placeholder="例:{username} 留下一道流光背影,优雅谢幕,我们下次再见。">{{ old('custom_leave_message', $user->custom_leave_message) }}</textarea>
|
||
</div>
|
||
<button type="submit"
|
||
class="w-full rounded-2xl bg-slate-900 px-5 py-3 text-sm font-bold text-white transition hover:bg-slate-800">
|
||
保存我的专属语句
|
||
</button>
|
||
</form>
|
||
@elseif ($user->isVip())
|
||
<div class="mt-5 rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-5 text-sm leading-7 text-slate-500">
|
||
当前会员档位暂未开放个人自定义功能,不过你仍会自动使用本等级配置的专属欢迎语、离开语和华丽特效。
|
||
</div>
|
||
@else
|
||
<div class="mt-5 rounded-2xl border border-dashed border-amber-200 bg-amber-50 px-4 py-5 text-sm leading-7 text-amber-800">
|
||
开通会员后,这里会解锁对应等级的专属进退场主题;若等级允许,还能设置你自己的欢迎语和离开语。
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="bg-white rounded-3xl border border-gray-100 shadow-sm p-6">
|
||
<div class="flex items-center justify-between gap-4 mb-5">
|
||
<div>
|
||
<h3 class="text-xl font-extrabold text-gray-900">我的购买记录</h3>
|
||
<p class="mt-1 text-sm text-gray-500">这里只显示你自己的会员订单记录,方便查看支付和开通状态。</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="overflow-x-auto">
|
||
<table class="w-full text-sm min-w-[860px]">
|
||
<thead>
|
||
<tr class="bg-slate-50 text-slate-600">
|
||
<th class="px-4 py-3 text-left font-bold rounded-tl-2xl">本地订单号</th>
|
||
<th class="px-4 py-3 text-left font-bold">会员等级</th>
|
||
<th class="px-4 py-3 text-center font-bold">金额</th>
|
||
<th class="px-4 py-3 text-center font-bold">状态</th>
|
||
<th class="px-4 py-3 text-center font-bold">支付时间</th>
|
||
<th class="px-4 py-3 text-center font-bold rounded-tr-2xl">开通时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@forelse ($paymentLogs as $log)
|
||
@php
|
||
$statusMap = [
|
||
'created' => ['text' => '待创建', 'class' => 'bg-slate-100 text-slate-700'],
|
||
'pending' => ['text' => '待支付', 'class' => 'bg-amber-100 text-amber-700'],
|
||
'paid' => ['text' => '已支付', 'class' => 'bg-emerald-100 text-emerald-700'],
|
||
'closed' => ['text' => '已关闭', 'class' => 'bg-gray-100 text-gray-500'],
|
||
'failed' => ['text' => '失败', 'class' => 'bg-rose-100 text-rose-700'],
|
||
];
|
||
$status = $statusMap[$log->status] ?? ['text' => $log->status, 'class' => 'bg-slate-100 text-slate-700'];
|
||
@endphp
|
||
<tr class="border-t border-gray-100 hover:bg-slate-50/80">
|
||
<td class="px-4 py-3 font-mono text-xs text-gray-600">{{ $log->order_no }}</td>
|
||
<td class="px-4 py-3">
|
||
<div class="flex items-center gap-2">
|
||
<span style="color: {{ $log->vipLevel?->color ?: '#111827' }}">{{ $log->vipLevel?->icon ?: '👑' }}</span>
|
||
<span class="font-bold text-gray-900">{{ $log->vip_name }}</span>
|
||
</div>
|
||
</td>
|
||
<td class="px-4 py-3 text-center font-bold text-rose-600">¥{{ number_format((float) $log->amount, 2) }}</td>
|
||
<td class="px-4 py-3 text-center"><span class="inline-flex px-2.5 py-1 rounded-full text-xs font-bold {{ $status['class'] }}">{{ $status['text'] }}</span></td>
|
||
<td class="px-4 py-3 text-center text-gray-500">{{ $log->paid_at?->format('Y-m-d H:i') ?? '未支付' }}</td>
|
||
<td class="px-4 py-3 text-center text-gray-500">{{ $log->opened_vip_at?->format('Y-m-d H:i') ?? '未开通' }}</td>
|
||
</tr>
|
||
@empty
|
||
<tr>
|
||
<td colspan="6" class="px-4 py-12 text-center text-gray-400">暂无会员购买记录,开通后会显示在这里。</td>
|
||
</tr>
|
||
@endforelse
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
@if ($paymentLogs->hasPages())
|
||
<div class="mt-5">{{ $paymentLogs->links() }}</div>
|
||
@endif
|
||
</section>
|
||
</div>
|
||
@endsection
|