Files
chatroom/resources/views/admin/game-configs/partials/riddle-config-card.blade.php
T
2026-04-29 13:39:41 +08:00

213 lines
10 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.
@php
$sharedConfig = gameRiddleSharedConfig($params);
$checkedRoomIds = collect($sharedConfig['room_ids'])->map(fn ($roomId) => (int) $roomId)->all();
@endphp
<div class="space-y-4">
<div class="rounded-xl border border-indigo-100 bg-indigo-50/60 p-4 text-xs leading-6 text-indigo-700">
猜成语与脑筋急转弯共用同一套奖励、过期时间、自动出题间隔与参与房间范围配置。
手动出题时再单独选择题型即可。
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50/70 p-4" data-idiom-config-card>
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
<div>
<div class="text-sm font-bold text-slate-800">猜谜活动公共设置</div>
<div class="text-xs text-slate-500">以下参数会同时作用于猜成语与脑筋急转弯。</div>
</div>
<div class="flex flex-wrap items-center gap-2">
@foreach ($riddleTypeOptions as $typeLabel)
<span class="rounded-full bg-white px-3 py-1 text-xs font-semibold text-slate-500 shadow-sm">{{ $typeLabel }}</span>
@endforeach
</div>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
<div>
<label class="mb-1 block text-xs font-bold text-gray-600">答对奖励金币</label>
<input type="number" name="params[reward_gold]"
value="{{ old('params.reward_gold', $sharedConfig['reward_gold']) }}"
min="0"
class="w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-indigo-400">
</div>
<div>
<label class="mb-1 block text-xs font-bold text-gray-600">答对奖励经验</label>
<input type="number" name="params[reward_exp]"
value="{{ old('params.reward_exp', $sharedConfig['reward_exp']) }}"
min="0"
class="w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-indigo-400">
</div>
<div>
<label class="mb-1 block text-xs font-bold text-gray-600">题目过期时间</label>
<input type="number" name="params[expire_minutes]"
value="{{ old('params.expire_minutes', $sharedConfig['expire_minutes']) }}"
min="0"
class="w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-indigo-400">
<p class="mt-1 text-xs text-gray-400">分钟,0 表示不过期。</p>
</div>
<div>
<label class="mb-1 block text-xs font-bold text-gray-600">自动出题间隔</label>
<input type="number" name="params[auto_start_interval]"
value="{{ old('params.auto_start_interval', $sharedConfig['auto_start_interval']) }}"
min="0"
class="w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-indigo-400">
<p class="mt-1 text-xs text-gray-400">分钟,0 表示仅手动出题。</p>
</div>
<div>
<label class="mb-1 block text-xs font-bold text-gray-600">参与房间模式</label>
<select name="params[room_scope_mode]"
data-idiom-room-mode
class="w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-indigo-400">
<option value="all" @selected($sharedConfig['room_mode'] === 'all')>全部房间</option>
<option value="single" @selected($sharedConfig['room_mode'] === 'single')>单选房间</option>
<option value="multiple" @selected($sharedConfig['room_mode'] === 'multiple')>多选房间</option>
</select>
</div>
<div class="xl:col-span-2">
<label class="mb-2 block text-xs font-bold text-gray-600" data-idiom-room-label>参与房间</label>
<div class="grid grid-cols-2 gap-2 rounded-xl border border-dashed border-slate-200 bg-white p-3 lg:grid-cols-3">
@foreach ($availableRooms as $room)
<label class="flex items-center gap-2 rounded-lg border border-slate-100 px-3 py-2 text-sm text-slate-600">
<input type="checkbox"
name="params[room_ids][]"
value="{{ $room->id }}"
@checked(in_array((int) $room->id, $checkedRoomIds, true))
data-idiom-room-checkbox
class="rounded border-slate-300 text-indigo-600">
<span>#{{ $room->id }} {{ $room->name }}</span>
</label>
@endforeach
</div>
<p class="mt-2 text-xs text-gray-400">单选模式下只保留一个房间,多选模式可同时勾选多个房间。</p>
</div>
</div>
</div>
</div>
<div class="mt-4 border-t border-gray-100 pt-4">
<div class="mb-3 text-xs font-bold text-gray-600">🧩 手动出题</div>
<div class="flex flex-wrap items-center gap-3">
<select id="idiom-manual-room"
class="rounded-lg border border-gray-300 px-3 py-2 text-sm text-slate-700">
@foreach ($availableRooms as $room)
<option value="{{ $room->id }}">#{{ $room->id }} {{ $room->name }}</option>
@endforeach
</select>
<select id="idiom-manual-type"
class="rounded-lg border border-gray-300 px-3 py-2 text-sm text-slate-700">
@foreach ($riddleTypeOptions as $typeKey => $typeLabel)
<option value="{{ $typeKey }}">{{ $typeLabel }}</option>
@endforeach
</select>
<button type="button" id="idiom-manual-start-btn"
data-idiom-start-url="{{ route('riddle-quiz.start') }}"
class="rounded-lg bg-gradient-to-r from-purple-600 to-indigo-600 px-4 py-2 text-sm font-bold text-white transition hover:opacity-90">
立即出题
</button>
<span class="text-xs text-gray-400">先选房间,再选题型,后台会按对应题型配置发题。</span>
</div>
</div>
@once
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function () {
function showAdminAlert(message, title = '提示', icon = '️') {
if (window.adminDialog?.alert) {
window.adminDialog.alert(message, title, icon);
return;
}
window.alert(message);
}
document.querySelectorAll('[data-idiom-config-form]').forEach(function (form) {
form.addEventListener('submit', function (event) {
let hasValidationError = false;
const modeSelect = this.querySelector('[data-idiom-room-mode]');
const roomCheckboxes = Array.from(this.querySelectorAll('[data-idiom-room-checkbox]'));
const checkedRooms = roomCheckboxes.filter(function (checkbox) {
return checkbox.checked;
});
if (modeSelect) {
if (modeSelect.value === 'single' && checkedRooms.length > 1) {
showAdminAlert('猜谜活动处于单选房间模式时,只能勾选一个房间。', '房间选择有误', '⚠️');
hasValidationError = true;
}
if (modeSelect.value === 'single' && checkedRooms.length === 0) {
const firstRoomCheckbox = roomCheckboxes[0];
if (firstRoomCheckbox) {
firstRoomCheckbox.checked = true;
}
}
if (modeSelect.value === 'multiple' && checkedRooms.length === 0) {
showAdminAlert('猜谜活动处于多选房间模式时,请至少选择一个房间。', '房间选择有误', '⚠️');
hasValidationError = true;
}
}
if (hasValidationError) {
event.preventDefault();
}
});
});
const manualStartButton = document.getElementById('idiom-manual-start-btn');
if (!manualStartButton) {
return;
}
manualStartButton.addEventListener('click', function () {
const startUrl = this.getAttribute('data-idiom-start-url') || '';
const roomId = Number.parseInt(document.getElementById('idiom-manual-room')?.value || '0', 10);
const quizType = document.getElementById('idiom-manual-type')?.value || '';
if (!startUrl || roomId <= 0 || !quizType) {
showAdminAlert('请先选择房间和题型。', '手动出题', '⚠️');
return;
}
const button = this;
button.disabled = true;
button.textContent = '出题中...';
fetch(startUrl, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content ?? '',
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
room_id: roomId,
quiz_type: quizType,
}),
})
.then(function (response) {
return response.json();
})
.then(function (response) {
if (response.status === 'success') {
showAdminAlert('题目已发送到目标房间。', '手动出题成功', '✅');
return;
}
showAdminAlert(response.message || '出题失败', '手动出题失败', '❌');
})
.catch(function () {
showAdminAlert('网络错误,出题失败', '手动出题失败', '🌐');
})
.finally(function () {
button.disabled = false;
button.textContent = '立即出题';
});
});
});
</script>
@endpush
@endonce