483 lines
12 KiB
Vue
483 lines
12 KiB
Vue
<template>
|
|
<div class="introduction-wrap overflow-y-auto">
|
|
<div class="titleBox ellipsis2">
|
|
{{ props.info.title }}
|
|
</div>
|
|
<div class="tags">
|
|
<span
|
|
class="tag"
|
|
@click="goAcgTagPage(item.id, item.name, 'video')"
|
|
v-for="item in info.tagDetails || []"
|
|
:key="item.id"
|
|
>
|
|
#{{ item.name }}
|
|
</span>
|
|
</div>
|
|
<div class="videoInfoBox flex-vcenter">
|
|
<div class="item margin-r-88">
|
|
<span>{{ watchCount(props.info.countBrowse) }} 观看量</span>
|
|
</div>
|
|
<div class="item" @click="onToogleLiked">
|
|
<span
|
|
class="acg-action-icon acg-action-icon--like"
|
|
:class="{ active: props.info.mediaStatus.hasLiked }"
|
|
aria-hidden="true"
|
|
/>
|
|
<span>{{ props.info.mediaStatus.hasLiked ? watchCount(props.info.countLike) : '点赞' }}</span>
|
|
</div>
|
|
<div class="item" @click="onToogleCollected">
|
|
<span
|
|
class="acg-action-icon acg-action-icon--collect"
|
|
:class="{ active: props.info.mediaStatus.hasCollected }"
|
|
aria-hidden="true"
|
|
/>
|
|
<span>{{ props.info.mediaStatus.hasCollected ? watchCount(props.info.countCollect) : '收藏' }}</span>
|
|
</div>
|
|
<div class="item" @click="openShare">
|
|
<img class="acg-share-icon" src="@/assets/images/ui/long-video-share.svg" width="24" height="24" alt="" />
|
|
<span>分享</span>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="actress-box flex-center-between"
|
|
v-if="props.info.actress && props.info.actress.id"
|
|
@click="
|
|
$router.push({
|
|
name: 'AcgActress',
|
|
query: {
|
|
id: props.info.actress.id,
|
|
},
|
|
})
|
|
"
|
|
>
|
|
<lazyImg class="portrait" :src="props.info.actress.portrait"></lazyImg>
|
|
<div class="info">
|
|
<p class="name">{{ props.info.actress.name }}</p>
|
|
<div class="count-box flex-vcenter">
|
|
<SvgIcon name="acg-video-icon-a-video" />
|
|
{{ watchCount(props.info.actress.acgCount) }}部
|
|
<SvgIcon name="acg-video-icon-a-collect" style="margin-left: 12px" />
|
|
{{ watchCount(props.info.actress.collectCount) }}
|
|
</div>
|
|
</div>
|
|
<SvgIcon class="icon" name="moreIcon" />
|
|
</div>
|
|
<!-- 选集区域 -->
|
|
<div class="episodeArea">
|
|
<div class="episodeHeader flex-center-between padding16">
|
|
<div class="episodeTitle">选集</div>
|
|
<div class="episodeAll flex-vcenter" @click="visibleCatalogue = true">
|
|
全{{ props.info.totalEpisode }}话
|
|
<SvgIcon class="icon" name="moreIcon" />
|
|
</div>
|
|
</div>
|
|
<div class="episodeBox" @touchstart.stop @touchmove.stop @touchend.stop>
|
|
<Episode
|
|
class="item"
|
|
@click="switchEpisodeNumberCatalogue(item)"
|
|
v-for="item in autoList"
|
|
:key="item.id"
|
|
:info="item"
|
|
:episode-number="state.episodeNumber"
|
|
></Episode>
|
|
</div>
|
|
</div>
|
|
<HomeHeader :advType="AdType.VIDEOADV" />
|
|
<!-- <RecommendList
|
|
:media-id="props.info.id"
|
|
:contentType="props.info.mediaType"
|
|
title="猜你喜欢"
|
|
:marginHide="true"
|
|
></RecommendList> -->
|
|
<RecommendedList :type="info.mediaType" :tagId="info.tagDetails?.[0]?.id" />
|
|
<!-- 分享弹窗 -->
|
|
<AppSharePopup
|
|
:is-open="visibleShare"
|
|
@close="visibleShare = false"
|
|
coverType="portrait"
|
|
:cover="props.info.verticalCover || props.info.horizontalCover"
|
|
/>
|
|
|
|
<Teleport to=".video-detail-wrap">
|
|
<van-popup v-model:show="visibleCatalogue" position="bottom" z-index="1001" :style="{ height: '438px' }">
|
|
<div class="play-list-box">
|
|
<div class="line"></div>
|
|
<div class="title flex-center-between">
|
|
剧集列表
|
|
<!-- <span @click="sort = !sort">
|
|
{{ sort ? '正序' : '倒序' }}
|
|
</span> -->
|
|
</div>
|
|
<div class="grading-group" v-if="gradingGroup.length > 1">
|
|
<div
|
|
class="grading-group-item"
|
|
v-for="(item, index) in gradingGroup"
|
|
:key="index"
|
|
@click.stop="state.gradingGroupIndex = index"
|
|
>
|
|
{{ item[0].episodeNumber }}-{{ item[item.length - 1].episodeNumber }}
|
|
</div>
|
|
</div>
|
|
<div class="list-box overflow-y-auto">
|
|
<PullRefresh :params="moreParams" @onLoad="onLoad" @onRefresh="onRefresh">
|
|
<div class="list">
|
|
<Episode
|
|
class="item"
|
|
:episodeNumber="state.episodeNumber"
|
|
:info="item"
|
|
v-for="item in gradingGroup[state.gradingGroupIndex]"
|
|
:key="item.id"
|
|
@click="state.episodeNumber = item.episodeNumber"
|
|
></Episode>
|
|
</div>
|
|
</PullRefresh>
|
|
</div>
|
|
</div>
|
|
</van-popup>
|
|
</Teleport>
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import { ref, watch, computed, watchEffect, Ref } from 'vue';
|
|
import { HistoryVideoType } from '@/enums/app';
|
|
import { goAcgTagPage } from '../../utils/common';
|
|
import { watchCount, videoTime } from '@/utils/index';
|
|
// import RecommendList from '../../components/recommendList.vue';
|
|
import { handleCollected, Collected_emit } from '../../utils/collect';
|
|
import { AdType } from '@/enums/app';
|
|
import mediaContentInfo from '../../utils/mediaContentInfo';
|
|
import CommunityApi from '@/service/community';
|
|
import { useGlobalStore } from '@/stores/global';
|
|
import Episode from '../../components/episode.vue';
|
|
const emits = defineEmits(['updateLiked', 'updateCollected', 'updateItem', 'openRoadLine']);
|
|
const globalStore = useGlobalStore();
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
info: Types.Media.MediaInfo;
|
|
}>(),
|
|
{
|
|
info: {},
|
|
},
|
|
);
|
|
|
|
const {
|
|
state,
|
|
currentItem,
|
|
autoList,
|
|
// switchEpisodeNumberCatalogue,
|
|
visibleCatalogue,
|
|
sort,
|
|
moreParams,
|
|
onLoad,
|
|
onRefresh,
|
|
getList,
|
|
buySuccess,
|
|
replaceRouter,
|
|
} = mediaContentInfo({
|
|
isGetInfo: false,
|
|
isGetHistoryInit: true,
|
|
pageSize: 30,
|
|
dbType: HistoryVideoType.AcgVideo,
|
|
isScrollTop: false,
|
|
});
|
|
const gradingGroup = computed(() => {
|
|
let arr = autoList.value || [];
|
|
if (arr.length > 30) {
|
|
const result = [];
|
|
for (let i = 0; i < arr.length; i += 30) {
|
|
result.push(arr.slice(i, i + 30));
|
|
}
|
|
return result;
|
|
}
|
|
return [arr];
|
|
});
|
|
watch(
|
|
() => currentItem.value.id,
|
|
() => {
|
|
emits('updateItem', currentItem.value);
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
defineExpose({
|
|
buySuccess,
|
|
});
|
|
const switchEpisodeNumberCatalogue = (item: Types.Acg.MediaContentListItem) => {
|
|
visibleCatalogue.value = false;
|
|
state.episodeNumber = item.episodeNumber;
|
|
replaceRouter(item.episodeNumber);
|
|
};
|
|
|
|
// 打开分享
|
|
const visibleShare = ref(false);
|
|
const openShare = () => {
|
|
const { id, verticalCover, horizontalCover } = props.info;
|
|
let obj = {
|
|
id,
|
|
cover: verticalCover || horizontalCover,
|
|
};
|
|
// globalStore.setShareInfo(obj);
|
|
visibleShare.value = true;
|
|
};
|
|
const onToogleCollected = () => {
|
|
try {
|
|
const {
|
|
id,
|
|
mediaStatus: { hasCollected },
|
|
} = props.info;
|
|
const tempIsCollect = !hasCollected;
|
|
handleCollected(id, tempIsCollect).then(() => {
|
|
emits('updateCollected', tempIsCollect);
|
|
Collected_emit(id, tempIsCollect);
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
};
|
|
|
|
const onToogleLiked = () => {
|
|
const zan = !props.info.mediaStatus.hasLiked;
|
|
(zan ? CommunityApi.zan : CommunityApi.cancleZan)(
|
|
zan
|
|
? {
|
|
type: 'video',
|
|
objID: props.info.id,
|
|
}
|
|
: {
|
|
type: 'video',
|
|
objIDs: [props.info.id],
|
|
},
|
|
).then(() => {
|
|
emits('updateLiked', zan);
|
|
});
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
@import '@/assets/styles/mixins.scss';
|
|
.introduction-wrap {
|
|
height: 100%;
|
|
padding: 0 16px;
|
|
color: var(--app-text-primary);
|
|
.titleBox {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
line-height: 22px;
|
|
margin: 18px 0;
|
|
}
|
|
|
|
.tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px 10px;
|
|
margin: 10px 0 14px;
|
|
.tag {
|
|
padding: 4px 8px;
|
|
border-radius: 3px;
|
|
background: rgba(255, 255, 255, 0.05);
|
|
color: var(--app-text-primary);
|
|
font-size: 12px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 18px; /* 150% */
|
|
}
|
|
}
|
|
|
|
.videoInfoBox {
|
|
color: #989898;
|
|
font-size: 12px;
|
|
font-weight: 400;
|
|
margin: 10px 0 18px;
|
|
justify-content: space-between;
|
|
|
|
.item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.acg-action-icon {
|
|
display: inline-block;
|
|
width: 24px;
|
|
height: 24px;
|
|
margin-right: 4px;
|
|
flex-shrink: 0;
|
|
background-color: #989898;
|
|
|
|
&--like {
|
|
mask: url('@/assets/images/ui/long-video-like.svg') center / contain no-repeat;
|
|
}
|
|
|
|
&--collect {
|
|
mask: url('@/assets/images/ui/long-video-collect.svg') center / contain no-repeat;
|
|
}
|
|
|
|
&.active {
|
|
background-color: #f52c56;
|
|
}
|
|
}
|
|
|
|
.acg-share-icon {
|
|
width: 24px;
|
|
height: 24px;
|
|
margin-right: 4px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
> span {
|
|
color: #989898;
|
|
}
|
|
}
|
|
}
|
|
.actress-box {
|
|
height: 60px;
|
|
margin: 24px 0;
|
|
.portrait {
|
|
width: 60px;
|
|
height: 60px;
|
|
flex-shrink: 0;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
margin-right: 12px;
|
|
}
|
|
.info {
|
|
flex: 1;
|
|
.name {
|
|
color: var(--app-text-primary);
|
|
font-size: 14px;
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
line-height: normal;
|
|
margin-bottom: 5px;
|
|
}
|
|
.count-box {
|
|
color: var(--app-text-secondary);
|
|
font-size: 12px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 18px; /* 150% */
|
|
svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
margin-right: 4px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.episodeArea {
|
|
margin-bottom: 14px;
|
|
border-top: 0.5px solid rgba(255, 255, 255, 0.1);
|
|
border-bottom: 0.5px solid rgba(255, 255, 255, 0.1);
|
|
padding-top: 10px;
|
|
.episodeHeader {
|
|
font-weight: 500;
|
|
.episodeTitle {
|
|
font-size: 16px;
|
|
}
|
|
.episodeAll {
|
|
color: var(--app-text-secondary);
|
|
font-size: 12px;
|
|
svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.episodeBox {
|
|
display: flex;
|
|
overflow-x: auto;
|
|
margin: 12px 0;
|
|
.item {
|
|
margin-right: 12px;
|
|
flex-shrink: 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.play-list-box {
|
|
$paddingBottom: 38px;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 20px 20px 0px 0px;
|
|
background: var(--app-background);
|
|
padding: 18px 16px $paddingBottom;
|
|
@include SafeArea('padding', 'bottom', 0);
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
color: var(--app-text-primary);
|
|
font-size: 12px;
|
|
color: var(--app-text-primary);
|
|
> .title {
|
|
font-size: 16px;
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
line-height: 25px; /* 140% */
|
|
margin: 16px 0;
|
|
span {
|
|
color: var(--app-text-secondary);
|
|
font-size: 12px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
line-height: 18px; /* 150% */
|
|
}
|
|
}
|
|
.line {
|
|
width: 36px;
|
|
height: 5px;
|
|
border-radius: 100px;
|
|
background: #464646;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.list-box {
|
|
flex: 1;
|
|
.list {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
|
grid-column-gap: 5px;
|
|
grid-row-gap: 9px;
|
|
}
|
|
}
|
|
}
|
|
.margin-r-88 {
|
|
margin-right: 88px;
|
|
}
|
|
|
|
.introduction-wrap,
|
|
.play-list-box {
|
|
:deep(.episode) {
|
|
color: var(--app-text-secondary);
|
|
border-color: transparent;
|
|
background: rgba(255, 255, 255, 0.05);
|
|
font-weight: 500;
|
|
|
|
&.active {
|
|
color: var(--app-primary);
|
|
border-color: var(--app-primary);
|
|
background: rgba(255, 126, 0, 0.2);
|
|
}
|
|
|
|
.byte-wrap .item {
|
|
background-color: var(--app-primary);
|
|
}
|
|
}
|
|
}
|
|
|
|
.introduction-wrap :deep(.recommendedList .horizontalVideoBox) {
|
|
.coverBox .vip_icon:not(.coins_icon):not(.free_trial_icon) {
|
|
background: var(--app-primary);
|
|
}
|
|
|
|
.videoTitle {
|
|
color: var(--app-text-primary);
|
|
font-weight: 400;
|
|
}
|
|
|
|
.acg-info span,
|
|
.videoTitleInfo {
|
|
color: var(--app-text-secondary);
|
|
}
|
|
}
|
|
</style>
|