358 lines
21 KiB
PHP
358 lines
21 KiB
PHP
{{--
|
||
文件功能:聊天室底部输入工具栏(两行结构)
|
||
第一行:发送对象、动作、字色、悄悄话、滚屏、分屏、管理操作
|
||
第二行:输入框 + 发送按钮
|
||
从 frame.blade.php 拆分,便于独立维护
|
||
|
||
依赖变量:$user, $room, $levelKick, $levelMute, $levelBan, $levelBanip
|
||
--}}
|
||
|
||
<div class="input-bar">
|
||
<form id="chat-form" onsubmit="sendMessage(event)">
|
||
{{-- 第一行:工具选项 --}}
|
||
<div class="input-row">
|
||
<label>对
|
||
<select id="to_user" name="to_user" style="color: #224466;">
|
||
<option value="大家" selected>大家</option>
|
||
</select>
|
||
说:
|
||
</label>
|
||
|
||
<label>动作:
|
||
<select id="action" name="action">
|
||
<option value="">无</option>
|
||
<option value="微笑">微笑</option>
|
||
<option value="大笑">大笑</option>
|
||
<option value="愤怒">愤怒</option>
|
||
<option value="哭泣">哭泣</option>
|
||
<option value="害羞">害羞</option>
|
||
<option value="鄙视">鄙视</option>
|
||
<option value="得意">得意</option>
|
||
<option value="疑惑">疑惑</option>
|
||
<option value="同情">同情</option>
|
||
<option value="无奈">无奈</option>
|
||
<option value="拳打">拳打</option>
|
||
<option value="飞吻">飞吻</option>
|
||
<option value="偷看">偷看</option>
|
||
{{-- 欢迎语专用 action,隐藏不对外显示,JS 临时切换用 --}}
|
||
<option value="欢迎" style="display:none"></option>
|
||
</select>
|
||
</label>
|
||
|
||
<label>字色:
|
||
<input type="color" id="font_color" name="font_color" value="{{ $user->s_color ?? '#000000' }}"
|
||
style="width: 22px; height: 18px; padding: 0; border: 1px solid navy; cursor: pointer;">
|
||
</label>
|
||
|
||
<label>字号:
|
||
<select id="font_size_select" style="color: #224466;" onchange="applyFontSize(this.value)">
|
||
<option value="12">12</option>
|
||
<option value="13">13</option>
|
||
<option value="14" selected>14</option>
|
||
<option value="15">15</option>
|
||
<option value="16">16</option>
|
||
<option value="18">18</option>
|
||
<option value="20">20</option>
|
||
<option value="22">22</option>
|
||
</select>
|
||
</label>
|
||
|
||
<label title="仅对方和自己可见">
|
||
<input type="checkbox" id="is_secret" name="is_secret" value="1">
|
||
悄悄话
|
||
</label>
|
||
|
||
<label title="勾选后关闭所有特效声音">
|
||
<input type="checkbox" id="sound_muted" onchange="toggleSoundMute(this.checked)">
|
||
🔇 禁音
|
||
</label>
|
||
|
||
<label title="自动滚屏到最新消息">
|
||
<input type="checkbox" id="auto_scroll" checked>
|
||
滚屏
|
||
</label>
|
||
|
||
|
||
{{-- 欢迎语快捷按钮 + 下拉浮层 --}}
|
||
<div style="position:relative;display:inline-block;" id="welcome-btn-wrap">
|
||
<button type="button" onclick="toggleWelcomeMenu(event)"
|
||
style="font-size:11px;padding:1px 6px;background:#e07820;color:#fff;border:none;border-radius:2px;cursor:pointer;">
|
||
💬 欢迎
|
||
</button>
|
||
<div id="welcome-menu" class="welcome-menu" style="display:none;">
|
||
@php
|
||
$welcomeMessages = [
|
||
'欢迎【{name}】来到我们的聊天室,请遵守规则,文明聊天!',
|
||
'【{name}】,你好!欢迎来访,有什么问题随时告诉我们!',
|
||
'热烈欢迎【{name}】加入,愿您在这里度过愉快的时光!',
|
||
'欢迎新朋友【{name}】!请先阅读公告,了解聊天室规则哦~',
|
||
'【{name}】来了!欢迎欢迎,希望你在这里玩得开心!',
|
||
'亲爱的【{name}】,欢迎光临本聊天室,请保持文明礼貌!',
|
||
'欢迎【{name}】入驻!有问题请联系管理员,我们随时为您服务!',
|
||
'【{name}】,初来乍到,欢迎多多关照,我们是一家人!',
|
||
'大家欢迎新成员【{name}】!请遵守群规,共建和谐聊天环境!',
|
||
'欢迎【{name}】莅临指导!希望你常来,让我们一起聊天!',
|
||
];
|
||
@endphp
|
||
@foreach ($welcomeMessages as $msg)
|
||
<div class="welcome-menu-item" onclick="sendWelcomeTpl({{ json_encode($msg) }})">
|
||
{{ $msg }}</div>
|
||
@endforeach
|
||
</div>
|
||
</div>
|
||
|
||
@if (
|
||
$user->user_level >= (int) \App\Models\Sysparam::getValue('level_announcement', '10') ||
|
||
$room->master == $user->username)
|
||
<button type="button" onclick="promptAnnouncement()"
|
||
style="font-size: 11px; padding: 1px 6px; background: #4a9; color: #fff; border: none; border-radius: 2px; cursor: pointer;">设公告</button>
|
||
@endif
|
||
|
||
<button type="button" id="fishing-btn" onclick="startFishing()"
|
||
style="font-size: 11px; padding: 1px 6px; background: #2563eb; color: #fff; border: none; border-radius: 2px; cursor: pointer;">🎣
|
||
钓鱼</button>
|
||
|
||
@if ($user->user_level >= (int) \App\Models\Sysparam::getValue('superlevel', '100'))
|
||
<button type="button" onclick="promptAnnounceMessage()"
|
||
style="font-size: 11px; padding: 1px 6px; background: #7c3aed; color: #fff; border: none; border-radius: 2px; cursor: pointer;">📢
|
||
公屏</button>
|
||
<button type="button" onclick="adminClearScreen()"
|
||
style="font-size: 11px; padding: 1px 6px; background: #dc2626; color: #fff; border: none; border-radius: 2px; cursor: pointer;">🧹
|
||
清屏</button>
|
||
<button type="button" id="red-packet-btn" onclick="sendRedPacket()"
|
||
style="font-size: 11px; padding: 1px 6px; background: linear-gradient(135deg, #dc2626, #d97706); color: #fff; border: none; border-radius: 2px; cursor: pointer; font-weight: bold;">🧧
|
||
礼包</button>
|
||
<button type="button" onclick="openAdminBaccaratLossCoverModal()"
|
||
style="font-size: 11px; padding: 1px 6px; background: linear-gradient(135deg, #15803d, #22c55e); color: #fff; border: none; border-radius: 2px; cursor: pointer; font-weight: bold;">🎁
|
||
买单活动</button>
|
||
{{-- 全屏特效按钮组(仅管理员可见) --}}
|
||
<button type="button" onclick="triggerEffect('fireworks')" title="全屏烟花"
|
||
style="font-size: 11px; padding: 1px 6px; background: #ea580c; color: #fff; border: none; border-radius: 2px; cursor: pointer;">🎆
|
||
烟花</button>
|
||
<button type="button" onclick="triggerEffect('rain')" title="全屏下雨"
|
||
style="font-size: 11px; padding: 1px 6px; background: #2563eb; color: #fff; border: none; border-radius: 2px; cursor: pointer;">🌧️
|
||
下雨</button>
|
||
<button type="button" onclick="triggerEffect('lightning')" title="全屏雷电"
|
||
style="font-size: 11px; padding: 1px 6px; background: #7c3aed; color: #fff; border: none; border-radius: 2px; cursor: pointer;">⚡
|
||
雷电</button>
|
||
<button type="button" onclick="triggerEffect('snow')" title="全屏下雪"
|
||
style="font-size: 11px; padding: 1px 6px; background: #0891b2; color: #fff; border: none; border-radius: 2px; cursor: pointer;">❄️
|
||
下雪</button>
|
||
@endif
|
||
|
||
<button type="button" onclick="localClearScreen()"
|
||
style="font-size: 11px; padding: 1px 6px; background: #64748b; color: #fff; border: none; border-radius: 2px; cursor: pointer;">🔄
|
||
清屏</button>
|
||
</div>
|
||
|
||
{{-- 第二行:输入框 + 发送 --}}
|
||
<div class="input-row">
|
||
<input type="text" id="content" name="content" class="say-input"
|
||
placeholder="在这里输入聊天内容,按 Enter 发送..." autocomplete="off">
|
||
<button type="submit" id="send-btn" class="send-btn">发送</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
@if ($user->user_level >= (int) \App\Models\Sysparam::getValue('superlevel', '100'))
|
||
<div id="baccarat-loss-cover-admin-modal"
|
||
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:10010; justify-content:center; align-items:center;">
|
||
<div
|
||
style="width:560px; max-width:96vw; max-height:88vh; overflow:hidden; border-radius:8px; background:#fff; box-shadow:0 8px 32px rgba(0,0,0,.3); display:flex; flex-direction:column;">
|
||
<div
|
||
style="background:linear-gradient(135deg,#15803d,#22c55e); color:#fff; padding:12px 16px; display:flex; justify-content:space-between; align-items:center;">
|
||
<div>
|
||
<div style="font-size:14px; font-weight:bold;">🎁 买单活动设置</div>
|
||
<div style="font-size:11px; color:rgba(255,255,255,.85); margin-top:2px;">创建百家乐“你玩游戏我买单”活动,并查看当前状态</div>
|
||
</div>
|
||
<span onclick="closeAdminBaccaratLossCoverModal()"
|
||
style="cursor:pointer; font-size:18px; opacity:.85;">×</span>
|
||
</div>
|
||
|
||
<div style="flex:1; overflow-y:auto; padding:16px; background:#f6fff8;">
|
||
<div id="blc-admin-current"
|
||
style="background:#fff; border:1px solid #dcfce7; border-radius:10px; padding:14px; color:#166534; margin-bottom:14px;">
|
||
正在加载当前活动…
|
||
</div>
|
||
|
||
<form id="baccarat-loss-cover-admin-form" onsubmit="submitBaccaratLossCoverEvent(event)"
|
||
style="background:#fff; border:1px solid #dcfce7; border-radius:10px; padding:14px;">
|
||
<div style="font-size:13px; font-weight:bold; color:#166534; margin-bottom:12px;">新建活动</div>
|
||
|
||
<div style="display:flex; flex-direction:column; gap:10px;">
|
||
<div>
|
||
<label style="display:block; font-size:12px; color:#4b5563; margin-bottom:4px;">活动标题</label>
|
||
<input type="text" id="blc-admin-title" maxlength="100" value="你玩游戏我买单"
|
||
style="width:100%; box-sizing:border-box; padding:8px 10px; border:1px solid #bbf7d0; border-radius:8px; font-size:12px;">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:12px; color:#4b5563; margin-bottom:4px;">活动说明</label>
|
||
<textarea id="blc-admin-description" rows="3"
|
||
style="width:100%; box-sizing:border-box; padding:8px 10px; border:1px solid #bbf7d0; border-radius:8px; font-size:12px; resize:vertical;">活动期间参与百家乐,赢得归个人,输掉的金币可在活动结束后领取补偿。</textarea>
|
||
</div>
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
|
||
<div>
|
||
<label style="display:block; font-size:12px; color:#4b5563; margin-bottom:4px;">开始时间</label>
|
||
<input type="datetime-local" id="blc-admin-starts-at"
|
||
style="width:100%; box-sizing:border-box; padding:8px 10px; border:1px solid #bbf7d0; border-radius:8px; font-size:12px;">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:12px; color:#4b5563; margin-bottom:4px;">结束时间</label>
|
||
<input type="datetime-local" id="blc-admin-ends-at"
|
||
style="width:100%; box-sizing:border-box; padding:8px 10px; border:1px solid #bbf7d0; border-radius:8px; font-size:12px;">
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:12px; color:#4b5563; margin-bottom:4px;">领取截止时间</label>
|
||
<input type="datetime-local" id="blc-admin-claim-deadline-at"
|
||
style="width:100%; box-sizing:border-box; padding:8px 10px; border:1px solid #bbf7d0; border-radius:8px; font-size:12px;">
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display:flex; gap:8px; justify-content:flex-end; margin-top:14px;">
|
||
<button type="button" onclick="closeAdminBaccaratLossCoverModal()"
|
||
style="padding:8px 16px; border:none; border-radius:8px; background:#dcfce7; color:#166534; font-size:12px; font-weight:bold; cursor:pointer;">
|
||
关闭
|
||
</button>
|
||
<button type="submit"
|
||
style="padding:8px 16px; border:none; border-radius:8px; background:#16a34a; color:#fff; font-size:12px; font-weight:bold; cursor:pointer;">
|
||
创建活动
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
const SUMMARY_URL = '{{ route('baccarat-loss-cover.summary') }}';
|
||
const STORE_URL = '{{ route('command.baccarat_loss_cover.store') }}';
|
||
|
||
function formatDateInput(date) {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const hour = String(date.getHours()).padStart(2, '0');
|
||
const minute = String(date.getMinutes()).padStart(2, '0');
|
||
return `${year}-${month}-${day}T${hour}:${minute}`;
|
||
}
|
||
|
||
async function loadAdminCurrentLossCoverEvent() {
|
||
const box = document.getElementById('blc-admin-current');
|
||
box.innerHTML = '正在加载当前活动…';
|
||
|
||
try {
|
||
const response = await fetch(SUMMARY_URL, {
|
||
headers: {
|
||
'Accept': 'application/json'
|
||
}
|
||
});
|
||
const data = await response.json();
|
||
const event = data.event;
|
||
|
||
if (!event) {
|
||
box.innerHTML = '<div style="font-size:12px; color:#4b5563;">当前没有进行中、待开始或待领取的买单活动。</div>';
|
||
return;
|
||
}
|
||
|
||
const closeButton = ['scheduled', 'active', 'settlement_pending'].includes(event.status) ?
|
||
`<button type="button" onclick="closeCurrentBaccaratLossCoverEvent(${event.id})" style="margin-top:10px; padding:7px 14px; border:none; border-radius:999px; background:#dc2626; color:#fff; font-size:12px; font-weight:bold; cursor:pointer;">立即结束</button>` :
|
||
'';
|
||
|
||
box.innerHTML = `
|
||
<div style="display:flex; justify-content:space-between; gap:10px; align-items:flex-start;">
|
||
<div style="flex:1;">
|
||
<div style="font-size:15px; font-weight:bold; color:#166534;">${event.title}</div>
|
||
<div style="font-size:12px; color:#4b5563; margin-top:4px;">开启人:${event.creator_username}</div>
|
||
</div>
|
||
<span style="padding:4px 10px; border-radius:999px; background:#dcfce7; color:#166534; font-size:12px; font-weight:bold;">${event.status_label}</span>
|
||
</div>
|
||
<div style="margin-top:10px; font-size:12px; color:#4b5563; line-height:1.7;">
|
||
活动时间:${new Date(event.starts_at).toLocaleString('zh-CN')} - ${new Date(event.ends_at).toLocaleString('zh-CN')}<br>
|
||
最终已发补偿:${Number(event.total_claimed_amount || 0).toLocaleString()} 金币
|
||
</div>
|
||
${closeButton}
|
||
`;
|
||
} catch (error) {
|
||
box.innerHTML = '<div style="font-size:12px; color:#dc2626;">当前活动加载失败,请稍后再试。</div>';
|
||
}
|
||
}
|
||
|
||
window.openAdminBaccaratLossCoverModal = async function() {
|
||
const now = new Date();
|
||
const end = new Date(now.getTime() + 30 * 60 * 1000);
|
||
const claimDeadline = new Date(end.getTime() + 24 * 60 * 60 * 1000);
|
||
|
||
document.getElementById('blc-admin-starts-at').value = formatDateInput(now);
|
||
document.getElementById('blc-admin-ends-at').value = formatDateInput(end);
|
||
document.getElementById('blc-admin-claim-deadline-at').value = formatDateInput(claimDeadline);
|
||
document.getElementById('baccarat-loss-cover-admin-modal').style.display = 'flex';
|
||
await loadAdminCurrentLossCoverEvent();
|
||
};
|
||
|
||
window.closeAdminBaccaratLossCoverModal = function() {
|
||
document.getElementById('baccarat-loss-cover-admin-modal').style.display = 'none';
|
||
};
|
||
|
||
window.submitBaccaratLossCoverEvent = async function(event) {
|
||
event.preventDefault();
|
||
|
||
const payload = {
|
||
title: document.getElementById('blc-admin-title').value,
|
||
description: document.getElementById('blc-admin-description').value,
|
||
starts_at: document.getElementById('blc-admin-starts-at').value,
|
||
ends_at: document.getElementById('blc-admin-ends-at').value,
|
||
claim_deadline_at: document.getElementById('blc-admin-claim-deadline-at').value,
|
||
};
|
||
|
||
try {
|
||
const response = await fetch(STORE_URL, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Accept': 'application/json',
|
||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '',
|
||
},
|
||
body: JSON.stringify(payload)
|
||
});
|
||
const data = await response.json();
|
||
|
||
if (data.ok) {
|
||
await window.chatDialog?.alert(data.message || '活动创建成功', '系统通知', '#16a34a');
|
||
await loadAdminCurrentLossCoverEvent();
|
||
return;
|
||
}
|
||
|
||
await window.chatDialog?.alert(data.message || '活动创建失败', '提示', '#f59e0b');
|
||
} catch (error) {
|
||
await window.chatDialog?.alert('活动创建失败,请稍后重试。', '提示', '#dc2626');
|
||
}
|
||
};
|
||
|
||
window.closeCurrentBaccaratLossCoverEvent = async function(eventId) {
|
||
try {
|
||
const response = await fetch(`/command/baccarat-loss-cover/${eventId}/close`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Accept': 'application/json',
|
||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '',
|
||
}
|
||
});
|
||
const data = await response.json();
|
||
await window.chatDialog?.alert(data.message || '活动状态已更新', '系统通知', '#16a34a');
|
||
await loadAdminCurrentLossCoverEvent();
|
||
} catch (error) {
|
||
await window.chatDialog?.alert('活动关闭失败,请稍后重试。', '提示', '#dc2626');
|
||
}
|
||
};
|
||
|
||
document.getElementById('baccarat-loss-cover-admin-modal').addEventListener('click', function(event) {
|
||
if (event.target === this) {
|
||
closeAdminBaccaratLossCoverModal();
|
||
}
|
||
});
|
||
})();
|
||
</script>
|
||
@endif
|