topfans/frontend/pages/square/composables/useDialogRotation.js
2026-04-13 16:16:41 +08:00

85 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ref } from 'vue'
export function useDialogRotation() {
let timer = null
let screenWidth = 375
let screenHeight = 812
const initDialogRotation = ({ screenW, screenH }) => {
screenWidth = screenW
screenHeight = screenH
}
const isCabinInViewport = (cabin) => {
return new Promise((resolve) => {
const query = uni.createSelectorQuery()
query.select(`#cabin-${cabin.key}`).boundingClientRect((rect) => {
if (!rect) {
resolve(false)
return
}
const visibleTop = Math.max(0, rect.top)
const visibleBottom = Math.min(screenHeight, rect.bottom)
const visibleLeft = Math.max(0, rect.left)
const visibleRight = Math.min(screenWidth, rect.right)
const visibleWidth = Math.max(0, visibleRight - visibleLeft)
const visibleHeight = Math.max(0, visibleBottom - visibleTop)
const visibleArea = visibleWidth * visibleHeight
const totalArea = rect.width * rect.height
const visiblePercent = totalArea > 0 ? visibleArea / totalArea : 0
resolve(visiblePercent > 0.7)
}).exec()
})
}
const rotateDialogVisibility = async (cabins) => {
if (!cabins.length) return
// 先全部重置为 false
cabins.forEach(c => c.showDialog = false)
// 筛选符合条件的 cabin有昵称、有展位剩余
const hasData = cabins.filter(c => c.nickname && c.sharedBoothSlotsRemaining !== null)
// 批量检查所有 cabin 是否在可视区域内
const viewportChecks = await Promise.all(hasData.map(c => isCabinInViewport(c)))
const eligible = hasData.filter((c, i) => viewportChecks[i])
if (eligible.length === 0) return
// 随机选择 2-3 个
const count = Math.min(Math.floor(Math.random() * 2) + 2, eligible.length, 3)
const shuffled = eligible.sort(() => Math.random() - 0.5)
for (let i = 0; i < count; i++) {
shuffled[i].showDialog = true
}
}
const startDialogRotation = (cabins) => {
stopDialogRotation()
const rotate = async () => {
await rotateDialogVisibility(cabins)
const interval = Math.floor(Math.random() * 1000) + 2000
timer = setTimeout(rotate, interval)
}
rotate()
}
const stopDialogRotation = () => {
if (timer) {
clearTimeout(timer)
timer = null
}
}
return {
initDialogRotation,
startDialogRotation,
stopDialogRotation,
}
}