3 Commits

4 changed files with 59 additions and 20 deletions
+5
View File
@@ -125,6 +125,11 @@ class ShopController extends Controller
'total_price' => $result['total_price'] ?? $item->price,
];
// 购买自动钓鱼卡后返回剩余分钟数,前端用于自动开启钓鱼
if ($item->type === 'auto_fishing') {
$response['auto_fishing_minutes_left'] = $this->shopService->getActiveAutoFishingMinutesLeft($user);
}
// ── 装扮购买:向前端透传槽位与样式信息,用于即时更新装扮状态 ──
if (! empty($result['slot'])) {
$response['slot'] = $result['slot'];
+20 -13
View File
@@ -200,34 +200,41 @@ function setFishingButton(text, disabled) {
}
/**
* 启动自动钓鱼冷却倒计时。
* 启动自动钓鱼冷却倒计时(基于时间戳,不受浏览器后台节流影响)
*
* @param {number} cooldown
* @param {number} cooldown 冷却秒数
* @returns {void}
*/
function startAutoFishingCooldown(cooldown) {
let remaining = cooldown;
setFishingButton(`⏳ 冷却 ${remaining}s`, true);
const endTime = Date.now() + cooldown * 1000;
setFishingButton(`⏳ 冷却 ${cooldown}s`, true);
showAutoFishStopButton(cooldown);
// 基于时间戳更新倒计时 UI — 后台节流后回来也能准确显示
autoFishCooldownCountdown = window.setInterval(() => {
remaining -= 1;
const remaining = Math.max(0, Math.ceil((endTime - Date.now()) / 1000));
setFishingButton(`⏳ 冷却 ${remaining}s`, true);
if (remaining <= 0) {
window.clearInterval(autoFishCooldownCountdown);
autoFishCooldownCountdown = null;
}
}, 1000);
}, 200);
autoFishCooldownTimer = window.setTimeout(() => {
autoFishCooldownTimer = null;
hideAutoFishStopButton();
if (autoFishing) {
void startFishing();
// 基于时间戳检测冷却结束 — 后台节流后立即触发
autoFishCooldownTimer = null;
const checkEnd = () => {
if (Date.now() >= endTime) {
autoFishCooldownTimer = null;
hideAutoFishStopButton();
if (autoFishing) {
void startFishing();
}
return;
}
}, cooldown * 1000);
autoFishCooldownTimer = window.setTimeout(checkEnd, 200);
};
autoFishCooldownTimer = window.setTimeout(checkEnd, Math.min(cooldown * 1000, 200));
}
/**
@@ -457,6 +457,9 @@ export function enqueueChatMessage(msg) {
state.chatMessageFlushTimer = scheduleFlush(flushQueuedChatMessages);
}
/** 后台恢复时公屏最大渲染条数,避免暴刷 */
const MAX_BURST_RENDER = 50;
/**
* 分批渲染待处理消息,给动画、输入和滚动留出主线程时间。
*/
@@ -466,6 +469,23 @@ export function flushQueuedChatMessages() {
state.chatMessageFlushTimer = null;
// 大批量消息堆积(后台标签页恢复)时,丢弃早于 MAX_BURST_RENDER 的消息,
// 插入一条省略提示,避免用户一回来就看到满屏消息狂刷。
if (state.pendingChatMessages.length > MAX_BURST_RENDER + 20) {
const skipped = state.pendingChatMessages.length - MAX_BURST_RENDER;
state.pendingChatMessages.splice(0, skipped);
const container = state.container;
if (container) {
const notice = document.createElement("div");
notice.className = "msg-line msg-burst-notice";
notice.style.cssText =
"text-align:center;padding:6px 0;margin:4px 0;font-size:12px;color:#94a3b8;border-top:1px dashed #d1d5db;border-bottom:1px dashed #d1d5db;";
notice.textContent = `⏫ 省略了 ${skipped} 条未读消息`;
container.appendChild(notice);
}
}
const batch = state.pendingChatMessages.splice(0, CHAT_MESSAGE_FLUSH_BATCH_SIZE);
const renderBatch = createChatMessageRenderBatch();
batch.forEach((msg) => appendMessage(msg, renderBatch));
+14 -7
View File
@@ -556,7 +556,7 @@ async function confirmAndBuyItem(item) {
const confirmed = await confirmShopPurchase(confirmMessage);
if (confirmed) {
buyItem(item.id, item.name, item.price, "all", "", quantity);
buyItem(item.id, item.name, item.price, "all", "", quantity, item.type);
}
}
@@ -645,7 +645,7 @@ export function confirmGift() {
}
closeGiftDialog();
buyItem(item.id, item.name, item.price, recipient, message);
buyItem(item.id, item.name, item.price, recipient, message, 1, item.type);
}
/**
@@ -659,7 +659,7 @@ export function confirmGift() {
* @param {number} quantity 购买数量
* @returns {Promise<void>}
*/
export async function buyItem(itemId, name, price, recipient, message, quantity = 1) {
export async function buyItem(itemId, name, price, recipient, message, quantity = 1, itemType = '') {
try {
const response = await fetch(getShopUrls().buy, {
method: "POST",
@@ -675,7 +675,7 @@ export async function buyItem(itemId, name, price, recipient, message, quantity
const data = await response.json();
if (data.status === "success") {
handleBuySuccess(data, name);
handleBuySuccess(data, name, itemType);
return;
}
@@ -692,7 +692,7 @@ export async function buyItem(itemId, name, price, recipient, message, quantity
* @param {string} itemName 商品名称
* @returns {void}
*/
function handleBuySuccess(data, itemName) {
function handleBuySuccess(data, itemName, itemType = '') {
const balance = document.getElementById("shop-jjb");
if (data.jjb !== undefined && balance) {
@@ -717,8 +717,15 @@ function handleBuySuccess(data, itemName) {
shopLoaded = false;
setTimeout(() => {
fetchShopData();
shopLoaded = true;
}, 1000);
}, 300);
// 自动钓鱼卡购买后立即开启自动钓鱼
if (itemType === "auto_fishing" && typeof window.checkAndAutoStartFishing === "function") {
if (!window.chatContext) window.chatContext = {};
window.chatContext.autoFishingMinutesLeft = Number(data.auto_fishing_minutes_left || 1);
window.chatContext.fishingCooldownSeconds = 0;
setTimeout(() => window.checkAndAutoStartFishing(), 500);
}
}
/**