469 lines
12 KiB
Vue
469 lines
12 KiB
Vue
<template>
|
|
<div ref="rootRef" class="video-detail-wrap">
|
|
<SvgIcon name="back_white_round" class="back" @click="$router.go(-1)" />
|
|
<template v-if="state.info.id">
|
|
<div class="movieBox">
|
|
<div class="videoAdv" v-if="state.advsList?.length && state.isShowAdv">
|
|
<div class="advVideoBox">
|
|
<AdvSwiper :list="state.advsList" :autoplay="2000" v-if="state.advsList.length" class="adv" />
|
|
<div class="timer_close" v-if="isVip">
|
|
<div v-if="state.timer > 0">
|
|
{{ state.timer }}s |
|
|
<span @click="state.isShowAdv = false">关闭广告</span>
|
|
</div>
|
|
<div v-else><span @click="state.isShowAdv = false">关闭</span></div>
|
|
</div>
|
|
<div class="timer_close" v-else>
|
|
<div v-if="state.timer > 0">
|
|
{{ state.timer }}s |
|
|
<span @click="vipJump">VIP可关闭广告</span>
|
|
</div>
|
|
<div v-else><span @click="state.isShowAdv = false">关闭</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<template v-else>
|
|
<AnimationHorizontalVideoInfo
|
|
:videoInfo="currentItem"
|
|
:mediaInfo="state.info"
|
|
v-if="currentItem?.videoUrl && showVideo"
|
|
:key="currentItem?.episodeNumber"
|
|
@buySuccess="beforeBuySuccess"
|
|
/>
|
|
</template>
|
|
</div>
|
|
<CountdownBanner
|
|
@openMemberPay="showPaymentStatusPopup = true"
|
|
/>
|
|
<div class="changeLineBox flex-vcenter" :class="!isVip ? 'top258' : ''">
|
|
<div class="flex-vcenter" @click.stop="openChangeRoadLine">
|
|
<SvgIcon name="changeLineIcon" />
|
|
<span>线路切换</span>
|
|
</div>
|
|
</div>
|
|
<van-tabs
|
|
v-model:active="tabActive"
|
|
:animated="true"
|
|
@rendered="onTabRendered"
|
|
class="tabs"
|
|
:class="{ newUser: !isVip }"
|
|
>
|
|
<van-tab :title="item.label" v-for="item in itemList" :key="item.value" :name="prefixKey + item.value">
|
|
<template v-slot:title>
|
|
{{ item.label }}
|
|
<Teleport to=".van-tabs__nav">
|
|
<span v-if="item.value === 2" class="countComment" :class="{ active: tabActive === prefixKey + 2 }">
|
|
{{ watchCount(state.info.countComment) }}
|
|
</span>
|
|
</Teleport>
|
|
</template>
|
|
<!--
|
|
@selectEpisode="selectEpisode" -->
|
|
<Introduction
|
|
v-if="tabIsInit(prefixKey + item.value) && item.value == 1 && state.info.id"
|
|
ref="introductionRef"
|
|
:info="state.info"
|
|
@updateCollected="updateCollected"
|
|
@updateLiked="updateLiked"
|
|
@updateItem="updateItem"
|
|
></Introduction>
|
|
<CommentBox
|
|
v-else-if="tabIsInit(prefixKey + item.value) && item.value == 2 && state.info.id"
|
|
:id="prefixKey + item.value"
|
|
ref="dvComment"
|
|
:isOpen="true"
|
|
renderType="normal"
|
|
objType="cartoon"
|
|
theme="black"
|
|
class="comment-comp"
|
|
@addComment="state.info.countComment += 1"
|
|
:showCollected="false"
|
|
></CommentBox>
|
|
</van-tab>
|
|
</van-tabs>
|
|
</template>
|
|
<Loading v-else />
|
|
</div>
|
|
<!-- 切换路线框 -->
|
|
<SelectionLinePopup :is-open="showChangeRoadLine" @closeSelectLine="closeSelectLine" @close="closeChangeRoadLine" />
|
|
<!-- 开通会员 -->
|
|
<PaymentStatusPopup
|
|
:show="showPaymentStatusPopup"
|
|
:video-id="String(state.info?.id || '')"
|
|
@close="closePaymentStatusPopup"
|
|
/>
|
|
</template>
|
|
<script lang="ts">
|
|
export default {
|
|
name: 'AcgVideoDetail',
|
|
};
|
|
</script>
|
|
<script lang="ts" setup>
|
|
import { ref, onUnmounted, nextTick, provide, computed, toRaw, watch, Ref, onMounted, defineAsyncComponent } from 'vue';
|
|
import { HistoryVideoType, AdType } from '@/enums/app';
|
|
import mediaInfo from '../utils/mediaInfo';
|
|
import { useUserStore } from '@/stores/user';
|
|
import MineApi from '@/service/mine';
|
|
import { watchCount } from '@/utils/index';
|
|
// import { Pay_emit } from '../utils/pay-mitt';
|
|
import type { PayInfo } from '../utils/pay-mitt';
|
|
import Introduction from './components/introduction.vue';
|
|
import tabAction from '@/utils/tabAction';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { getAdItem } from '@/utils/getConfig';
|
|
import CountdownBanner from '@/components/CountdownBanner/index.vue';
|
|
|
|
const PaymentStatusPopup = defineAsyncComponent(() => import('@/components/paymentStatusPopup/index.vue'));
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const currentItem = ref({}) as Ref<Types.Acg.MediaContentListItem>;
|
|
const itemList = [
|
|
{
|
|
label: '简介',
|
|
value: 1,
|
|
},
|
|
{
|
|
label: '评论',
|
|
value: 2,
|
|
},
|
|
];
|
|
const showPaymentStatusPopup = ref(false);
|
|
const closePaymentStatusPopup = () => {
|
|
showPaymentStatusPopup.value = false;
|
|
};
|
|
const prefixKey = 'acg_video_';
|
|
const { tabActive, tabIsInit, onTabRendered } = tabAction(true);
|
|
|
|
const { isVip } = useUserStore();
|
|
|
|
const showVideo = ref(true);
|
|
const { state, historyData, addHistory } = mediaInfo({ dbType: HistoryVideoType.AcgVideo });
|
|
|
|
provide('historyData', historyData);
|
|
|
|
const showChangeRoadLine = ref(false);
|
|
// ------------------- 广告相关逻辑完善 -------------------
|
|
const vipJump = () => {
|
|
router.push('/member');
|
|
};
|
|
|
|
// 获取广告
|
|
const getRandomAdv = () => {
|
|
state.advsList = <any>[];
|
|
let advs = getAdItem(AdType.NEW_FREE_VIDEO).filter((item: any) => item.watchTime > 0);
|
|
if (advs.length > 0) {
|
|
state.advsList = advs;
|
|
if (!(isVip || historyData.value?.mediaStatus?.hasPaid)) {
|
|
state.isShowAdv = true;
|
|
return;
|
|
}
|
|
}
|
|
state.isShowAdv = false;
|
|
};
|
|
|
|
// 倒计时
|
|
const countdown = () => {
|
|
let advs = getAdItem(AdType.NEW_FREE_VIDEO);
|
|
if (advs && advs.length) {
|
|
state.timer = getAdItem(AdType.NEW_FREE_VIDEO)[0].watchTime;
|
|
} else {
|
|
state.timer = 0;
|
|
}
|
|
if (state.countdowner) {
|
|
clearInterval(state.countdowner);
|
|
}
|
|
state.countdowner = setInterval(() => {
|
|
state.timer--;
|
|
if (state.timer <= 0) {
|
|
clearInterval(state.countdowner);
|
|
state.countdowner = null;
|
|
}
|
|
}, 1000);
|
|
};
|
|
onUnmounted(() => {
|
|
state.countdowner && clearInterval(state.countdowner);
|
|
});
|
|
// 只在动漫数据获取到后再处理广告
|
|
watch(
|
|
() => currentItem.value,
|
|
(val) => {
|
|
if (val) {
|
|
getRandomAdv();
|
|
if (state.advsList.length > 0) {
|
|
countdown();
|
|
}
|
|
}
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
const openChangeRoadLine = () => {
|
|
showChangeRoadLine.value = true;
|
|
};
|
|
const closeChangeRoadLine = () => {
|
|
showChangeRoadLine.value = false;
|
|
};
|
|
|
|
// 关闭线路选择
|
|
const closeSelectLine = () => {
|
|
showVideo.value = false;
|
|
showChangeRoadLine.value = false;
|
|
nextTick(() => {
|
|
showVideo.value = true;
|
|
});
|
|
};
|
|
|
|
const dvComment = ref();
|
|
|
|
const initComment = () => {
|
|
dvComment.value[0].state.videoInfo = toRaw(state.info);
|
|
dvComment.value[0].getCommentList();
|
|
};
|
|
|
|
watch(
|
|
dvComment,
|
|
(el) => {
|
|
if (!el) return;
|
|
initComment();
|
|
},
|
|
{
|
|
once: true,
|
|
},
|
|
);
|
|
const updateCollected = (collected: boolean) => {
|
|
state.info.mediaStatus.hasCollected = collected;
|
|
state.info.countCollect = state.info.countCollect + (collected ? +1 : -1);
|
|
};
|
|
|
|
const updateLiked = (liked: boolean) => {
|
|
state.info.mediaStatus.hasLiked = liked;
|
|
state.info.countLike = state.info.countLike + (liked ? +1 : -1);
|
|
};
|
|
|
|
const updateItem = (item: any) => {
|
|
currentItem.value = item;
|
|
if (route.query.tabActive) {
|
|
tabActive.value = (prefixKey + route.query.tabActive) as string;
|
|
}
|
|
};
|
|
|
|
const introductionRef = ref();
|
|
const beforeBuySuccess = (obj: PayInfo) => {
|
|
if (obj.type === 'all') {
|
|
state.info.mediaStatus.hasPaid = true;
|
|
historyData.value.mediaStatus.hasPaid = true;
|
|
addHistory(Number(route.query.episodeNumber || 1));
|
|
}
|
|
introductionRef.value[0].buySuccess(obj.type);
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.video-detail-wrap {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
.back {
|
|
width: 24px;
|
|
height: 24px;
|
|
flex-shrink: 0;
|
|
position: fixed;
|
|
top: 16px;
|
|
left: 16px;
|
|
z-index: 800;
|
|
}
|
|
|
|
.movieBox {
|
|
width: 375px;
|
|
height: 212px;
|
|
position: sticky;
|
|
top: 0;
|
|
left: 0;
|
|
//margin-left: -6px;
|
|
z-index: 2;
|
|
.videoAdv {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 99999;
|
|
width: 100%;
|
|
height: 212px;
|
|
background: rgba(0, 0, 0, 1);
|
|
.advVideoBox {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
z-index: 10;
|
|
.timer_close {
|
|
font-size: 12px;
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
z-index: 10;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
padding: 4px 12px;
|
|
border-radius: 40px;
|
|
color: white;
|
|
|
|
// span {
|
|
// color: #ff7f0f;
|
|
// }
|
|
}
|
|
|
|
.adv {
|
|
height: 211px;
|
|
width: 375px;
|
|
overflow: hidden;
|
|
:deep(.van-swipe-item) {
|
|
height: 211px !important;
|
|
width: 375px !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.newUserBg {
|
|
height: 46px;
|
|
background: url('@/assets/images/png/newUserBg.png') no-repeat;
|
|
background-size: 100% 100%;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
padding-left: 98px;
|
|
padding-right: 9px;
|
|
color: #fff;
|
|
&.noNewUser {
|
|
// background-image: url('@/assets/images/png/newUserBg2.png');
|
|
background-image: url('@/assets/images/png/newUserBg.png');
|
|
}
|
|
.nowOpenBtn {
|
|
color: #000;
|
|
background: linear-gradient(270deg, #e3b284 0%, #feeede 100%);
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
font-size: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
margin-left: 4px;
|
|
}
|
|
}
|
|
}
|
|
.changeLineBox {
|
|
position: absolute;
|
|
top: 212px;
|
|
right: 16px;
|
|
z-index: 2;
|
|
height: 44px;
|
|
width: 100px;
|
|
justify-content: flex-end;
|
|
|
|
color: #989898;
|
|
font-size: 12px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
margin-right: 4px;
|
|
}
|
|
}
|
|
.countComment {
|
|
position: absolute;
|
|
top: 12px;
|
|
left: 112px;
|
|
color: rgba(255, 255, 255, 0.45);
|
|
font-size: 12px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 18px; /* 150% */
|
|
&.active {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
}
|
|
}
|
|
.tabs {
|
|
--van-tab-active-text-color: rgba(255, 255, 255, 0.9);
|
|
--van-tab-text-color: rgba(255, 255, 255, 0.45);
|
|
height: calc(100% - 269px + 11px);
|
|
:deep(> .van-tabs__wrap) {
|
|
background-color: unset;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
.van-tabs__nav {
|
|
background: unset;
|
|
.van-tab {
|
|
font-size: 14px;
|
|
padding: unset;
|
|
width: 60px;
|
|
flex: unset;
|
|
}
|
|
|
|
.van-tabs__line {
|
|
background-color: $themeColor;
|
|
height: 4px;
|
|
width: 16px;
|
|
border-radius: 2px 2px 0 0;
|
|
}
|
|
}
|
|
}
|
|
:deep(> .van-tabs__content) {
|
|
height: calc(100% - 44px);
|
|
overflow-x: hidden;
|
|
.van-tab__panel {
|
|
height: 100%;
|
|
max-width: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
}
|
|
&.newUser {
|
|
height: calc(100% - 269px + 11px);
|
|
}
|
|
}
|
|
|
|
.comment-comp {
|
|
height: 100%;
|
|
:deep(.comment-wrap) {
|
|
height: 100%;
|
|
.wrapper {
|
|
height: 100%;
|
|
}
|
|
.headerBox {
|
|
display: none;
|
|
}
|
|
.slider {
|
|
display: none;
|
|
}
|
|
.main {
|
|
background: transparent;
|
|
// border-top: 1px solid #e0e0e0;
|
|
height: 100%;
|
|
}
|
|
.bottomBox {
|
|
position: sticky;
|
|
left: 0;
|
|
bottom: 0;
|
|
.commentBtnBox {
|
|
.commentInput {
|
|
padding-left: 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.top258 {
|
|
top: 258px !important;
|
|
}
|
|
:deep(.adv_swiper) {
|
|
border-radius: unset !important;
|
|
.adv-container {
|
|
.adv-swiper-slide {
|
|
border-radius: unset !important;
|
|
.cover {
|
|
border-radius: unset !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|