|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
|
use App\Models\Venue;
|
|
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
|
|
|
|
|
|
class VenueController extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
public function store(Request $request): JsonResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
abort_unless($request->user()?->isSuperAdmin(), 403, '仅超级管理员可操作');
|
|
|
|
|
|
|
|
|
|
|
|
$data = $request->validate([
|
|
|
|
|
|
'name' => ['required', 'string', 'max:120'],
|
|
|
|
|
|
'venue_type' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'venue_types' => ['nullable', 'array'],
|
|
|
|
|
|
'venue_types.*' => ['string', 'max:80'],
|
|
|
|
|
|
'unit_name' => ['nullable', 'string', 'max:120'],
|
|
|
|
|
|
'district' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'ticket_type' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'appointment_type' => ['nullable', 'string', 'max:40'],
|
|
|
|
|
|
'open_time' => ['nullable', 'string', 'max:120'],
|
|
|
|
|
|
'reservation_notice' => ['nullable', 'string'],
|
|
|
|
|
|
'study_courses' => ['nullable', 'string'],
|
|
|
|
|
|
'address' => ['nullable', 'string', 'max:255'],
|
|
|
|
|
|
'contact_phone' => ['nullable', 'string', 'max:20'],
|
|
|
|
|
|
'lat' => ['nullable', 'numeric'],
|
|
|
|
|
|
'lng' => ['nullable', 'numeric'],
|
|
|
|
|
|
'cover_image' => ['nullable', 'string', 'max:255'],
|
|
|
|
|
|
'gallery_media' => ['nullable', 'array'],
|
|
|
|
|
|
'gallery_media.*.type' => ['required_with:gallery_media', 'in:image,video'],
|
|
|
|
|
|
'gallery_media.*.url' => ['required_with:gallery_media', 'string', 'max:255'],
|
|
|
|
|
|
'detail_html' => ['nullable', 'string'],
|
|
|
|
|
|
'live_people_count' => ['nullable', 'integer', 'min:0'],
|
|
|
|
|
|
'sort' => ['nullable', 'integer', 'min:0'],
|
|
|
|
|
|
'is_active' => ['boolean'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$venue = Venue::create($data + ['is_active' => $data['is_active'] ?? true]);
|
|
|
|
|
|
return response()->json($venue, 201);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function index(Request $request): JsonResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
$user = $request->user();
|
|
|
|
|
|
$keyword = trim((string) $request->string('keyword'));
|
|
|
|
|
|
$district = trim((string) $request->string('district'));
|
|
|
|
|
|
$venueType = trim((string) $request->string('venue_type'));
|
|
|
|
|
|
$ticketType = trim((string) $request->string('ticket_type'));
|
|
|
|
|
|
$isActive = $request->input('is_active');
|
|
|
|
|
|
|
|
|
|
|
|
// 必须用关联本身的查询,勿用 getQuery()->get(),否则会绕过 BelongsToMany::get()
|
|
|
|
|
|
// 的 select `venues.*`,在 join user_venue 时 `id` 可能被 pivot 表的 id 覆盖(列表 id 比库大 1)。
|
|
|
|
|
|
if ($user->isSuperAdmin()) {
|
|
|
|
|
|
$query = Venue::query();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$query = $user->venues();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($keyword !== '') {
|
|
|
|
|
|
$query->where(function ($q) use ($keyword) {
|
|
|
|
|
|
$q->where('name', 'like', '%' . $keyword . '%')
|
|
|
|
|
|
->orWhere('address', 'like', '%' . $keyword . '%')
|
|
|
|
|
|
->orWhere('unit_name', 'like', '%' . $keyword . '%')
|
|
|
|
|
|
->orWhere('open_time', 'like', '%' . $keyword . '%')
|
|
|
|
|
|
->orWhere('reservation_notice', 'like', '%' . $keyword . '%')
|
|
|
|
|
|
->orWhere('study_courses', 'like', '%' . $keyword . '%');
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($district !== '') {
|
|
|
|
|
|
$query->where('district', $district);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($venueType !== '') {
|
|
|
|
|
|
$query->where(function ($q) use ($venueType) {
|
|
|
|
|
|
$q->where('venue_type', $venueType)
|
|
|
|
|
|
->orWhereJsonContains('venue_types', $venueType);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($ticketType !== '') {
|
|
|
|
|
|
$query->where('ticket_type', $ticketType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ($isActive !== null && $isActive !== '') {
|
|
|
|
|
|
$query->where('is_active', (int) $isActive === 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$venues = $query->orderBy('venues.sort')->orderByDesc('venues.id')->get();
|
|
|
|
|
|
return response()->json($venues);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function update(Request $request, int $id): JsonResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
$venue = Venue::query()->findOrFail($id);
|
|
|
|
|
|
$this->ensureVenuePermission($request, $venue->id);
|
|
|
|
|
|
|
|
|
|
|
|
$data = $request->validate([
|
|
|
|
|
|
'name' => ['sometimes', 'string', 'max:120'],
|
|
|
|
|
|
'venue_type' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'venue_types' => ['nullable', 'array'],
|
|
|
|
|
|
'venue_types.*' => ['string', 'max:80'],
|
|
|
|
|
|
'unit_name' => ['nullable', 'string', 'max:120'],
|
|
|
|
|
|
'district' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'ticket_type' => ['nullable', 'string', 'max:80'],
|
|
|
|
|
|
'appointment_type' => ['nullable', 'string', 'max:40'],
|
|
|
|
|
|
'open_time' => ['nullable', 'string', 'max:120'],
|
|
|
|
|
|
'reservation_notice' => ['nullable', 'string'],
|
|
|
|
|
|
'study_courses' => ['nullable', 'string'],
|
|
|
|
|
|
'address' => ['nullable', 'string', 'max:255'],
|
|
|
|
|
|
'contact_phone' => ['nullable', 'string', 'max:20'],
|
|
|
|
|
|
'lat' => ['nullable', 'numeric'],
|
|
|
|
|
|
'lng' => ['nullable', 'numeric'],
|
|
|
|
|
|
'cover_image' => ['nullable', 'string', 'max:255'],
|
|
|
|
|
|
'gallery_media' => ['nullable', 'array'],
|
|
|
|
|
|
'gallery_media.*.type' => ['required_with:gallery_media', 'in:image,video'],
|
|
|
|
|
|
'gallery_media.*.url' => ['required_with:gallery_media', 'string', 'max:255'],
|
|
|
|
|
|
'detail_html' => ['nullable', 'string'],
|
|
|
|
|
|
'live_people_count' => ['nullable', 'integer', 'min:0'],
|
|
|
|
|
|
'sort' => ['nullable', 'integer', 'min:0'],
|
|
|
|
|
|
'is_active' => ['boolean'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
if (!$request->user()?->isSuperAdmin()) {
|
|
|
|
|
|
unset($data['sort']);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$venue->fill($data)->save();
|
|
|
|
|
|
|
|
|
|
|
|
return response()->json($venue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function ensureVenuePermission(Request $request, int $venueId): void
|
|
|
|
|
|
{
|
|
|
|
|
|
$user = $request->user();
|
|
|
|
|
|
if ($user->isSuperAdmin()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$allowed = $user->venues()->where('venues.id', $venueId)->exists();
|
|
|
|
|
|
abort_unless($allowed, 403, '仅可操作已绑定场馆');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|