import "./bootstrap"; // 这个文件负责处理浏览器与 Laravel Reverb WebSocket 服务器的通信。 // 通过 Presence Channel 实现聊天室的核心监听。 function isHolidayObject(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } function firstHolidayDefined(...values) { for (const value of values) { if (value !== undefined && value !== null && value !== "") { return value; } } return null; } function pickHolidayObject(...values) { for (const value of values) { if (isHolidayObject(value)) { return value; } } return {}; } function mergeHolidayObjects(...values) { return Object.assign({}, ...values.filter(isHolidayObject)); } function toHolidayNumber(value, fallback = null) { if (value === undefined || value === null || value === "") { return fallback; } const parsedValue = Number(value); return Number.isFinite(parsedValue) ? parsedValue : fallback; } export function normalizeHolidayBroadcastEvent(payload = {}) { const runPayload = pickHolidayObject(payload.run, payload.holiday_run); const snapshotPayload = pickHolidayObject( payload.snapshot, payload.run_snapshot, payload.batch_snapshot, runPayload.snapshot, runPayload.batch_snapshot, ); const eventPayload = pickHolidayObject( payload.event, payload.holiday_event, runPayload.event, runPayload.template, snapshotPayload.event, snapshotPayload.template, ); const mergedPayload = mergeHolidayObjects( eventPayload, payload, runPayload, snapshotPayload, ); const fixedAmount = toHolidayNumber( firstHolidayDefined( snapshotPayload.fixed_amount, runPayload.fixed_amount, payload.fixed_amount, ), ); return { ...payload, ...mergedPayload, run_id: firstHolidayDefined( payload.run_id, runPayload.run_id, runPayload.id, snapshotPayload.run_id, ), event_id: firstHolidayDefined( payload.event_id, runPayload.event_id, snapshotPayload.event_id, eventPayload.id, ), name: firstHolidayDefined( snapshotPayload.name, runPayload.name, payload.name, eventPayload.name, "节日福利", ), description: firstHolidayDefined( snapshotPayload.description, runPayload.description, payload.description, eventPayload.description, "", ), total_amount: toHolidayNumber( firstHolidayDefined( snapshotPayload.total_amount, runPayload.total_amount, payload.total_amount, ), 0, ) ?? 0, max_claimants: toHolidayNumber( firstHolidayDefined( snapshotPayload.max_claimants, runPayload.max_claimants, payload.max_claimants, ), 0, ) ?? 0, distribute_type: firstHolidayDefined( snapshotPayload.distribute_type, runPayload.distribute_type, payload.distribute_type, fixedAmount !== null ? "fixed" : "random", ), fixed_amount: fixedAmount, scheduled_for: firstHolidayDefined( snapshotPayload.scheduled_for, runPayload.scheduled_for, payload.scheduled_for, snapshotPayload.send_at, runPayload.send_at, payload.send_at, ), expires_at: firstHolidayDefined( snapshotPayload.expires_at, runPayload.expires_at, payload.expires_at, snapshotPayload.claim_deadline_at, runPayload.claim_deadline_at, payload.claim_deadline_at, ), repeat_type: firstHolidayDefined( snapshotPayload.repeat_type, runPayload.repeat_type, payload.repeat_type, eventPayload.repeat_type, ), round_no: firstHolidayDefined( snapshotPayload.round_no, runPayload.round_no, payload.round_no, snapshotPayload.sequence, runPayload.sequence, payload.sequence, snapshotPayload.issue_no, runPayload.issue_no, payload.issue_no, ), round_label: firstHolidayDefined( snapshotPayload.round_label, runPayload.round_label, payload.round_label, snapshotPayload.batch_label, runPayload.batch_label, payload.batch_label, ), snapshot: mergeHolidayObjects(eventPayload, runPayload, snapshotPayload), }; } window.normalizeHolidayBroadcastEvent = normalizeHolidayBroadcastEvent; export function initChat(roomId) { if (!roomId) { console.error("未提供 roomId,无法初始化 WebSocket 连接。"); return; } const userId = window.chatContext?.userId; // 监听全局系统事件(如 AI 机器人开关) window.Echo.channel('chat.system') .listen('ChatBotToggled', (e) => { console.log("机器人开关:", e); window.dispatchEvent(new CustomEvent("chat:bot-toggled", { detail: e })); }); // 加入带有登录人员追踪的 Presence Channel window.Echo.join(`room.${roomId}`) // 当自己成功连接时,获取当前在这里的所有人列表 .here((users) => { console.log("当前房间内的在线人员:", users); // 触发自定义事件,让具体的前端 UI 去接管渲染 window.dispatchEvent( new CustomEvent("chat:here", { detail: users }), ); }) // 监听其他人的加入 .joining((user) => { console.log(user.username + " 进入了房间"); window.dispatchEvent( new CustomEvent("chat:joining", { detail: user }), ); }) // 监听其他人的离开 .leaving((user) => { console.log(user.username + " 离开了房间"); window.dispatchEvent( new CustomEvent("chat:leaving", { detail: user }), ); }) // 监听新发送的文本消息 .listen("MessageSent", (e) => { console.log("收到新发言:", e.message); window.dispatchEvent( new CustomEvent("chat:message", { detail: e.message }), ); }) // 监听踢出事件(通常判断是不是自己被踢出了) .listen("UserKicked", (e) => { console.log("踢出通知:", e); window.dispatchEvent(new CustomEvent("chat:kicked", { detail: e })); }) // 监听封口禁言事件 .listen("UserMuted", (e) => { console.log("禁言通知:", e); window.dispatchEvent(new CustomEvent("chat:muted", { detail: e })); }) // 监听房间主题被改变 .listen("RoomTitleUpdated", (e) => { console.log("主题改变:", e); window.dispatchEvent( new CustomEvent("chat:title-updated", { detail: e }), ); }) // 监听管理员全员清屏 .listen("ScreenCleared", (e) => { console.log("全员清屏:", e); window.dispatchEvent( new CustomEvent("chat:screen-cleared", { detail: e }), ); }) // 监听站长触发的全员刷新 .listen("BrowserRefreshRequested", (e) => { console.log("全员刷新:", e); window.dispatchEvent( new CustomEvent("chat:browser-refresh-requested", { detail: e }), ); }) // 监听管理员触发的全屏特效(烟花/下雨/雷电) .listen("EffectBroadcast", (e) => { console.log("特效播放:", e); window.dispatchEvent(new CustomEvent("chat:effect", { detail: e })); }) // 监听任命公告(礼花 + 隆重弹窗) .listen("AppointmentAnnounced", (e) => { console.log("任命公告:", e); window.dispatchEvent( new CustomEvent("chat:appointment-announced", { detail: e }), ); }) // ─── 婚姻系统:全局事件(广播给整个房间) ──────────────── .listen(".marriage.accepted", (e) => { console.log("结婚公告:", e); window.dispatchEvent( new CustomEvent("chat:marriage-accepted", { detail: e }), ); }) .listen(".marriage.divorced", (e) => { console.log("离婚公告:", e); window.dispatchEvent( new CustomEvent("chat:marriage-divorced", { detail: e }), ); }) .listen(".wedding.celebration", (e) => { console.log("婚礼庆典:", e); window.dispatchEvent( new CustomEvent("chat:wedding-celebration", { detail: e }), ); }) // ─── 节日福利:系统定时发放 ──────────────────────────────── .listen(".holiday.started", (e) => { const holidayPayload = normalizeHolidayBroadcastEvent(e); console.log("节日福利批次开始:", holidayPayload); window.dispatchEvent( new CustomEvent("chat:holiday.started", { detail: holidayPayload }), ); }) // ─── 百家乐:开局 & 结算 ────────────────────────────────── .listen(".baccarat.opened", (e) => { console.log("百家乐开局:", e); window.dispatchEvent( new CustomEvent("chat:baccarat.opened", { detail: e }), ); }) .listen(".baccarat.pool_updated", (e) => { console.log("百家乐押注更新:", e); window.dispatchEvent( new CustomEvent("chat:baccarat.pool_updated", { detail: e }), ); }) .listen(".baccarat.settled", (e) => { console.log("百家乐结算:", e); window.dispatchEvent( new CustomEvent("chat:baccarat.settled", { detail: e }), ); }) // ─── 赛马:开场 / 进度 / 结算 ──────────────────────────────── .listen(".horse.opened", (e) => { console.log("赛马开场:", e); window.dispatchEvent( new CustomEvent("chat:horse.opened", { detail: e }), ); }) .listen(".horse.progress", (e) => { console.log("赛马进度:", e); window.dispatchEvent( new CustomEvent("chat:horse.progress", { detail: e }), ); }) .listen(".horse.settled", (e) => { console.log("赛马结算:", e); window.dispatchEvent( new CustomEvent("chat:horse.settled", { detail: e }), ); }); // 监听当前用户私有消息,确保悄悄话与定向系统通知不会泄漏给整个房间。 if (userId) { window.Echo.private(`user.${userId}`) .listen("MessageSent", (e) => { console.log("收到私有聊天消息:", e.message); window.dispatchEvent( new CustomEvent("chat:message", { detail: e.message }), ); }) .listen("UserBrowserRefreshRequested", (e) => { console.log("收到定向刷新通知:", e); window.dispatchEvent( new CustomEvent("chat:user-browser-refresh-requested", { detail: e }), ); }); } } /** * 初始化婚姻私人频道监听(求婚通知 / 拒绝通知 / 红包领取通知) * 在用户登录成功后调用,监听 user.{id} 私人频道的婚姻事件。 * * @param {number} userId 当前登录用户 ID */ export function initMarriagePrivateChannel(userId) { if (!userId || !window.Echo) return; window.Echo.private(`user.${userId}`) // 收到求婚通知(目标方) .listen(".marriage.proposed", (e) => { console.log("收到求婚:", e); window.dispatchEvent( new CustomEvent("chat:marriage-proposed", { detail: e }), ); }) // 求婚被拒绝(发起方) .listen(".marriage.rejected", (e) => { console.log("求婚被拒:", e); window.dispatchEvent( new CustomEvent("chat:marriage-rejected", { detail: e }), ); }) // 求婚过期(发起方) .listen(".marriage.expired", (e) => { console.log("求婚超时:", e); window.dispatchEvent( new CustomEvent("chat:marriage-expired", { detail: e }), ); }) // 协议离婚申请通知(对方) .listen(".marriage.divorce-requested", (e) => { console.log("离婚申请:", e); window.dispatchEvent( new CustomEvent("chat:divorce-requested", { detail: e }), ); }) // 红包领取成功通知 .listen(".envelope.claimed", (e) => { console.log("红包到账:", e); window.dispatchEvent( new CustomEvent("chat:envelope-claimed", { detail: e }), ); }); } // 供全局调用 window.initChat = initChat; window.initMarriagePrivateChannel = initMarriagePrivateChannel;