259 lines
7.1 KiB
Vue
259 lines
7.1 KiB
Vue
<script setup>
|
|
import { ref, computed, onMounted, onBeforeUnmount } from "vue"
|
|
import lockClosed from "@/static/images/lockdfd@2x.png"
|
|
import lockOpen from "@/static/images/lock4@2x.png"
|
|
import { liveStore } from "@/stores/live/index.js"
|
|
import xButton from '@/components/x-button/index.vue'
|
|
import tangPopup from './tangPopup.vue'
|
|
import { goodStore } from "@/stores/goods/index.js"
|
|
import { authStore } from "~/stores/auth/index.js"
|
|
import {showMinWindow} from "~/components/liveMinWindow/createMinWindow.js";
|
|
import {hideMinWindow1, showMinWindow1} from "~/components/floatingBubble/floating.js";
|
|
|
|
const { quoteStatus, changeStatus, show, auctionData, getSocketData ,lastSnapshot,fullLive} = liveStore()
|
|
const { pageRef } = goodStore()
|
|
const { userInfo ,payment} = authStore()
|
|
const showTang = ref(false)
|
|
const router = useRouter()
|
|
// 拖动相关状态
|
|
const isDragging = ref(false)
|
|
const startX = ref(0)
|
|
const startY = ref(0)
|
|
const currentTop = ref(196)
|
|
const currentLeft = ref(window.innerWidth - 60)
|
|
const sidebarRef = ref(null)
|
|
|
|
// 限制拖动范围
|
|
const minTop = 0
|
|
const maxTop = window.innerHeight - 180
|
|
const minLeft = 0
|
|
const maxLeft = window.innerWidth - 60
|
|
|
|
// 吸附相关
|
|
const snapThreshold = 30
|
|
const snapPosition = () => {
|
|
const centerX = currentLeft.value + 30
|
|
if (centerX < window.innerWidth / 2) {
|
|
currentLeft.value = 0
|
|
} else {
|
|
currentLeft.value = window.innerWidth - 60
|
|
}
|
|
}
|
|
|
|
// 开始拖动
|
|
const handleMouseDown = (e) => {
|
|
isDragging.value = true
|
|
startX.value = e.clientX - currentLeft.value
|
|
startY.value = e.clientY - currentTop.value
|
|
document.addEventListener('mousemove', handleMouseMove)
|
|
document.addEventListener('mouseup', handleMouseUp)
|
|
}
|
|
|
|
// 拖动中
|
|
const handleMouseMove = (e) => {
|
|
if (!isDragging.value) return
|
|
|
|
let newTop = e.clientY - startY.value
|
|
let newLeft = e.clientX - startX.value
|
|
|
|
// 限制范围
|
|
newTop = Math.max(minTop, Math.min(newTop, maxTop))
|
|
newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft))
|
|
|
|
currentTop.value = newTop
|
|
currentLeft.value = newLeft
|
|
|
|
// 更新位置
|
|
if (sidebarRef.value) {
|
|
sidebarRef.value.style.top = `${newTop}px`
|
|
sidebarRef.value.style.left = `${newLeft}px`
|
|
}
|
|
}
|
|
|
|
// 结束拖动
|
|
const handleMouseUp = () => {
|
|
isDragging.value = false
|
|
snapPosition()
|
|
if (sidebarRef.value) {
|
|
sidebarRef.value.style.left = `${currentLeft.value}px`
|
|
}
|
|
document.removeEventListener('mousemove', handleMouseMove)
|
|
document.removeEventListener('mouseup', handleMouseUp)
|
|
}
|
|
|
|
// 触摸事件处理
|
|
const handleTouchStart = (e) => {
|
|
isDragging.value = true
|
|
startX.value = e.touches[0].clientX - currentLeft.value
|
|
startY.value = e.touches[0].clientY - currentTop.value
|
|
}
|
|
|
|
const handleTouchMove = (e) => {
|
|
if (!isDragging.value) return
|
|
|
|
let newTop = e.touches[0].clientY - startY.value
|
|
let newLeft = e.touches[0].clientX - startX.value
|
|
|
|
newTop = Math.max(minTop, Math.min(newTop, maxTop))
|
|
newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft))
|
|
|
|
currentTop.value = newTop
|
|
currentLeft.value = newLeft
|
|
|
|
if (sidebarRef.value) {
|
|
sidebarRef.value.style.top = `${newTop}px`
|
|
sidebarRef.value.style.left = `${newLeft}px`
|
|
}
|
|
}
|
|
|
|
const handleTouchEnd = () => {
|
|
isDragging.value = false
|
|
snapPosition()
|
|
if (sidebarRef.value) {
|
|
sidebarRef.value.style.left = `${currentLeft.value}px`
|
|
}
|
|
}
|
|
|
|
const captureVideoFrame = () => {
|
|
try {
|
|
const video = document.querySelector('#J_prismPlayer video')
|
|
if (!video) {
|
|
return null
|
|
}
|
|
|
|
const canvas = document.createElement('canvas')
|
|
canvas.width = video.videoWidth
|
|
canvas.height = video.videoHeight
|
|
|
|
const ctx = canvas.getContext('2d')
|
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
|
return canvas.toDataURL('image/jpeg', 0.9)
|
|
} catch (error) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const handleCapture = () => {
|
|
/* const imageUrl = captureVideoFrame()
|
|
if (imageUrl) {
|
|
lastSnapshot.value=imageUrl
|
|
|
|
/!* showMinWindow(lastSnapshot.value,{
|
|
onClick:()=>{
|
|
router.replace('/')
|
|
fullLive.value=true
|
|
}
|
|
})*!/
|
|
}*/
|
|
showMinWindow1({
|
|
onClick:()=>{
|
|
router.replace('/')
|
|
fullLive.value=true
|
|
hideMinWindow1()
|
|
}
|
|
})
|
|
}
|
|
|
|
// 组件挂载时添加事件监听
|
|
onMounted(() => {
|
|
if (sidebarRef.value) {
|
|
sidebarRef.value.style.top = `${currentTop.value}px`
|
|
sidebarRef.value.style.left = `${currentLeft.value}px`
|
|
}
|
|
})
|
|
|
|
// 组件卸载时清理事件监听
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('mousemove', handleMouseMove)
|
|
document.removeEventListener('mouseup', handleMouseUp)
|
|
})
|
|
|
|
const openOne = () => {
|
|
showTang.value = true
|
|
}
|
|
|
|
const paySide = computed(() => {
|
|
//当前是否已成交
|
|
return auctionData.value.needPayBuys?.length>0
|
|
})
|
|
|
|
const goPay = () => {
|
|
payment.value.leftCurrency=auctionData.value.needPayBuys?.[0]?.leftCurrency
|
|
payment.value.leftPrice=auctionData.value.needPayBuys?.[0]?.leftPrice
|
|
payment.value.buyUid=auctionData.value.needPayBuys?.[0]?.uuid
|
|
payment.value.auctionArtworkUuid=auctionData.value.needPayBuys?.[0]?.auctionArtworkUuid
|
|
handleCapture()
|
|
router.push('/signature/protocol')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
ref="sidebarRef"
|
|
class="bg-white w-60px rounded-4px overflow-hidden absolute z-999 cursor-move"
|
|
@mousedown="handleMouseDown"
|
|
@touchstart="handleTouchStart"
|
|
@touchmove="handleTouchMove"
|
|
@touchend="handleTouchEnd"
|
|
>
|
|
<!-- 拍品信息 -->
|
|
<van-button
|
|
class="w-60px !h-60px"
|
|
@click.stop="openOne"
|
|
style="border: none;border-radius: 0"
|
|
>
|
|
<div class="text-center flex flex-col justify-center items-center text-#7D7D7F text-12px">
|
|
<div>{{ $t('live_room.lots') }}</div>
|
|
<div>({{ auctionData?.artwork?.index }}/{{ pageRef.itemCount ?? 0 }})</div>
|
|
</div>
|
|
</van-button>
|
|
|
|
<tangPopup v-model:show="showTang"></tangPopup>
|
|
|
|
<!-- 出价开关 -->
|
|
<van-button
|
|
class="w-60px !h-60px"
|
|
@click.stop="changeStatus"
|
|
style="border-right: none;border-left: none;border-radius: 0;padding: 0"
|
|
>
|
|
<div class="text-center flex flex-col justify-center items-center">
|
|
<div class="mb-4px">
|
|
<img
|
|
:src="quoteStatus ? lockClosed : lockOpen"
|
|
class="w-16px h-21px"
|
|
alt="锁图标"
|
|
/>
|
|
</div>
|
|
<div
|
|
:class="quoteStatus ? 'text-gray-500' : 'text-blue-600'"
|
|
class="text-10px transition-colors duration-200"
|
|
>
|
|
{{ quoteStatus ? $t('live_room.colse_bid') : $t('live_room.start_bid') }}
|
|
</div>
|
|
</div>
|
|
</van-button>
|
|
|
|
<!-- 支付 -->
|
|
<van-button
|
|
v-if="paySide"
|
|
class="w-60px !h-60px"
|
|
style="border: none;border-radius: 0"
|
|
@click.stop="goPay"
|
|
>
|
|
<div class="text-center flex flex-col justify-center items-center text-yellow-600">
|
|
<div class="text-10px">{{auctionData.needPayBuys?.[0]?.leftCurrency}}</div>
|
|
<div class="text-12px">{{auctionData.needPayBuys?.[0]?.leftPrice}}</div>
|
|
<div class="text-10px">{{ $t('art_detail_page.button') }}</div>
|
|
</div>
|
|
</van-button>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.cursor-move {
|
|
cursor: move;
|
|
user-select: none;
|
|
touch-action: none;
|
|
transition: left 0.3s ease;
|
|
}
|
|
</style> |