Files
chatroom/app/Http/Controllers/VipCenterController.php

215 lines
8.1 KiB
PHP
Raw Normal View History

<?php
/**
* 文件功能:前台会员中心控制器
* 负责展示会员等级、权益说明、当前会员状态、用户购买记录与会员个性化进退场设置
*/
namespace App\Http\Controllers;
use App\Http\Requests\UpdateVipPresenceSettingsRequest;
use App\Models\Sysparam;
use App\Models\VipLevel;
use App\Models\VipPaymentOrder;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class VipCenterController extends Controller
{
/**
* 显示会员中心页面
*
* @param Request $request 当前请求对象
*/
2026-04-12 17:06:38 +08:00
public function index(Request $request): View|\Illuminate\Http\JsonResponse
{
$user = $request->user();
// 会员等级按后台排序字段展示,方便用户对比不同档位权益。
$vipLevels = VipLevel::query()
->withCount('users')
->orderByDesc('sort_order')
->orderBy('id')
->get();
// 仅展示当前用户自己的购买记录,避免泄露其他会员订单信息。
$paymentLogs = $this->buildPaymentLogs($user->id);
$paidOrders = VipPaymentOrder::query()
->where('user_id', $user->id)
->where('status', 'paid')
->count();
$totalAmount = (float) VipPaymentOrder::query()
->where('user_id', $user->id)
->where('status', 'paid')
->sum('amount');
2026-04-12 23:25:38 +08:00
$vipPaymentEnabled = Sysparam::getValue('vip_payment_enabled', '0') === '1';
$effectOptions = [
'none' => '无特效',
'fireworks' => '烟花',
'rain' => '下雨',
'lightning' => '闪电',
'snow' => '下雪',
'sakura' => '樱花飘落',
'meteors' => '流星',
'gold-rain' => '金币雨',
'hearts' => '爱心飘落',
'confetti' => '彩带庆典',
'fireflies' => '萤火虫',
];
$bannerStyleOptions = [
'aurora' => '鎏光星幕',
'storm' => '雷霆风暴',
'royal' => '王者金辉',
'cosmic' => '星穹幻彩',
'farewell' => '告别暮光',
2026-04-12 17:06:38 +08:00
];
if ($request->expectsJson()) {
2026-04-12 23:25:38 +08:00
$data = [
'user' => [
'id' => $user->id,
'username' => $user->username,
'is_vip' => $user->isVip(),
'vip_name' => $user->vipName(),
'hy_time' => $user->hy_time?->format('Y-m-d H:i'),
'vip_level_id' => $user->vip_level_id,
'can_customize' => $user->canCustomizeVipPresence(),
'custom_join_message' => $user->custom_join_message,
'custom_leave_message' => $user->custom_leave_message,
'custom_join_effect' => $user->custom_join_effect,
'custom_leave_effect' => $user->custom_leave_effect,
'vip_level' => $user->vipLevel ? [
'id' => $user->vipLevel->id,
'name' => $user->vipLevel->name,
'icon' => $user->vipLevel->icon,
'color' => $user->vipLevel->color,
'join_effect' => $user->vipLevel->joinEffectKey(),
'join_banner' => $user->vipLevel->joinBannerStyleKey(),
'leave_effect' => $user->vipLevel->leaveEffectKey(),
'leave_banner' => $user->vipLevel->leaveBannerStyleKey(),
'join_templates' => $user->vipLevel->join_templates_array,
'leave_templates' => $user->vipLevel->leave_templates_array,
] : null,
],
'vipLevels' => $vipLevels->map(function ($vip) use ($user) {
$isCurrent = $user->isVip() && (int) $user->vip_level_id === (int) $vip->id;
$isHigher = $user->isVip() ? $vip->isHigherThan($user->vip_level_id) : true;
$isLower = $user->isVip() && ! $isCurrent && ! $isHigher;
return [
'id' => $vip->id,
'name' => $vip->name,
'icon' => $vip->icon,
'color' => $vip->color,
'price' => (float) $vip->price,
'upgrade_price' => $user->isVip() ? (float) $vip->getUpgradePrice($user->vip_level_id) : (float) $vip->price,
'duration_days' => $vip->duration_days,
'exp_multiplier' => $vip->exp_multiplier,
'jjb_multiplier' => $vip->jjb_multiplier,
'description' => $vip->description,
'is_current' => $isCurrent,
'is_higher' => $isHigher,
'is_lower' => $isLower,
];
}), 'paymentLogs' => $paymentLogs->items(),
'vipPaymentEnabled' => $vipPaymentEnabled,
'paidOrders' => $paidOrders,
'totalAmount' => $totalAmount,
'effectOptions' => $effectOptions,
'bannerStyleOptions' => $bannerStyleOptions,
];
2026-04-12 17:06:38 +08:00
return response()->json([
'status' => 'success',
'data' => $data,
]);
}
2026-04-12 23:25:38 +08:00
return view('vip.center', [
'user' => $user,
'vipLevels' => $vipLevels,
'paymentLogs' => $paymentLogs,
'vipPaymentEnabled' => $vipPaymentEnabled,
'paidOrders' => $paidOrders,
'totalAmount' => $totalAmount,
'effectOptions' => $effectOptions,
'bannerStyleOptions' => $bannerStyleOptions,
]);
}
/**
* 保存会员个人自定义欢迎语与离开语。
*/
2026-04-12 17:06:38 +08:00
public function updatePresenceSettings(UpdateVipPresenceSettingsRequest $request): RedirectResponse|\Illuminate\Http\JsonResponse
{
$user = $request->user();
// 只有有效会员且当前等级允许自定义时,才允许保存专属语句。
if (! $user->canCustomizeVipPresence()) {
2026-04-12 17:06:38 +08:00
if ($request->expectsJson()) {
return response()->json([
'status' => 'error',
'message' => '当前会员等级暂不支持自定义欢迎语和离开语。',
], 403);
}
return redirect()
->route('vip.center')
->with('error', '当前会员等级暂不支持自定义欢迎语和离开语。');
}
$data = $request->validated();
// 空字符串统一转成 null避免数据库保存无意义空白值。
$user->update([
'custom_join_message' => $this->sanitizeNullableMessage($data['custom_join_message'] ?? null),
'custom_leave_message' => $this->sanitizeNullableMessage($data['custom_leave_message'] ?? null),
2026-04-12 17:06:38 +08:00
'custom_join_effect' => $data['custom_join_effect'] ?? null,
'custom_leave_effect' => $data['custom_leave_effect'] ?? null,
]);
2026-04-12 17:06:38 +08:00
if ($request->expectsJson()) {
return response()->json([
'status' => 'success',
'message' => '设置已保存。',
]);
}
return redirect()
->route('vip.center')
2026-04-12 17:06:38 +08:00
->with('success', '设置已保存。');
}
/**
* 构建当前用户的购买记录分页数据
*
* @param int $userId 当前登录用户 ID
*/
private function buildPaymentLogs(int $userId): LengthAwarePaginator
{
return VipPaymentOrder::query()
->with('vipLevel:id,name,color,icon')
->where('user_id', $userId)
->latest('id')
->paginate(10)
->withQueryString();
}
/**
* 将可空文案统一整理为数据库可保存的字符串。
*/
private function sanitizeNullableMessage(?string $message): ?string
{
$message = trim((string) $message);
return $message === '' ? null : $message;
}
}