<script setup> import {ref, onMounted, onBeforeUnmount, watch} 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" import {useI18n} from 'vue-i18n' import {CountUp} from 'countup.js' const { t } = useI18n() const countUpRef = ref(null) const nextPriceRef = ref(null) const { auctionDetail} = goodStore(); const player = ref(null) const {quoteStatus, show, playerId, show1, auctionData, getSocketData, getLiveLink, fullLive} = liveStore() const pullLink = ref('') const handlePlayerError = (error) => { console.error('播放器错误:', error) showConfirmDialog({ message: t('live_room.error_mess'), showCancelButton: true }).then(() => { initializePlayer() }).catch(() => { }) // player.value?.play() } 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', () => { console.log('loading') }) player.value.on('error', handlePlayerError) } catch (error) { showConfirmDialog({ message: t('live_room.error_mess'), showCancelButton: true }).then(() => { initializePlayer() }).catch(() => { }) console.error('播放器初始化失败:', error) } } onMounted(async () => { pullLink.value = await getLiveLink() 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 = 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')) } } 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"> <sideButton class="absolute top-196px right-0 z-999"></sideButton> <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> <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> <div class="min-w-50px">{{auctionData?.nowAuctionPrice?.nextPrice}}</div> </div> <div v-if="quoteStatus&&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"> /* 定义过渡动画 */ .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>