liveh5-nuxt/app/pages/liveRoom/index.client.vue

246 lines
7.5 KiB
Vue
Raw Normal View History

<script setup>
import {ref, onMounted, onBeforeUnmount, watch,useTemplateRef } from 'vue'
import AliyunPlayer from 'aliyun-aliplayer'
import 'aliyun-aliplayer/build/skins/default/aliplayer-min.css'
import sideButton from '@/pages/liveRoom/components/SideButton/index.vue'
import broadcast from '@/pages/liveRoom/components/Broadcast/index.vue'
import {liveStore} from "@/stores/live/index.js"
import liveLoading from '@/components/liveLoading/index.vue'
import paymentResults from '@/pages/liveRoom/components/PaymentResults/index.vue'
import paymentInput from '@/pages/liveRoom/components/PaymentInput/index.vue'
import {goodStore} from "@/stores/goods/index.js"
import {message} from "~/components/x-message/useMessage.js"
import {showConfirmDialog} from 'vant';
import {artworkBuy} from "@/api/goods/index.js"
2025-02-12 06:34:05 +00:00
import {useI18n} from 'vue-i18n'
import floating2 from '@/components/floating2/index.vue'
import { useThrottleFn } from '@vueuse/core'
const { t } = useI18n()
const { auctionDetail,getAuctionDetail} = goodStore();
const player = ref(null)
const {quoteStatus, show, playerId, show1, auctionData, getSocketData, getLiveLink, fullLive} = liveStore()
const pullLink = ref('')
const handlePlayerError = (error) => {
showConfirmDialog({
message: t('live_room.error_mess'),
showCancelButton: true
}).then(() => {
initializePlayer()
}).catch(() => {
})
}
const loading1=ref(false)
const initializePlayer = async () => {
try {
if (player.value) {
player.value.dispose()
}
// 判断是否是微信浏览器
const isWechat = /MicroMessenger/i.test(navigator.userAgent)
const playerConfig = {
id: playerId.value,
source: pullLink.value,
isLive: true,
preload: true,
autoplay: true, // 改为 true
muted: true, // 默认静音
diagnosisButtonVisible:false,
// vodRetry:10,
// liveRetry:10,
autoplayPolicy: {
fallbackToMute: true
},
width: '100%', //容器的大小
height: '100%', //容器的大小
skinLayout: false,
controlBarVisibility: 'never',
license: {
domain: "szjixun.cn",
key: "OProxmWaOZ2XVHXLtf4030126521c43429403194970aa8af9"
}
}
player.value = new AliyunPlayer(playerConfig, (playerInstance) => {
// 在微信环境下,需要用户手动触发播放
if (isWechat) {
const startPlay = () => {
playerInstance?.play()
document.removeEventListener('WeixinJSBridgeReady', startPlay)
document.removeEventListener('touchstart', startPlay)
}
document.addEventListener('WeixinJSBridgeReady', startPlay)
document.addEventListener('touchstart', startPlay)
}
loading1.value = true
playerInstance?.play()
})
player.value.on('playing', () => {
loading1.value = false
})
player.value.on('loading', () => {
2025-03-02 03:09:06 +00:00
})
player.value.on('error', handlePlayerError)
} catch (error) {
showConfirmDialog({
message: t('live_room.error_mess'),
showCancelButton: true
}).then(() => {
initializePlayer()
}).catch(() => {
})
2025-03-02 03:09:06 +00:00
}
}
onMounted(async () => {
await getAuctionDetail()
pullLink.value = await getLiveLink()
if (auctionDetail.value.isLiving===1){
initializePlayer()
}
})
onActivated(()=>{
if (auctionDetail.value.isLiving===1){
initializePlayer()
}
})
onBeforeUnmount(() => {
player.value?.dispose()
player.value = null
})
watch(() => fullLive.value, async (newVal) => {
if (!newVal) return
await getSocketData()
})
const goBuy = useThrottleFn(async () => {
const res = await artworkBuy({
auctionArtworkUuid: auctionData.value?.artwork?.uuid,
buyMoney: String(auctionData?.value.nowAuctionPrice?.nowPrice??0)
})
if (res.status === 0) {
message.success(t('live_room.success_mess'))
}
}, 2000)
const sideButtonRef = useTemplateRef('sideButtonRef')
const tipOpen = () => {
message.warning(t('live_room.warn_mess'))
}
</script>
<template>
<div class="relative h-full">
<div :id="playerId" class="w-full h-full"></div>
<div v-if="loading1" class="absolute left-1/2 transform translate-x--1/2 top-1/2 translate-y--1/2">
<van-loading type="spinner" >直播加载中...</van-loading>
</div>
<transition name="fade">
<div v-if="fullLive">
<floating2
:snap-edge="true"
:position="{right:0,top:300}"
>
<sideButton></sideButton>
</floating2>
<div class="absolute left-1/2 transform -translate-x-1/2 flex flex-col items-center"
style="bottom:calc(var(--safe-area-inset-bottom) + 26px)">
<div class="text-16px text-#FFB25F font-600 flex">
<div class="mr-5px">{{ t('live_room.now_price') }}{{ auctionData?.nowAuctionPrice?.currency }}</div>
2025-02-20 11:03:39 +00:00
<div class="min-w-50px">{{auctionData?.nowAuctionPrice?.nowPrice}}</div>
</div>
<div class="text-16px text-#fff font-600 flex">
<div class="mr-5px">{{ t('live_room.lower_price') }}{{ auctionData?.nowAuctionPrice?.currency }}</div>
2025-02-20 11:03:39 +00:00
<div class="min-w-50px">{{auctionData?.nowAuctionPrice?.nextPrice}}</div>
</div>
<div v-if="quoteStatus&&auctionData?.nowAuctionPrice?.nowPrice&&auctionData?.nowAuctionPrice?.nowPrice!=='0'" class="mt-10px mb-10px">
<van-button @click.stop="goBuy" color="#FFB25F" class="w-344px !h-[40px]">
<div>{{
`${t('live_room.confirm')} ${auctionData?.nowAuctionPrice?.currency} ${auctionData?.nowAuctionPrice?.nowPrice ?? 0}`
}}
</div>
</van-button>
</div>
<div v-else class="mt-10px mb-10px">
<van-button @click="tipOpen" color="#D6D6D8" class="w-344px !h-[40px]" >
<div class="text-#7D7D7F text-14px">{{ t('live_room.button') }}</div>
</van-button>
</div>
<broadcast></broadcast>
</div>
<paymentInput v-model:show="show"/>
<div>
</div>
<paymentResults v-model:show="show1" type="error"/>
<div v-if="auctionData?.wsType==='newArtwork'"
class="w-344px h-31px rounded-4px absolute top-9px bg-[#151824]/45 backdrop-blur-[10px] backdrop-saturate-[180%] left-1/2 transform translate-x--1/2 flex text-#fff text-14px items-center px-12px line-height-none">
<div class="mr-11px whitespace-nowrap">LOT{{ auctionData.artwork.index }}</div>
<div class="mr-10px truncate">{{ auctionData.artwork.name }}</div>
<div class="whitespace-nowrap">{{ t('live_room.start') }}</div>
</div>
</div>
</transition>
</div>
</template>
<style scoped lang="scss">
.draggable-card {
z-index: 999999;
padding: 16px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
position: absolute;
cursor: move;
user-select: none;
transition: box-shadow 0.3s;
}
.draggable-card.is-dragging {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}
/* 定义过渡动画 */
.fade-enter-active {
transition: opacity 1s ease;
}
.fade-leave-active {
transition: opacity 0.2s ease;
}
/* 定义进入和离开的状态 */
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
.my-rolling-text {
--van-rolling-text-item-width: 10px;
--van-rolling-text-font-size: 16px;
--van-rolling-text-color: #FFB25F;
}
.my-rolling-text1 {
--van-rolling-text-item-width: 10px;
--van-rolling-text-font-size: 16px;
--van-rolling-text-color: #FFF;
}
:deep(.prism-license-watermark) {
display: none !important;
}
</style>