Files
chatroom/resources/views/vip/center.blade.php

314 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{--
文件功能:前台会员中心页面
展示当前用户会员状态、会员等级权益、购买入口以及用户自己的会员购买记录
--}}
@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