迁移钓鱼游戏脚本
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
* - holiday-modal.js:处理节日福利弹窗和系统消息入口。
|
||||
* - initial-state.js:恢复首屏历史消息、欢迎消息、入场特效和挂起婚姻事件。
|
||||
* - bank-modal.js:处理银行弹窗、转账、排行和标签切换。
|
||||
* - fishing.js:处理钓鱼入口与自动钓鱼相关交互。
|
||||
* - fishing.js:处理钓鱼抛竿、收竿、浮漂和自动钓鱼循环。
|
||||
* - fortune-panel.js:提供神秘占卜 fortunePanel Alpine 组件。
|
||||
* - profile-controls.js:处理用户资料和资料相关按钮。
|
||||
* - shop-controls.js:处理商店弹窗的基础按钮事件。
|
||||
@@ -106,7 +106,7 @@ export {
|
||||
switchBankTab,
|
||||
toggleBankRankSort,
|
||||
} from "./chat-room/bank-modal.js";
|
||||
export { bindFishingControls } from "./chat-room/fishing.js";
|
||||
export { bindFishingControls, checkAndAutoStartFishing, createBobber, reelFish, removeBobber, resetFishingBtn, startFishing, stopAutoFishing } from "./chat-room/fishing.js";
|
||||
export { bindFortunePanelControls, fortunePanel } from "./chat-room/fortune-panel.js";
|
||||
export { bindProfileControls } from "./chat-room/profile-controls.js";
|
||||
export { bindShopControls } from "./chat-room/shop-controls.js";
|
||||
@@ -200,7 +200,7 @@ import {
|
||||
switchBankTab,
|
||||
toggleBankRankSort,
|
||||
} from "./chat-room/bank-modal.js";
|
||||
import { bindFishingControls } from "./chat-room/fishing.js";
|
||||
import { bindFishingControls, checkAndAutoStartFishing, createBobber, reelFish, removeBobber, resetFishingBtn, startFishing, stopAutoFishing } from "./chat-room/fishing.js";
|
||||
import { bindFortunePanelControls, fortunePanel } from "./chat-room/fortune-panel.js";
|
||||
import { bindProfileControls } from "./chat-room/profile-controls.js";
|
||||
import { bindShopControls } from "./chat-room/shop-controls.js";
|
||||
@@ -314,6 +314,13 @@ if (typeof window !== "undefined") {
|
||||
switchBankTab,
|
||||
toggleBankRankSort,
|
||||
bindFishingControls,
|
||||
checkAndAutoStartFishing,
|
||||
createBobber,
|
||||
reelFish,
|
||||
removeBobber,
|
||||
resetFishingBtn,
|
||||
startFishing,
|
||||
stopAutoFishing,
|
||||
bindFortunePanelControls,
|
||||
fortunePanel,
|
||||
bindMarriageStatusControls,
|
||||
@@ -408,6 +415,13 @@ if (typeof window !== "undefined") {
|
||||
window.openLotteryPanel = openLotteryPanel;
|
||||
window.openBankModal = openBankModal;
|
||||
window.showLotteryMsg = showLotteryMsg;
|
||||
window.checkAndAutoStartFishing = checkAndAutoStartFishing;
|
||||
window.createBobber = createBobber;
|
||||
window.reelFish = reelFish;
|
||||
window.removeBobber = removeBobber;
|
||||
window.resetFishingBtn = resetFishingBtn;
|
||||
window.startFishing = startFishing;
|
||||
window.stopAutoFishing = stopAutoFishing;
|
||||
window.buyVip = buyVip;
|
||||
window.closeVipModal = closeVipModal;
|
||||
window.openVipModal = openVipModal;
|
||||
|
||||
@@ -1,13 +1,605 @@
|
||||
// 聊天室钓鱼入口事件绑定,先兼容存量全局 startFishing 实现。
|
||||
// 聊天室钓鱼小游戏模块,管理抛竿、收竿、自动钓鱼循环和浮漂交互。
|
||||
|
||||
import { escapeHtml } from "./html.js";
|
||||
|
||||
let fishingEventsBound = false;
|
||||
let fishingTimer = null;
|
||||
let fishingReelTimeout = null;
|
||||
let fishToken = null;
|
||||
let autoFishing = false;
|
||||
let autoFishCooldownTimer = null;
|
||||
let autoFishCooldownCountdown = null;
|
||||
|
||||
/**
|
||||
* 绑定钓鱼按钮点击事件。
|
||||
* 读取 CSRF Token。
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function csrf() {
|
||||
return document.querySelector('meta[name="csrf-token"]')?.content || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私聊消息容器,钓鱼提示沿用旧版展示位置。
|
||||
*
|
||||
* @returns {HTMLElement|null}
|
||||
*/
|
||||
function messageContainer() {
|
||||
return document.getElementById("chat-messages-container2");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否允许自动滚动。
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldAutoScroll() {
|
||||
return typeof window.isChatAutoScrollEnabled === "function" ? window.isChatAutoScrollEnabled() : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加一条钓鱼提示消息。
|
||||
*
|
||||
* @param {string} html
|
||||
* @returns {void}
|
||||
*/
|
||||
function appendFishingMessage(html) {
|
||||
const container = messageContainer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const line = document.createElement("div");
|
||||
line.className = "msg-line";
|
||||
line.innerHTML = html;
|
||||
container.appendChild(line);
|
||||
|
||||
if (shouldAutoScroll()) {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前本地时间文本。
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function timeText() {
|
||||
return new Date().toLocaleTimeString("zh-CN", { hour12: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入浮漂和自动钓鱼按钮需要的动画样式。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function ensureFishingStyles() {
|
||||
if (!document.getElementById("bobber-style")) {
|
||||
const style = document.createElement("style");
|
||||
style.id = "bobber-style";
|
||||
style.textContent = `
|
||||
@keyframes bobberFloat {
|
||||
0%,100% { transform: translateY(0) rotate(-8deg); }
|
||||
50% { transform: translateY(-10px) rotate(8deg); }
|
||||
}
|
||||
@keyframes bobberSink {
|
||||
0% { transform: translateY(0) scale(1); opacity:1; }
|
||||
30% { transform: translateY(12px) scale(1.3); opacity:1; }
|
||||
100% { transform: translateY(40px) scale(0.5); opacity:0; }
|
||||
}
|
||||
#fishing-bobber.sinking {
|
||||
animation: bobberSink 1.5s forwards !important;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
if (!document.getElementById("auto-fish-stop-style")) {
|
||||
const style = document.createElement("style");
|
||||
style.id = "auto-fish-stop-style";
|
||||
style.textContent = `
|
||||
@keyframes autoFishBtnPulse {
|
||||
0%,100% { box-shadow: 0 4px 12px rgba(220,38,38,0.4); }
|
||||
50% { box-shadow: 0 4px 20px rgba(220,38,38,0.7); }
|
||||
}
|
||||
#auto-fish-stop-btn {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
background: linear-gradient(135deg, #dc2626, #b91c1c);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 8px 18px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
animation: autoFishBtnPulse 1.8s ease-in-out infinite;
|
||||
touch-action: none;
|
||||
}
|
||||
#auto-fish-stop-btn:active { cursor: grabbing; }
|
||||
#auto-fish-stop-btn .drag-hint {
|
||||
display: block;
|
||||
font-size: 9px;
|
||||
font-weight: normal;
|
||||
opacity: .65;
|
||||
margin-top: 1px;
|
||||
text-align: center;
|
||||
letter-spacing: .5px;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建浮漂 DOM 元素。
|
||||
*
|
||||
* @param {number} x 水平百分比
|
||||
* @param {number} y 垂直百分比
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
export function createBobber(x, y) {
|
||||
ensureFishingStyles();
|
||||
|
||||
const bobber = document.createElement("div");
|
||||
bobber.id = "fishing-bobber";
|
||||
bobber.style.cssText = `
|
||||
position: fixed;
|
||||
left: ${Number(x) || 50}vw;
|
||||
top: ${Number(y) || 50}vh;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
z-index: 9999;
|
||||
animation: bobberFloat 1.2s ease-in-out infinite;
|
||||
filter: drop-shadow(0 2px 6px rgba(0,0,0,0.4));
|
||||
user-select: none;
|
||||
transition: transform 0.3s;
|
||||
`;
|
||||
bobber.textContent = "🪝";
|
||||
bobber.title = "鱼上钩了!快点击!";
|
||||
|
||||
return bobber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除当前浮漂。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function removeBobber() {
|
||||
document.getElementById("fishing-bobber")?.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取钓鱼按钮。
|
||||
*
|
||||
* @returns {HTMLButtonElement|null}
|
||||
*/
|
||||
function fishingButton() {
|
||||
const button = document.getElementById("fishing-btn");
|
||||
|
||||
return button instanceof HTMLButtonElement ? button : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置钓鱼按钮文案和禁用状态。
|
||||
*
|
||||
* @param {string} text
|
||||
* @param {boolean} disabled
|
||||
* @returns {void}
|
||||
*/
|
||||
function setFishingButton(text, disabled) {
|
||||
const button = fishingButton();
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.textContent = text;
|
||||
button.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动自动钓鱼冷却倒计时。
|
||||
*
|
||||
* @param {number} cooldown
|
||||
* @returns {void}
|
||||
*/
|
||||
function startAutoFishingCooldown(cooldown) {
|
||||
let remaining = cooldown;
|
||||
setFishingButton(`⏳ 冷却 ${remaining}s`, true);
|
||||
showAutoFishStopButton(cooldown);
|
||||
|
||||
autoFishCooldownCountdown = window.setInterval(() => {
|
||||
remaining -= 1;
|
||||
setFishingButton(`⏳ 冷却 ${remaining}s`, true);
|
||||
|
||||
if (remaining <= 0) {
|
||||
window.clearInterval(autoFishCooldownCountdown);
|
||||
autoFishCooldownCountdown = null;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
autoFishCooldownTimer = window.setTimeout(() => {
|
||||
autoFishCooldownTimer = null;
|
||||
hideAutoFishStopButton();
|
||||
|
||||
if (autoFishing) {
|
||||
void startFishing();
|
||||
}
|
||||
}, cooldown * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示可拖动的停止自动钓鱼按钮。
|
||||
*
|
||||
* @param {number} cooldown
|
||||
* @returns {void}
|
||||
*/
|
||||
function showAutoFishStopButton(cooldown) {
|
||||
if (document.getElementById("auto-fish-stop-btn")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensureFishingStyles();
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.id = "auto-fish-stop-btn";
|
||||
button.innerHTML = `🛑 停止自动钓鱼<span class="drag-hint">冷却 ${Number(cooldown) || 0}s · 可拖动</span>`;
|
||||
|
||||
try {
|
||||
const saved = JSON.parse(window.localStorage.getItem("autoFishBtnPos") || "null");
|
||||
if (saved) {
|
||||
button.style.left = `${Number(saved.left) || 0}px`;
|
||||
button.style.top = `${Number(saved.top) || 0}px`;
|
||||
} else {
|
||||
button.style.bottom = "80px";
|
||||
button.style.right = "20px";
|
||||
}
|
||||
} catch (error) {
|
||||
button.style.bottom = "80px";
|
||||
button.style.right = "20px";
|
||||
}
|
||||
|
||||
bindAutoFishStopDrag(button);
|
||||
document.body.appendChild(button);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给停止自动钓鱼按钮绑定拖拽和点击停止事件。
|
||||
*
|
||||
* @param {HTMLButtonElement} button
|
||||
* @returns {void}
|
||||
*/
|
||||
function bindAutoFishStopDrag(button) {
|
||||
let isDragging = false;
|
||||
let startX = 0;
|
||||
let startY = 0;
|
||||
let startLeft = 0;
|
||||
let startTop = 0;
|
||||
|
||||
const dragStart = (event) => {
|
||||
const rect = button.getBoundingClientRect();
|
||||
button.style.left = `${rect.left}px`;
|
||||
button.style.top = `${rect.top}px`;
|
||||
button.style.right = "auto";
|
||||
button.style.bottom = "auto";
|
||||
|
||||
isDragging = false;
|
||||
const point = event.touches ? event.touches[0] : event;
|
||||
startX = point.clientX;
|
||||
startY = point.clientY;
|
||||
startLeft = rect.left;
|
||||
startTop = rect.top;
|
||||
|
||||
document.addEventListener("mousemove", dragMove, { passive: false });
|
||||
document.addEventListener("mouseup", dragEnd);
|
||||
document.addEventListener("touchmove", dragMove, { passive: false });
|
||||
document.addEventListener("touchend", dragEnd);
|
||||
};
|
||||
|
||||
const dragMove = (event) => {
|
||||
event.preventDefault();
|
||||
const point = event.touches ? event.touches[0] : event;
|
||||
const dx = point.clientX - startX;
|
||||
const dy = point.clientY - startY;
|
||||
|
||||
if (Math.abs(dx) > 3 || Math.abs(dy) > 3) {
|
||||
isDragging = true;
|
||||
}
|
||||
|
||||
if (!isDragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextLeft = Math.max(0, Math.min(window.innerWidth - button.offsetWidth, startLeft + dx));
|
||||
const nextTop = Math.max(0, Math.min(window.innerHeight - button.offsetHeight, startTop + dy));
|
||||
button.style.left = `${nextLeft}px`;
|
||||
button.style.top = `${nextTop}px`;
|
||||
};
|
||||
|
||||
const dragEnd = () => {
|
||||
document.removeEventListener("mousemove", dragMove);
|
||||
document.removeEventListener("mouseup", dragEnd);
|
||||
document.removeEventListener("touchmove", dragMove);
|
||||
document.removeEventListener("touchend", dragEnd);
|
||||
|
||||
if (isDragging) {
|
||||
window.localStorage.setItem("autoFishBtnPos", JSON.stringify({
|
||||
left: Number.parseInt(button.style.left, 10),
|
||||
top: Number.parseInt(button.style.top, 10),
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
button.addEventListener("mousedown", dragStart);
|
||||
button.addEventListener("touchstart", dragStart, { passive: true });
|
||||
button.addEventListener("click", () => {
|
||||
if (!isDragging) {
|
||||
stopAutoFishing();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏停止自动钓鱼按钮。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function hideAutoFishStopButton() {
|
||||
document.getElementById("auto-fish-stop-btn")?.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始钓鱼:调用抛竿接口并显示浮漂。
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function startFishing() {
|
||||
setFishingButton("🎣 抛竿中...", true);
|
||||
|
||||
try {
|
||||
const response = await fetch(window.chatContext.fishCastUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": csrf(),
|
||||
"Accept": "application/json",
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok || data.status !== "success") {
|
||||
window.chatDialog?.alert?.(data.message || "钓鱼失败", "操作失败", "#cc4444");
|
||||
setFishingButton("🎣 钓鱼", false);
|
||||
return;
|
||||
}
|
||||
|
||||
fishToken = data.token;
|
||||
autoFishing = Boolean(data.auto_fishing);
|
||||
appendFishingMessage(`<span style="color:#2563eb;font-weight:bold;">🎣【钓鱼】</span>${escapeHtml(data.message)}<span class="msg-time">(${timeText()})</span>`);
|
||||
setFishingButton("🎣 等待中...", true);
|
||||
|
||||
const bobber = createBobber(data.bobber_x, data.bobber_y);
|
||||
document.body.appendChild(bobber);
|
||||
|
||||
fishingTimer = window.setTimeout(() => {
|
||||
bobber.classList.add("sinking");
|
||||
bobber.textContent = "🐟";
|
||||
|
||||
if (data.auto_fishing) {
|
||||
appendFishingMessage(`<span style="color:#7c3aed;font-weight:bold;">🎣 自动钓鱼卡生效!自动收竿中... <span style="font-size:10px;opacity:0.7">(剩余${Number(data.auto_fishing_minutes_left) || 0}分钟)</span></span>`);
|
||||
fishingReelTimeout = window.setTimeout(() => {
|
||||
removeBobber();
|
||||
void reelFish();
|
||||
}, 1800);
|
||||
return;
|
||||
}
|
||||
|
||||
appendFishingMessage('<span style="color:#d97706;font-weight:bold;font-size:14px;">🐟 鱼上钩了!快点击屏幕上的浮漂!</span>');
|
||||
setFishingButton("🎣 点击浮漂!", true);
|
||||
bobber.addEventListener("click", () => {
|
||||
removeBobber();
|
||||
|
||||
if (fishingReelTimeout) {
|
||||
window.clearTimeout(fishingReelTimeout);
|
||||
fishingReelTimeout = null;
|
||||
}
|
||||
|
||||
void reelFish();
|
||||
}, { once: true });
|
||||
|
||||
fishingReelTimeout = window.setTimeout(() => {
|
||||
removeBobber();
|
||||
fishToken = null;
|
||||
appendFishingMessage('<span style="color:#999;">💨 你反应太慢了,鱼跑掉了...</span>');
|
||||
resetFishingBtn();
|
||||
}, 8000);
|
||||
}, Number(data.wait_time || 0) * 1000);
|
||||
} catch (error) {
|
||||
window.chatDialog?.alert?.(`网络错误:${error.message}`, "网络异常", "#cc4444");
|
||||
removeBobber();
|
||||
setFishingButton("🎣 钓鱼", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收竿并提交本次钓鱼 token。
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function reelFish() {
|
||||
setFishingButton("🎣 拉竿中...", true);
|
||||
|
||||
if (fishingReelTimeout) {
|
||||
window.clearTimeout(fishingReelTimeout);
|
||||
fishingReelTimeout = null;
|
||||
}
|
||||
|
||||
const token = fishToken;
|
||||
fishToken = null;
|
||||
|
||||
try {
|
||||
const response = await fetch(window.chatContext.fishReelUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": csrf(),
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ token }),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok && data.status === "success") {
|
||||
const result = data.result || {};
|
||||
const color = Number(result.exp || 0) >= 0 ? "#16a34a" : "#dc2626";
|
||||
appendFishingMessage(
|
||||
`<span style="color:${color};font-weight:bold;">${escapeHtml(result.emoji || "🎣")}【钓鱼结果】</span>${escapeHtml(result.message || "")}` +
|
||||
` <span style="color:#666;font-size:11px;">(经验:${Number(data.exp_num) || 0} 金币:${Number(data.jjb) || 0})</span>` +
|
||||
`<span class="msg-time">(${timeText()})</span>`,
|
||||
);
|
||||
|
||||
if (autoFishing) {
|
||||
startAutoFishingCooldown(Number(data.cooldown_seconds) || 300);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
appendFishingMessage(`<span style="color:red;">【钓鱼】${escapeHtml(data.message || "操作失败")}</span><span class="msg-time">(${timeText()})</span>`);
|
||||
|
||||
if (autoFishing) {
|
||||
retryAutoFishing();
|
||||
return;
|
||||
}
|
||||
|
||||
autoFishing = false;
|
||||
}
|
||||
} catch (error) {
|
||||
if (autoFishing) {
|
||||
appendFishingMessage('<span style="color:#d97706;">⚠️ 网络异常,5秒后自动重试钓鱼...</span>');
|
||||
retryAutoFishing();
|
||||
return;
|
||||
}
|
||||
|
||||
window.chatDialog?.alert?.(`网络错误:${error.message}`, "网络异常", "#cc4444");
|
||||
autoFishing = false;
|
||||
}
|
||||
|
||||
resetFishingBtn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动钓鱼异常时短暂等待后重试。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function retryAutoFishing() {
|
||||
setFishingButton("⏳ 重试中...", true);
|
||||
autoFishCooldownTimer = window.setTimeout(() => {
|
||||
autoFishCooldownTimer = null;
|
||||
|
||||
if (autoFishing) {
|
||||
void startFishing();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动停止自动钓鱼循环。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function stopAutoFishing() {
|
||||
autoFishing = false;
|
||||
clearAutoFishingTimers();
|
||||
hideAutoFishStopButton();
|
||||
appendFishingMessage('<span style="color:#6b7280;">🛑 已停止自动钓鱼。</span>');
|
||||
resetFishingBtn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理自动钓鱼冷却计时器。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
function clearAutoFishingTimers() {
|
||||
if (autoFishCooldownTimer) {
|
||||
window.clearTimeout(autoFishCooldownTimer);
|
||||
autoFishCooldownTimer = null;
|
||||
}
|
||||
|
||||
if (autoFishCooldownCountdown) {
|
||||
window.clearInterval(autoFishCooldownCountdown);
|
||||
autoFishCooldownCountdown = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置钓鱼按钮和临时状态。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function resetFishingBtn() {
|
||||
autoFishing = false;
|
||||
clearAutoFishingTimers();
|
||||
hideAutoFishStopButton();
|
||||
|
||||
if (fishingTimer) {
|
||||
window.clearTimeout(fishingTimer);
|
||||
fishingTimer = null;
|
||||
}
|
||||
|
||||
if (fishingReelTimeout) {
|
||||
window.clearTimeout(fishingReelTimeout);
|
||||
fishingReelTimeout = null;
|
||||
}
|
||||
|
||||
setFishingButton("🎣 钓鱼", false);
|
||||
removeBobber();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查自动钓鱼卡状态并恢复自动循环。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function checkAndAutoStartFishing() {
|
||||
const minutesLeft = Number(window.chatContext?.autoFishingMinutesLeft || 0);
|
||||
const initialCooldown = Number(window.chatContext?.fishingCooldownSeconds || 0);
|
||||
|
||||
if (minutesLeft <= 0 || autoFishing) {
|
||||
return;
|
||||
}
|
||||
|
||||
autoFishing = true;
|
||||
|
||||
if (initialCooldown > 0) {
|
||||
console.log(`检测到自动钓鱼卡有效,恢复钓鱼状态,剩余冷却 ${initialCooldown}s`);
|
||||
startAutoFishingCooldown(initialCooldown);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("检测到自动钓鱼卡有效,自动抛竿");
|
||||
void startFishing();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定钓鱼按钮、全局兼容入口和清屏恢复事件。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function bindFishingControls() {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.createBobber = createBobber;
|
||||
window.removeBobber = removeBobber;
|
||||
window.startFishing = startFishing;
|
||||
window.reelFish = reelFish;
|
||||
window.stopAutoFishing = stopAutoFishing;
|
||||
window.resetFishingBtn = resetFishingBtn;
|
||||
window.checkAndAutoStartFishing = checkAndAutoStartFishing;
|
||||
|
||||
if (fishingEventsBound || typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
@@ -19,10 +611,15 @@ export function bindFishingControls() {
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
void startFishing();
|
||||
});
|
||||
|
||||
// 钓鱼完整流程仍在 fishing-panel.blade.php,当前模块只统一按钮事件入口。
|
||||
if (typeof window.startFishing === "function") {
|
||||
window.startFishing();
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
checkAndAutoStartFishing();
|
||||
window.addEventListener("chat:screen-cleared", () => {
|
||||
if (!autoFishing) {
|
||||
checkAndAutoStartFishing();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user