Files
thebet365/apps/player/src/composables/useDesktopBetPopover.ts
Mars 8000c23418 fix(player): 优化桌面快速下注 hover 并修复充值 API 重复方法
删除 deposit.service 中重复的 getPlayerDepositOrder,避免 API 编译失败引发 500;快速下注弹层按卡片实例激活,同场赛事不再多处联动,移入快速下注区域时保持 VS 动画;记录列表改为整行可点,编号统一中性色样式。
2026-07-02 11:12:36 +08:00

102 lines
2.8 KiB
TypeScript

import { ref } from 'vue';
import type { SlipItem } from '../stores/betSlip';
const visible = ref(false);
const anchorX = ref(0);
const anchorY = ref(0);
const pendingItem = ref<SlipItem | null>(null);
const activeCardRootId = ref<string | null>(null);
const placement = ref<'top' | 'bottom'>('bottom');
let closeTimer: number | undefined = undefined;
export function useDesktopBetPopover() {
function openAt(event: MouseEvent, item: SlipItem) {
cancelClose();
const el = (event.currentTarget || event.target) as HTMLElement;
const btn = el?.closest?.('button') || el;
const rect = btn?.getBoundingClientRect?.();
if (!rect) return;
const popW = 190;
const popH = 170;
const pad = 12; // increased pad to leave space for the arrow pointer
// Calculate center X of the button
const btnCenterX = rect.left + rect.width / 2;
let x = btnCenterX - popW / 2;
// Default: place below button (center bottom)
let y = rect.bottom + pad;
placement.value = 'bottom';
if (typeof window !== 'undefined') {
const spaceBelow = window.innerHeight - rect.bottom;
if (spaceBelow < popH + pad) {
// Not enough space below, place above button (center top)
y = rect.top - popH - pad;
placement.value = 'top';
}
// Keep within viewport boundaries
x = Math.max(pad, Math.min(x, window.innerWidth - popW - pad));
y = Math.max(pad, Math.min(y, window.innerHeight - popH - pad));
}
anchorX.value = x;
anchorY.value = y;
pendingItem.value = item;
const root = el?.closest?.('[data-bet-card-root]') as HTMLElement | null;
activeCardRootId.value = root?.dataset.betCardRoot ?? null;
visible.value = true;
}
function close() {
visible.value = false;
pendingItem.value = null;
activeCardRootId.value = null;
if (closeTimer !== undefined) {
window.clearTimeout(closeTimer);
closeTimer = undefined;
}
}
function scheduleClose(delay = 200) {
if (closeTimer !== undefined) {
window.clearTimeout(closeTimer);
}
closeTimer = window.setTimeout(() => {
visible.value = false;
pendingItem.value = null;
activeCardRootId.value = null;
closeTimer = undefined;
}, delay);
}
function cancelClose() {
if (closeTimer !== undefined) {
window.clearTimeout(closeTimer);
closeTimer = undefined;
}
}
function isActiveForCard(cardRootId: string | null | undefined) {
if (!cardRootId || !visible.value || !pendingItem.value) return false;
return activeCardRootId.value === cardRootId;
}
return {
visible,
anchorX,
anchorY,
pendingItem,
activeCardRootId,
placement,
openAt,
close,
scheduleClose,
cancelClose,
isActiveForCard,
};
}