Files
chatroom/resources/views/admin/rooms/index.blade.php
lkddi a41e701fed 功能:后台房间管理新增「创建房间」功能
- RoomManagerController 新增 store() 方法,含房间名唯一校验、默认值设置
- 路由增加 POST /admin/rooms -> admin.rooms.store
- 视图增加「+ 新增房间」折叠表单(仅 id=1 超管可见)
- 补充 Flash 成功/错误提示展示
- 原有编辑/删除功能保持不变
2026-03-03 14:36:09 +08:00

202 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.
@extends('admin.layouts.app')
@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">
<div>
<h2 class="text-lg font-bold text-gray-800">房间管理</h2>
<p class="text-xs text-gray-500 mt-1">管理聊天室房间的名称、介绍、公告和权限设置。</p>
</div>
{{-- 新增房间按钮 --}}
@if (auth()->id() === 1)
<button onclick="document.getElementById('create-room-form').classList.toggle('hidden')"
class="px-4 py-2 bg-indigo-600 text-white rounded-md text-sm font-bold hover:bg-indigo-700 transition shadow-sm">
+ 新增房间
</button>
@endif
</div>
{{-- 新增房间表单(默认隐藏) --}}
@if (auth()->id() === 1)
<div id="create-room-form" class="hidden border-b border-gray-200 bg-indigo-50 p-6">
<h3 class="text-sm font-bold text-indigo-800 mb-4"> 创建新房间</h3>
<form action="{{ route('admin.rooms.store') }}" method="POST">
@csrf
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房间名称 <span
class="text-red-500">*</span></label>
<input type="text" name="room_name" value="{{ old('room_name') }}" required
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="填写房间名称(唯一)">
@error('room_name')
<p class="text-red-500 text-xs mt-1">{{ $message }}</p>
@enderror
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房主用户名</label>
<input type="text" name="room_owner" value="{{ old('room_owner') }}"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="留空为无房主">
</div>
<div class="md:col-span-2">
<label class="block text-xs font-bold text-gray-600 mb-1">房间介绍</label>
<input type="text" name="room_des" value="{{ old('room_des') }}"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="描述这个房间的用途和氛围">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">进入等级限制</label>
<input type="number" name="permit_level" value="{{ old('permit_level', 0) }}" min="0"
max="15"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房间状态</label>
<select name="door_open"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm">
<option value="1" selected>开放</option>
<option value="0">关闭</option>
</select>
</div>
</div>
<div class="mt-4 flex gap-3">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-md font-bold hover:bg-indigo-700 shadow-sm transition text-sm">
确认创建
</button>
<button type="button" onclick="document.getElementById('create-room-form').classList.add('hidden')"
class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md font-bold hover:bg-gray-300 transition text-sm">
取消
</button>
</div>
</form>
</div>
@endif
{{-- Flash 消息 --}}
@if (session('success'))
<div class="mx-6 mt-4 p-3 bg-green-50 border border-green-200 rounded-lg text-green-700 text-sm">
{{ session('success') }}
</div>
@endif
@if (session('error'))
<div class="mx-6 mt-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">
{{ session('error') }}
</div>
@endif
{{-- 新增房间表单展开时自动滚到顶部校验错误 --}}
@if ($errors->any())
<script>
document.getElementById('create-room-form').classList.remove('hidden');
</script>
@endif
<div class="p-6">
<div class="space-y-4">
@foreach ($rooms as $room)
<div class="border border-gray-200 rounded-lg overflow-hidden" x-data="{ editing: false }">
{{-- 房间信息行 --}}
<div class="flex items-center justify-between p-4 bg-gray-50 cursor-pointer"
@click="editing = !editing">
<div class="flex items-center gap-4">
<span
class="text-xs font-bold bg-indigo-100 text-indigo-700 px-2 py-1 rounded">#{{ $room->id }}</span>
<div>
<span class="font-bold text-gray-800">{{ $room->room_name }}</span>
@if ($room->room_keep)
<span
class="ml-2 text-xs px-1.5 py-0.5 rounded bg-amber-100 text-amber-700">系统房间</span>
@endif
@if (!$room->door_open)
<span class="ml-1 text-xs px-1.5 py-0.5 rounded bg-red-100 text-red-600">已关闭</span>
@endif
</div>
</div>
<div class="flex items-center gap-3 text-xs text-gray-500">
<span>房主: {{ $room->room_owner ?: '无' }}</span>
<span>人气: {{ $room->visit_num ?? 0 }}</span>
<span>等级限制: {{ $room->permit_level ?? 0 }}</span>
<svg class="w-4 h-4 transition-transform" :class="editing ? 'rotate-180' : ''"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
{{-- 编辑表单(展开) --}}
<div x-show="editing" x-collapse class="border-t border-gray-200">
<form action="{{ route('admin.rooms.update', $room->id) }}" method="POST" class="p-4">
@csrf
@method('PUT')
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房间名称</label>
<input type="text" name="room_name" value="{{ $room->room_name }}" required
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房主用户名</label>
<input type="text" name="room_owner" value="{{ $room->room_owner }}"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="留空为无房主">
</div>
<div class="md:col-span-2">
<label class="block text-xs font-bold text-gray-600 mb-1">房间介绍</label>
<input type="text" name="room_des" value="{{ $room->room_des }}"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="描述这个房间的用途和氛围">
</div>
<div class="md:col-span-2">
<label class="block text-xs font-bold text-gray-600 mb-1">公告/祝福语
<span class="text-gray-400 font-normal">(在聊天室顶部滚动显示)</span></label>
<input type="text" name="announcement" value="{{ $room->announcement }}"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm"
placeholder="例:祝大家新年快乐!">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">进入等级限制</label>
<input type="number" name="permit_level" value="{{ $room->permit_level ?? 0 }}"
min="0" max="15"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">房间状态</label>
<select name="door_open"
class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 bg-white border text-sm">
<option value="1" {{ $room->door_open ? 'selected' : '' }}>开放</option>
<option value="0" {{ !$room->door_open ? 'selected' : '' }}>关闭</option>
</select>
</div>
</div>
<div class="mt-4 flex items-center gap-3">
<button type="submit"
class="px-5 py-2 bg-indigo-600 text-white rounded-md font-bold hover:bg-indigo-700 shadow-sm transition text-sm">
保存修改
</button>
@unless ($room->room_keep)
<form action="{{ route('admin.rooms.destroy', $room->id) }}" method="POST"
class="inline"
onsubmit="return confirm('确定要删除房间「{{ $room->room_name }}」吗?此操作不可撤销!')">
@csrf
@method('DELETE')
<button type="submit"
class="px-4 py-2 bg-red-500 text-white rounded-md font-bold hover:bg-red-600 transition text-sm">
删除房间
</button>
</form>
@endunless
</div>
</form>
</div>
</div>
@endforeach
</div>
</div>
</div>
@endsection