Files
chatroom/resources/views/admin/vip/index.blade.php
lkddi fd3214eaff 功能:VIP 赞助会员系统
- 新建 vip_levels 表(名称、图标、颜色、经验/金币倍率、专属进入/离开模板)
- 默认4个等级种子:白银🥈(×1.5)、黄金🥇(×2.0)、钻石💎(×3.0)、至尊👑(×5.0)
- 后台 VIP 等级 CRUD 管理(新增/编辑/删除,配置模板和倍率)
- 后台用户编辑弹窗支持设置 VIP 等级和到期时间
- ChatController 心跳经验按 VIP 倍率加成
- FishingController 正向奖励按 VIP 倍率加成(负面惩罚不变)
- 在线名单显示 VIP 图标和管理员🛡️标识
- VIP 用户进入/离开使用专属颜色和标题
- 后台侧栏新增「👑 VIP 会员等级」入口
2026-02-26 21:30:07 +08:00

245 lines
13 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.
{{--
文件功能:后台 VIP 会员等级管理页面
提供会员等级的新增、编辑、删除功能
后台可自由管理所有会员等级配置
@author ChatRoom Laravel
@version 1.0.0
--}}
@extends('admin.layouts.app')
@section('title', 'VIP 会员等级管理')
@section('content')
<div x-data="{
showForm: false,
editing: null,
form: {
name: '',
icon: '⭐',
color: '#f59e0b',
exp_multiplier: 1.5,
jjb_multiplier: 1.2,
sort_order: 0,
price: 10,
duration_days: 30,
join_templates: '',
leave_templates: '',
},
openCreate() {
this.editing = null;
this.form = {
name: '',
icon: '⭐',
color: '#f59e0b',
exp_multiplier: 1.5,
jjb_multiplier: 1.2,
sort_order: 0,
price: 10,
duration_days: 30,
join_templates: '',
leave_templates: '',
};
this.showForm = true;
},
openEdit(level) {
this.editing = level;
this.form = {
name: level.name,
icon: level.icon,
color: level.color,
exp_multiplier: level.exp_multiplier,
jjb_multiplier: level.jjb_multiplier,
sort_order: level.sort_order,
price: level.price,
duration_days: level.duration_days,
join_templates: level.join_templates_text,
leave_templates: level.leave_templates_text,
};
this.showForm = true;
}
}">
{{-- 头部操作栏 --}}
<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>
<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>
</div>
{{-- 等级卡片列表 --}}
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
@foreach ($levels as $level)
<div class="bg-white rounded-xl shadow-sm border overflow-hidden hover:shadow-md transition">
<div class="p-5">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center space-x-2">
<span class="text-2xl">{{ $level->icon }}</span>
<span class="font-bold text-lg"
style="color: {{ $level->color }}">{{ $level->name }}</span>
</div>
<span
class="text-xs bg-gray-100 px-2 py-0.5 rounded text-gray-500">排序:{{ $level->sort_order }}</span>
</div>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span class="text-gray-500">经验倍率</span>
<span class="font-bold text-green-600">×{{ $level->exp_multiplier }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-500">金币倍率</span>
<span class="font-bold text-yellow-600">×{{ $level->jjb_multiplier }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-500">赞助金额</span>
<span class="font-bold text-gray-700">¥{{ $level->price }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-500">有效天数</span>
<span class="font-bold">{{ $level->duration_days ?: '永久' }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-500">当前会员</span>
<span class="font-bold text-indigo-600">{{ $level->users()->count() }} </span>
</div>
</div>
</div>
<div class="border-t bg-gray-50 px-5 py-3 flex justify-end space-x-2">
<button
@click="openEdit({
id: {{ $level->id }},
name: '{{ addslashes($level->name) }}',
icon: '{{ $level->icon }}',
color: '{{ $level->color }}',
exp_multiplier: {{ $level->exp_multiplier }},
jjb_multiplier: {{ $level->jjb_multiplier }},
sort_order: {{ $level->sort_order }},
price: {{ $level->price }},
duration_days: {{ $level->duration_days }},
join_templates_text: `{{ str_replace('`', '', implode("\n", $level->join_templates_array)) }}`,
leave_templates_text: `{{ str_replace('`', '', implode("\n", $level->leave_templates_array)) }}`,
requestUrl: '{{ route('admin.vip.update', $level->id) }}'
})"
class="text-xs bg-indigo-50 text-indigo-600 font-bold px-3 py-1.5 rounded hover:bg-indigo-600 hover:text-white transition">
编辑
</button>
<form action="{{ route('admin.vip.destroy', $level->id) }}" method="POST"
onsubmit="return confirm('确定删除等级 [{{ $level->name }}] 吗?关联用户会变为普通用户。')">
@csrf @method('DELETE')
<button type="submit"
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">
删除
</button>
</form>
</div>
</div>
@endforeach
</div>
@if ($levels->isEmpty())
<div class="text-center py-16 text-gray-400">
<p class="text-lg">暂无会员等级,点击右上角"新增等级"创建</p>
</div>
@endif
{{-- 新增/编辑弹窗 --}}
<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-lg max-h-[90vh] overflow-y-auto" x-transition>
<div class="bg-indigo-900 px-6 py-4 flex justify-between items-center rounded-t-xl text-white">
<h3 class="font-bold text-lg" x-text="editing ? '编辑等级:' + editing.name : '新增会员等级'"></h3>
<button @click="showForm = false" class="text-gray-400 hover:text-white text-xl">&times;</button>
</div>
<div class="p-6">
<form :action="editing ? editing.requestUrl : '{{ route('admin.vip.store') }}'" method="POST">
@csrf
<template x-if="editing"><input type="hidden" name="_method" value="PUT"></template>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">等级名称</label>
<input type="text" name="name" x-model="form.name" required maxlength="50"
class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">图标 (Emoji)</label>
<input type="text" name="icon" x-model="form.icon" required maxlength="20"
class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">颜色</label>
<div class="flex items-center space-x-2">
<input type="color" name="color" x-model="form.color"
class="w-10 h-8 border rounded cursor-pointer">
<input type="text" x-model="form.color" maxlength="10"
class="flex-1 border rounded-md p-2 text-sm font-mono">
</div>
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">排序 (越大越高级)</label>
<input type="number" name="sort_order" x-model="form.sort_order" required min="0"
class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">经验倍率</label>
<input type="number" name="exp_multiplier" x-model="form.exp_multiplier" required
min="1" step="0.1" class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">金币倍率</label>
<input type="number" name="jjb_multiplier" x-model="form.jjb_multiplier" required
min="1" step="0.1" class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">赞助金额 ()</label>
<input type="number" name="price" x-model="form.price" required min="0"
class="w-full border rounded-md p-2 text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">有效天数 (0=永久)</label>
<input type="number" name="duration_days" x-model="form.duration_days" required
min="0" class="w-full border rounded-md p-2 text-sm">
</div>
</div>
{{-- 专属模板 --}}
<div class="mt-4">
<label class="block text-xs font-bold text-gray-600 mb-1">进入欢迎语模板
<span class="font-normal text-gray-400">(每行一条,用 {username} 代替用户名)</span></label>
<textarea name="join_templates" x-model="form.join_templates" rows="3" placeholder="例:贵宾{username}驾到!全场起立!"
class="w-full border rounded-md p-2 text-sm"></textarea>
</div>
<div class="mt-3">
<label class="block text-xs font-bold text-gray-600 mb-1">离开提示语模板
<span class="font-normal text-gray-400">(每行一条)</span></label>
<textarea name="leave_templates" x-model="form.leave_templates" rows="3" placeholder="例:贵宾{username}潇洒离去..."
class="w-full border rounded-md p-2 text-sm"></textarea>
</div>
<div class="flex justify-end space-x-3 pt-4 mt-4 border-t">
<button type="button" @click="showForm = false"
class="px-4 py-2 border rounded font-medium text-gray-600 hover:bg-gray-50">取消</button>
<button type="submit"
class="px-4 py-2 bg-indigo-600 text-white rounded font-bold hover:bg-indigo-700 shadow-sm"
x-text="editing ? '保存修改' : '创建等级'"></button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection