迁移双色球彩票脚本
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
* - friend-panel.js:处理好友面板、搜索和好友快捷操作。
|
* - friend-panel.js:处理好友面板、搜索和好友快捷操作。
|
||||||
* - friend-notifications.js:监听好友通知和通用 BannerNotification。
|
* - friend-notifications.js:监听好友通知和通用 BannerNotification。
|
||||||
* - lightbox.js:处理聊天图片预览灯箱。
|
* - lightbox.js:处理聊天图片预览灯箱。
|
||||||
|
* - lottery-panel.js:提供双色球彩票 lotteryPanel Alpine 组件和全局开关入口。
|
||||||
* - mobile-drawer.js:处理移动端抽屉、房间列表和在线名单。
|
* - mobile-drawer.js:处理移动端抽屉、房间列表和在线名单。
|
||||||
* - marriage-status.js:处理婚姻状态展示与用户名片联动。
|
* - marriage-status.js:处理婚姻状态展示与用户名片联动。
|
||||||
* - toolbar.js:处理工具栏按钮和功能快捷入口。
|
* - toolbar.js:处理工具栏按钮和功能快捷入口。
|
||||||
@@ -56,6 +57,7 @@ export { bindChatToast } from "./chat-room/toast.js";
|
|||||||
export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
||||||
export { bindFriendNotificationControls, setupBannerNotification, setupFriendNotification, showFriendBanner } from "./chat-room/friend-notifications.js";
|
export { bindFriendNotificationControls, setupBannerNotification, setupFriendNotification, showFriendBanner } from "./chat-room/friend-notifications.js";
|
||||||
export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
||||||
|
export { bindLotteryPanelControls, closeLotteryPanel, lotteryPanel, openLotteryPanel, showLotteryMsg } from "./chat-room/lottery-panel.js";
|
||||||
export {
|
export {
|
||||||
bindMobileDrawerControls,
|
bindMobileDrawerControls,
|
||||||
closeMobileDrawer,
|
closeMobileDrawer,
|
||||||
@@ -148,6 +150,7 @@ import { bindChatToast } from "./chat-room/toast.js";
|
|||||||
import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
||||||
import { bindFriendNotificationControls, setupBannerNotification, setupFriendNotification, showFriendBanner } from "./chat-room/friend-notifications.js";
|
import { bindFriendNotificationControls, setupBannerNotification, setupFriendNotification, showFriendBanner } from "./chat-room/friend-notifications.js";
|
||||||
import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
||||||
|
import { bindLotteryPanelControls, closeLotteryPanel, lotteryPanel, openLotteryPanel, showLotteryMsg } from "./chat-room/lottery-panel.js";
|
||||||
import {
|
import {
|
||||||
bindMobileDrawerControls,
|
bindMobileDrawerControls,
|
||||||
closeMobileDrawer,
|
closeMobileDrawer,
|
||||||
@@ -240,6 +243,11 @@ if (typeof window !== "undefined") {
|
|||||||
sendToChatBot,
|
sendToChatBot,
|
||||||
bindGlobalDialogControls,
|
bindGlobalDialogControls,
|
||||||
bindDailySignInControls,
|
bindDailySignInControls,
|
||||||
|
bindLotteryPanelControls,
|
||||||
|
closeLotteryPanel,
|
||||||
|
lotteryPanel,
|
||||||
|
openLotteryPanel,
|
||||||
|
showLotteryMsg,
|
||||||
applyFontSize,
|
applyFontSize,
|
||||||
bindChatFontSizeControl,
|
bindChatFontSizeControl,
|
||||||
bindChatImageUploadControl,
|
bindChatImageUploadControl,
|
||||||
@@ -382,9 +390,13 @@ if (typeof window !== "undefined") {
|
|||||||
window.closeGameHall = closeGameHall;
|
window.closeGameHall = closeGameHall;
|
||||||
window.fetchBankRanking = fetchBankRanking;
|
window.fetchBankRanking = fetchBankRanking;
|
||||||
window.fortunePanel = fortunePanel;
|
window.fortunePanel = fortunePanel;
|
||||||
|
window.closeLotteryPanel = closeLotteryPanel;
|
||||||
window.deferChatGameBootstrap = deferChatGameBootstrap;
|
window.deferChatGameBootstrap = deferChatGameBootstrap;
|
||||||
|
window.lotteryPanel = lotteryPanel;
|
||||||
window.openGameHall = openGameHall;
|
window.openGameHall = openGameHall;
|
||||||
|
window.openLotteryPanel = openLotteryPanel;
|
||||||
window.openBankModal = openBankModal;
|
window.openBankModal = openBankModal;
|
||||||
|
window.showLotteryMsg = showLotteryMsg;
|
||||||
window.switchBankTab = switchBankTab;
|
window.switchBankTab = switchBankTab;
|
||||||
window.toggleBankRankSort = toggleBankRankSort;
|
window.toggleBankRankSort = toggleBankRankSort;
|
||||||
window.applyFontSize = applyFontSize;
|
window.applyFontSize = applyFontSize;
|
||||||
@@ -395,6 +407,7 @@ if (typeof window !== "undefined") {
|
|||||||
bindAppointmentAnnouncementControls();
|
bindAppointmentAnnouncementControls();
|
||||||
bindGlobalDialogControls();
|
bindGlobalDialogControls();
|
||||||
bindDailySignInControls();
|
bindDailySignInControls();
|
||||||
|
bindLotteryPanelControls();
|
||||||
bindChatFontSizeControl();
|
bindChatFontSizeControl();
|
||||||
bindChatImageUploadControl();
|
bindChatImageUploadControl();
|
||||||
bindChatComposerControls();
|
bindChatComposerControls();
|
||||||
|
|||||||
@@ -0,0 +1,343 @@
|
|||||||
|
// 聊天室双色球彩票面板,提供 lotteryPanel Alpine 组件和全局开关入口。
|
||||||
|
|
||||||
|
let lotteryPanelEventsBound = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取 CSRF Token。
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function csrf() {
|
||||||
|
return document.querySelector('meta[name="csrf-token"]')?.content || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示彩票面板内联消息。
|
||||||
|
*
|
||||||
|
* @param {string} message
|
||||||
|
* @param {boolean} success
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function showLotteryMsg(message, success) {
|
||||||
|
const element = document.getElementById("lottery-buy-msg");
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.style.background = success ? "#f0fdf4" : "#fff5f5";
|
||||||
|
element.style.border = success ? "1px solid #86efac" : "1px solid #fecaca";
|
||||||
|
element.style.color = success ? "#16a34a" : "#dc2626";
|
||||||
|
element.textContent = message;
|
||||||
|
element.style.display = "block";
|
||||||
|
element.style.opacity = "1";
|
||||||
|
|
||||||
|
window.clearTimeout(element._t);
|
||||||
|
element._t = window.setTimeout(() => {
|
||||||
|
element.style.opacity = "0";
|
||||||
|
window.setTimeout(() => {
|
||||||
|
element.style.display = "none";
|
||||||
|
}, 400);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建双色球彩票面板 Alpine 组件。
|
||||||
|
*
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
export function lotteryPanel() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
loading: true,
|
||||||
|
ruleOpen: false,
|
||||||
|
buying: false,
|
||||||
|
issueNo: "--",
|
||||||
|
status: "open",
|
||||||
|
isOpen: false,
|
||||||
|
isSuperIssue: false,
|
||||||
|
poolAmount: 0,
|
||||||
|
secondsLeft: 0,
|
||||||
|
drawAt: null,
|
||||||
|
drawRed1: null,
|
||||||
|
drawRed2: null,
|
||||||
|
drawRed3: null,
|
||||||
|
drawBlue: null,
|
||||||
|
selectedReds: [],
|
||||||
|
selectedBlue: null,
|
||||||
|
cart: [],
|
||||||
|
myTickets: [],
|
||||||
|
history: [],
|
||||||
|
_timer: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化倒计时文字。
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get countdownText() {
|
||||||
|
const seconds = this.secondsLeft;
|
||||||
|
if (seconds <= 0) {
|
||||||
|
return "即将开奖";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seconds >= 3600) {
|
||||||
|
return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const minutes = Math.floor(seconds / 60);
|
||||||
|
const restSeconds = seconds % 60;
|
||||||
|
|
||||||
|
return `${String(minutes).padStart(2, "0")}:${String(restSeconds).padStart(2, "0")}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开面板并加载数据。
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async open() {
|
||||||
|
this.show = true;
|
||||||
|
await this.loadData();
|
||||||
|
this.startTimer();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载当期状态、我的购票和历史开奖。
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async loadData() {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [currentResponse, historyResponse] = await Promise.all([
|
||||||
|
fetch("/lottery/current", {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
fetch("/lottery/history", {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
const current = await currentResponse.json();
|
||||||
|
const history = await historyResponse.json();
|
||||||
|
|
||||||
|
if (current.issue) {
|
||||||
|
const issue = current.issue;
|
||||||
|
this.issueNo = issue.issue_no;
|
||||||
|
this.status = issue.status;
|
||||||
|
this.isOpen = current.is_open;
|
||||||
|
this.isSuperIssue = issue.is_super_issue;
|
||||||
|
this.poolAmount = issue.pool_amount;
|
||||||
|
this.secondsLeft = issue.seconds_left;
|
||||||
|
this.drawRed1 = issue.red1;
|
||||||
|
this.drawRed2 = issue.red2;
|
||||||
|
this.drawRed3 = issue.red3;
|
||||||
|
this.drawBlue = issue.blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.myTickets = current.my_tickets ?? [];
|
||||||
|
this.history = history.issues ?? [];
|
||||||
|
} catch (error) {
|
||||||
|
// 网络异常时保留现有面板数据,避免清空用户正在选择的号码。
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动开奖倒计时。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
startTimer() {
|
||||||
|
window.clearInterval(this._timer);
|
||||||
|
this._timer = window.setInterval(() => {
|
||||||
|
if (this.secondsLeft > 0) {
|
||||||
|
this.secondsLeft -= 1;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换红球选择状态。
|
||||||
|
*
|
||||||
|
* @param {number} number
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
toggleRed(number) {
|
||||||
|
if (this.selectedReds.includes(number)) {
|
||||||
|
this.selectedReds = this.selectedReds.filter((red) => red !== number);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selectedReds.length < 3) {
|
||||||
|
this.selectedReds = [...this.selectedReds, number];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端机选号码并加入购物车。
|
||||||
|
*
|
||||||
|
* @param {number} [count]
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async doQuickPick(count = 1) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/lottery/quick-pick?count=${count}`);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
for (const number of data.numbers) {
|
||||||
|
if (this.cart.length < 10) {
|
||||||
|
this.cart.push({
|
||||||
|
reds: number.reds,
|
||||||
|
blue: number.blue,
|
||||||
|
quick: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedReds = [];
|
||||||
|
this.selectedBlue = null;
|
||||||
|
} catch (error) {
|
||||||
|
// 机选失败保持当前选号状态,用户仍可手动选择。
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将当前选号加入购物车。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
addToCart() {
|
||||||
|
if (this.selectedReds.length !== 3 || !this.selectedBlue) {
|
||||||
|
showLotteryMsg("⚠️ 请选满 3 个红球和 1 个蓝球", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.cart.length >= 10) {
|
||||||
|
showLotteryMsg("⚠️ 单次最多加入 10 注", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cart.push({
|
||||||
|
reds: [...this.selectedReds].sort((a, b) => a - b),
|
||||||
|
blue: this.selectedBlue,
|
||||||
|
quick: false,
|
||||||
|
});
|
||||||
|
this.selectedReds = [];
|
||||||
|
this.selectedBlue = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交购物车并批量购票。
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async submitCart() {
|
||||||
|
if (this.cart.length === 0 || this.buying) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buying = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/lottery/buy", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"X-CSRF-TOKEN": csrf(),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
numbers: this.cart.map((item) => ({
|
||||||
|
reds: item.reds,
|
||||||
|
blue: item.blue,
|
||||||
|
})),
|
||||||
|
quick_pick: false,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && data.status === "success") {
|
||||||
|
showLotteryMsg(`✅ ${data.message}`, true);
|
||||||
|
this.cart = [];
|
||||||
|
|
||||||
|
// 购票成功后同步全局金币,避免其他面板继续显示旧余额。
|
||||||
|
if (window.chatContext) {
|
||||||
|
window.chatContext.userJjb = Math.max(0, (window.chatContext.userJjb ?? 0) - data.count * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.loadData();
|
||||||
|
} else {
|
||||||
|
showLotteryMsg(`❌ ${data.message || "购票失败"}`, false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showLotteryMsg("🌐 网络异常,请稍后重试", false);
|
||||||
|
} finally {
|
||||||
|
this.buying = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开彩票面板。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function openLotteryPanel() {
|
||||||
|
const panel = document.getElementById("lottery-panel");
|
||||||
|
if (panel && window.Alpine) {
|
||||||
|
void window.Alpine.$data(panel)?.open?.();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭彩票面板并清理倒计时。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function closeLotteryPanel() {
|
||||||
|
const panel = document.getElementById("lottery-panel");
|
||||||
|
if (!panel || !window.Alpine) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = window.Alpine.$data(panel);
|
||||||
|
data.show = false;
|
||||||
|
window.clearInterval(data._timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定彩票面板全局入口和关闭按钮事件。
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function bindLotteryPanelControls() {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.lotteryPanel = lotteryPanel;
|
||||||
|
window.openLotteryPanel = openLotteryPanel;
|
||||||
|
window.closeLotteryPanel = closeLotteryPanel;
|
||||||
|
window.showLotteryMsg = showLotteryMsg;
|
||||||
|
|
||||||
|
if (lotteryPanelEventsBound || typeof document === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lotteryPanelEventsBound = true;
|
||||||
|
document.addEventListener("click", (event) => {
|
||||||
|
if (!(event.target instanceof Element) || !event.target.closest("[data-lottery-panel-close]")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
closeLotteryPanel();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -406,264 +406,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
{{-- 双色球彩票 Alpine 组件已迁移到 resources/js/chat-room/lottery-panel.js --}}
|
||||||
/**
|
|
||||||
* 双色球彩票面板 Alpine.js 组件
|
|
||||||
*/
|
|
||||||
function lotteryPanel() {
|
|
||||||
return {
|
|
||||||
// ─── 状态 ───
|
|
||||||
show: false,
|
|
||||||
loading: true,
|
|
||||||
ruleOpen: false,
|
|
||||||
buying: false,
|
|
||||||
|
|
||||||
// ─── 期次数据 ───
|
|
||||||
issueNo: '--',
|
|
||||||
status: 'open',
|
|
||||||
isOpen: false,
|
|
||||||
isSuperIssue: false,
|
|
||||||
poolAmount: 0,
|
|
||||||
secondsLeft: 0,
|
|
||||||
drawAt: null,
|
|
||||||
drawRed1: null,
|
|
||||||
drawRed2: null,
|
|
||||||
drawRed3: null,
|
|
||||||
drawBlue: null,
|
|
||||||
|
|
||||||
// ─── 选号 ───
|
|
||||||
selectedReds: [],
|
|
||||||
selectedBlue: null,
|
|
||||||
cart: [], // 待购清单
|
|
||||||
|
|
||||||
// ─── 数据 ───
|
|
||||||
myTickets: [],
|
|
||||||
history: [],
|
|
||||||
|
|
||||||
// ─── 倒计时 ───
|
|
||||||
_timer: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化倒计时文字(如 4h 22m 或 01:59)
|
|
||||||
*/
|
|
||||||
get countdownText() {
|
|
||||||
const s = this.secondsLeft;
|
|
||||||
if (s <= 0) return '即将开奖';
|
|
||||||
if (s >= 3600) return `${Math.floor(s/3600)}h ${Math.floor((s%3600)/60)}m`;
|
|
||||||
const m = Math.floor(s / 60);
|
|
||||||
const sec = s % 60;
|
|
||||||
return `${String(m).padStart(2,'0')}:${String(sec).padStart(2,'0')}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开面板并加载数据
|
|
||||||
*/
|
|
||||||
async open() {
|
|
||||||
this.show = true;
|
|
||||||
await this.loadData();
|
|
||||||
this.startTimer();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载当期状态、我的购票、历史开奖
|
|
||||||
*/
|
|
||||||
async loadData() {
|
|
||||||
this.loading = true;
|
|
||||||
try {
|
|
||||||
const [currentRes, histRes] = await Promise.all([
|
|
||||||
fetch('/lottery/current', {
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
fetch('/lottery/history', {
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
const current = await currentRes.json();
|
|
||||||
const hist = await histRes.json();
|
|
||||||
|
|
||||||
if (current.issue) {
|
|
||||||
const iss = current.issue;
|
|
||||||
this.issueNo = iss.issue_no;
|
|
||||||
this.status = iss.status;
|
|
||||||
this.isOpen = current.is_open;
|
|
||||||
this.isSuperIssue = iss.is_super_issue;
|
|
||||||
this.poolAmount = iss.pool_amount;
|
|
||||||
this.secondsLeft = iss.seconds_left;
|
|
||||||
this.drawRed1 = iss.red1;
|
|
||||||
this.drawRed2 = iss.red2;
|
|
||||||
this.drawRed3 = iss.red3;
|
|
||||||
this.drawBlue = iss.blue;
|
|
||||||
}
|
|
||||||
this.myTickets = current.my_tickets ?? [];
|
|
||||||
this.history = hist.issues ?? [];
|
|
||||||
} catch (e) {
|
|
||||||
// 网络异常静默处理
|
|
||||||
}
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动倒计时 ticker
|
|
||||||
*/
|
|
||||||
startTimer() {
|
|
||||||
clearInterval(this._timer);
|
|
||||||
this._timer = setInterval(() => {
|
|
||||||
if (this.secondsLeft > 0) {
|
|
||||||
this.secondsLeft--;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换红球选择状态
|
|
||||||
*/
|
|
||||||
toggleRed(n) {
|
|
||||||
if (this.selectedReds.includes(n)) {
|
|
||||||
this.selectedReds = this.selectedReds.filter(r => r !== n);
|
|
||||||
} else if (this.selectedReds.length < 3) {
|
|
||||||
this.selectedReds = [...this.selectedReds, n];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务端机选号码(立即加入购物车)
|
|
||||||
*/
|
|
||||||
async doQuickPick(count = 1) {
|
|
||||||
try {
|
|
||||||
const res = await fetch(`/lottery/quick-pick?count=${count}`);
|
|
||||||
const data = await res.json();
|
|
||||||
for (const num of data.numbers) {
|
|
||||||
if (this.cart.length < 10) {
|
|
||||||
this.cart.push({
|
|
||||||
reds: num.reds,
|
|
||||||
blue: num.blue,
|
|
||||||
quick: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 清空当前选号
|
|
||||||
this.selectedReds = [];
|
|
||||||
this.selectedBlue = null;
|
|
||||||
} catch {}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将当前选号加入购物车
|
|
||||||
*/
|
|
||||||
addToCart() {
|
|
||||||
if (this.selectedReds.length !== 3 || !this.selectedBlue) {
|
|
||||||
showLotteryMsg('⚠️ 请选满 3 个红球和 1 个蓝球', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.cart.length >= 10) {
|
|
||||||
showLotteryMsg('⚠️ 单次最多加入 10 注', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.cart.push({
|
|
||||||
reds: [...this.selectedReds].sort((a, b) => a - b),
|
|
||||||
blue: this.selectedBlue,
|
|
||||||
quick: false
|
|
||||||
});
|
|
||||||
// 清空选号等待下一注
|
|
||||||
this.selectedReds = [];
|
|
||||||
this.selectedBlue = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 提交购物车(批量购买)
|
|
||||||
*/
|
|
||||||
async submitCart() {
|
|
||||||
if (this.cart.length === 0 || this.buying) return;
|
|
||||||
this.buying = true;
|
|
||||||
try {
|
|
||||||
const res = await fetch('/lottery/buy', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
numbers: this.cart.map(c => ({
|
|
||||||
reds: c.reds,
|
|
||||||
blue: c.blue
|
|
||||||
})),
|
|
||||||
quick_pick: false,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const data = await res.json();
|
|
||||||
if (res.ok && data.status === 'success') {
|
|
||||||
showLotteryMsg('✅ ' + data.message, true);
|
|
||||||
this.cart = [];
|
|
||||||
|
|
||||||
// 更新金币余额显示
|
|
||||||
if (window.chatContext) {
|
|
||||||
window.chatContext.userJjb = Math.max(0, (window.chatContext.userJjb ?? 0) - data
|
|
||||||
.count * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 刷新我的购票列表
|
|
||||||
await this.loadData();
|
|
||||||
} else {
|
|
||||||
showLotteryMsg('❌ ' + (data.message || '购票失败'), false);
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
showLotteryMsg('🌐 网络异常,请稍后重试', false);
|
|
||||||
}
|
|
||||||
this.buying = false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示彩票面板内联消息(3s 后自动消失)
|
|
||||||
*
|
|
||||||
* @param {string} msg
|
|
||||||
* @param {boolean} success
|
|
||||||
*/
|
|
||||||
function showLotteryMsg(msg, success) {
|
|
||||||
const el = document.getElementById('lottery-buy-msg');
|
|
||||||
if (!el) return;
|
|
||||||
el.style.background = success ? '#f0fdf4' : '#fff5f5';
|
|
||||||
el.style.border = success ? '1px solid #86efac' : '1px solid #fecaca';
|
|
||||||
el.style.color = success ? '#16a34a' : '#dc2626';
|
|
||||||
el.textContent = msg;
|
|
||||||
el.style.display = 'block';
|
|
||||||
el.style.opacity = '1';
|
|
||||||
clearTimeout(el._t);
|
|
||||||
el._t = setTimeout(() => {
|
|
||||||
el.style.opacity = '0';
|
|
||||||
setTimeout(() => {
|
|
||||||
el.style.display = 'none';
|
|
||||||
}, 400);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 打开彩票面板 */
|
|
||||||
window.openLotteryPanel = function() {
|
|
||||||
const panel = document.getElementById('lottery-panel');
|
|
||||||
if (panel) Alpine.$data(panel).open();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 关闭彩票面板 */
|
|
||||||
window.closeLotteryPanel = function() {
|
|
||||||
const panel = document.getElementById('lottery-panel');
|
|
||||||
if (panel) {
|
|
||||||
const data = Alpine.$data(panel);
|
|
||||||
data.show = false;
|
|
||||||
clearInterval(data._timer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 顶部关闭按钮由脚本集中绑定,避免标题栏继续保留内联 onclick。
|
|
||||||
document.querySelectorAll('[data-lottery-panel-close]').forEach(button => {
|
|
||||||
button.addEventListener('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
closeLotteryPanel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user