feat(home): 实现首页直播间全屏功能

- 新增 fullLive 全局状态管理直播间的全屏状态
- 修改 AppHeader组件,根据 fullLive 状态控制返回按钮的显示
- 更新 default 布局,根据 fullLive 状态控制 AppFooter 的显示- 调整 LiveRoom组件,支持全屏模式下的布局变化
- 修改 home 页面,实现直播间全屏和列表之间的切换
This commit is contained in:
xingyy 2025-01-13 20:59:25 +08:00
parent 16bc0d6acc
commit d27e6bc0c5
6 changed files with 184 additions and 137 deletions

View File

@ -1,10 +1,15 @@
<script setup> <script setup>
import { useAppFooterRouteNames as routeWhiteList } from '~/config' import { useAppFooterRouteNames as routeWhiteList } from '~/config'
import { homeStore } from "@/stores/home/index.js";
const { fullLive } = homeStore()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
function onBack() { function onBack() {
if (fullLive.value){
fullLive.value=false
return
}
if (window.history.state.back) if (window.history.state.back)
history.back() history.back()
else else
@ -25,12 +30,13 @@ const subTitle = computed(() => {
return route.meta.subTitle ? t(route.meta.subTitle) : '' return route.meta.subTitle ? t(route.meta.subTitle) : ''
}) })
const showLeftArrow = computed(() => route.name && routeWhiteList.includes(route.name)) const showLeftArrow = computed(() => route.name && routeWhiteList.includes(route.name))
</script> </script>
<template> <template>
<VanNavBar <VanNavBar
:title="title" :title="title"
:left-arrow="!showLeftArrow" :left-arrow="!showLeftArrow||fullLive"
placeholder clickable fixed placeholder clickable fixed
@click-left="onBack" @click-left="onBack"
> >

View File

@ -3,8 +3,7 @@
</script> </script>
<template> <template>
<div class="w-full h-[188px] bg-[] bg-#606165"> <div class="w-full h-full bg-[] bg-#606165">
</div> </div>
</template> </template>

View File

@ -1,13 +1,13 @@
<template> <template>
<main class="flex flex-col min-h-svh"> <main class="flex flex-col min-h-svh">
<AppHeader class="h-[var(--van-nav-bar-height)]" /> <AppHeader class="h-[var(--van-nav-bar-height)]" />
<div class="flex-1 flex flex-col"> <div class="flex-1 flex flex-col">
<slot /> <slot />
</div> </div>
<AppFooter v-if="!fullLive" />
<AppFooter />
</main> </main>
</template> </template>
<script setup lang="ts"> <script setup >
import { homeStore } from "@/stores/home/index.js";
const { fullLive } = homeStore()
</script> </script>

View File

@ -8,7 +8,12 @@ const player = ref(null)
const quoteStatus = ref(false) const quoteStatus = ref(false)
const isPlayerReady = ref(false) const isPlayerReady = ref(false)
const config = useRuntimeConfig() const config = useRuntimeConfig()
console.log('config', config) const props = defineProps({
fullLive: {
type: Boolean,
default: false,
},
})
const playerConfig = { const playerConfig = {
id: 'J_prismPlayer', id: 'J_prismPlayer',
source: 'artc://live-pull-sh-01.szjixun.cn/live/live?auth_key=1736748343-0-0-feef65166e5cc62957c35b6e3eec82a1', source: 'artc://live-pull-sh-01.szjixun.cn/live/live?auth_key=1736748343-0-0-feef65166e5cc62957c35b6e3eec82a1',
@ -56,43 +61,45 @@ onBeforeUnmount(() => {
</script> </script>
<template> <template>
<div class="relative"> <div class="relative h-full" >
<div id="J_prismPlayer" class="w-screen" style="height: calc(100vh - var(--van-nav-bar-height))"></div> <div id="J_prismPlayer" class="w-screen" :style="fullLive?'height: calc(100vh - var(--van-nav-bar-height))':'height:100%'"></div>
<div class="absolute bg-#fff w-60px top-196px right-0 z-999 rounded-l-4px"> <template v-if="fullLive">
<div <div class="absolute bg-#fff w-60px top-196px right-0 z-999 rounded-l-4px">
class="w-full h-60px text-#7D7D7F text-12px flex flex-col justify-center items-center border-b-1px border-b-#D3D3D3"> <div
<div>拍品</div> class="w-full h-60px text-#7D7D7F text-12px flex flex-col justify-center items-center border-b-1px border-b-#D3D3D3">
<div>(1/188)</div> <div>拍品</div>
</div> <div>(1/188)</div>
<div class="w-full h-60px flex flex-col items-center justify-center" @click="changeStatus">
<div class="mb-3px">
<img :src="quoteStatus ? lockdfd : lock4"
class="w-16px h-21px"
alt="">
</div> </div>
<div :class="quoteStatus ? 'text-#7D7D7F' : 'text-#2B53AC'" <div class="w-full h-60px flex flex-col items-center justify-center" @click="changeStatus">
class="text-10px"> <div class="mb-3px">
{{ quoteStatus ? '关闭出价' : '开启出价' }} <img :src="quoteStatus ? lockdfd : lock4"
class="w-16px h-21px"
alt="">
</div>
<div :class="quoteStatus ? 'text-#7D7D7F' : 'text-#2B53AC'"
class="text-10px">
{{ quoteStatus ? '关闭出价' : '开启出价' }}
</div>
</div> </div>
</div> </div>
</div> <div class="absolute top-505px left-1/2 transform -translate-x-1/2 flex flex-col items-center">
<div class="text-16px text-#FFB25F font-600">
当前价RMB
<van-rolling-text class="my-rolling-text" :start-num="0" :target-num="3000" direction="up"/>
</div>
<div class="text-16px text-#fff font-600">
下口价RMB
<van-rolling-text class="my-rolling-text1" :start-num="0" :target-num="3500" direction="up"/>
</div>
<div
:class="`w-344px h-[40px] ${quoteStatus ? 'bg-#FFB25F' : 'bg-#D6D6D8'} rounded-4px ${quoteStatus ? 'text-#fff' : 'text-#7D7D7F'} text-14px flex justify-center items-center mt-10px mb-10px`">
{{ quoteStatus ? '确认出价 RMB 3,000' : '点击"开启出价",即刻参与竞拍 ' }}
</div>
<div class="w-344px h-86px bg-#fff rounded-4px">
</div>
</div>
</template>
<div class="absolute top-505px left-1/2 transform -translate-x-1/2 flex flex-col items-center">
<div class="text-16px text-#FFB25F font-600">
当前价RMB
<van-rolling-text class="my-rolling-text" :start-num="0" :target-num="3000" direction="up"/>
</div>
<div class="text-16px text-#fff font-600">
下口价RMB
<van-rolling-text class="my-rolling-text1" :start-num="0" :target-num="3500" direction="up"/>
</div>
<div
:class="`w-344px h-[40px] ${quoteStatus ? 'bg-#FFB25F' : 'bg-#D6D6D8'} rounded-4px ${quoteStatus ? 'text-#fff' : 'text-#7D7D7F'} text-14px flex justify-center items-center mt-10px mb-10px`">
{{ quoteStatus ? '确认出价 RMB 3,000' : '点击"开启出价",即刻参与竞拍 ' }}
</div>
<div class="w-344px h-86px bg-#fff rounded-4px">
</div>
</div>
</div> </div>
</template> </template>
@ -108,4 +115,7 @@ onBeforeUnmount(() => {
--van-rolling-text-font-size: 16px; --van-rolling-text-font-size: 16px;
--van-rolling-text-color: #FFF; --van-rolling-text-color: #FFF;
} }
:deep(.prism-license-watermark){
display: none!important;
}
</style> </style>

View File

@ -1,9 +1,11 @@
<script setup> <script setup>
import liveBroadcast from '@/components/liveBroadcast/index.vue' import liveBroadcast from '@/components/liveBroadcast/index.vue'
import {useRect} from '@vant/use'; import {useRect} from '@vant/use';
import LiveRoom from '@/pages/LiveRoom/index.client.vue'
import itemDetail from '@/components/itemDetail/index.vue' import itemDetail from '@/components/itemDetail/index.vue'
import { homeStore } from "@/stores/home/index.js";
const { fullLive } = homeStore()
definePageMeta({ definePageMeta({
layout: 'default', layout: 'default',
i18n: 'menu.home', i18n: 'menu.home',
@ -94,120 +96,140 @@ const openShow = () => {
show.value = true show.value = true
}) })
} }
const changeLive=()=>{
fullLive.value= true
}
</script> </script>
<template> <template>
<div class="bg-#fff flex-grow-1"> <div class="bg-#fff flex-grow-1">
<liveBroadcast ref="liveRef"/> <div
<van-tabs sticky animated> ref="liveRef"
<van-tab title="拍品列表"> @click="changeLive"
<div class="px-[16px] pt-[16px]"> :class="[
<van-pull-refresh> 'transform transition-all duration-500 origin-top ease-out ease-in',
<van-list fullLive ? 'scale-100 h-[calc(100vh-var(--van-nav-bar-height))]' : 'scale-100 h-188px'
v-model:loading="loading" ]"
:finished="finished" >
finished-text="没有更多了" <client-only>
@load="loadData" <LiveRoom :fullLive="fullLive" />
> </client-only>
<div class="w-full flex gap-[16px]"> </div>
<div class="flex flex-1 flex-col gap-[16px]"> <div v-show="!fullLive" :class="[
<div 'bg-white transform transition-all duration-500 ease-out',
v-for="(item, index) in leftColumn" fullLive ? 'translate-y-full' : 'translate-y-0'
:key="index" ]">
class="w-full" <van-tabs sticky animated>
@click="openShow" <van-tab title="拍品列表">
> <div class="px-[16px] pt-[16px]">
<div class="relative w-full"> <van-pull-refresh>
<van-image <van-list
:src="item.image" v-model:loading="loading"
:style="{ aspectRatio: item.ratio }" :finished="finished"
fit="cover" finished-text="没有更多了"
class="w-full" @load="loadData"
/> >
<div <div class="w-full flex gap-[16px]">
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]"> <div class="flex flex-1 flex-col gap-[16px]">
LOT{{ index * 2 + 1 }} <div
v-for="(item, index) in leftColumn"
:key="index"
class="w-full"
@click="openShow"
>
<div class="relative w-full">
<van-image
:src="item.image"
:style="{ aspectRatio: item.ratio }"
fit="cover"
class="w-full"
/>
<div
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]">
LOT{{ index * 2 + 1 }}
</div>
</div>
<div class="pt-[8px]">
<div class="text-[14px] text-[#000000] leading-[20px]">
{{ item.title }}
</div>
<div class="mt-[4px] text-[12px] text-[#575757]">
起拍价{{ item.startingPrice }}
</div>
<div
v-if="item.transactionPrice"
class="mt-[4px] text-[12px] text-[#b58047]"
>
成交价{{ item.transactionPrice }}
</div>
</div> </div>
</div> </div>
<div class="pt-[8px]"> </div>
<div class="text-[14px] text-[#000000] leading-[20px]"> <div class="flex flex-1 flex-col gap-[16px]">
{{ item.title }} <div
v-for="(item, index) in rightColumn"
:key="index"
class="w-full"
@click="openShow"
>
<div class="relative w-full">
<van-image
:src="item.image"
:style="{ aspectRatio: item.ratio }"
fit="cover"
class="w-full"
/>
<div
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]">
LOT{{ index * 2 + 2 }}
</div>
</div> </div>
<div class="mt-[4px] text-[12px] text-[#575757]"> <div class="pt-[8px]">
起拍价{{ item.startingPrice }} <div class="text-[14px] text-[#000000] leading-[20px]">
</div> {{ item.title }}
<div </div>
v-if="item.transactionPrice" <div class="mt-[4px] text-[12px] text-[#575757]">
class="mt-[4px] text-[12px] text-[#b58047]" 起拍价{{ item.startingPrice }}
> </div>
成交价{{ item.transactionPrice }} <div
v-if="item.transactionPrice"
class="mt-[4px] text-[12px] text-[#b58047]"
>
成交价{{ item.transactionPrice }}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="flex flex-1 flex-col gap-[16px]"> </van-list>
<div </van-pull-refresh>
v-for="(item, index) in rightColumn"
:key="index"
class="w-full"
@click="openShow"
>
<div class="relative w-full">
<van-image
:src="item.image"
:style="{ aspectRatio: item.ratio }"
fit="cover"
class="w-full"
/>
<div
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]">
LOT{{ index * 2 + 2 }}
</div>
</div>
<div class="pt-[8px]">
<div class="text-[14px] text-[#000000] leading-[20px]">
{{ item.title }}
</div>
<div class="mt-[4px] text-[12px] text-[#575757]">
起拍价{{ item.startingPrice }}
</div>
<div
v-if="item.transactionPrice"
class="mt-[4px] text-[12px] text-[#b58047]"
>
成交价{{ item.transactionPrice }}
</div>
</div>
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</van-tab>
<van-tab title="拍卖说明">
<div class="px-16px pt-14px">
<div class="text-#575757 text-14px">
这里是后台富文本配置的说明啊即可打开三等奖撒度老师的湿答答是快乐的阿四大皆空
</div> </div>
<div></div> </van-tab>
<van-tab title="拍卖说明">
<div class="px-16px pt-14px">
<div class="text-#575757 text-14px">
这里是后台富文本配置的说明啊即可打开三等奖撒度老师的湿答答是快乐的阿四大皆空
</div>
<div></div>
</div>
</van-tab>
</van-tabs>
<van-back-top right="15vw" bottom="10vh"/>
<van-action-sheet :round="false" v-model:show="show" title="拍品详情">
<div class="content bg-[#F0F0F0]" :style="`height: calc(100vh - ${showHeight+85}px)`">
<itemDetail></itemDetail>
</div> </div>
</van-tab> </van-action-sheet>
</van-tabs> </div>
<van-back-top right="15vw" bottom="10vh"/>
<van-action-sheet :round="false" v-model:show="show" title="拍品详情">
<div class="content bg-[#F0F0F0]" :style="`height: calc(100vh - ${showHeight+85}px)`">
<itemDetail></itemDetail>
</div>
</van-action-sheet>
</div> </div>
</template> </template>
<style> <style>
:root:root { :root:root {
--van-action-sheet-header-height: 39px; --van-action-sheet-header-height: 39px;
} }
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
:deep(.van-swipe__indicator) { :deep(.van-swipe__indicator) {
width: 8px; width: 8px;
@ -218,3 +240,6 @@ const openShow = () => {
background: rgba(0, 0, 0, 0.8); background: rgba(0, 0, 0, 0.8);
} }
</style> </style>
<style scoped>
</style>

7
app/stores/home/index.js Normal file
View File

@ -0,0 +1,7 @@
import { createGlobalState } from '@vueuse/core'
export const homeStore = createGlobalState(() => {
const fullLive=ref(false)
return{
fullLive
}
})