Add baccarat loss cover activity

This commit is contained in:
2026-04-11 23:27:29 +08:00
parent dd9a8c5db8
commit e43dceab2c
22 changed files with 1898 additions and 5 deletions
@@ -122,6 +122,9 @@
<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;">🎆
@@ -150,3 +153,205 @@
</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;">&times;</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